123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331 |
- /*
- ===========================================================================
- 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 MANUALPAGES_TXT "manualpages.txt"
- #define MANUALPAGES_SKIN "skins/manualpages.skin"
- #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 );
- //BC
- virtual void LoadManual();
- //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;
- static idCVar manualcount; //bc
- 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> );
- idCVar idDeclManagerLocal::manualcount( "manualcount", "0", CVAR_INTEGER, "how many pages in manual" );
- 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" );
- //bc 3-8-2016 loadmanual for base game
- idStr game = cvarSystem->GetCVarString( "fs_game" );
- if (!game || game == "")
- {
- LoadManual();
- }
- 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
- //BC
- //fileSystem->RemoveFile(MANUALPAGES_SKIN);
- }
- void idDeclManagerLocal::LoadManual( )
- {
- void *buffer;
- idStr rawManualpages;
- if (fileSystem->ReadFile(MANUALPAGES_TXT, &buffer))
- {
- int i;
- idList<idStr> imageNames;
- rawManualpages = (char *) buffer;
- fileSystem->FreeFile( buffer );
- rawManualpages.StripTrailingWhitespace(); //remove whitespace.
- rawManualpages.StripLeading( ' ' ); //remove whitespace.
- rawManualpages.ToLower(); //force lower case.
- for (i = rawManualpages.Length(); i >= 0; i--)
- {
- if (rawManualpages[i] == '\n')
- {
- if (rawManualpages.Mid(i+1, rawManualpages.Length()).IsEmpty() || rawManualpages.Mid(i+1, rawManualpages.Length()).Length() <= 1)
- {
- rawManualpages = rawManualpages.Left(i);
- continue;
- }
- imageNames.Insert(rawManualpages.Mid(i+1, rawManualpages.Length()), 0);
- //imageNames.Append( rawManualpages.Mid(i+1, rawManualpages.Length()) );
- //common->Printf("zzofds %d %d \"%s\"\n", i, rawManualpages.Mid(i+1, rawManualpages.Length()).Length(), rawManualpages.Mid(i+1, rawManualpages.Length()).c_str() );
- rawManualpages = rawManualpages.Left(i); //strip.
- continue;
- }
- if (i <= 0 && !rawManualpages.Mid(0, rawManualpages.Length()).IsEmpty() && rawManualpages.Mid(0, rawManualpages.Length()).Length() > 1)
- {
- //common->Printf("zzofdsFIRST %d %d \"%s\" \n", i, rawManualpages.Mid(0, rawManualpages.Length()).Length(), rawManualpages.Mid(0, rawManualpages.Length()).c_str() );
-
- imageNames.Insert( rawManualpages.Mid(0, rawManualpages.Length()), 0);
- //imageNames.Append( rawManualpages.Mid(0, rawManualpages.Length()) );
- }
- }
- idFile *f;
- f = fileSystem->OpenFileWrite( MANUALPAGES_SKIN );
- for (i = 0; i < imageNames.Num() - 1; i++)
- {
- int pageA, pageB;
- if (i % 2 == 0 || i <= 0)
- {
- pageA = 0;
- pageB = 1;
- }
- else
- {
- pageA = 1;
- pageB = 0;
- }
- f->Printf( va("skin manualpage_%d_%d\n{\nmodels/weapon_map/page_%d %s\nmodels/weapon_map/page_%d %s\n}\n\n",
- i, i+1,
- pageA, imageNames[i].c_str(),
- pageB, imageNames[i+1].c_str() ));
- }
-
-
- fileSystem->CloseFile( f );
- manualcount.SetInteger(imageNames.Num());
- }
- }
- /*
- ===================
- 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;
- }
|