12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
- 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.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- /*
- GUIs and script remain separately parsed
- Following a parse, all referenced media (and other decls) will have been touched.
- sinTable and cosTable are required for the rotate material keyword to function
- A new FindType on a purged decl will cause it to be reloaded, but a stale pointer to a purged
- decl will look like a defaulted decl.
- Moving a decl from one file to another will not be handled correctly by a reload, the material
- will be defaulted.
- NULL or empty decl names will always return NULL
- Should probably make a default decl for this
- Decls are initially created without a textSource
- A parse without textSource set should always just call MakeDefault()
- A parse that has an error should internally call MakeDefault()
- A purge does nothing to a defaulted decl
- Should we have a "purged" media state separate from the "defaulted" media state?
- reloading over a decl name that was defaulted
- reloading over a decl name that was valid
- missing reload over a previously explicit definition
- */
- #define USE_COMPRESSED_DECLS
- //#define GET_HUFFMAN_FREQUENCIES
- class idDeclType {
- public:
- idStr typeName;
- declType_t type;
- idDecl * (*allocator)( void );
- };
- class idDeclFolder {
- public:
- idStr folder;
- idStr extension;
- declType_t defaultType;
- };
- class idDeclFile;
- class idDeclLocal : public idDeclBase {
- friend class idDeclFile;
- friend class idDeclManagerLocal;
- public:
- idDeclLocal();
- virtual ~idDeclLocal() {};
- virtual const char * GetName( void ) const;
- virtual declType_t GetType( void ) const;
- virtual declState_t GetState( void ) const;
- virtual bool IsImplicit( void ) const;
- virtual bool IsValid( void ) const;
- virtual void Invalidate( void );
- virtual void Reload( void );
- virtual void EnsureNotPurged( void );
- virtual int Index( void ) const;
- virtual int GetLineNum( void ) const;
- virtual const char * GetFileName( void ) const;
- virtual size_t Size( void ) const;
- virtual void GetText( char *text ) const;
- virtual int GetTextLength( void ) const;
- virtual void SetText( const char *text );
- virtual bool ReplaceSourceFileText( void );
- virtual bool SourceFileChanged( void ) const;
- virtual void MakeDefault( void );
- virtual bool EverReferenced( void ) const;
- protected:
- virtual bool SetDefaultText( void );
- virtual const char * DefaultDefinition( void ) const;
- virtual bool Parse( const char *text, const int textLength );
- virtual void FreeData( void );
- virtual void List( void ) const;
- virtual void Print( void ) const;
- protected:
- void AllocateSelf( void );
- // Parses the decl definition.
- // After calling parse, a decl will be guaranteed usable.
- void ParseLocal( void );
- // Does a MakeDefualt, but flags the decl so that it
- // will Parse() the next time the decl is found.
- void Purge( void );
- // Set textSource possible with compression.
- void SetTextLocal( const char *text, const int length );
- private:
- idDecl * self;
- idStr name; // name of the decl
- char * textSource; // decl text definition
- int textLength; // length of textSource
- int compressedLength; // compressed length
- idDeclFile * sourceFile; // source file in which the decl was defined
- int sourceTextOffset; // offset in source file to decl text
- int sourceTextLength; // length of decl text in source file
- int sourceLine; // this is where the actual declaration token starts
- int checksum; // checksum of the decl text
- declType_t type; // decl type
- declState_t declState; // decl state
- int index; // index in the per-type list
- bool parsedOutsideLevelLoad; // these decls will never be purged
- bool everReferenced; // set to true if the decl was ever used
- bool referencedThisLevel; // set to true when the decl is used for the current level
- bool redefinedInReload; // used during file reloading to make sure a decl that has
- // its source removed will be defaulted
- idDeclLocal * nextInFile; // next decl in the decl file
- };
- class idDeclFile {
- public:
- idDeclFile();
- idDeclFile( const char *fileName, declType_t defaultType );
- void Reload( bool force );
- int LoadAndParse();
- public:
- idStr fileName;
- declType_t defaultType;
- ID_TIME_T timestamp;
- int checksum;
- int fileSize;
- int numLines;
- idDeclLocal * decls;
- };
- class idDeclManagerLocal : public idDeclManager {
- friend class idDeclLocal;
- public:
- virtual void Init( void );
- virtual void Shutdown( void );
- virtual void Reload( bool force );
- virtual void BeginLevelLoad();
- virtual void EndLevelLoad();
- virtual void RegisterDeclType( const char *typeName, declType_t type, idDecl *(*allocator)( void ) );
- virtual void RegisterDeclFolder( const char *folder, const char *extension, declType_t defaultType );
- virtual int GetChecksum( void ) const;
- virtual int GetNumDeclTypes( void ) const;
- virtual int GetNumDecls( declType_t type );
- virtual const char * GetDeclNameFromType( declType_t type ) const;
- virtual declType_t GetDeclTypeFromName( const char *typeName ) const;
- virtual const idDecl * FindType( declType_t type, const char *name, bool makeDefault = true );
- virtual const idDecl * DeclByIndex( declType_t type, int index, bool forceParse = true );
- virtual const idDecl* FindDeclWithoutParsing( declType_t type, const char *name, bool makeDefault = true );
- virtual void ReloadFile( const char* filename, bool force );
- virtual void ListType( const idCmdArgs &args, declType_t type );
- virtual void PrintType( const idCmdArgs &args, declType_t type );
- virtual idDecl * CreateNewDecl( declType_t type, const char *name, const char *fileName );
- //BSM Added for the material editors rename capabilities
- virtual bool RenameDecl( declType_t type, const char* oldName, const char* newName );
- virtual void MediaPrint( const char *fmt, ... ) id_attribute((format(printf,2,3)));
- virtual void WritePrecacheCommands( idFile *f );
- virtual const idMaterial * FindMaterial( const char *name, bool makeDefault = true );
- virtual const idDeclSkin * FindSkin( const char *name, bool makeDefault = true );
- virtual const idSoundShader * FindSound( const char *name, bool makeDefault = true );
- virtual const idMaterial * MaterialByIndex( int index, bool forceParse = true );
- virtual const idDeclSkin * SkinByIndex( int index, bool forceParse = true );
- virtual const idSoundShader * SoundByIndex( int index, bool forceParse = true );
- public:
- static void MakeNameCanonical( const char *name, char *result, int maxLength );
- idDeclLocal * FindTypeWithoutParsing( declType_t type, const char *name, bool makeDefault = true );
- idDeclType * GetDeclType( int type ) const { return declTypes[type]; }
- const idDeclFile * GetImplicitDeclFile( void ) const { return &implicitDecls; }
- private:
- idList<idDeclType *> declTypes;
- idList<idDeclFolder *> declFolders;
- idList<idDeclFile *> loadedFiles;
- idHashIndex hashTables[DECL_MAX_TYPES];
- idList<idDeclLocal *> linearLists[DECL_MAX_TYPES];
- idDeclFile implicitDecls; // this holds all the decls that were created because explicit
- // text definitions were not found. Decls that became default
- // because of a parse error are not in this list.
- int checksum; // checksum of all loaded decl text
- int indent; // for MediaPrint
- bool insideLevelLoad;
- static idCVar decl_show;
- private:
- static void ListDecls_f( const idCmdArgs &args );
- static void ReloadDecls_f( const idCmdArgs &args );
- static void TouchDecl_f( const idCmdArgs &args );
- };
- 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> );
- idDeclManagerLocal declManagerLocal;
- idDeclManager * declManager = &declManagerLocal;
- /*
- ====================================================================================
- decl text huffman compression
- ====================================================================================
- */
- const int MAX_HUFFMAN_SYMBOLS = 256;
- typedef struct huffmanNode_s {
- int symbol;
- int frequency;
- struct huffmanNode_s * next;
- struct huffmanNode_s * children[2];
- } huffmanNode_t;
- typedef struct huffmanCode_s {
- unsigned long bits[8];
- int numBits;
- } huffmanCode_t;
- // compression ratio = 64%
- static int huffmanFrequencies[] = {
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00078fb6, 0x000352a7, 0x00000002, 0x00000001, 0x0002795e, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00049600, 0x000000dd, 0x00018732, 0x0000005a, 0x00000007, 0x00000092, 0x0000000a, 0x00000919,
- 0x00002dcf, 0x00002dda, 0x00004dfc, 0x0000039a, 0x000058be, 0x00002d13, 0x00014d8c, 0x00023c60,
- 0x0002ddb0, 0x0000d1fc, 0x000078c4, 0x00003ec7, 0x00003113, 0x00006b59, 0x00002499, 0x0000184a,
- 0x0000250b, 0x00004e38, 0x000001ca, 0x00000011, 0x00000020, 0x000023da, 0x00000012, 0x00000091,
- 0x0000000b, 0x00000b14, 0x0000035d, 0x0000137e, 0x000020c9, 0x00000e11, 0x000004b4, 0x00000737,
- 0x000006b8, 0x00001110, 0x000006b3, 0x000000fe, 0x00000f02, 0x00000d73, 0x000005f6, 0x00000be4,
- 0x00000d86, 0x0000014d, 0x00000d89, 0x0000129b, 0x00000db3, 0x0000015a, 0x00000167, 0x00000375,
- 0x00000028, 0x00000112, 0x00000018, 0x00000678, 0x0000081a, 0x00000677, 0x00000003, 0x00018112,
- 0x00000001, 0x000441ee, 0x000124b0, 0x0001fa3f, 0x00026125, 0x0005a411, 0x0000e50f, 0x00011820,
- 0x00010f13, 0x0002e723, 0x00003518, 0x00005738, 0x0002cc26, 0x0002a9b7, 0x0002db81, 0x0003b5fa,
- 0x000185d2, 0x00001299, 0x00030773, 0x0003920d, 0x000411cd, 0x00018751, 0x00005fbd, 0x000099b0,
- 0x00009242, 0x00007cf2, 0x00002809, 0x00005a1d, 0x00000001, 0x00005a1d, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001,
- };
- static huffmanCode_t huffmanCodes[MAX_HUFFMAN_SYMBOLS];
- static huffmanNode_t *huffmanTree = NULL;
- static int totalUncompressedLength = 0;
- static int totalCompressedLength = 0;
- static int maxHuffmanBits = 0;
- /*
- ================
- ClearHuffmanFrequencies
- ================
- */
- void ClearHuffmanFrequencies( void ) {
- int i;
- for( i = 0; i < MAX_HUFFMAN_SYMBOLS; i++ ) {
- huffmanFrequencies[i] = 1;
- }
- }
- /*
- ================
- InsertHuffmanNode
- ================
- */
- huffmanNode_t *InsertHuffmanNode( huffmanNode_t *firstNode, huffmanNode_t *node ) {
- huffmanNode_t *n, *lastNode;
- lastNode = NULL;
- for ( n = firstNode; n; n = n->next ) {
- if ( node->frequency <= n->frequency ) {
- break;
- }
- lastNode = n;
- }
- if ( lastNode ) {
- node->next = lastNode->next;
- lastNode->next = node;
- } else {
- node->next = firstNode;
- firstNode = node;
- }
- return firstNode;
- }
- /*
- ================
- BuildHuffmanCode_r
- ================
- */
- void BuildHuffmanCode_r( huffmanNode_t *node, huffmanCode_t code, huffmanCode_t codes[MAX_HUFFMAN_SYMBOLS] ) {
- if ( node->symbol == -1 ) {
- huffmanCode_t newCode = code;
- assert( code.numBits < sizeof( codes[0].bits ) * 8 );
- newCode.numBits++;
- if ( code.numBits > maxHuffmanBits ) {
- maxHuffmanBits = newCode.numBits;
- }
- BuildHuffmanCode_r( node->children[0], newCode, codes );
- newCode.bits[code.numBits >> 5] |= 1 << ( code.numBits & 31 );
- BuildHuffmanCode_r( node->children[1], newCode, codes );
- } else {
- assert( code.numBits <= sizeof( codes[0].bits ) * 8 );
- codes[node->symbol] = code;
- }
- }
- /*
- ================
- FreeHuffmanTree_r
- ================
- */
- void FreeHuffmanTree_r( huffmanNode_t *node ) {
- if ( node->symbol == -1 ) {
- FreeHuffmanTree_r( node->children[0] );
- FreeHuffmanTree_r( node->children[1] );
- }
- delete node;
- }
- /*
- ================
- HuffmanHeight_r
- ================
- */
- int HuffmanHeight_r( huffmanNode_t *node ) {
- if ( node == NULL ) {
- return -1;
- }
- int left = HuffmanHeight_r( node->children[0] );
- int right = HuffmanHeight_r( node->children[1] );
- if ( left > right ) {
- return left + 1;
- }
- return right + 1;
- }
- /*
- ================
- SetupHuffman
- ================
- */
- void SetupHuffman( void ) {
- int i, height;
- huffmanNode_t *firstNode, *node;
- huffmanCode_t code;
- firstNode = NULL;
- for( i = 0; i < MAX_HUFFMAN_SYMBOLS; i++ ) {
- node = new huffmanNode_t;
- node->symbol = i;
- node->frequency = huffmanFrequencies[i];
- node->next = NULL;
- node->children[0] = NULL;
- node->children[1] = NULL;
- firstNode = InsertHuffmanNode( firstNode, node );
- }
- for( i = 1; i < MAX_HUFFMAN_SYMBOLS; i++ ) {
- node = new huffmanNode_t;
- node->symbol = -1;
- node->frequency = firstNode->frequency + firstNode->next->frequency;
- node->next = NULL;
- node->children[0] = firstNode;
- node->children[1] = firstNode->next;
- firstNode = InsertHuffmanNode( firstNode->next->next, node );
- }
- maxHuffmanBits = 0;
- memset( &code, 0, sizeof( code ) );
- BuildHuffmanCode_r( firstNode, code, huffmanCodes );
- huffmanTree = firstNode;
- height = HuffmanHeight_r( firstNode );
- assert( maxHuffmanBits == height );
- }
- /*
- ================
- ShutdownHuffman
- ================
- */
- void ShutdownHuffman( void ) {
- if ( huffmanTree ) {
- FreeHuffmanTree_r( huffmanTree );
- }
- }
- /*
- ================
- HuffmanCompressText
- ================
- */
- int HuffmanCompressText( const char *text, int textLength, byte *compressed, int maxCompressedSize ) {
- int i, j;
- idBitMsg msg;
- totalUncompressedLength += textLength;
- msg.Init( compressed, maxCompressedSize );
- msg.BeginWriting();
- for ( i = 0; i < textLength; i++ ) {
- const huffmanCode_t &code = huffmanCodes[(unsigned char)text[i]];
- for ( j = 0; j < ( code.numBits >> 5 ); j++ ) {
- msg.WriteBits( code.bits[j], 32 );
- }
- if ( code.numBits & 31 ) {
- msg.WriteBits( code.bits[j], code.numBits & 31 );
- }
- }
- totalCompressedLength += msg.GetSize();
- return msg.GetSize();
- }
- /*
- ================
- HuffmanDecompressText
- ================
- */
- int HuffmanDecompressText( char *text, int textLength, const byte *compressed, int compressedSize ) {
- int i, bit;
- idBitMsg msg;
- huffmanNode_t *node;
- msg.Init( compressed, compressedSize );
- msg.SetSize( compressedSize );
- msg.BeginReading();
- for ( i = 0; i < textLength; i++ ) {
- node = huffmanTree;
- do {
- bit = msg.ReadBits( 1 );
- node = node->children[bit];
- } while( node->symbol == -1 );
- text[i] = node->symbol;
- }
- text[i] = '\0';
- return msg.GetReadCount();
- }
- /*
- ================
- ListHuffmanFrequencies_f
- ================
- */
- void ListHuffmanFrequencies_f( const idCmdArgs &args ) {
- int i;
- float compression;
- compression = !totalUncompressedLength ? 100 : 100 * totalCompressedLength / totalUncompressedLength;
- common->Printf( "// compression ratio = %d%%\n", (int)compression );
- common->Printf( "static int huffmanFrequencies[] = {\n" );
- for( i = 0; i < MAX_HUFFMAN_SYMBOLS; i += 8 ) {
- common->Printf( "\t0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x,\n",
- huffmanFrequencies[i+0], huffmanFrequencies[i+1],
- huffmanFrequencies[i+2], huffmanFrequencies[i+3],
- huffmanFrequencies[i+4], huffmanFrequencies[i+5],
- huffmanFrequencies[i+6], huffmanFrequencies[i+7]);
- }
- common->Printf( "}\n" );
- }
- /*
- ====================================================================================
- idDeclFile
- ====================================================================================
- */
- /*
- ================
- idDeclFile::idDeclFile
- ================
- */
- idDeclFile::idDeclFile( const char *fileName, declType_t defaultType ) {
- this->fileName = fileName;
- this->defaultType = defaultType;
- this->timestamp = 0;
- this->checksum = 0;
- this->fileSize = 0;
- this->numLines = 0;
- this->decls = NULL;
- }
- /*
- ================
- idDeclFile::idDeclFile
- ================
- */
- idDeclFile::idDeclFile() {
- this->fileName = "<implicit file>";
- this->defaultType = DECL_MAX_TYPES;
- this->timestamp = 0;
- this->checksum = 0;
- this->fileSize = 0;
- this->numLines = 0;
- this->decls = NULL;
- }
- /*
- ================
- idDeclFile::Reload
- ForceReload will cause it to reload even if the timestamp hasn't changed
- ================
- */
- void idDeclFile::Reload( bool force ) {
- // check for an unchanged timestamp
- if ( !force && timestamp != 0 ) {
- ID_TIME_T testTimeStamp;
- fileSystem->ReadFile( fileName, NULL, &testTimeStamp );
- if ( testTimeStamp == timestamp ) {
- return;
- }
- }
- // parse the text
- LoadAndParse();
- }
- /*
- ================
- idDeclFile::LoadAndParse
- This is used during both the initial load, and any reloads
- ================
- */
- int c_savedMemory = 0;
- int idDeclFile::LoadAndParse() {
- int i, numTypes;
- idLexer src;
- idToken token;
- int startMarker;
- char * buffer;
- int length, size;
- int sourceLine;
- idStr name;
- idDeclLocal *newDecl;
- bool reparse;
- // load the text
- common->DPrintf( "...loading '%s'\n", fileName.c_str() );
- length = fileSystem->ReadFile( fileName, (void **)&buffer, ×tamp );
- if ( length == -1 ) {
- common->FatalError( "couldn't load %s", fileName.c_str() );
- return 0;
- }
- if ( !src.LoadMemory( buffer, length, fileName ) ) {
- common->Error( "Couldn't parse %s", fileName.c_str() );
- Mem_Free( buffer );
- return 0;
- }
- // mark all the defs that were from the last reload of this file
- for ( idDeclLocal *decl = decls; decl; decl = decl->nextInFile ) {
- decl->redefinedInReload = false;
- }
- src.SetFlags( DECL_LEXER_FLAGS );
- checksum = MD5_BlockChecksum( buffer, length );
- fileSize = length;
- // scan through, identifying each individual declaration
- while( 1 ) {
- startMarker = src.GetFileOffset();
- sourceLine = src.GetLineNum();
- // parse the decl type name
- if ( !src.ReadToken( &token ) ) {
- break;
- }
- declType_t identifiedType = DECL_MAX_TYPES;
- // get the decl type from the type name
- numTypes = declManagerLocal.GetNumDeclTypes();
- for ( i = 0; i < numTypes; i++ ) {
- idDeclType *typeInfo = declManagerLocal.GetDeclType( i );
- if ( typeInfo && typeInfo->typeName.Icmp( token ) == 0 ) {
- identifiedType = (declType_t) typeInfo->type;
- break;
- }
- }
- if ( i >= numTypes ) {
- if ( token.Icmp( "{" ) == 0 ) {
- // if we ever see an open brace, we somehow missed the [type] <name> prefix
- src.Warning( "Missing decl name" );
- src.SkipBracedSection( false );
- continue;
- } else {
- if ( defaultType == DECL_MAX_TYPES ) {
- src.Warning( "No type" );
- continue;
- }
- src.UnreadToken( &token );
- // use the default type
- identifiedType = defaultType;
- }
- }
- // now parse the name
- if ( !src.ReadToken( &token ) ) {
- src.Warning( "Type without definition at end of file" );
- break;
- }
- if ( !token.Icmp( "{" ) ) {
- // if we ever see an open brace, we somehow missed the [type] <name> prefix
- src.Warning( "Missing decl name" );
- src.SkipBracedSection( false );
- continue;
- }
- // FIXME: export decls are only used by the model exporter, they are skipped here for now
- if ( identifiedType == DECL_MODELEXPORT ) {
- src.SkipBracedSection();
- continue;
- }
- name = token;
- // make sure there's a '{'
- if ( !src.ReadToken( &token ) ) {
- src.Warning( "Type without definition at end of file" );
- break;
- }
- if ( token != "{" ) {
- src.Warning( "Expecting '{' but found '%s'", token.c_str() );
- continue;
- }
- src.UnreadToken( &token );
- // now take everything until a matched closing brace
- src.SkipBracedSection();
- size = src.GetFileOffset() - startMarker;
- // look it up, possibly getting a newly created default decl
- reparse = false;
- newDecl = declManagerLocal.FindTypeWithoutParsing( identifiedType, name, false );
- if ( newDecl ) {
- // update the existing copy
- if ( newDecl->sourceFile != this || newDecl->redefinedInReload ) {
- src.Warning( "%s '%s' previously defined at %s:%i", declManagerLocal.GetDeclNameFromType( identifiedType ),
- name.c_str(), newDecl->sourceFile->fileName.c_str(), newDecl->sourceLine );
- continue;
- }
- if ( newDecl->declState != DS_UNPARSED ) {
- reparse = true;
- }
- } else {
- // allow it to be created as a default, then add it to the per-file list
- newDecl = declManagerLocal.FindTypeWithoutParsing( identifiedType, name, true );
- newDecl->nextInFile = this->decls;
- this->decls = newDecl;
- }
- newDecl->redefinedInReload = true;
- if ( newDecl->textSource ) {
- Mem_Free( newDecl->textSource );
- newDecl->textSource = NULL;
- }
- newDecl->SetTextLocal( buffer + startMarker, size );
- newDecl->sourceFile = this;
- newDecl->sourceTextOffset = startMarker;
- newDecl->sourceTextLength = size;
- newDecl->sourceLine = sourceLine;
- newDecl->declState = DS_UNPARSED;
- // if it is currently in use, reparse it immedaitely
- if ( reparse ) {
- newDecl->ParseLocal();
- }
- }
- numLines = src.GetLineNum();
- Mem_Free( buffer );
- // any defs that weren't redefinedInReload should now be defaulted
- for ( idDeclLocal *decl = decls ; decl ; decl = decl->nextInFile ) {
- if ( decl->redefinedInReload == false ) {
- decl->MakeDefault();
- decl->sourceTextOffset = decl->sourceFile->fileSize;
- decl->sourceTextLength = 0;
- decl->sourceLine = decl->sourceFile->numLines;
- }
- }
- return checksum;
- }
- /*
- ====================================================================================
- idDeclManagerLocal
- ====================================================================================
- */
- const char *listDeclStrings[] = { "current", "all", "ever", NULL };
- /*
- ===================
- idDeclManagerLocal::Init
- ===================
- */
- void idDeclManagerLocal::Init( void ) {
- common->Printf( "----- Initializing Decls -----\n" );
- checksum = 0;
- #ifdef USE_COMPRESSED_DECLS
- SetupHuffman();
- #endif
- #ifdef GET_HUFFMAN_FREQUENCIES
- ClearHuffmanFrequencies();
- #endif
- // decls used throughout the engine
- RegisterDeclType( "table", DECL_TABLE, idDeclAllocator<idDeclTable> );
- RegisterDeclType( "material", DECL_MATERIAL, idDeclAllocator<idMaterial> );
- RegisterDeclType( "skin", DECL_SKIN, idDeclAllocator<idDeclSkin> );
- RegisterDeclType( "sound", DECL_SOUND, idDeclAllocator<idSoundShader> );
- RegisterDeclType( "entityDef", DECL_ENTITYDEF, idDeclAllocator<idDeclEntityDef> );
- RegisterDeclType( "mapDef", DECL_MAPDEF, idDeclAllocator<idDeclEntityDef> );
- RegisterDeclType( "fx", DECL_FX, idDeclAllocator<idDeclFX> );
- RegisterDeclType( "particle", DECL_PARTICLE, idDeclAllocator<idDeclParticle> );
- RegisterDeclType( "articulatedFigure", DECL_AF, idDeclAllocator<idDeclAF> );
- RegisterDeclType( "pda", DECL_PDA, idDeclAllocator<idDeclPDA> );
- RegisterDeclType( "email", DECL_EMAIL, idDeclAllocator<idDeclEmail> );
- RegisterDeclType( "video", DECL_VIDEO, idDeclAllocator<idDeclVideo> );
- RegisterDeclType( "audio", DECL_AUDIO, idDeclAllocator<idDeclAudio> );
- RegisterDeclFolder( "materials", ".mtr", DECL_MATERIAL );
- RegisterDeclFolder( "skins", ".skin", DECL_SKIN );
- RegisterDeclFolder( "sound", ".sndshd", DECL_SOUND );
- // add console commands
- cmdSystem->AddCommand( "listDecls", ListDecls_f, CMD_FL_SYSTEM, "lists all decls" );
- cmdSystem->AddCommand( "reloadDecls", ReloadDecls_f, CMD_FL_SYSTEM, "reloads decls" );
- cmdSystem->AddCommand( "touch", TouchDecl_f, CMD_FL_SYSTEM, "touches a decl" );
- cmdSystem->AddCommand( "listTables", idListDecls_f<DECL_TABLE>, CMD_FL_SYSTEM, "lists tables", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listMaterials", idListDecls_f<DECL_MATERIAL>, CMD_FL_SYSTEM, "lists materials", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listSkins", idListDecls_f<DECL_SKIN>, CMD_FL_SYSTEM, "lists skins", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listSoundShaders", idListDecls_f<DECL_SOUND>, CMD_FL_SYSTEM, "lists sound shaders", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listEntityDefs", idListDecls_f<DECL_ENTITYDEF>, CMD_FL_SYSTEM, "lists entity defs", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listFX", idListDecls_f<DECL_FX>, CMD_FL_SYSTEM, "lists FX systems", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listParticles", idListDecls_f<DECL_PARTICLE>, CMD_FL_SYSTEM, "lists particle systems", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listAF", idListDecls_f<DECL_AF>, CMD_FL_SYSTEM, "lists articulated figures", idCmdSystem::ArgCompletion_String<listDeclStrings>);
- cmdSystem->AddCommand( "listPDAs", idListDecls_f<DECL_PDA>, CMD_FL_SYSTEM, "lists PDAs", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listEmails", idListDecls_f<DECL_EMAIL>, CMD_FL_SYSTEM, "lists Emails", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listVideos", idListDecls_f<DECL_VIDEO>, CMD_FL_SYSTEM, "lists Videos", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "listAudios", idListDecls_f<DECL_AUDIO>, CMD_FL_SYSTEM, "lists Audios", idCmdSystem::ArgCompletion_String<listDeclStrings> );
- cmdSystem->AddCommand( "printTable", idPrintDecls_f<DECL_TABLE>, CMD_FL_SYSTEM, "prints a table", idCmdSystem::ArgCompletion_Decl<DECL_TABLE> );
- cmdSystem->AddCommand( "printMaterial", idPrintDecls_f<DECL_MATERIAL>, CMD_FL_SYSTEM, "prints a material", idCmdSystem::ArgCompletion_Decl<DECL_MATERIAL> );
- cmdSystem->AddCommand( "printSkin", idPrintDecls_f<DECL_SKIN>, CMD_FL_SYSTEM, "prints a skin", idCmdSystem::ArgCompletion_Decl<DECL_SKIN> );
- cmdSystem->AddCommand( "printSoundShader", idPrintDecls_f<DECL_SOUND>, CMD_FL_SYSTEM, "prints a sound shader", idCmdSystem::ArgCompletion_Decl<DECL_SOUND> );
- cmdSystem->AddCommand( "printEntityDef", idPrintDecls_f<DECL_ENTITYDEF>, CMD_FL_SYSTEM, "prints an entity def", idCmdSystem::ArgCompletion_Decl<DECL_ENTITYDEF> );
- cmdSystem->AddCommand( "printFX", idPrintDecls_f<DECL_FX>, CMD_FL_SYSTEM, "prints an FX system", idCmdSystem::ArgCompletion_Decl<DECL_FX> );
- cmdSystem->AddCommand( "printParticle", idPrintDecls_f<DECL_PARTICLE>, CMD_FL_SYSTEM, "prints a particle system", idCmdSystem::ArgCompletion_Decl<DECL_PARTICLE> );
- cmdSystem->AddCommand( "printAF", idPrintDecls_f<DECL_AF>, CMD_FL_SYSTEM, "prints an articulated figure", idCmdSystem::ArgCompletion_Decl<DECL_AF> );
- cmdSystem->AddCommand( "printPDA", idPrintDecls_f<DECL_PDA>, CMD_FL_SYSTEM, "prints an PDA", idCmdSystem::ArgCompletion_Decl<DECL_PDA> );
- cmdSystem->AddCommand( "printEmail", idPrintDecls_f<DECL_EMAIL>, CMD_FL_SYSTEM, "prints an Email", idCmdSystem::ArgCompletion_Decl<DECL_EMAIL> );
- cmdSystem->AddCommand( "printVideo", idPrintDecls_f<DECL_VIDEO>, CMD_FL_SYSTEM, "prints a Audio", idCmdSystem::ArgCompletion_Decl<DECL_VIDEO> );
- cmdSystem->AddCommand( "printAudio", idPrintDecls_f<DECL_AUDIO>, CMD_FL_SYSTEM, "prints an Video", idCmdSystem::ArgCompletion_Decl<DECL_AUDIO> );
- cmdSystem->AddCommand( "listHuffmanFrequencies", ListHuffmanFrequencies_f, CMD_FL_SYSTEM, "lists decl text character frequencies" );
- common->Printf( "------------------------------\n" );
- }
- /*
- ===================
- idDeclManagerLocal::Shutdown
- ===================
- */
- void idDeclManagerLocal::Shutdown( void ) {
- int i, j;
- idDeclLocal *decl;
- // free decls
- for ( i = 0; i < DECL_MAX_TYPES; i++ ) {
- for ( j = 0; j < linearLists[i].Num(); j++ ) {
- decl = linearLists[i][j];
- if ( decl->self != NULL ) {
- decl->self->FreeData();
- delete decl->self;
- }
- if ( decl->textSource ) {
- Mem_Free( decl->textSource );
- decl->textSource = NULL;
- }
- delete decl;
- }
- linearLists[i].Clear();
- hashTables[i].Free();
- }
- // free decl files
- loadedFiles.DeleteContents( true );
- // free the decl types and folders
- declTypes.DeleteContents( true );
- declFolders.DeleteContents( true );
- #ifdef USE_COMPRESSED_DECLS
- ShutdownHuffman();
- #endif
- }
- /*
- ===================
- idDeclManagerLocal::Reload
- ===================
- */
- void idDeclManagerLocal::Reload( bool force ) {
- for ( int i = 0; i < loadedFiles.Num(); i++ ) {
- loadedFiles[i]->Reload( force );
- }
- }
- /*
- ===================
- idDeclManagerLocal::BeginLevelLoad
- ===================
- */
- void idDeclManagerLocal::BeginLevelLoad() {
- insideLevelLoad = true;
- // clear all the referencedThisLevel flags and purge all the data
- // so the next reference will cause a reparse
- for ( int i = 0; i < DECL_MAX_TYPES; i++ ) {
- int num = linearLists[i].Num();
- for ( int j = 0 ; j < num ; j++ ) {
- idDeclLocal *decl = linearLists[i][j];
- decl->Purge();
- }
- }
- }
- /*
- ===================
- idDeclManagerLocal::EndLevelLoad
- ===================
- */
- void idDeclManagerLocal::EndLevelLoad() {
- insideLevelLoad = false;
- // we don't need to do anything here, but the image manager, model manager,
- // and sound sample manager will need to free media that was not referenced
- }
- /*
- ===================
- idDeclManagerLocal::RegisterDeclType
- ===================
- */
- void idDeclManagerLocal::RegisterDeclType( const char *typeName, declType_t type, idDecl *(*allocator)( void ) ) {
- idDeclType *declType;
- if ( type < declTypes.Num() && declTypes[(int)type] ) {
- common->Warning( "idDeclManager::RegisterDeclType: type '%s' already exists", typeName );
- return;
- }
- declType = new idDeclType;
- declType->typeName = typeName;
- declType->type = type;
- declType->allocator = allocator;
- if ( (int)type + 1 > declTypes.Num() ) {
- declTypes.AssureSize( (int)type + 1, NULL );
- }
- declTypes[type] = declType;
- }
- /*
- ===================
- idDeclManagerLocal::RegisterDeclFolder
- ===================
- */
- void idDeclManagerLocal::RegisterDeclFolder( const char *folder, const char *extension, declType_t defaultType ) {
- int i, j;
- idStr fileName;
- idDeclFolder *declFolder;
- idFileList *fileList;
- idDeclFile *df;
- // check whether this folder / extension combination already exists
- for ( i = 0; i < declFolders.Num(); i++ ) {
- if ( declFolders[i]->folder.Icmp( folder ) == 0 && declFolders[i]->extension.Icmp( extension ) == 0 ) {
- break;
- }
- }
- if ( i < declFolders.Num() ) {
- declFolder = declFolders[i];
- } else {
- declFolder = new idDeclFolder;
- declFolder->folder = folder;
- declFolder->extension = extension;
- declFolder->defaultType = defaultType;
- declFolders.Append( declFolder );
- }
- // scan for decl files
- fileList = fileSystem->ListFiles( declFolder->folder, declFolder->extension, true );
- // load and parse decl files
- for ( i = 0; i < fileList->GetNumFiles(); i++ ) {
- fileName = declFolder->folder + "/" + fileList->GetFile( i );
- // check whether this file has already been loaded
- for ( j = 0; j < loadedFiles.Num(); j++ ) {
- if ( fileName.Icmp( loadedFiles[j]->fileName ) == 0 ) {
- break;
- }
- }
- if ( j < loadedFiles.Num() ) {
- df = loadedFiles[j];
- } else {
- df = new idDeclFile( fileName, defaultType );
- loadedFiles.Append( df );
- }
- df->LoadAndParse();
- }
- fileSystem->FreeFileList( fileList );
- }
- /*
- ===================
- idDeclManagerLocal::GetChecksum
- ===================
- */
- int idDeclManagerLocal::GetChecksum( void ) const {
- int i, j, total, num;
- int *checksumData;
- // get the total number of decls
- total = 0;
- for ( i = 0; i < DECL_MAX_TYPES; i++ ) {
- total += linearLists[i].Num();
- }
- checksumData = (int *) _alloca16( total * 2 * sizeof( int ) );
- total = 0;
- for ( i = 0; i < DECL_MAX_TYPES; i++ ) {
- declType_t type = (declType_t) i;
- // FIXME: not particularly pretty but PDAs and associated decls are localized and should not be checksummed
- if ( type == DECL_PDA || type == DECL_VIDEO || type == DECL_AUDIO || type == DECL_EMAIL ) {
- continue;
- }
-
- num = linearLists[i].Num();
- for ( j = 0; j < num; j++ ) {
- idDeclLocal *decl = linearLists[i][j];
- if ( decl->sourceFile == &implicitDecls ) {
- continue;
- }
- checksumData[total*2+0] = total;
- checksumData[total*2+1] = decl->checksum;
- total++;
- }
- }
- LittleRevBytes( checksumData, sizeof(int), total * 2 );
- return MD5_BlockChecksum( checksumData, total * 2 * sizeof( int ) );
- }
- /*
- ===================
- idDeclManagerLocal::GetNumDeclTypes
- ===================
- */
- int idDeclManagerLocal::GetNumDeclTypes( void ) const {
- return declTypes.Num();
- }
- /*
- ===================
- idDeclManagerLocal::GetDeclNameFromType
- ===================
- */
- const char * idDeclManagerLocal::GetDeclNameFromType( declType_t type ) const {
- int typeIndex = (int)type;
- if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
- common->FatalError( "idDeclManager::GetDeclNameFromType: bad type: %i", typeIndex );
- }
- return declTypes[typeIndex]->typeName;
- }
- /*
- ===================
- idDeclManagerLocal::GetDeclTypeFromName
- ===================
- */
- declType_t idDeclManagerLocal::GetDeclTypeFromName( const char *typeName ) const {
- int i;
- for ( i = 0; i < declTypes.Num(); i++ ) {
- if ( declTypes[i] && declTypes[i]->typeName.Icmp( typeName ) == 0 ) {
- return (declType_t)declTypes[i]->type;
- }
- }
- return DECL_MAX_TYPES;
- }
- /*
- =================
- idDeclManagerLocal::FindType
- External users will always cause the decl to be parsed before returning
- =================
- */
- const idDecl *idDeclManagerLocal::FindType( declType_t type, const char *name, bool makeDefault ) {
- idDeclLocal *decl;
- if ( !name || !name[0] ) {
- name = "_emptyName";
- //common->Warning( "idDeclManager::FindType: empty %s name", GetDeclType( (int)type )->typeName.c_str() );
- }
- decl = FindTypeWithoutParsing( type, name, makeDefault );
- if ( !decl ) {
- return NULL;
- }
- decl->AllocateSelf();
- // if it hasn't been parsed yet, parse it now
- if ( decl->declState == DS_UNPARSED ) {
- decl->ParseLocal();
- }
- // mark it as referenced
- decl->referencedThisLevel = true;
- decl->everReferenced = true;
- if ( insideLevelLoad ) {
- decl->parsedOutsideLevelLoad = false;
- }
- return decl->self;
- }
- /*
- ===============
- idDeclManagerLocal::FindDeclWithoutParsing
- ===============
- */
- const idDecl* idDeclManagerLocal::FindDeclWithoutParsing( declType_t type, const char *name, bool makeDefault) {
- idDeclLocal* decl;
- decl = FindTypeWithoutParsing(type, name, makeDefault);
- if(decl) {
- return decl->self;
- }
- return NULL;
- }
- /*
- ===============
- idDeclManagerLocal::ReloadFile
- ===============
- */
- void idDeclManagerLocal::ReloadFile( const char* filename, bool force ) {
- for ( int i = 0; i < loadedFiles.Num(); i++ ) {
- if(!loadedFiles[i]->fileName.Icmp(filename)) {
- checksum ^= loadedFiles[i]->checksum;
- loadedFiles[i]->Reload( force );
- checksum ^= loadedFiles[i]->checksum;
- }
- }
- }
- /*
- ===================
- idDeclManagerLocal::GetNumDecls
- ===================
- */
- int idDeclManagerLocal::GetNumDecls( declType_t type ) {
- int typeIndex = (int)type;
- if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
- common->FatalError( "idDeclManager::GetNumDecls: bad type: %i", typeIndex );
- }
- return linearLists[ typeIndex ].Num();
- }
- /*
- ===================
- idDeclManagerLocal::DeclByIndex
- ===================
- */
- const idDecl *idDeclManagerLocal::DeclByIndex( declType_t type, int index, bool forceParse ) {
- int typeIndex = (int)type;
- if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
- common->FatalError( "idDeclManager::DeclByIndex: bad type: %i", typeIndex );
- }
- if ( index < 0 || index >= linearLists[ typeIndex ].Num() ) {
- common->Error( "idDeclManager::DeclByIndex: out of range" );
- }
- idDeclLocal *decl = linearLists[ typeIndex ][ index ];
- decl->AllocateSelf();
- if ( forceParse && decl->declState == DS_UNPARSED ) {
- decl->ParseLocal();
- }
- return decl->self;
- }
- /*
- ===================
- idDeclManagerLocal::ListType
- list*
- Lists decls currently referenced
- list* ever
- Lists decls that have been referenced at least once since app launched
- list* all
- Lists every decl declared, even if it hasn't been referenced or parsed
- FIXME: alphabetized, wildcards?
- ===================
- */
- void idDeclManagerLocal::ListType( const idCmdArgs &args, declType_t type ) {
- bool all, ever;
- if ( !idStr::Icmp( args.Argv( 1 ), "all" ) ) {
- all = true;
- } else {
- all = false;
- }
- if ( !idStr::Icmp( args.Argv( 1 ), "ever" ) ) {
- ever = true;
- } else {
- ever = false;
- }
- common->Printf( "--------------------\n" );
- int printed = 0;
- int count = linearLists[ (int)type ].Num();
- for ( int i = 0 ; i < count ; i++ ) {
- idDeclLocal *decl = linearLists[ (int)type ][ i ];
- if ( !all && decl->declState == DS_UNPARSED ) {
- continue;
- }
- if ( !all && !ever && !decl->referencedThisLevel ) {
- continue;
- }
- if ( decl->referencedThisLevel ) {
- common->Printf( "*" );
- } else if ( decl->everReferenced ) {
- common->Printf( "." );
- } else {
- common->Printf( " " );
- }
- if ( decl->declState == DS_DEFAULTED ) {
- common->Printf( "D" );
- } else {
- common->Printf( " " );
- }
- common->Printf( "%4i: ", decl->index );
- printed++;
- if ( decl->declState == DS_UNPARSED ) {
- // doesn't have any type specific data yet
- common->Printf( "%s\n", decl->GetName() );
- } else {
- decl->self->List();
- }
- }
- common->Printf( "--------------------\n" );
- common->Printf( "%i of %i %s\n", printed, count, declTypes[type]->typeName.c_str() );
- }
- /*
- ===================
- idDeclManagerLocal::PrintType
- ===================
- */
- void idDeclManagerLocal::PrintType( const idCmdArgs &args, declType_t type ) {
- // individual decl types may use additional command parameters
- if ( args.Argc() < 2 ) {
- common->Printf( "USAGE: Print<decl type> <decl name> [type specific parms]\n" );
- return;
- }
- // look it up, skipping the public path so it won't parse or reference
- idDeclLocal *decl = FindTypeWithoutParsing( type, args.Argv( 1 ), false );
- if ( !decl ) {
- common->Printf( "%s '%s' not found.\n", declTypes[ type ]->typeName.c_str(), args.Argv( 1 ) );
- return;
- }
- // print information common to all decls
- common->Printf( "%s %s:\n", declTypes[ type ]->typeName.c_str(), decl->name.c_str() );
- common->Printf( "source: %s:%i\n", decl->sourceFile->fileName.c_str(), decl->sourceLine );
- common->Printf( "----------\n" );
- if ( decl->textSource != NULL ) {
- char *declText = (char *)_alloca( decl->textLength + 1 );
- decl->GetText( declText );
- common->Printf( "%s\n", declText );
- } else {
- common->Printf( "NO SOURCE\n" );
- }
- common->Printf( "----------\n" );
- switch( decl->declState ) {
- case DS_UNPARSED:
- common->Printf( "Unparsed.\n" );
- break;
- case DS_DEFAULTED:
- common->Printf( "<DEFAULTED>\n" );
- break;
- case DS_PARSED:
- common->Printf( "Parsed.\n" );
- break;
- }
- if ( decl->referencedThisLevel ) {
- common->Printf( "Currently referenced this level.\n" );
- } else if ( decl->everReferenced ) {
- common->Printf( "Referenced in a previous level.\n" );
- } else {
- common->Printf( "Never referenced.\n" );
- }
- // allow type-specific data to be printed
- if ( decl->self != NULL ) {
- decl->self->Print();
- }
- }
- /*
- ===================
- idDeclManagerLocal::CreateNewDecl
- ===================
- */
- idDecl *idDeclManagerLocal::CreateNewDecl( declType_t type, const char *name, const char *_fileName ) {
- int typeIndex = (int)type;
- int i, hash;
- if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
- common->FatalError( "idDeclManager::CreateNewDecl: bad type: %i", typeIndex );
- }
- char canonicalName[MAX_STRING_CHARS];
- MakeNameCanonical( name, canonicalName, sizeof( canonicalName ) );
- idStr fileName = _fileName;
- fileName.BackSlashesToSlashes();
- // see if it already exists
- hash = hashTables[typeIndex].GenerateKey( canonicalName, false );
- for ( i = hashTables[typeIndex].First( hash ); i >= 0; i = hashTables[typeIndex].Next( i ) ) {
- if ( linearLists[typeIndex][i]->name.Icmp( canonicalName ) == 0 ) {
- linearLists[typeIndex][i]->AllocateSelf();
- return linearLists[typeIndex][i]->self;
- }
- }
- idDeclFile *sourceFile;
- // find existing source file or create a new one
- for ( i = 0; i < loadedFiles.Num(); i++ ) {
- if ( loadedFiles[i]->fileName.Icmp( fileName ) == 0 ) {
- break;
- }
- }
- if ( i < loadedFiles.Num() ) {
- sourceFile = loadedFiles[i];
- } else {
- sourceFile = new idDeclFile( fileName, type );
- loadedFiles.Append( sourceFile );
- }
- idDeclLocal *decl = new idDeclLocal;
- decl->name = canonicalName;
- decl->type = type;
- decl->declState = DS_UNPARSED;
- decl->AllocateSelf();
- idStr header = declTypes[typeIndex]->typeName;
- idStr defaultText = decl->self->DefaultDefinition();
- int size = header.Length() + 1 + idStr::Length( canonicalName ) + 1 + defaultText.Length();
- char *declText = ( char * ) _alloca( size + 1 );
- memcpy( declText, header, header.Length() );
- declText[header.Length()] = ' ';
- memcpy( declText + header.Length() + 1, canonicalName, idStr::Length( canonicalName ) );
- declText[header.Length() + 1 + idStr::Length( canonicalName )] = ' ';
- memcpy( declText + header.Length() + 1 + idStr::Length( canonicalName ) + 1, defaultText, defaultText.Length() + 1 );
- decl->SetTextLocal( declText, size );
- decl->sourceFile = sourceFile;
- decl->sourceTextOffset = sourceFile->fileSize;
- decl->sourceTextLength = 0;
- decl->sourceLine = sourceFile->numLines;
- decl->ParseLocal();
- // add this decl to the source file list
- decl->nextInFile = sourceFile->decls;
- sourceFile->decls = decl;
- // add it to the hash table and linear list
- decl->index = linearLists[typeIndex].Num();
- hashTables[typeIndex].Add( hash, linearLists[typeIndex].Append( decl ) );
- return decl->self;
- }
- /*
- ===============
- idDeclManagerLocal::RenameDecl
- ===============
- */
- bool idDeclManagerLocal::RenameDecl( declType_t type, const char* oldName, const char* newName ) {
- char canonicalOldName[MAX_STRING_CHARS];
- MakeNameCanonical( oldName, canonicalOldName, sizeof( canonicalOldName ));
- char canonicalNewName[MAX_STRING_CHARS];
- MakeNameCanonical( newName, canonicalNewName, sizeof( canonicalNewName ) );
- idDeclLocal *decl = NULL;
- // make sure it already exists
- int typeIndex = (int)type;
- int i, hash;
- hash = hashTables[typeIndex].GenerateKey( canonicalOldName, false );
- for ( i = hashTables[typeIndex].First( hash ); i >= 0; i = hashTables[typeIndex].Next( i ) ) {
- if ( linearLists[typeIndex][i]->name.Icmp( canonicalOldName ) == 0 ) {
- decl = linearLists[typeIndex][i];
- break;
- }
- }
- if(!decl)
- return false;
- //if ( !hashTables[(int)type].Get( canonicalOldName, &declPtr ) )
- // return false;
- //decl = *declPtr;
- //Change the name
- decl->name = canonicalNewName;
- // add it to the hash table
- //hashTables[(int)decl->type].Set( decl->name, decl );
- int newhash = hashTables[typeIndex].GenerateKey( canonicalNewName, false );
- hashTables[typeIndex].Add( newhash, decl->index );
- //Remove the old hash item
- hashTables[typeIndex].Remove(hash, decl->index);
- return true;
- }
- /*
- ===================
- idDeclManagerLocal::MediaPrint
- This is just used to nicely indent media caching prints
- ===================
- */
- void idDeclManagerLocal::MediaPrint( const char *fmt, ... ) {
- if ( !decl_show.GetInteger() ) {
- return;
- }
- for ( int i = 0 ; i < indent ; i++ ) {
- common->Printf( " " );
- }
- va_list argptr;
- char buffer[1024];
- va_start (argptr,fmt);
- idStr::vsnPrintf( buffer, sizeof(buffer), fmt, argptr );
- va_end (argptr);
- buffer[sizeof(buffer)-1] = '\0';
- common->Printf( "%s", buffer );
- }
- /*
- ===================
- idDeclManagerLocal::WritePrecacheCommands
- ===================
- */
- void idDeclManagerLocal::WritePrecacheCommands( idFile *f ) {
- for ( int i = 0; i < declTypes.Num(); i++ ) {
- int num;
- if ( declTypes[i] == NULL ) {
- continue;
- }
- num = linearLists[i].Num();
- for ( int j = 0 ; j < num ; j++ ) {
- idDeclLocal *decl = linearLists[i][j];
- if ( !decl->referencedThisLevel ) {
- continue;
- }
- char str[1024];
- sprintf( str, "touch %s %s\n", declTypes[i]->typeName.c_str(), decl->GetName() );
- common->Printf( "%s", str );
- f->Printf( "%s", str );
- }
- }
- }
- /********************************************************************/
- const idMaterial *idDeclManagerLocal::FindMaterial( const char *name, bool makeDefault ) {
- return static_cast<const idMaterial *>( FindType( DECL_MATERIAL, name, makeDefault ) );
- }
- const idMaterial *idDeclManagerLocal::MaterialByIndex( int index, bool forceParse ) {
- return static_cast<const idMaterial *>( DeclByIndex( DECL_MATERIAL, index, forceParse ) );
- }
- /********************************************************************/
- const idDeclSkin *idDeclManagerLocal::FindSkin( const char *name, bool makeDefault ) {
- return static_cast<const idDeclSkin *>( FindType( DECL_SKIN, name, makeDefault ) );
- }
- const idDeclSkin *idDeclManagerLocal::SkinByIndex( int index, bool forceParse ) {
- return static_cast<const idDeclSkin *>( DeclByIndex( DECL_SKIN, index, forceParse ) );
- }
- /********************************************************************/
- const idSoundShader *idDeclManagerLocal::FindSound( const char *name, bool makeDefault ) {
- return static_cast<const idSoundShader *>( FindType( DECL_SOUND, name, makeDefault ) );
- }
- const idSoundShader *idDeclManagerLocal::SoundByIndex( int index, bool forceParse ) {
- return static_cast<const idSoundShader *>( DeclByIndex( DECL_SOUND, index, forceParse ) );
- }
- /*
- ===================
- idDeclManagerLocal::MakeNameCanonical
- ===================
- */
- void idDeclManagerLocal::MakeNameCanonical( const char *name, char *result, int maxLength ) {
- int i, lastDot;
- lastDot = -1;
- for ( i = 0; i < maxLength && name[i] != '\0'; i++ ) {
- int c = name[i];
- if ( c == '\\' ) {
- result[i] = '/';
- } else if ( c == '.' ) {
- lastDot = i;
- result[i] = c;
- } else {
- result[i] = idStr::ToLower( c );
- }
- }
- if ( lastDot != -1 ) {
- result[lastDot] = '\0';
- } else {
- result[i] = '\0';
- }
- }
- /*
- ================
- idDeclManagerLocal::ListDecls_f
- ================
- */
- void idDeclManagerLocal::ListDecls_f( const idCmdArgs &args ) {
- int i, j;
- int totalDecls = 0;
- int totalText = 0;
- int totalStructs = 0;
- for ( i = 0; i < declManagerLocal.declTypes.Num(); i++ ) {
- int size, num;
- if ( declManagerLocal.declTypes[i] == NULL ) {
- continue;
- }
- num = declManagerLocal.linearLists[i].Num();
- totalDecls += num;
- size = 0;
- for ( j = 0; j < num; j++ ) {
- size += declManagerLocal.linearLists[i][j]->Size();
- if ( declManagerLocal.linearLists[i][j]->self != NULL ) {
- size += declManagerLocal.linearLists[i][j]->self->Size();
- }
- }
- totalStructs += size;
- common->Printf( "%4ik %4i %s\n", size >> 10, num, declManagerLocal.declTypes[i]->typeName.c_str() );
- }
- for ( i = 0 ; i < declManagerLocal.loadedFiles.Num() ; i++ ) {
- idDeclFile *df = declManagerLocal.loadedFiles[i];
- totalText += df->fileSize;
- }
- common->Printf( "%i total decls is %i decl files\n", totalDecls, declManagerLocal.loadedFiles.Num() );
- common->Printf( "%iKB in text, %iKB in structures\n", totalText >> 10, totalStructs >> 10 );
- }
- /*
- ===================
- idDeclManagerLocal::ReloadDecls_f
- Reload will not find any new files created in the directories, it
- will only reload existing files.
- A reload will never cause anything to be purged.
- ===================
- */
- void idDeclManagerLocal::ReloadDecls_f( const idCmdArgs &args ) {
- bool force;
- if ( !idStr::Icmp( args.Argv( 1 ), "all" ) ) {
- force = true;
- common->Printf( "reloading all decl files:\n" );
- } else {
- force = false;
- common->Printf( "reloading changed decl files:\n" );
- }
- soundSystem->SetMute( true );
- declManagerLocal.Reload( force );
- soundSystem->SetMute( false );
- }
- /*
- ===================
- idDeclManagerLocal::TouchDecl_f
- ===================
- */
- void idDeclManagerLocal::TouchDecl_f( const idCmdArgs &args ) {
- int i;
- if ( args.Argc() != 3 ) {
- common->Printf( "usage: touch <type> <name>\n" );
- common->Printf( "valid types: " );
- for ( int i = 0 ; i < declManagerLocal.declTypes.Num() ; i++ ) {
- if ( declManagerLocal.declTypes[i] ) {
- common->Printf( "%s ", declManagerLocal.declTypes[i]->typeName.c_str() );
- }
- }
- common->Printf( "\n" );
- return;
- }
- for ( i = 0; i < declManagerLocal.declTypes.Num(); i++ ) {
- if ( declManagerLocal.declTypes[i] && declManagerLocal.declTypes[i]->typeName.Icmp( args.Argv( 1 ) ) == 0 ) {
- break;
- }
- }
- if ( i >= declManagerLocal.declTypes.Num() ) {
- common->Printf( "unknown decl type '%s'\n", args.Argv( 1 ) );
- return;
- }
- const idDecl *decl = declManagerLocal.FindType( (declType_t)i, args.Argv( 2 ), false );
- if ( !decl ) {
- common->Printf( "%s '%s' not found\n", declManagerLocal.declTypes[i]->typeName.c_str(), args.Argv( 2 ) );
- }
- }
- /*
- ===================
- idDeclManagerLocal::FindTypeWithoutParsing
- This finds or creats the decl, but does not cause a parse. This is only used internally.
- ===================
- */
- idDeclLocal *idDeclManagerLocal::FindTypeWithoutParsing( declType_t type, const char *name, bool makeDefault ) {
- int typeIndex = (int)type;
- int i, hash;
- if ( typeIndex < 0 || typeIndex >= declTypes.Num() || declTypes[typeIndex] == NULL ) {
- common->FatalError( "idDeclManager::FindTypeWithoutParsing: bad type: %i", typeIndex );
- }
- char canonicalName[MAX_STRING_CHARS];
- MakeNameCanonical( name, canonicalName, sizeof( canonicalName ) );
- // see if it already exists
- hash = hashTables[typeIndex].GenerateKey( canonicalName, false );
- for ( i = hashTables[typeIndex].First( hash ); i >= 0; i = hashTables[typeIndex].Next( i ) ) {
- if ( linearLists[typeIndex][i]->name.Icmp( canonicalName ) == 0 ) {
- // only print these when decl_show is set to 2, because it can be a lot of clutter
- if ( decl_show.GetInteger() > 1 ) {
- MediaPrint( "referencing %s %s\n", declTypes[ type ]->typeName.c_str(), name );
- }
- return linearLists[typeIndex][i];
- }
- }
- if ( !makeDefault ) {
- return NULL;
- }
- idDeclLocal *decl = new idDeclLocal;
- decl->self = NULL;
- decl->name = canonicalName;
- decl->type = type;
- decl->declState = DS_UNPARSED;
- decl->textSource = NULL;
- decl->textLength = 0;
- decl->sourceFile = &implicitDecls;
- decl->referencedThisLevel = false;
- decl->everReferenced = false;
- decl->parsedOutsideLevelLoad = !insideLevelLoad;
- // add it to the linear list and hash table
- decl->index = linearLists[typeIndex].Num();
- hashTables[typeIndex].Add( hash, linearLists[typeIndex].Append( decl ) );
- return decl;
- }
- /*
- ====================================================================================
- idDeclLocal
- ====================================================================================
- */
- /*
- =================
- idDeclLocal::idDeclLocal
- =================
- */
- idDeclLocal::idDeclLocal( void ) {
- name = "unnamed";
- textSource = NULL;
- textLength = 0;
- compressedLength = 0;
- sourceFile = NULL;
- sourceTextOffset = 0;
- sourceTextLength = 0;
- sourceLine = 0;
- checksum = 0;
- type = DECL_ENTITYDEF;
- index = 0;
- declState = DS_UNPARSED;
- parsedOutsideLevelLoad = false;
- referencedThisLevel = false;
- everReferenced = false;
- redefinedInReload = false;
- nextInFile = NULL;
- }
- /*
- =================
- idDeclLocal::GetName
- =================
- */
- const char *idDeclLocal::GetName( void ) const {
- return name.c_str();
- }
- /*
- =================
- idDeclLocal::GetType
- =================
- */
- declType_t idDeclLocal::GetType( void ) const {
- return type;
- }
- /*
- =================
- idDeclLocal::GetState
- =================
- */
- declState_t idDeclLocal::GetState( void ) const {
- return declState;
- }
- /*
- =================
- idDeclLocal::IsImplicit
- =================
- */
- bool idDeclLocal::IsImplicit( void ) const {
- return ( sourceFile == declManagerLocal.GetImplicitDeclFile() );
- }
- /*
- =================
- idDeclLocal::IsValid
- =================
- */
- bool idDeclLocal::IsValid( void ) const {
- return ( declState != DS_UNPARSED );
- }
- /*
- =================
- idDeclLocal::Invalidate
- =================
- */
- void idDeclLocal::Invalidate( void ) {
- declState = DS_UNPARSED;
- }
- /*
- =================
- idDeclLocal::EnsureNotPurged
- =================
- */
- void idDeclLocal::EnsureNotPurged( void ) {
- if ( declState == DS_UNPARSED ) {
- ParseLocal();
- }
- }
- /*
- =================
- idDeclLocal::Index
- =================
- */
- int idDeclLocal::Index( void ) const {
- return index;
- }
- /*
- =================
- idDeclLocal::GetLineNum
- =================
- */
- int idDeclLocal::GetLineNum( void ) const {
- return sourceLine;
- }
- /*
- =================
- idDeclLocal::GetFileName
- =================
- */
- const char *idDeclLocal::GetFileName( void ) const {
- return ( sourceFile ) ? sourceFile->fileName.c_str() : "*invalid*";
- }
- /*
- =================
- idDeclLocal::Size
- =================
- */
- size_t idDeclLocal::Size( void ) const {
- return sizeof( idDecl ) + name.Allocated();
- }
- /*
- =================
- idDeclLocal::GetText
- =================
- */
- void idDeclLocal::GetText( char *text ) const {
- #ifdef USE_COMPRESSED_DECLS
- HuffmanDecompressText( text, textLength, (byte *)textSource, compressedLength );
- #else
- memcpy( text, textSource, textLength+1 );
- #endif
- }
- /*
- =================
- idDeclLocal::GetTextLength
- =================
- */
- int idDeclLocal::GetTextLength( void ) const {
- return textLength;
- }
- /*
- =================
- idDeclLocal::SetText
- =================
- */
- void idDeclLocal::SetText( const char *text ) {
- SetTextLocal( text, idStr::Length( text ) );
- }
- /*
- =================
- idDeclLocal::SetTextLocal
- =================
- */
- void idDeclLocal::SetTextLocal( const char *text, const int length ) {
- Mem_Free( textSource );
- checksum = MD5_BlockChecksum( text, length );
- #ifdef GET_HUFFMAN_FREQUENCIES
- for( int i = 0; i < length; i++ ) {
- huffmanFrequencies[((const unsigned char *)text)[i]]++;
- }
- #endif
- #ifdef USE_COMPRESSED_DECLS
- int maxBytesPerCode = ( maxHuffmanBits + 7 ) >> 3;
- byte *compressed = (byte *)_alloca( length * maxBytesPerCode );
- compressedLength = HuffmanCompressText( text, length, compressed, length * maxBytesPerCode );
- textSource = (char *)Mem_Alloc( compressedLength );
- memcpy( textSource, compressed, compressedLength );
- #else
- compressedLength = length;
- textSource = (char *) Mem_Alloc( length + 1 );
- memcpy( textSource, text, length );
- textSource[length] = '\0';
- #endif
- textLength = length;
- }
- /*
- =================
- idDeclLocal::ReplaceSourceFileText
- =================
- */
- bool idDeclLocal::ReplaceSourceFileText( void ) {
- int oldFileLength, newFileLength;
- char *buffer;
- idFile *file;
- common->Printf( "Writing \'%s\' to \'%s\'...\n", GetName(), GetFileName() );
- if ( sourceFile == &declManagerLocal.implicitDecls ) {
- common->Warning( "Can't save implicit declaration %s.", GetName() );
- return false;
- }
- // get length and allocate buffer to hold the file
- oldFileLength = sourceFile->fileSize;
- newFileLength = oldFileLength - sourceTextLength + textLength;
- buffer = (char *) Mem_Alloc( Max( newFileLength, oldFileLength ) );
- // read original file
- if ( sourceFile->fileSize ) {
- file = fileSystem->OpenFileRead( GetFileName() );
- if ( !file ) {
- Mem_Free( buffer );
- common->Warning( "Couldn't open %s for reading.", GetFileName() );
- return false;
- }
- if ( file->Length() != sourceFile->fileSize || file->Timestamp() != sourceFile->timestamp ) {
- Mem_Free( buffer );
- common->Warning( "The file %s has been modified outside of the engine.", GetFileName() );
- return false;
- }
- file->Read( buffer, oldFileLength );
- fileSystem->CloseFile( file );
- if ( MD5_BlockChecksum( buffer, oldFileLength ) != sourceFile->checksum ) {
- Mem_Free( buffer );
- common->Warning( "The file %s has been modified outside of the engine.", GetFileName() );
- return false;
- }
- }
- // insert new text
- char *declText = (char *) _alloca( textLength + 1 );
- GetText( declText );
- memmove( buffer + sourceTextOffset + textLength, buffer + sourceTextOffset + sourceTextLength, oldFileLength - sourceTextOffset - sourceTextLength );
- memcpy( buffer + sourceTextOffset, declText, textLength );
- // write out new file
- file = fileSystem->OpenFileWrite( GetFileName(), "fs_devpath" );
- if ( !file ) {
- Mem_Free( buffer );
- common->Warning( "Couldn't open %s for writing.", GetFileName() );
- return false;
- }
- file->Write( buffer, newFileLength );
- fileSystem->CloseFile( file );
- // set new file size, checksum and timestamp
- sourceFile->fileSize = newFileLength;
- sourceFile->checksum = MD5_BlockChecksum( buffer, newFileLength );
- fileSystem->ReadFile( GetFileName(), NULL, &sourceFile->timestamp );
- // free buffer
- Mem_Free( buffer );
- // move all decls in the same file
- for ( idDeclLocal *decl = sourceFile->decls; decl; decl = decl->nextInFile ) {
- if (decl->sourceTextOffset > sourceTextOffset) {
- decl->sourceTextOffset += textLength - sourceTextLength;
- }
- }
- // set new size of text in source file
- sourceTextLength = textLength;
- return true;
- }
- /*
- =================
- idDeclLocal::SourceFileChanged
- =================
- */
- bool idDeclLocal::SourceFileChanged( void ) const {
- int newLength;
- ID_TIME_T newTimestamp;
- if ( sourceFile->fileSize <= 0 ) {
- return false;
- }
- newLength = fileSystem->ReadFile( GetFileName(), NULL, &newTimestamp );
- if ( newLength != sourceFile->fileSize || newTimestamp != sourceFile->timestamp ) {
- return true;
- }
- return false;
- }
- /*
- =================
- idDeclLocal::MakeDefault
- =================
- */
- void idDeclLocal::MakeDefault() {
- static int recursionLevel;
- const char *defaultText;
- declManagerLocal.MediaPrint( "DEFAULTED\n" );
- declState = DS_DEFAULTED;
- AllocateSelf();
- defaultText = self->DefaultDefinition();
- // a parse error inside a DefaultDefinition() string could
- // cause an infinite loop, but normal default definitions could
- // still reference other default definitions, so we can't
- // just dump out on the first recursion
- if ( ++recursionLevel > 100 ) {
- common->FatalError( "idDecl::MakeDefault: bad DefaultDefinition(): %s", defaultText );
- }
- // always free data before parsing
- self->FreeData();
- // parse
- self->Parse( defaultText, strlen( defaultText ) );
- // we could still eventually hit the recursion if we have enough Error() calls inside Parse...
- --recursionLevel;
- }
- /*
- =================
- idDeclLocal::SetDefaultText
- =================
- */
- bool idDeclLocal::SetDefaultText( void ) {
- return false;
- }
- /*
- =================
- idDeclLocal::DefaultDefinition
- =================
- */
- const char *idDeclLocal::DefaultDefinition() const {
- return "{ }";
- }
- /*
- =================
- idDeclLocal::Parse
- =================
- */
- bool idDeclLocal::Parse( const char *text, const int textLength ) {
- idLexer src;
- src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
- src.SetFlags( DECL_LEXER_FLAGS );
- src.SkipUntilString( "{" );
- src.SkipBracedSection( false );
- return true;
- }
- /*
- =================
- idDeclLocal::FreeData
- =================
- */
- void idDeclLocal::FreeData() {
- }
- /*
- =================
- idDeclLocal::List
- =================
- */
- void idDeclLocal::List() const {
- common->Printf( "%s\n", GetName() );
- }
- /*
- =================
- idDeclLocal::Print
- =================
- */
- void idDeclLocal::Print() const {
- }
- /*
- =================
- idDeclLocal::Reload
- =================
- */
- void idDeclLocal::Reload( void ) {
- this->sourceFile->Reload( false );
- }
- /*
- =================
- idDeclLocal::AllocateSelf
- =================
- */
- void idDeclLocal::AllocateSelf( void ) {
- if ( self == NULL ) {
- self = declManagerLocal.GetDeclType( (int)type )->allocator();
- self->base = this;
- }
- }
- /*
- =================
- idDeclLocal::ParseLocal
- =================
- */
- void idDeclLocal::ParseLocal( void ) {
- bool generatedDefaultText = false;
- AllocateSelf();
- // always free data before parsing
- self->FreeData();
- declManagerLocal.MediaPrint( "parsing %s %s\n", declManagerLocal.declTypes[type]->typeName.c_str(), name.c_str() );
- // if no text source try to generate default text
- if ( textSource == NULL ) {
- generatedDefaultText = self->SetDefaultText();
- }
- // indent for DEFAULTED or media file references
- declManagerLocal.indent++;
- // no text immediately causes a MakeDefault()
- if ( textSource == NULL ) {
- MakeDefault();
- declManagerLocal.indent--;
- return;
- }
- declState = DS_PARSED;
- // parse
- char *declText = (char *) _alloca( ( GetTextLength() + 1 ) * sizeof( char ) );
- GetText( declText );
- self->Parse( declText, GetTextLength() );
- // free generated text
- if ( generatedDefaultText ) {
- Mem_Free( textSource );
- textSource = 0;
- textLength = 0;
- }
- declManagerLocal.indent--;
- }
- /*
- =================
- idDeclLocal::Purge
- =================
- */
- void idDeclLocal::Purge( void ) {
- // never purge things that were referenced outside level load,
- // like the console and menu graphics
- if ( parsedOutsideLevelLoad ) {
- return;
- }
- referencedThisLevel = false;
- MakeDefault();
- // the next Find() for this will re-parse the real data
- declState = DS_UNPARSED;
- }
- /*
- =================
- idDeclLocal::EverReferenced
- =================
- */
- bool idDeclLocal::EverReferenced( void ) const {
- return everReferenced;
- }
|