doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Parser.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 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.
23 
24 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.
25 
26 ===========================================================================
27 */
28 
29 #include "precompiled.h"
30 #pragma hdrstop
31 
32 //#define DEBUG_EVAL
33 #define MAX_DEFINEPARMS 128
34 #define DEFINEHASHSIZE 2048
35 
36 #define TOKEN_FL_RECURSIVE_DEFINE 1
37 
39 
40 /*
41 ================
42 idParser::SetBaseFolder
43 ================
44 */
45 void idParser::SetBaseFolder( const char *path) {
47 }
48 
49 /*
50 ================
51 idParser::AddGlobalDefine
52 ================
53 */
54 int idParser::AddGlobalDefine( const char *string ) {
55  define_t *define;
56 
57  define = idParser::DefineFromString(string);
58  if (!define) {
59  return false;
60  }
61  define->next = globaldefines;
62  globaldefines = define;
63  return true;
64 }
65 
66 /*
67 ================
68 idParser::RemoveGlobalDefine
69 ================
70 */
71 int idParser::RemoveGlobalDefine( const char *name ) {
72  define_t *d, *prev;
73 
74  for ( prev = NULL, d = idParser::globaldefines; d; prev = d, d = d->next ) {
75  if ( !strcmp( d->name, name ) ) {
76  break;
77  }
78  }
79  if ( d ) {
80  if ( prev ) {
81  prev->next = d->next;
82  }
83  else {
84  idParser::globaldefines = d->next;
85  }
87  return true;
88  }
89  return false;
90 }
91 
92 /*
93 ================
94 idParser::RemoveAllGlobalDefines
95 ================
96 */
98  define_t *define;
99 
100  for ( define = globaldefines; define; define = globaldefines ) {
102  idParser::FreeDefine(define);
103  }
104 }
105 
106 
107 /*
108 ===============================================================================
109 
110 idParser
111 
112 ===============================================================================
113 */
114 
115 /*
116 ================
117 idParser::PrintDefine
118 ================
119 */
121  idLib::common->Printf("define->name = %s\n", define->name);
122  idLib::common->Printf("define->flags = %d\n", define->flags);
123  idLib::common->Printf("define->builtin = %d\n", define->builtin);
124  idLib::common->Printf("define->numparms = %d\n", define->numparms);
125 }
126 
127 /*
128 ================
129 PC_PrintDefineHashTable
130 ================
131 * /
132 static void PC_PrintDefineHashTable(define_t **definehash) {
133  int i;
134  define_t *d;
135 
136  for (i = 0; i < DEFINEHASHSIZE; i++) {
137  Log_Write("%4d:", i);
138  for (d = definehash[i]; d; d = d->hashnext) {
139  Log_Write(" %s", d->name);
140  }
141  Log_Write("\n");
142  }
143 }
144 */
145 
146 /*
147 ================
148 PC_NameHash
149 ================
150 */
151 ID_INLINE int PC_NameHash( const char *name ) {
152  int hash, i;
153 
154  hash = 0;
155  for ( i = 0; name[i] != '\0'; i++ ) {
156  hash += name[i] * (119 + i);
157  }
158  hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (DEFINEHASHSIZE-1);
159  return hash;
160 }
161 
162 /*
163 ================
164 idParser::AddDefineToHash
165 ================
166 */
167 void idParser::AddDefineToHash( define_t *define, define_t **definehash ) {
168  int hash;
169 
170  hash = PC_NameHash(define->name);
171  define->hashnext = definehash[hash];
172  definehash[hash] = define;
173 }
174 
175 /*
176 ================
177 FindHashedDefine
178 ================
179 */
180 define_t *idParser::FindHashedDefine( define_t **definehash, const char *name ) {
181  define_t *d;
182  int hash;
183 
184  hash = PC_NameHash(name);
185  for ( d = definehash[hash]; d; d = d->hashnext ) {
186  if ( !strcmp(d->name, name) ) {
187  return d;
188  }
189  }
190  return NULL;
191 }
192 
193 /*
194 ================
195 idParser::FindDefine
196 ================
197 */
198 define_t *idParser::FindDefine( define_t *defines, const char *name ) {
199  define_t *d;
200 
201  for ( d = defines; d; d = d->next ) {
202  if ( !strcmp(d->name, name) ) {
203  return d;
204  }
205  }
206  return NULL;
207 }
208 
209 /*
210 ================
211 idParser::FindDefineParm
212 ================
213 */
214 int idParser::FindDefineParm( define_t *define, const char *name ) {
215  idToken *p;
216  int i;
217 
218  i = 0;
219  for ( p = define->parms; p; p = p->next ) {
220  if ( (*p) == name ) {
221  return i;
222  }
223  i++;
224  }
225  return -1;
226 }
227 
228 /*
229 ================
230 idParser::CopyDefine
231 ================
232 */
234  define_t *newdefine;
235  idToken *token, *newtoken, *lasttoken;
236 
237  newdefine = (define_t *) Mem_Alloc(sizeof(define_t) + strlen(define->name) + 1);
238  //copy the define name
239  newdefine->name = (char *) newdefine + sizeof(define_t);
240  strcpy(newdefine->name, define->name);
241  newdefine->flags = define->flags;
242  newdefine->builtin = define->builtin;
243  newdefine->numparms = define->numparms;
244  //the define is not linked
245  newdefine->next = NULL;
246  newdefine->hashnext = NULL;
247  //copy the define tokens
248  newdefine->tokens = NULL;
249  for (lasttoken = NULL, token = define->tokens; token; token = token->next) {
250  newtoken = new idToken(token);
251  newtoken->next = NULL;
252  if (lasttoken) lasttoken->next = newtoken;
253  else newdefine->tokens = newtoken;
254  lasttoken = newtoken;
255  }
256  //copy the define parameters
257  newdefine->parms = NULL;
258  for (lasttoken = NULL, token = define->parms; token; token = token->next) {
259  newtoken = new idToken(token);
260  newtoken->next = NULL;
261  if (lasttoken) lasttoken->next = newtoken;
262  else newdefine->parms = newtoken;
263  lasttoken = newtoken;
264  }
265  return newdefine;
266 }
267 
268 /*
269 ================
270 idParser::FreeDefine
271 ================
272 */
274  idToken *t, *next;
275 
276  //free the define parameters
277  for (t = define->parms; t; t = next) {
278  next = t->next;
279  delete t;
280  }
281  //free the define tokens
282  for (t = define->tokens; t; t = next) {
283  next = t->next;
284  delete t;
285  }
286  //free the define
287  Mem_Free( define );
288 }
289 
290 /*
291 ================
292 idParser::DefineFromString
293 ================
294 */
295 define_t *idParser::DefineFromString( const char *string ) {
296  idParser src;
297  define_t *def;
298 
299  if ( !src.LoadMemory(string, strlen(string), "*defineString") ) {
300  return NULL;
301  }
302  // create a define from the source
303  if ( !src.Directive_define() ) {
304  src.FreeSource();
305  return NULL;
306  }
307  def = src.CopyFirstDefine();
308  src.FreeSource();
309  //if the define was created succesfully
310  return def;
311 }
312 
313 /*
314 ================
315 idParser::Error
316 ================
317 */
318 void idParser::Error( const char *str, ... ) const {
319  char text[MAX_STRING_CHARS];
320  va_list ap;
321 
322  va_start(ap, str);
323  vsprintf(text, str, ap);
324  va_end(ap);
325  if ( idParser::scriptstack ) {
326  idParser::scriptstack->Error( text );
327  }
328 }
329 
330 /*
331 ================
332 idParser::Warning
333 ================
334 */
335 void idParser::Warning( const char *str, ... ) const {
336  char text[MAX_STRING_CHARS];
337  va_list ap;
338 
339  va_start(ap, str);
340  vsprintf(text, str, ap);
341  va_end(ap);
342  if ( idParser::scriptstack ) {
344  }
345 }
346 
347 /*
348 ================
349 idParser::PushIndent
350 ================
351 */
352 void idParser::PushIndent( int type, int skip ) {
353  indent_t *indent;
354 
355  indent = (indent_t *) Mem_Alloc(sizeof(indent_t));
356  indent->type = type;
357  indent->script = idParser::scriptstack;
358  indent->skip = (skip != 0);
359  idParser::skip += indent->skip;
360  indent->next = idParser::indentstack;
361  idParser::indentstack = indent;
362 }
363 
364 /*
365 ================
366 idParser::PopIndent
367 ================
368 */
369 void idParser::PopIndent( int *type, int *skip ) {
370  indent_t *indent;
371 
372  *type = 0;
373  *skip = 0;
374 
375  indent = idParser::indentstack;
376  if (!indent) return;
377 
378  // must be an indent from the current script
380  return;
381  }
382 
383  *type = indent->type;
384  *skip = indent->skip;
386  idParser::skip -= indent->skip;
387  Mem_Free( indent );
388 }
389 
390 /*
391 ================
392 idParser::PushScript
393 ================
394 */
395 void idParser::PushScript( idLexer *script ) {
396  idLexer *s;
397 
398  for ( s = idParser::scriptstack; s; s = s->next ) {
399  if ( !idStr::Icmp(s->GetFileName(), script->GetFileName()) ) {
400  idParser::Warning( "'%s' recursively included", script->GetFileName() );
401  return;
402  }
403  }
404  //push the script on the script stack
405  script->next = idParser::scriptstack;
406  idParser::scriptstack = script;
407 }
408 
409 /*
410 ================
411 idParser::ReadSourceToken
412 ================
413 */
415  idToken *t;
416  idLexer *script;
417  int type, skip, changedScript;
418 
419  if ( !idParser::scriptstack ) {
420  idLib::common->FatalError( "idParser::ReadSourceToken: not loaded" );
421  return false;
422  }
423  changedScript = 0;
424  // if there's no token already available
425  while( !idParser::tokens ) {
426  // if there's a token to read from the script
427  if ( idParser::scriptstack->ReadToken( token ) ) {
428  token->linesCrossed += changedScript;
429 
430  // set the marker based on the start of the token read in
431  if ( !marker_p ) {
432  marker_p = token->whiteSpaceEnd_p;
433  }
434  return true;
435  }
436  // if at the end of the script
437  if ( idParser::scriptstack->EndOfFile() ) {
438  // remove all indents of the script
440  idParser::Warning( "missing #endif" );
441  idParser::PopIndent( &type, &skip );
442  }
443  changedScript = 1;
444  }
445  // if this was the initial script
446  if ( !idParser::scriptstack->next ) {
447  return false;
448  }
449  // remove the script and return to the previous one
450  script = idParser::scriptstack;
452  delete script;
453  }
454  // copy the already available token
455  *token = idParser::tokens;
456  // remove the token from the source
457  t = idParser::tokens;
459  delete t;
460  return true;
461 }
462 
463 /*
464 ================
465 idParser::UnreadSourceToken
466 ================
467 */
469  idToken *t;
470 
471  t = new idToken(token);
472  t->next = idParser::tokens;
474  return true;
475 }
476 
477 /*
478 ================
479 idParser::ReadDefineParms
480 ================
481 */
482 int idParser::ReadDefineParms( define_t *define, idToken **parms, int maxparms ) {
483  define_t *newdefine;
484  idToken token, *t, *last;
485  int i, done, lastcomma, numparms, indent;
486 
487  if ( !idParser::ReadSourceToken( &token ) ) {
488  idParser::Error( "define '%s' missing parameters", define->name );
489  return false;
490  }
491 
492  if ( define->numparms > maxparms ) {
493  idParser::Error( "define with more than %d parameters", maxparms );
494  return false;
495  }
496 
497  for ( i = 0; i < define->numparms; i++ ) {
498  parms[i] = NULL;
499  }
500  // if no leading "("
501  if ( token != "(" ) {
502  idParser::UnreadSourceToken( &token );
503  idParser::Error( "define '%s' missing parameters", define->name );
504  return false;
505  }
506  // read the define parameters
507  for ( done = 0, numparms = 0, indent = 1; !done; ) {
508  if ( numparms >= maxparms ) {
509  idParser::Error( "define '%s' with too many parameters", define->name );
510  return false;
511  }
512  parms[numparms] = NULL;
513  lastcomma = 1;
514  last = NULL;
515  while( !done ) {
516 
517  if ( !idParser::ReadSourceToken( &token ) ) {
518  idParser::Error( "define '%s' incomplete", define->name );
519  return false;
520  }
521 
522  if ( token == "," ) {
523  if ( indent <= 1 ) {
524  if ( lastcomma ) {
525  idParser::Warning( "too many comma's" );
526  }
527  if ( numparms >= define->numparms ) {
528  idParser::Warning( "too many define parameters" );
529  }
530  lastcomma = 1;
531  break;
532  }
533  }
534  else if ( token == "(" ) {
535  indent++;
536  }
537  else if ( token == ")" ) {
538  indent--;
539  if ( indent <= 0 ) {
540  if ( !parms[define->numparms-1] ) {
541  idParser::Warning( "too few define parameters" );
542  }
543  done = 1;
544  break;
545  }
546  }
547  else if ( token.type == TT_NAME ) {
548  newdefine = FindHashedDefine( idParser::definehash, token.c_str() );
549  if ( newdefine ) {
550  if ( !idParser::ExpandDefineIntoSource( &token, newdefine ) ) {
551  return false;
552  }
553  continue;
554  }
555  }
556 
557  lastcomma = 0;
558 
559  if ( numparms < define->numparms ) {
560 
561  t = new idToken( token );
562  t->next = NULL;
563  if (last) last->next = t;
564  else parms[numparms] = t;
565  last = t;
566  }
567  }
568  numparms++;
569  }
570  return true;
571 }
572 
573 /*
574 ================
575 idParser::StringizeTokens
576 ================
577 */
578 int idParser::StringizeTokens( idToken *tokens, idToken *token ) {
579  idToken *t;
580 
581  token->type = TT_STRING;
582  token->whiteSpaceStart_p = NULL;
583  token->whiteSpaceEnd_p = NULL;
584  (*token) = "";
585  for ( t = tokens; t; t = t->next ) {
586  token->Append( t->c_str() );
587  }
588  return true;
589 }
590 
591 /*
592 ================
593 idParser::MergeTokens
594 ================
595 */
597  // merging of a name with a name or number
598  if ( t1->type == TT_NAME && (t2->type == TT_NAME || (t2->type == TT_NUMBER && !(t2->subtype & TT_FLOAT))) ) {
599  t1->Append( t2->c_str() );
600  return true;
601  }
602  // merging of two strings
603  if (t1->type == TT_STRING && t2->type == TT_STRING) {
604  t1->Append( t2->c_str() );
605  return true;
606  }
607  // merging of two numbers
608  if ( t1->type == TT_NUMBER && t2->type == TT_NUMBER &&
609  !(t1->subtype & (TT_HEX|TT_BINARY)) && !(t2->subtype & (TT_HEX|TT_BINARY)) &&
610  (!(t1->subtype & TT_FLOAT) || !(t2->subtype & TT_FLOAT)) ) {
611  t1->Append( t2->c_str() );
612  return true;
613  }
614 
615  return false;
616 }
617 
618 /*
619 ================
620 idParser::AddBuiltinDefines
621 ================
622 */
624  int i;
625  define_t *define;
626  struct builtin
627  {
628  const char *string;
629  int id;
630  } builtin[] = {
631  { "__LINE__", BUILTIN_LINE },
632  { "__FILE__", BUILTIN_FILE },
633  { "__DATE__", BUILTIN_DATE },
634  { "__TIME__", BUILTIN_TIME },
635  { "__STDC__", BUILTIN_STDC },
636  { NULL, 0 }
637  };
638 
639  for (i = 0; builtin[i].string; i++) {
640  define = (define_t *) Mem_Alloc(sizeof(define_t) + strlen(builtin[i].string) + 1);
641  define->name = (char *) define + sizeof(define_t);
642  strcpy(define->name, builtin[i].string);
643  define->flags = DEFINE_FIXED;
644  define->builtin = builtin[i].id;
645  define->numparms = 0;
646  define->parms = NULL;
647  define->tokens = NULL;
648  // add the define to the source
650  }
651 }
652 
653 /*
654 ================
655 idParser::CopyFirstDefine
656 ================
657 */
659  int i;
660 
661  for ( i = 0; i < DEFINEHASHSIZE; i++ ) {
662  if ( idParser::definehash[i] ) {
663  return CopyDefine(idParser::definehash[i]);
664  }
665  }
666  return NULL;
667 }
668 
669 /*
670 ================
671 idParser::ExpandBuiltinDefine
672 ================
673 */
674 int idParser::ExpandBuiltinDefine( idToken *deftoken, define_t *define, idToken **firsttoken, idToken **lasttoken ) {
675  idToken *token;
676  ID_TIME_T t;
677  char *curtime;
678  char buf[MAX_STRING_CHARS];
679 
680  token = new idToken(deftoken);
681  switch( define->builtin ) {
682  case BUILTIN_LINE: {
683  sprintf( buf, "%d", deftoken->line );
684  (*token) = buf;
685  token->intvalue = deftoken->line;
686  token->floatvalue = deftoken->line;
687  token->type = TT_NUMBER;
689  token->line = deftoken->line;
690  token->linesCrossed = deftoken->linesCrossed;
691  token->flags = 0;
692  *firsttoken = token;
693  *lasttoken = token;
694  break;
695  }
696  case BUILTIN_FILE: {
697  (*token) = idParser::scriptstack->GetFileName();
698  token->type = TT_NAME;
699  token->subtype = token->Length();
700  token->line = deftoken->line;
701  token->linesCrossed = deftoken->linesCrossed;
702  token->flags = 0;
703  *firsttoken = token;
704  *lasttoken = token;
705  break;
706  }
707  case BUILTIN_DATE: {
708  t = time(NULL);
709  curtime = ctime(&t);
710  (*token) = "\"";
711  token->Append( curtime+4 );
712  token[7] = '\0';
713  token->Append( curtime+20 );
714  token[10] = '\0';
715  token->Append( "\"" );
716  free(curtime);
717  token->type = TT_STRING;
718  token->subtype = token->Length();
719  token->line = deftoken->line;
720  token->linesCrossed = deftoken->linesCrossed;
721  token->flags = 0;
722  *firsttoken = token;
723  *lasttoken = token;
724  break;
725  }
726  case BUILTIN_TIME: {
727  t = time(NULL);
728  curtime = ctime(&t);
729  (*token) = "\"";
730  token->Append( curtime+11 );
731  token[8] = '\0';
732  token->Append( "\"" );
733  free(curtime);
734  token->type = TT_STRING;
735  token->subtype = token->Length();
736  token->line = deftoken->line;
737  token->linesCrossed = deftoken->linesCrossed;
738  token->flags = 0;
739  *firsttoken = token;
740  *lasttoken = token;
741  break;
742  }
743  case BUILTIN_STDC: {
744  idParser::Warning( "__STDC__ not supported\n" );
745  *firsttoken = NULL;
746  *lasttoken = NULL;
747  break;
748  }
749  default: {
750  *firsttoken = NULL;
751  *lasttoken = NULL;
752  break;
753  }
754  }
755  return true;
756 }
757 
758 /*
759 ================
760 idParser::ExpandDefine
761 ================
762 */
763 int idParser::ExpandDefine( idToken *deftoken, define_t *define, idToken **firsttoken, idToken **lasttoken ) {
764  idToken *parms[MAX_DEFINEPARMS], *dt, *pt, *t;
765  idToken *t1, *t2, *first, *last, *nextpt, token;
766  int parmnum, i;
767 
768  // if it is a builtin define
769  if ( define->builtin ) {
770  return idParser::ExpandBuiltinDefine( deftoken, define, firsttoken, lasttoken );
771  }
772  // if the define has parameters
773  if ( define->numparms ) {
774  if ( !idParser::ReadDefineParms( define, parms, MAX_DEFINEPARMS ) ) {
775  return false;
776  }
777 #ifdef DEBUG_EVAL
778  for ( i = 0; i < define->numparms; i++ ) {
779  Log_Write("define parms %d:", i);
780  for ( pt = parms[i]; pt; pt = pt->next ) {
781  Log_Write( "%s", pt->c_str() );
782  }
783  }
784 #endif //DEBUG_EVAL
785  }
786  // empty list at first
787  first = NULL;
788  last = NULL;
789  // create a list with tokens of the expanded define
790  for ( dt = define->tokens; dt; dt = dt->next ) {
791  parmnum = -1;
792  // if the token is a name, it could be a define parameter
793  if ( dt->type == TT_NAME ) {
794  parmnum = FindDefineParm( define, dt->c_str() );
795  }
796  // if it is a define parameter
797  if ( parmnum >= 0 ) {
798  for ( pt = parms[parmnum]; pt; pt = pt->next ) {
799  t = new idToken(pt);
800  //add the token to the list
801  t->next = NULL;
802  if (last) last->next = t;
803  else first = t;
804  last = t;
805  }
806  }
807  else {
808  // if stringizing operator
809  if ( (*dt) == "#" ) {
810  // the stringizing operator must be followed by a define parameter
811  if ( dt->next ) {
812  parmnum = FindDefineParm( define, dt->next->c_str() );
813  }
814  else {
815  parmnum = -1;
816  }
817 
818  if ( parmnum >= 0 ) {
819  // step over the stringizing operator
820  dt = dt->next;
821  // stringize the define parameter tokens
822  if ( !idParser::StringizeTokens( parms[parmnum], &token ) ) {
823  idParser::Error( "can't stringize tokens" );
824  return false;
825  }
826  t = new idToken(token);
827  t->line = deftoken->line;
828  }
829  else {
830  idParser::Warning( "stringizing operator without define parameter" );
831  continue;
832  }
833  }
834  else {
835  t = new idToken(dt);
836  t->line = deftoken->line;
837  }
838  // add the token to the list
839  t->next = NULL;
840 // the token being read from the define list should use the line number of
841 // the original file, not the header file
842  t->line = deftoken->line;
843 
844  if ( last ) last->next = t;
845  else first = t;
846  last = t;
847  }
848  }
849  // check for the merging operator
850  for ( t = first; t; ) {
851  if ( t->next ) {
852  // if the merging operator
853  if ( (*t->next) == "##" ) {
854  t1 = t;
855  t2 = t->next->next;
856  if ( t2 ) {
857  if ( !idParser::MergeTokens( t1, t2 ) ) {
858  idParser::Error( "can't merge '%s' with '%s'", t1->c_str(), t2->c_str() );
859  return false;
860  }
861  delete t1->next;
862  t1->next = t2->next;
863  if ( t2 == last ) last = t1;
864  delete t2;
865  continue;
866  }
867  }
868  }
869  t = t->next;
870  }
871  // store the first and last token of the list
872  *firsttoken = first;
873  *lasttoken = last;
874  // free all the parameter tokens
875  for ( i = 0; i < define->numparms; i++ ) {
876  for ( pt = parms[i]; pt; pt = nextpt ) {
877  nextpt = pt->next;
878  delete pt;
879  }
880  }
881 
882  return true;
883 }
884 
885 /*
886 ================
887 idParser::ExpandDefineIntoSource
888 ================
889 */
891  idToken *firsttoken, *lasttoken;
892 
893  if ( !idParser::ExpandDefine( deftoken, define, &firsttoken, &lasttoken ) ) {
894  return false;
895  }
896  // if the define is not empty
897  if ( firsttoken && lasttoken ) {
898  firsttoken->linesCrossed += deftoken->linesCrossed;
899  lasttoken->next = idParser::tokens;
900  idParser::tokens = firsttoken;
901  }
902  return true;
903 }
904 
905 /*
906 ================
907 idParser::ReadLine
908 
909 reads a token from the current line, continues reading on the next
910 line only if a backslash '\' is found
911 ================
912 */
914  int crossline;
915 
916  crossline = 0;
917  do {
918  if (!idParser::ReadSourceToken( token )) {
919  return false;
920  }
921 
922  if (token->linesCrossed > crossline) {
924  return false;
925  }
926  crossline = 1;
927  } while( (*token) == "\\" );
928  return true;
929 }
930 
931 /*
932 ================
933 idParser::Directive_include
934 ================
935 */
937  idLexer *script;
938  idToken token;
939  idStr path;
940 
941  if ( !idParser::ReadSourceToken( &token ) ) {
942  idParser::Error( "#include without file name" );
943  return false;
944  }
945  if ( token.linesCrossed > 0 ) {
946  idParser::Error( "#include without file name" );
947  return false;
948  }
949  if ( token.type == TT_STRING ) {
950  script = new idLexer;
951  // try relative to the current file
952  path = scriptstack->GetFileName();
953  path.StripFilename();
954  path += "/";
955  path += token;
956  if ( !script->LoadFile( path, OSPath ) ) {
957  // try absolute path
958  path = token;
959  if ( !script->LoadFile( path, OSPath ) ) {
960  // try from the include path
961  path = includepath + token;
962  if ( !script->LoadFile( path, OSPath ) ) {
963  delete script;
964  script = NULL;
965  }
966  }
967  }
968  }
969  else if ( token.type == TT_PUNCTUATION && token == "<" ) {
970  path = idParser::includepath;
971  while( idParser::ReadSourceToken( &token ) ) {
972  if ( token.linesCrossed > 0 ) {
973  idParser::UnreadSourceToken( &token );
974  break;
975  }
976  if ( token.type == TT_PUNCTUATION && token == ">" ) {
977  break;
978  }
979  path += token;
980  }
981  if ( token != ">" ) {
982  idParser::Warning( "#include missing trailing >" );
983  }
984  if ( !path.Length() ) {
985  idParser::Error( "#include without file name between < >" );
986  return false;
987  }
989  return true;
990  }
991  script = new idLexer;
992  if ( !script->LoadFile( includepath + path, OSPath ) ) {
993  delete script;
994  script = NULL;
995  }
996  }
997  else {
998  idParser::Error( "#include without file name" );
999  return false;
1000  }
1001  if (!script) {
1002  idParser::Error( "file '%s' not found", path.c_str() );
1003  return false;
1004  }
1005  script->SetFlags( idParser::flags );
1007  idParser::PushScript( script );
1008  return true;
1009 }
1010 
1011 /*
1012 ================
1013 idParser::Directive_undef
1014 ================
1015 */
1017  idToken token;
1018  define_t *define, *lastdefine;
1019  int hash;
1020 
1021  //
1022  if (!idParser::ReadLine( &token )) {
1023  idParser::Error( "undef without name" );
1024  return false;
1025  }
1026  if (token.type != TT_NAME) {
1027  idParser::UnreadSourceToken( &token );
1028  idParser::Error( "expected name but found '%s'", token.c_str() );
1029  return false;
1030  }
1031 
1032  hash = PC_NameHash( token.c_str() );
1033  for (lastdefine = NULL, define = idParser::definehash[hash]; define; define = define->hashnext) {
1034  if (!strcmp(define->name, token.c_str()))
1035  {
1036  if (define->flags & DEFINE_FIXED) {
1037  idParser::Warning( "can't undef '%s'", token.c_str() );
1038  }
1039  else {
1040  if (lastdefine) {
1041  lastdefine->hashnext = define->hashnext;
1042  }
1043  else {
1044  idParser::definehash[hash] = define->hashnext;
1045  }
1046  FreeDefine(define);
1047  }
1048  break;
1049  }
1050  lastdefine = define;
1051  }
1052  return true;
1053 }
1054 
1055 /*
1056 ================
1057 idParser::Directive_define
1058 ================
1059 */
1061  idToken token, *t, *last;
1062  define_t *define;
1063 
1064  if (!idParser::ReadLine( &token )) {
1065  idParser::Error( "#define without name" );
1066  return false;
1067  }
1068  if (token.type != TT_NAME) {
1069  idParser::UnreadSourceToken( &token );
1070  idParser::Error( "expected name after #define, found '%s'", token.c_str() );
1071  return false;
1072  }
1073  // check if the define already exists
1074  define = FindHashedDefine(idParser::definehash, token.c_str());
1075  if (define) {
1076  if (define->flags & DEFINE_FIXED) {
1077  idParser::Error( "can't redefine '%s'", token.c_str() );
1078  return false;
1079  }
1080  idParser::Warning( "redefinition of '%s'", token.c_str() );
1081  // unread the define name before executing the #undef directive
1082  idParser::UnreadSourceToken( &token );
1084  return false;
1085  // if the define was not removed (define->flags & DEFINE_FIXED)
1086  define = FindHashedDefine(idParser::definehash, token.c_str());
1087  }
1088  // allocate define
1089  define = (define_t *) Mem_ClearedAlloc(sizeof(define_t) + token.Length() + 1);
1090  define->name = (char *) define + sizeof(define_t);
1091  strcpy(define->name, token.c_str());
1092  // add the define to the source
1094  // if nothing is defined, just return
1095  if ( !idParser::ReadLine( &token ) ) {
1096  return true;
1097  }
1098  // if it is a define with parameters
1099  if ( token.WhiteSpaceBeforeToken() == 0 && token == "(" ) {
1100  // read the define parameters
1101  last = NULL;
1102  if ( !idParser::CheckTokenString(")") ) {
1103  while(1) {
1104  if ( !idParser::ReadLine( &token ) ) {
1105  idParser::Error( "expected define parameter" );
1106  return false;
1107  }
1108  // if it isn't a name
1109  if (token.type != TT_NAME) {
1110  idParser::Error( "invalid define parameter" );
1111  return false;
1112  }
1113 
1114  if (FindDefineParm(define, token.c_str()) >= 0) {
1115  idParser::Error( "two the same define parameters" );
1116  return false;
1117  }
1118  // add the define parm
1119  t = new idToken(token);
1120  t->ClearTokenWhiteSpace();
1121  t->next = NULL;
1122  if (last) last->next = t;
1123  else define->parms = t;
1124  last = t;
1125  define->numparms++;
1126  // read next token
1127  if (!idParser::ReadLine( &token )) {
1128  idParser::Error( "define parameters not terminated" );
1129  return false;
1130  }
1131 
1132  if ( token == ")" ) {
1133  break;
1134  }
1135  // then it must be a comma
1136  if ( token != "," ) {
1137  idParser::Error( "define not terminated" );
1138  return false;
1139  }
1140  }
1141  }
1142  if ( !idParser::ReadLine( &token ) ) {
1143  return true;
1144  }
1145  }
1146  // read the defined stuff
1147  last = NULL;
1148  do
1149  {
1150  t = new idToken(token);
1151  if ( t->type == TT_NAME && !strcmp( t->c_str(), define->name ) ) {
1153  idParser::Warning( "recursive define (removed recursion)" );
1154  }
1155  t->ClearTokenWhiteSpace();
1156  t->next = NULL;
1157  if ( last ) last->next = t;
1158  else define->tokens = t;
1159  last = t;
1160  } while( idParser::ReadLine( &token ) );
1161 
1162  if ( last ) {
1163  // check for merge operators at the beginning or end
1164  if ( (*define->tokens) == "##" || (*last) == "##" ) {
1165  idParser::Error( "define with misplaced ##" );
1166  return false;
1167  }
1168  }
1169  return true;
1170 }
1171 
1172 /*
1173 ================
1174 idParser::AddDefine
1175 ================
1176 */
1177 int idParser::AddDefine( const char *string ) {
1178  define_t *define;
1179 
1180  define = DefineFromString( string );
1181  if (!define) {
1182  return false;
1183  }
1185  return true;
1186 }
1187 
1188 /*
1189 ================
1190 idParser::AddGlobalDefinesToSource
1191 ================
1192 */
1194  define_t *define, *newdefine;
1195 
1196  for (define = globaldefines; define; define = define->next) {
1197  newdefine = CopyDefine( define );
1199  }
1200 }
1201 
1202 /*
1203 ================
1204 idParser::Directive_if_def
1205 ================
1206 */
1208  idToken token;
1209  define_t *d;
1210  int skip;
1211 
1212  if ( !idParser::ReadLine( &token ) ) {
1213  idParser::Error( "#ifdef without name" );
1214  return false;
1215  }
1216  if (token.type != TT_NAME) {
1217  idParser::UnreadSourceToken( &token );
1218  idParser::Error( "expected name after #ifdef, found '%s'", token.c_str() );
1219  return false;
1220  }
1222  skip = (type == INDENT_IFDEF) == (d == NULL);
1223  idParser::PushIndent( type, skip );
1224  return true;
1225 }
1226 
1227 /*
1228 ================
1229 idParser::Directive_ifdef
1230 ================
1231 */
1234 }
1235 
1236 /*
1237 ================
1238 idParser::Directive_ifndef
1239 ================
1240 */
1243 }
1244 
1245 /*
1246 ================
1247 idParser::Directive_else
1248 ================
1249 */
1251  int type, skip;
1252 
1253  idParser::PopIndent( &type, &skip );
1254  if (!type) {
1255  idParser::Error( "misplaced #else" );
1256  return false;
1257  }
1258  if (type == INDENT_ELSE) {
1259  idParser::Error( "#else after #else" );
1260  return false;
1261  }
1263  return true;
1264 }
1265 
1266 /*
1267 ================
1268 idParser::Directive_endif
1269 ================
1270 */
1272  int type, skip;
1273 
1274  idParser::PopIndent( &type, &skip );
1275  if (!type) {
1276  idParser::Error( "misplaced #endif" );
1277  return false;
1278  }
1279  return true;
1280 }
1281 
1282 /*
1283 ================
1284 idParser::EvaluateTokens
1285 ================
1286 */
1287 typedef struct operator_s
1288 {
1289  int op;
1292  struct operator_s *prev, *next;
1293 } operator_t;
1294 
1295 typedef struct value_s
1296 {
1297  signed long int intvalue;
1298  double floatvalue;
1300  struct value_s *prev, *next;
1301 } value_t;
1302 
1303 int PC_OperatorPriority(int op) {
1304  switch(op) {
1305  case P_MUL: return 15;
1306  case P_DIV: return 15;
1307  case P_MOD: return 15;
1308  case P_ADD: return 14;
1309  case P_SUB: return 14;
1310 
1311  case P_LOGIC_AND: return 7;
1312  case P_LOGIC_OR: return 6;
1313  case P_LOGIC_GEQ: return 12;
1314  case P_LOGIC_LEQ: return 12;
1315  case P_LOGIC_EQ: return 11;
1316  case P_LOGIC_UNEQ: return 11;
1317 
1318  case P_LOGIC_NOT: return 16;
1319  case P_LOGIC_GREATER: return 12;
1320  case P_LOGIC_LESS: return 12;
1321 
1322  case P_RSHIFT: return 13;
1323  case P_LSHIFT: return 13;
1324 
1325  case P_BIN_AND: return 10;
1326  case P_BIN_OR: return 8;
1327  case P_BIN_XOR: return 9;
1328  case P_BIN_NOT: return 16;
1329 
1330  case P_COLON: return 5;
1331  case P_QUESTIONMARK: return 5;
1332  }
1333  return false;
1334 }
1335 
1336 //#define AllocValue() GetClearedMemory(sizeof(value_t));
1337 //#define FreeValue(val) FreeMemory(val)
1338 //#define AllocOperator(op) op = (operator_t *) GetClearedMemory(sizeof(operator_t));
1339 //#define FreeOperator(op) FreeMemory(op);
1340 
1341 #define MAX_VALUES 64
1342 #define MAX_OPERATORS 64
1343 
1344 #define AllocValue(val) \
1345  if ( numvalues >= MAX_VALUES ) { \
1346  idParser::Error( "out of value space\n" ); \
1347  error = 1; \
1348  break; \
1349  } \
1350  else { \
1351  val = &value_heap[numvalues++]; \
1352  }
1353 
1354 #define FreeValue(val)
1355 
1356 #define AllocOperator(op) \
1357  if ( numoperators >= MAX_OPERATORS ) { \
1358  idParser::Error( "out of operator space\n" ); \
1359  error = 1; \
1360  break; \
1361  } \
1362  else { \
1363  op = &operator_heap[numoperators++]; \
1364  }
1365 
1366 #define FreeOperator(op)
1367 
1368 int idParser::EvaluateTokens( idToken *tokens, signed long int *intvalue, double *floatvalue, int integer ) {
1369  operator_t *o, *firstoperator, *lastoperator;
1370  value_t *v, *firstvalue, *lastvalue, *v1, *v2;
1371  idToken *t;
1372  int brace = 0;
1373  int parentheses = 0;
1374  int error = 0;
1375  int lastwasvalue = 0;
1376  int negativevalue = 0;
1377  int questmarkintvalue = 0;
1378  double questmarkfloatvalue = 0;
1379  int gotquestmarkvalue = false;
1380  int lastoperatortype = 0;
1381  //
1382  operator_t operator_heap[MAX_OPERATORS];
1383  int numoperators = 0;
1384  value_t value_heap[MAX_VALUES];
1385  int numvalues = 0;
1386 
1387  firstoperator = lastoperator = NULL;
1388  firstvalue = lastvalue = NULL;
1389  if (intvalue) *intvalue = 0;
1390  if (floatvalue) *floatvalue = 0;
1391  for ( t = tokens; t; t = t->next ) {
1392  switch( t->type ) {
1393  case TT_NAME:
1394  {
1395  if ( lastwasvalue || negativevalue ) {
1396  idParser::Error( "syntax error in #if/#elif" );
1397  error = 1;
1398  break;
1399  }
1400  if ( (*t) != "defined" ) {
1401  idParser::Error( "undefined name '%s' in #if/#elif", t->c_str() );
1402  error = 1;
1403  break;
1404  }
1405  t = t->next;
1406  if ( (*t) == "(" ) {
1407  brace = true;
1408  t = t->next;
1409  }
1410  if (!t || t->type != TT_NAME) {
1411  idParser::Error( "defined() without name in #if/#elif" );
1412  error = 1;
1413  break;
1414  }
1415  //v = (value_t *) GetClearedMemory(sizeof(value_t));
1416  AllocValue(v);
1418  v->intvalue = 1;
1419  v->floatvalue = 1;
1420  }
1421  else {
1422  v->intvalue = 0;
1423  v->floatvalue = 0;
1424  }
1425  v->parentheses = parentheses;
1426  v->next = NULL;
1427  v->prev = lastvalue;
1428  if (lastvalue) lastvalue->next = v;
1429  else firstvalue = v;
1430  lastvalue = v;
1431  if (brace) {
1432  t = t->next;
1433  if (!t || (*t) != ")" ) {
1434  idParser::Error( "defined missing ) in #if/#elif" );
1435  error = 1;
1436  break;
1437  }
1438  }
1439  brace = false;
1440  // defined() creates a value
1441  lastwasvalue = 1;
1442  break;
1443  }
1444  case TT_NUMBER:
1445  {
1446  if (lastwasvalue) {
1447  idParser::Error( "syntax error in #if/#elif" );
1448  error = 1;
1449  break;
1450  }
1451  //v = (value_t *) GetClearedMemory(sizeof(value_t));
1452  AllocValue(v);
1453  if (negativevalue) {
1454  v->intvalue = - t->GetIntValue();
1455  v->floatvalue = - t->GetFloatValue();
1456  }
1457  else {
1458  v->intvalue = t->GetIntValue();
1459  v->floatvalue = t->GetFloatValue();
1460  }
1461  v->parentheses = parentheses;
1462  v->next = NULL;
1463  v->prev = lastvalue;
1464  if (lastvalue) lastvalue->next = v;
1465  else firstvalue = v;
1466  lastvalue = v;
1467  //last token was a value
1468  lastwasvalue = 1;
1469  //
1470  negativevalue = 0;
1471  break;
1472  }
1473  case TT_PUNCTUATION:
1474  {
1475  if (negativevalue) {
1476  idParser::Error( "misplaced minus sign in #if/#elif" );
1477  error = 1;
1478  break;
1479  }
1480  if (t->subtype == P_PARENTHESESOPEN) {
1481  parentheses++;
1482  break;
1483  }
1484  else if (t->subtype == P_PARENTHESESCLOSE) {
1485  parentheses--;
1486  if (parentheses < 0) {
1487  idParser::Error( "too many ) in #if/#elsif" );
1488  error = 1;
1489  }
1490  break;
1491  }
1492  //check for invalid operators on floating point values
1493  if ( !integer ) {
1494  if (t->subtype == P_BIN_NOT || t->subtype == P_MOD ||
1495  t->subtype == P_RSHIFT || t->subtype == P_LSHIFT ||
1496  t->subtype == P_BIN_AND || t->subtype == P_BIN_OR ||
1497  t->subtype == P_BIN_XOR) {
1498  idParser::Error( "illigal operator '%s' on floating point operands\n", t->c_str() );
1499  error = 1;
1500  break;
1501  }
1502  }
1503  switch( t->subtype ) {
1504  case P_LOGIC_NOT:
1505  case P_BIN_NOT:
1506  {
1507  if (lastwasvalue) {
1508  idParser::Error( "! or ~ after value in #if/#elif" );
1509  error = 1;
1510  break;
1511  }
1512  break;
1513  }
1514  case P_INC:
1515  case P_DEC:
1516  {
1517  idParser::Error( "++ or -- used in #if/#elif" );
1518  break;
1519  }
1520  case P_SUB:
1521  {
1522  if (!lastwasvalue) {
1523  negativevalue = 1;
1524  break;
1525  }
1526  }
1527 
1528  case P_MUL:
1529  case P_DIV:
1530  case P_MOD:
1531  case P_ADD:
1532 
1533  case P_LOGIC_AND:
1534  case P_LOGIC_OR:
1535  case P_LOGIC_GEQ:
1536  case P_LOGIC_LEQ:
1537  case P_LOGIC_EQ:
1538  case P_LOGIC_UNEQ:
1539 
1540  case P_LOGIC_GREATER:
1541  case P_LOGIC_LESS:
1542 
1543  case P_RSHIFT:
1544  case P_LSHIFT:
1545 
1546  case P_BIN_AND:
1547  case P_BIN_OR:
1548  case P_BIN_XOR:
1549 
1550  case P_COLON:
1551  case P_QUESTIONMARK:
1552  {
1553  if (!lastwasvalue) {
1554  idParser::Error( "operator '%s' after operator in #if/#elif", t->c_str() );
1555  error = 1;
1556  break;
1557  }
1558  break;
1559  }
1560  default:
1561  {
1562  idParser::Error( "invalid operator '%s' in #if/#elif", t->c_str() );
1563  error = 1;
1564  break;
1565  }
1566  }
1567  if (!error && !negativevalue) {
1568  //o = (operator_t *) GetClearedMemory(sizeof(operator_t));
1569  AllocOperator(o);
1570  o->op = t->subtype;
1572  o->parentheses = parentheses;
1573  o->next = NULL;
1574  o->prev = lastoperator;
1575  if (lastoperator) lastoperator->next = o;
1576  else firstoperator = o;
1577  lastoperator = o;
1578  lastwasvalue = 0;
1579  }
1580  break;
1581  }
1582  default:
1583  {
1584  idParser::Error( "unknown '%s' in #if/#elif", t->c_str() );
1585  error = 1;
1586  break;
1587  }
1588  }
1589  if (error) {
1590  break;
1591  }
1592  }
1593  if (!error) {
1594  if (!lastwasvalue) {
1595  idParser::Error( "trailing operator in #if/#elif" );
1596  error = 1;
1597  }
1598  else if (parentheses) {
1599  idParser::Error( "too many ( in #if/#elif" );
1600  error = 1;
1601  }
1602  }
1603  //
1604  gotquestmarkvalue = false;
1605  questmarkintvalue = 0;
1606  questmarkfloatvalue = 0;
1607  //while there are operators
1608  while( !error && firstoperator ) {
1609  v = firstvalue;
1610  for (o = firstoperator; o->next; o = o->next) {
1611  //if the current operator is nested deeper in parentheses
1612  //than the next operator
1613  if (o->parentheses > o->next->parentheses) {
1614  break;
1615  }
1616  //if the current and next operator are nested equally deep in parentheses
1617  if (o->parentheses == o->next->parentheses) {
1618  //if the priority of the current operator is equal or higher
1619  //than the priority of the next operator
1620  if (o->priority >= o->next->priority) {
1621  break;
1622  }
1623  }
1624  //if the arity of the operator isn't equal to 1
1625  if (o->op != P_LOGIC_NOT && o->op != P_BIN_NOT) {
1626  v = v->next;
1627  }
1628  //if there's no value or no next value
1629  if (!v) {
1630  idParser::Error( "mising values in #if/#elif" );
1631  error = 1;
1632  break;
1633  }
1634  }
1635  if (error) {
1636  break;
1637  }
1638  v1 = v;
1639  v2 = v->next;
1640 #ifdef DEBUG_EVAL
1641  if (integer) {
1642  Log_Write("operator %s, value1 = %d", idParser::scriptstack->getPunctuationFromId(o->op), v1->intvalue);
1643  if (v2) Log_Write("value2 = %d", v2->intvalue);
1644  }
1645  else {
1646  Log_Write("operator %s, value1 = %f", idParser::scriptstack->getPunctuationFromId(o->op), v1->floatvalue);
1647  if (v2) Log_Write("value2 = %f", v2->floatvalue);
1648  }
1649 #endif //DEBUG_EVAL
1650  switch(o->op) {
1651  case P_LOGIC_NOT: v1->intvalue = !v1->intvalue;
1652  v1->floatvalue = !v1->floatvalue; break;
1653  case P_BIN_NOT: v1->intvalue = ~v1->intvalue;
1654  break;
1655  case P_MUL: v1->intvalue *= v2->intvalue;
1656  v1->floatvalue *= v2->floatvalue; break;
1657  case P_DIV: if (!v2->intvalue || !v2->floatvalue)
1658  {
1659  idParser::Error( "divide by zero in #if/#elif\n" );
1660  error = 1;
1661  break;
1662  }
1663  v1->intvalue /= v2->intvalue;
1664  v1->floatvalue /= v2->floatvalue; break;
1665  case P_MOD: if (!v2->intvalue)
1666  {
1667  idParser::Error( "divide by zero in #if/#elif\n" );
1668  error = 1;
1669  break;
1670  }
1671  v1->intvalue %= v2->intvalue; break;
1672  case P_ADD: v1->intvalue += v2->intvalue;
1673  v1->floatvalue += v2->floatvalue; break;
1674  case P_SUB: v1->intvalue -= v2->intvalue;
1675  v1->floatvalue -= v2->floatvalue; break;
1676  case P_LOGIC_AND: v1->intvalue = v1->intvalue && v2->intvalue;
1677  v1->floatvalue = v1->floatvalue && v2->floatvalue; break;
1678  case P_LOGIC_OR: v1->intvalue = v1->intvalue || v2->intvalue;
1679  v1->floatvalue = v1->floatvalue || v2->floatvalue; break;
1680  case P_LOGIC_GEQ: v1->intvalue = v1->intvalue >= v2->intvalue;
1681  v1->floatvalue = v1->floatvalue >= v2->floatvalue; break;
1682  case P_LOGIC_LEQ: v1->intvalue = v1->intvalue <= v2->intvalue;
1683  v1->floatvalue = v1->floatvalue <= v2->floatvalue; break;
1684  case P_LOGIC_EQ: v1->intvalue = v1->intvalue == v2->intvalue;
1685  v1->floatvalue = v1->floatvalue == v2->floatvalue; break;
1686  case P_LOGIC_UNEQ: v1->intvalue = v1->intvalue != v2->intvalue;
1687  v1->floatvalue = v1->floatvalue != v2->floatvalue; break;
1688  case P_LOGIC_GREATER: v1->intvalue = v1->intvalue > v2->intvalue;
1689  v1->floatvalue = v1->floatvalue > v2->floatvalue; break;
1690  case P_LOGIC_LESS: v1->intvalue = v1->intvalue < v2->intvalue;
1691  v1->floatvalue = v1->floatvalue < v2->floatvalue; break;
1692  case P_RSHIFT: v1->intvalue >>= v2->intvalue;
1693  break;
1694  case P_LSHIFT: v1->intvalue <<= v2->intvalue;
1695  break;
1696  case P_BIN_AND: v1->intvalue &= v2->intvalue;
1697  break;
1698  case P_BIN_OR: v1->intvalue |= v2->intvalue;
1699  break;
1700  case P_BIN_XOR: v1->intvalue ^= v2->intvalue;
1701  break;
1702  case P_COLON:
1703  {
1704  if (!gotquestmarkvalue) {
1705  idParser::Error( ": without ? in #if/#elif" );
1706  error = 1;
1707  break;
1708  }
1709  if (integer) {
1710  if (!questmarkintvalue)
1711  v1->intvalue = v2->intvalue;
1712  }
1713  else {
1714  if (!questmarkfloatvalue)
1715  v1->floatvalue = v2->floatvalue;
1716  }
1717  gotquestmarkvalue = false;
1718  break;
1719  }
1720  case P_QUESTIONMARK:
1721  {
1722  if (gotquestmarkvalue) {
1723  idParser::Error( "? after ? in #if/#elif" );
1724  error = 1;
1725  break;
1726  }
1727  questmarkintvalue = v1->intvalue;
1728  questmarkfloatvalue = v1->floatvalue;
1729  gotquestmarkvalue = true;
1730  break;
1731  }
1732  }
1733 #ifdef DEBUG_EVAL
1734  if (integer) Log_Write("result value = %d", v1->intvalue);
1735  else Log_Write("result value = %f", v1->floatvalue);
1736 #endif //DEBUG_EVAL
1737  if (error)
1738  break;
1739  lastoperatortype = o->op;
1740  //if not an operator with arity 1
1741  if (o->op != P_LOGIC_NOT && o->op != P_BIN_NOT) {
1742  //remove the second value if not question mark operator
1743  if (o->op != P_QUESTIONMARK) {
1744  v = v->next;
1745  }
1746  //
1747  if (v->prev) v->prev->next = v->next;
1748  else firstvalue = v->next;
1749  if (v->next) v->next->prev = v->prev;
1750  else lastvalue = v->prev;
1751  //FreeMemory(v);
1752  FreeValue(v);
1753  }
1754  //remove the operator
1755  if (o->prev) o->prev->next = o->next;
1756  else firstoperator = o->next;
1757  if (o->next) o->next->prev = o->prev;
1758  else lastoperator = o->prev;
1759  //FreeMemory(o);
1760  FreeOperator(o);
1761  }
1762  if (firstvalue) {
1763  if (intvalue) *intvalue = firstvalue->intvalue;
1764  if (floatvalue) *floatvalue = firstvalue->floatvalue;
1765  }
1766  for (o = firstoperator; o; o = lastoperator) {
1767  lastoperator = o->next;
1768  //FreeMemory(o);
1769  FreeOperator(o);
1770  }
1771  for (v = firstvalue; v; v = lastvalue) {
1772  lastvalue = v->next;
1773  //FreeMemory(v);
1774  FreeValue(v);
1775  }
1776  if (!error) {
1777  return true;
1778  }
1779  if (intvalue) {
1780  *intvalue = 0;
1781  }
1782  if (floatvalue) {
1783  *floatvalue = 0;
1784  }
1785  return false;
1786 }
1787 
1788 /*
1789 ================
1790 idParser::Evaluate
1791 ================
1792 */
1793 int idParser::Evaluate( signed long int *intvalue, double *floatvalue, int integer ) {
1794  idToken token, *firsttoken, *lasttoken;
1795  idToken *t, *nexttoken;
1796  define_t *define;
1797  int defined = false;
1798 
1799  if (intvalue) {
1800  *intvalue = 0;
1801  }
1802  if (floatvalue) {
1803  *floatvalue = 0;
1804  }
1805  //
1806  if ( !idParser::ReadLine( &token ) ) {
1807  idParser::Error( "no value after #if/#elif" );
1808  return false;
1809  }
1810  firsttoken = NULL;
1811  lasttoken = NULL;
1812  do {
1813  //if the token is a name
1814  if (token.type == TT_NAME) {
1815  if (defined) {
1816  defined = false;
1817  t = new idToken(token);
1818  t->next = NULL;
1819  if (lasttoken) lasttoken->next = t;
1820  else firsttoken = t;
1821  lasttoken = t;
1822  }
1823  else if ( token == "defined" ) {
1824  defined = true;
1825  t = new idToken(token);
1826  t->next = NULL;
1827  if (lasttoken) lasttoken->next = t;
1828  else firsttoken = t;
1829  lasttoken = t;
1830  }
1831  else {
1832  //then it must be a define
1833  define = FindHashedDefine(idParser::definehash, token.c_str());
1834  if (!define) {
1835  idParser::Error( "can't Evaluate '%s', not defined", token.c_str() );
1836  return false;
1837  }
1838  if ( !idParser::ExpandDefineIntoSource( &token, define ) ) {
1839  return false;
1840  }
1841  }
1842  }
1843  //if the token is a number or a punctuation
1844  else if (token.type == TT_NUMBER || token.type == TT_PUNCTUATION) {
1845  t = new idToken(token);
1846  t->next = NULL;
1847  if (lasttoken) lasttoken->next = t;
1848  else firsttoken = t;
1849  lasttoken = t;
1850  }
1851  else {
1852  idParser::Error( "can't Evaluate '%s'", token.c_str() );
1853  return false;
1854  }
1855  } while(idParser::ReadLine( &token ));
1856  //
1857  if ( !idParser::EvaluateTokens( firsttoken, intvalue, floatvalue, integer ) ) {
1858  return false;
1859  }
1860  //
1861 #ifdef DEBUG_EVAL
1862  Log_Write("eval:");
1863 #endif //DEBUG_EVAL
1864  for (t = firsttoken; t; t = nexttoken) {
1865 #ifdef DEBUG_EVAL
1866  Log_Write(" %s", t->c_str());
1867 #endif //DEBUG_EVAL
1868  nexttoken = t->next;
1869  delete t;
1870  } //end for
1871 #ifdef DEBUG_EVAL
1872  if (integer) Log_Write("eval result: %d", *intvalue);
1873  else Log_Write("eval result: %f", *floatvalue);
1874 #endif //DEBUG_EVAL
1875  //
1876  return true;
1877 }
1878 
1879 /*
1880 ================
1881 idParser::DollarEvaluate
1882 ================
1883 */
1884 int idParser::DollarEvaluate( signed long int *intvalue, double *floatvalue, int integer) {
1885  int indent, defined = false;
1886  idToken token, *firsttoken, *lasttoken;
1887  idToken *t, *nexttoken;
1888  define_t *define;
1889 
1890  if (intvalue) {
1891  *intvalue = 0;
1892  }
1893  if (floatvalue) {
1894  *floatvalue = 0;
1895  }
1896  //
1897  if ( !idParser::ReadSourceToken( &token ) ) {
1898  idParser::Error( "no leading ( after $evalint/$evalfloat" );
1899  return false;
1900  }
1901  if ( !idParser::ReadSourceToken( &token ) ) {
1902  idParser::Error( "nothing to Evaluate" );
1903  return false;
1904  }
1905  indent = 1;
1906  firsttoken = NULL;
1907  lasttoken = NULL;
1908  do {
1909  //if the token is a name
1910  if (token.type == TT_NAME) {
1911  if (defined) {
1912  defined = false;
1913  t = new idToken(token);
1914  t->next = NULL;
1915  if (lasttoken) lasttoken->next = t;
1916  else firsttoken = t;
1917  lasttoken = t;
1918  }
1919  else if ( token == "defined" ) {
1920  defined = true;
1921  t = new idToken(token);
1922  t->next = NULL;
1923  if (lasttoken) lasttoken->next = t;
1924  else firsttoken = t;
1925  lasttoken = t;
1926  }
1927  else {
1928  //then it must be a define
1929  define = FindHashedDefine(idParser::definehash, token.c_str());
1930  if (!define) {
1931  idParser::Warning( "can't Evaluate '%s', not defined", token.c_str() );
1932  return false;
1933  }
1934  if ( !idParser::ExpandDefineIntoSource( &token, define ) ) {
1935  return false;
1936  }
1937  }
1938  }
1939  //if the token is a number or a punctuation
1940  else if (token.type == TT_NUMBER || token.type == TT_PUNCTUATION) {
1941  if ( token[0] == '(' ) indent++;
1942  else if ( token[0] == ')' ) indent--;
1943  if (indent <= 0) {
1944  break;
1945  }
1946  t = new idToken(token);
1947  t->next = NULL;
1948  if (lasttoken) lasttoken->next = t;
1949  else firsttoken = t;
1950  lasttoken = t;
1951  }
1952  else {
1953  idParser::Error( "can't Evaluate '%s'", token.c_str() );
1954  return false;
1955  }
1956  } while(idParser::ReadSourceToken( &token ));
1957  //
1958  if (!idParser::EvaluateTokens( firsttoken, intvalue, floatvalue, integer)) {
1959  return false;
1960  }
1961  //
1962 #ifdef DEBUG_EVAL
1963  Log_Write("$eval:");
1964 #endif //DEBUG_EVAL
1965  for (t = firsttoken; t; t = nexttoken) {
1966 #ifdef DEBUG_EVAL
1967  Log_Write(" %s", t->c_str());
1968 #endif //DEBUG_EVAL
1969  nexttoken = t->next;
1970  delete t;
1971  } //end for
1972 #ifdef DEBUG_EVAL
1973  if (integer) Log_Write("$eval result: %d", *intvalue);
1974  else Log_Write("$eval result: %f", *floatvalue);
1975 #endif //DEBUG_EVAL
1976  //
1977  return true;
1978 }
1979 
1980 /*
1981 ================
1982 idParser::Directive_elif
1983 ================
1984 */
1986  signed long int value;
1987  int type, skip;
1988 
1989  idParser::PopIndent( &type, &skip );
1990  if (!type || type == INDENT_ELSE) {
1991  idParser::Error( "misplaced #elif" );
1992  return false;
1993  }
1994  if ( !idParser::Evaluate( &value, NULL, true ) ) {
1995  return false;
1996  }
1997  skip = (value == 0);
1999  return true;
2000 }
2001 
2002 /*
2003 ================
2004 idParser::Directive_if
2005 ================
2006 */
2008  signed long int value;
2009  int skip;
2010 
2011  if ( !idParser::Evaluate( &value, NULL, true ) ) {
2012  return false;
2013  }
2014  skip = (value == 0);
2016  return true;
2017 }
2018 
2019 /*
2020 ================
2021 idParser::Directive_line
2022 ================
2023 */
2025  idToken token;
2026 
2027  idParser::Error( "#line directive not supported" );
2028  while( idParser::ReadLine( &token ) ) {
2029  }
2030  return true;
2031 }
2032 
2033 /*
2034 ================
2035 idParser::Directive_error
2036 ================
2037 */
2039  idToken token;
2040 
2041  if ( !idParser::ReadLine( &token) || token.type != TT_STRING ) {
2042  idParser::Error( "#error without string" );
2043  return false;
2044  }
2045  idParser::Error( "#error: %s", token.c_str() );
2046  return true;
2047 }
2048 
2049 /*
2050 ================
2051 idParser::Directive_warning
2052 ================
2053 */
2055  idToken token;
2056 
2057  if ( !idParser::ReadLine( &token) || token.type != TT_STRING ) {
2058  idParser::Warning( "#warning without string" );
2059  return false;
2060  }
2061  idParser::Warning( "#warning: %s", token.c_str() );
2062  return true;
2063 }
2064 
2065 /*
2066 ================
2067 idParser::Directive_pragma
2068 ================
2069 */
2071  idToken token;
2072 
2073  idParser::Warning( "#pragma directive not supported" );
2074  while( idParser::ReadLine( &token ) ) {
2075  }
2076  return true;
2077 }
2078 
2079 /*
2080 ================
2081 idParser::UnreadSignToken
2082 ================
2083 */
2085  idToken token;
2086 
2088  token.whiteSpaceStart_p = NULL;
2089  token.whiteSpaceEnd_p = NULL;
2090  token.linesCrossed = 0;
2091  token.flags = 0;
2092  token = "-";
2093  token.type = TT_PUNCTUATION;
2094  token.subtype = P_SUB;
2095  idParser::UnreadSourceToken( &token );
2096 }
2097 
2098 /*
2099 ================
2100 idParser::Directive_eval
2101 ================
2102 */
2104  signed long int value;
2105  idToken token;
2106  char buf[128];
2107 
2108  if ( !idParser::Evaluate( &value, NULL, true ) ) {
2109  return false;
2110  }
2111 
2113  token.whiteSpaceStart_p = NULL;
2114  token.whiteSpaceEnd_p = NULL;
2115  token.linesCrossed = 0;
2116  token.flags = 0;
2117  sprintf(buf, "%d", abs(value));
2118  token = buf;
2119  token.type = TT_NUMBER;
2121  idParser::UnreadSourceToken( &token );
2122  if ( value < 0 ) {
2124  }
2125  return true;
2126 }
2127 
2128 /*
2129 ================
2130 idParser::Directive_evalfloat
2131 ================
2132 */
2134  double value;
2135  idToken token;
2136  char buf[128];
2137 
2138  if ( !idParser::Evaluate( NULL, &value, false ) ) {
2139  return false;
2140  }
2141 
2143  token.whiteSpaceStart_p = NULL;
2144  token.whiteSpaceEnd_p = NULL;
2145  token.linesCrossed = 0;
2146  token.flags = 0;
2147  sprintf(buf, "%1.2f", idMath::Fabs(value));
2148  token = buf;
2149  token.type = TT_NUMBER;
2151  idParser::UnreadSourceToken( &token );
2152  if (value < 0) {
2154  }
2155  return true;
2156 }
2157 
2158 /*
2159 ================
2160 idParser::ReadDirective
2161 ================
2162 */
2164  idToken token;
2165 
2166  //read the directive name
2167  if ( !idParser::ReadSourceToken( &token ) ) {
2168  idParser::Error( "found '#' without name" );
2169  return false;
2170  }
2171  //directive name must be on the same line
2172  if (token.linesCrossed > 0) {
2173  idParser::UnreadSourceToken( &token );
2174  idParser::Error( "found '#' at end of line" );
2175  return false;
2176  }
2177  //if if is a name
2178  if (token.type == TT_NAME) {
2179  if ( token == "if" ) {
2180  return idParser::Directive_if();
2181  }
2182  else if ( token == "ifdef" ) {
2183  return idParser::Directive_ifdef();
2184  }
2185  else if ( token == "ifndef" ) {
2186  return idParser::Directive_ifndef();
2187  }
2188  else if ( token == "elif" ) {
2189  return idParser::Directive_elif();
2190  }
2191  else if ( token == "else" ) {
2192  return idParser::Directive_else();
2193  }
2194  else if ( token == "endif" ) {
2195  return idParser::Directive_endif();
2196  }
2197  else if (idParser::skip > 0) {
2198  // skip the rest of the line
2199  while( idParser::ReadLine( &token ) ) {
2200  }
2201  return true;
2202  }
2203  else {
2204  if ( token == "include" ) {
2205  return idParser::Directive_include();
2206  }
2207  else if ( token == "define" ) {
2208  return idParser::Directive_define();
2209  }
2210  else if ( token == "undef" ) {
2211  return idParser::Directive_undef();
2212  }
2213  else if ( token == "line" ) {
2214  return idParser::Directive_line();
2215  }
2216  else if ( token == "error" ) {
2217  return idParser::Directive_error();
2218  }
2219  else if ( token == "warning" ) {
2220  return idParser::Directive_warning();
2221  }
2222  else if ( token == "pragma" ) {
2223  return idParser::Directive_pragma();
2224  }
2225  else if ( token == "eval" ) {
2226  return idParser::Directive_eval();
2227  }
2228  else if ( token == "evalfloat" ) {
2230  }
2231  }
2232  }
2233  idParser::Error( "unknown precompiler directive '%s'", token.c_str() );
2234  return false;
2235 }
2236 
2237 /*
2238 ================
2239 idParser::DollarDirective_evalint
2240 ================
2241 */
2243  signed long int value;
2244  idToken token;
2245  char buf[128];
2246 
2247  if ( !idParser::DollarEvaluate( &value, NULL, true ) ) {
2248  return false;
2249  }
2250 
2252  token.whiteSpaceStart_p = NULL;
2253  token.whiteSpaceEnd_p = NULL;
2254  token.linesCrossed = 0;
2255  token.flags = 0;
2256  sprintf( buf, "%d", abs( value ) );
2257  token = buf;
2258  token.type = TT_NUMBER;
2260  token.intvalue = abs( value );
2261  token.floatvalue = abs( value );
2262  idParser::UnreadSourceToken( &token );
2263  if ( value < 0 ) {
2265  }
2266  return true;
2267 }
2268 
2269 /*
2270 ================
2271 idParser::DollarDirective_evalfloat
2272 ================
2273 */
2275  double value;
2276  idToken token;
2277  char buf[128];
2278 
2279  if ( !idParser::DollarEvaluate( NULL, &value, false ) ) {
2280  return false;
2281  }
2282 
2284  token.whiteSpaceStart_p = NULL;
2285  token.whiteSpaceEnd_p = NULL;
2286  token.linesCrossed = 0;
2287  token.flags = 0;
2288  sprintf( buf, "%1.2f", fabs( value ) );
2289  token = buf;
2290  token.type = TT_NUMBER;
2292  token.intvalue = (unsigned long) fabs( value );
2293  token.floatvalue = fabs( value );
2294  idParser::UnreadSourceToken( &token );
2295  if ( value < 0 ) {
2297  }
2298  return true;
2299 }
2300 
2301 /*
2302 ================
2303 idParser::ReadDollarDirective
2304 ================
2305 */
2307  idToken token;
2308 
2309  // read the directive name
2310  if ( !idParser::ReadSourceToken( &token ) ) {
2311  idParser::Error( "found '$' without name" );
2312  return false;
2313  }
2314  // directive name must be on the same line
2315  if ( token.linesCrossed > 0 ) {
2316  idParser::UnreadSourceToken( &token );
2317  idParser::Error( "found '$' at end of line" );
2318  return false;
2319  }
2320  // if if is a name
2321  if (token.type == TT_NAME) {
2322  if ( token == "evalint" ) {
2324  }
2325  else if ( token == "evalfloat" ) {
2327  }
2328  }
2329  idParser::UnreadSourceToken( &token );
2330  return false;
2331 }
2332 
2333 /*
2334 ================
2335 idParser::ReadToken
2336 ================
2337 */
2339  define_t *define;
2340 
2341  while(1) {
2342  if ( !idParser::ReadSourceToken( token ) ) {
2343  return false;
2344  }
2345  // check for precompiler directives
2346  if ( token->type == TT_PUNCTUATION && (*token)[0] == '#' && (*token)[1] == '\0' ) {
2347  // read the precompiler directive
2348  if ( !idParser::ReadDirective() ) {
2349  return false;
2350  }
2351  continue;
2352  }
2353  // if skipping source because of conditional compilation
2354  if ( idParser::skip ) {
2355  continue;
2356  }
2357  // recursively concatenate strings that are behind each other still resolving defines
2358  if ( token->type == TT_STRING && !(idParser::scriptstack->GetFlags() & LEXFL_NOSTRINGCONCAT) ) {
2359  idToken newtoken;
2360  if ( idParser::ReadToken( &newtoken ) ) {
2361  if ( newtoken.type == TT_STRING ) {
2362  token->Append( newtoken.c_str() );
2363  }
2364  else {
2365  idParser::UnreadSourceToken( &newtoken );
2366  }
2367  }
2368  }
2369  //
2371  // check for special precompiler directives
2372  if ( token->type == TT_PUNCTUATION && (*token)[0] == '$' && (*token)[1] == '\0' ) {
2373  // read the precompiler directive
2375  continue;
2376  }
2377  }
2378  }
2379  // if the token is a name
2380  if ( token->type == TT_NAME && !( token->flags & TOKEN_FL_RECURSIVE_DEFINE ) ) {
2381  // check if the name is a define macro
2382  define = FindHashedDefine( idParser::definehash, token->c_str() );
2383  // if it is a define macro
2384  if ( define ) {
2385  // expand the defined macro
2386  if ( !idParser::ExpandDefineIntoSource( token, define ) ) {
2387  return false;
2388  }
2389  continue;
2390  }
2391  }
2392  // found a token
2393  return true;
2394  }
2395 }
2396 
2397 /*
2398 ================
2399 idParser::ExpectTokenString
2400 ================
2401 */
2402 int idParser::ExpectTokenString( const char *string ) {
2403  idToken token;
2404 
2405  if ( !idParser::ReadToken( &token ) ) {
2406  idParser::Error( "couldn't find expected '%s'", string );
2407  return false;
2408  }
2409 
2410  if ( token != string ) {
2411  idParser::Error( "expected '%s' but found '%s'", string, token.c_str() );
2412  return false;
2413  }
2414  return true;
2415 }
2416 
2417 /*
2418 ================
2419 idParser::ExpectTokenType
2420 ================
2421 */
2422 int idParser::ExpectTokenType( int type, int subtype, idToken *token ) {
2423  idStr str;
2424 
2425  if ( !idParser::ReadToken( token ) ) {
2426  idParser::Error( "couldn't read expected token" );
2427  return 0;
2428  }
2429 
2430  if ( token->type != type ) {
2431  switch( type ) {
2432  case TT_STRING: str = "string"; break;
2433  case TT_LITERAL: str = "literal"; break;
2434  case TT_NUMBER: str = "number"; break;
2435  case TT_NAME: str = "name"; break;
2436  case TT_PUNCTUATION: str = "punctuation"; break;
2437  default: str = "unknown type"; break;
2438  }
2439  idParser::Error( "expected a %s but found '%s'", str.c_str(), token->c_str() );
2440  return 0;
2441  }
2442  if ( token->type == TT_NUMBER ) {
2443  if ( (token->subtype & subtype) != subtype ) {
2444  str.Clear();
2445  if ( subtype & TT_DECIMAL ) str = "decimal ";
2446  if ( subtype & TT_HEX ) str = "hex ";
2447  if ( subtype & TT_OCTAL ) str = "octal ";
2448  if ( subtype & TT_BINARY ) str = "binary ";
2449  if ( subtype & TT_UNSIGNED ) str += "unsigned ";
2450  if ( subtype & TT_LONG ) str += "long ";
2451  if ( subtype & TT_FLOAT ) str += "float ";
2452  if ( subtype & TT_INTEGER ) str += "integer ";
2453  str.StripTrailing( ' ' );
2454  idParser::Error( "expected %s but found '%s'", str.c_str(), token->c_str() );
2455  return 0;
2456  }
2457  }
2458  else if ( token->type == TT_PUNCTUATION ) {
2459  if ( subtype < 0 ) {
2460  idParser::Error( "BUG: wrong punctuation subtype" );
2461  return 0;
2462  }
2463  if ( token->subtype != subtype ) {
2464  idParser::Error( "expected '%s' but found '%s'", scriptstack->GetPunctuationFromId( subtype ), token->c_str() );
2465  return 0;
2466  }
2467  }
2468  return 1;
2469 }
2470 
2471 /*
2472 ================
2473 idParser::ExpectAnyToken
2474 ================
2475 */
2477  if (!idParser::ReadToken( token )) {
2478  idParser::Error( "couldn't read expected token" );
2479  return false;
2480  }
2481  else {
2482  return true;
2483  }
2484 }
2485 
2486 /*
2487 ================
2488 idParser::CheckTokenString
2489 ================
2490 */
2491 int idParser::CheckTokenString( const char *string ) {
2492  idToken tok;
2493 
2494  if ( !ReadToken( &tok ) ) {
2495  return false;
2496  }
2497  //if the token is available
2498  if ( tok == string ) {
2499  return true;
2500  }
2501 
2502  UnreadSourceToken( &tok );
2503  return false;
2504 }
2505 
2506 /*
2507 ================
2508 idParser::CheckTokenType
2509 ================
2510 */
2511 int idParser::CheckTokenType( int type, int subtype, idToken *token ) {
2512  idToken tok;
2513 
2514  if ( !ReadToken( &tok ) ) {
2515  return false;
2516  }
2517  //if the type matches
2518  if (tok.type == type && (tok.subtype & subtype) == subtype) {
2519  *token = tok;
2520  return true;
2521  }
2522 
2523  UnreadSourceToken( &tok );
2524  return false;
2525 }
2526 
2527 /*
2528 ================
2529 idParser::PeekTokenString
2530 ================
2531 */
2532 int idParser::PeekTokenString( const char *string ) {
2533  idToken tok;
2534 
2535  if ( !ReadToken( &tok ) ) {
2536  return false;
2537  }
2538 
2539  UnreadSourceToken( &tok );
2540 
2541  // if the token is available
2542  if ( tok == string ) {
2543  return true;
2544  }
2545  return false;
2546 }
2547 
2548 /*
2549 ================
2550 idParser::PeekTokenType
2551 ================
2552 */
2553 int idParser::PeekTokenType( int type, int subtype, idToken *token ) {
2554  idToken tok;
2555 
2556  if ( !ReadToken( &tok ) ) {
2557  return false;
2558  }
2559 
2560  UnreadSourceToken( &tok );
2561 
2562  // if the type matches
2563  if ( tok.type == type && ( tok.subtype & subtype ) == subtype ) {
2564  *token = tok;
2565  return true;
2566  }
2567  return false;
2568 }
2569 
2570 /*
2571 ================
2572 idParser::SkipUntilString
2573 ================
2574 */
2575 int idParser::SkipUntilString( const char *string ) {
2576  idToken token;
2577 
2578  while(idParser::ReadToken( &token )) {
2579  if ( token == string ) {
2580  return true;
2581  }
2582  }
2583  return false;
2584 }
2585 
2586 /*
2587 ================
2588 idParser::SkipRestOfLine
2589 ================
2590 */
2592  idToken token;
2593 
2594  while(idParser::ReadToken( &token )) {
2595  if ( token.linesCrossed ) {
2596  idParser::UnreadSourceToken( &token );
2597  return true;
2598  }
2599  }
2600  return false;
2601 }
2602 
2603 /*
2604 =================
2605 idParser::SkipBracedSection
2606 
2607 Skips until a matching close brace is found.
2608 Internal brace depths are properly skipped.
2609 =================
2610 */
2611 int idParser::SkipBracedSection( bool parseFirstBrace ) {
2612  idToken token;
2613  int depth;
2614 
2615  depth = parseFirstBrace ? 0 : 1;
2616  do {
2617  if ( !ReadToken( &token ) ) {
2618  return false;
2619  }
2620  if( token.type == TT_PUNCTUATION ) {
2621  if( token == "{" ) {
2622  depth++;
2623  } else if ( token == "}" ) {
2624  depth--;
2625  }
2626  }
2627  } while( depth );
2628  return true;
2629 }
2630 
2631 /*
2632 =================
2633 idParser::ParseBracedSectionExact
2634 
2635 The next token should be an open brace.
2636 Parses until a matching close brace is found.
2637 Maintains the exact formating of the braced section
2638 
2639  FIXME: what about precompilation ?
2640 =================
2641 */
2642 const char *idParser::ParseBracedSectionExact( idStr &out, int tabs ) {
2643  return scriptstack->ParseBracedSectionExact( out, tabs );
2644 }
2645 
2646 /*
2647 =================
2648 idParser::ParseBracedSection
2649 
2650 The next token should be an open brace.
2651 Parses until a matching close brace is found.
2652 Internal brace depths are properly skipped.
2653 =================
2654 */
2655 const char *idParser::ParseBracedSection( idStr &out, int tabs ) {
2656  idToken token;
2657  int i, depth;
2658  bool doTabs = false;
2659  if (tabs >= 0) {
2660  doTabs = true;
2661  }
2662 
2663  out.Empty();
2664  if ( !idParser::ExpectTokenString( "{" ) ) {
2665  return out.c_str();
2666  }
2667  out = "{";
2668  depth = 1;
2669  do {
2670  if ( !idParser::ReadToken( &token ) ) {
2671  Error( "missing closing brace" );
2672  return out.c_str();
2673  }
2674 
2675  // if the token is on a new line
2676  for ( i = 0; i < token.linesCrossed; i++ ) {
2677  out += "\r\n";
2678  }
2679 
2680  if (doTabs && token.linesCrossed) {
2681  i = tabs;
2682  if (token[0] == '}' && i > 0) {
2683  i--;
2684  }
2685  while (i-- > 0) {
2686  out += "\t";
2687  }
2688  }
2689  if ( token.type == TT_PUNCTUATION ) {
2690  if ( token[0] == '{' ) {
2691  depth++;
2692  if (doTabs) {
2693  tabs++;
2694  }
2695  }
2696  else if ( token[0] == '}' ) {
2697  depth--;
2698  if (doTabs) {
2699  tabs--;
2700  }
2701  }
2702  }
2703 
2704  if ( token.type == TT_STRING ) {
2705  out += "\"" + token + "\"";
2706  }
2707  else {
2708  out += token;
2709  }
2710  out += " ";
2711  } while( depth );
2712 
2713  return out.c_str();
2714 }
2715 
2716 /*
2717 =================
2718 idParser::ParseRestOfLine
2719 
2720  parse the rest of the line
2721 =================
2722 */
2723 const char *idParser::ParseRestOfLine( idStr &out ) {
2724  idToken token;
2725 
2726  out.Empty();
2727  while(idParser::ReadToken( &token )) {
2728  if ( token.linesCrossed ) {
2729  idParser::UnreadSourceToken( &token );
2730  break;
2731  }
2732  if ( out.Length() ) {
2733  out += " ";
2734  }
2735  out += token;
2736  }
2737  return out.c_str();
2738 }
2739 
2740 /*
2741 ================
2742 idParser::UnreadToken
2743 ================
2744 */
2746  idParser::UnreadSourceToken( token );
2747 }
2748 
2749 /*
2750 ================
2751 idParser::ReadTokenOnLine
2752 ================
2753 */
2755  idToken tok;
2756 
2757  if (!idParser::ReadToken( &tok )) {
2758  return false;
2759  }
2760  // if no lines were crossed before this token
2761  if ( !tok.linesCrossed ) {
2762  *token = tok;
2763  return true;
2764  }
2765  //
2767  return false;
2768 }
2769 
2770 /*
2771 ================
2772 idParser::ParseInt
2773 ================
2774 */
2775 int idParser::ParseInt( void ) {
2776  idToken token;
2777 
2778  if ( !idParser::ReadToken( &token ) ) {
2779  idParser::Error( "couldn't read expected integer" );
2780  return 0;
2781  }
2782  if ( token.type == TT_PUNCTUATION && token == "-" ) {
2784  return -((signed int) token.GetIntValue());
2785  }
2786  else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
2787  idParser::Error( "expected integer value, found '%s'", token.c_str() );
2788  }
2789  return token.GetIntValue();
2790 }
2791 
2792 /*
2793 ================
2794 idParser::ParseBool
2795 ================
2796 */
2797 bool idParser::ParseBool( void ) {
2798  idToken token;
2799 
2800  if ( !idParser::ExpectTokenType( TT_NUMBER, 0, &token ) ) {
2801  idParser::Error( "couldn't read expected boolean" );
2802  return false;
2803  }
2804  return ( token.GetIntValue() != 0 );
2805 }
2806 
2807 /*
2808 ================
2809 idParser::ParseFloat
2810 ================
2811 */
2812 float idParser::ParseFloat( void ) {
2813  idToken token;
2814 
2815  if ( !idParser::ReadToken( &token ) ) {
2816  idParser::Error( "couldn't read expected floating point number" );
2817  return 0.0f;
2818  }
2819  if ( token.type == TT_PUNCTUATION && token == "-" ) {
2820  idParser::ExpectTokenType( TT_NUMBER, 0, &token );
2821  return -token.GetFloatValue();
2822  }
2823  else if ( token.type != TT_NUMBER ) {
2824  idParser::Error( "expected float value, found '%s'", token.c_str() );
2825  }
2826  return token.GetFloatValue();
2827 }
2828 
2829 /*
2830 ================
2831 idParser::Parse1DMatrix
2832 ================
2833 */
2834 int idParser::Parse1DMatrix( int x, float *m ) {
2835  int i;
2836 
2837  if ( !idParser::ExpectTokenString( "(" ) ) {
2838  return false;
2839  }
2840 
2841  for ( i = 0; i < x; i++ ) {
2842  m[i] = idParser::ParseFloat();
2843  }
2844 
2845  if ( !idParser::ExpectTokenString( ")" ) ) {
2846  return false;
2847  }
2848  return true;
2849 }
2850 
2851 /*
2852 ================
2853 idParser::Parse2DMatrix
2854 ================
2855 */
2856 int idParser::Parse2DMatrix( int y, int x, float *m ) {
2857  int i;
2858 
2859  if ( !idParser::ExpectTokenString( "(" ) ) {
2860  return false;
2861  }
2862 
2863  for ( i = 0; i < y; i++ ) {
2864  if ( !idParser::Parse1DMatrix( x, m + i * x ) ) {
2865  return false;
2866  }
2867  }
2868 
2869  if ( !idParser::ExpectTokenString( ")" ) ) {
2870  return false;
2871  }
2872  return true;
2873 }
2874 
2875 /*
2876 ================
2877 idParser::Parse3DMatrix
2878 ================
2879 */
2880 int idParser::Parse3DMatrix( int z, int y, int x, float *m ) {
2881  int i;
2882 
2883  if ( !idParser::ExpectTokenString( "(" ) ) {
2884  return false;
2885  }
2886 
2887  for ( i = 0 ; i < z; i++ ) {
2888  if ( !idParser::Parse2DMatrix( y, x, m + i * x*y ) ) {
2889  return false;
2890  }
2891  }
2892 
2893  if ( !idParser::ExpectTokenString( ")" ) ) {
2894  return false;
2895  }
2896  return true;
2897 }
2898 
2899 /*
2900 ================
2901 idParser::GetLastWhiteSpace
2902 ================
2903 */
2904 int idParser::GetLastWhiteSpace( idStr &whiteSpace ) const {
2905  if ( scriptstack ) {
2906  scriptstack->GetLastWhiteSpace( whiteSpace );
2907  } else {
2908  whiteSpace.Clear();
2909  }
2910  return whiteSpace.Length();
2911 }
2912 
2913 /*
2914 ================
2915 idParser::SetMarker
2916 ================
2917 */
2918 void idParser::SetMarker( void ) {
2919  marker_p = NULL;
2920 }
2921 
2922 /*
2923 ================
2924 idParser::GetStringFromMarker
2925 
2926  FIXME: this is very bad code, the script isn't even garrenteed to still be around
2927 ================
2928 */
2929 void idParser::GetStringFromMarker( idStr& out, bool clean ) {
2930  char* p;
2931  char save;
2932 
2933  if ( marker_p == NULL ) {
2935  }
2936 
2937  if ( tokens ) {
2938  p = (char*)tokens->whiteSpaceStart_p;
2939  } else {
2940  p = (char*)scriptstack->script_p;
2941  }
2942 
2943  // Set the end character to NULL to give us a complete string
2944  save = *p;
2945  *p = 0;
2946 
2947  // If cleaning then reparse
2948  if ( clean ) {
2949  idParser temp( marker_p, strlen( marker_p ), "temp", flags );
2950  idToken token;
2951  while ( temp.ReadToken ( &token ) ) {
2952  out += token;
2953  }
2954  } else {
2955  out = marker_p;
2956  }
2957 
2958  // restore the character we set to NULL
2959  *p = save;
2960 }
2961 
2962 /*
2963 ================
2964 idParser::SetIncludePath
2965 ================
2966 */
2967 void idParser::SetIncludePath( const char *path ) {
2969  // add trailing path seperator
2970  if (idParser::includepath[idParser::includepath.Length()-1] != '\\' &&
2971  idParser::includepath[idParser::includepath.Length()-1] != '/') {
2972  idParser::includepath += PATHSEPERATOR_STR;
2973  }
2974 }
2975 
2976 /*
2977 ================
2978 idParser::SetPunctuations
2979 ================
2980 */
2983 }
2984 
2985 /*
2986 ================
2987 idParser::SetFlags
2988 ================
2989 */
2990 void idParser::SetFlags( int flags ) {
2991  idLexer *s;
2992 
2994  for ( s = idParser::scriptstack; s; s = s->next ) {
2995  s->SetFlags( flags );
2996  }
2997 }
2998 
2999 /*
3000 ================
3001 idParser::GetFlags
3002 ================
3003 */
3004 int idParser::GetFlags( void ) const {
3005  return idParser::flags;
3006 }
3007 
3008 /*
3009 ================
3010 idParser::LoadFile
3011 ================
3012 */
3013 int idParser::LoadFile( const char *filename, bool OSPath ) {
3014  idLexer *script;
3015 
3016  if ( idParser::loaded ) {
3017  idLib::common->FatalError("idParser::loadFile: another source already loaded");
3018  return false;
3019  }
3020  script = new idLexer( filename, 0, OSPath );
3021  if ( !script->IsLoaded() ) {
3022  delete script;
3023  return false;
3024  }
3025  script->SetFlags( idParser::flags );
3027  script->next = NULL;
3030  idParser::scriptstack = script;
3033  idParser::skip = 0;
3034  idParser::loaded = true;
3035 
3036  if ( !idParser::definehash ) {
3040  }
3041  return true;
3042 }
3043 
3044 /*
3045 ================
3046 idParser::LoadMemory
3047 ================
3048 */
3049 int idParser::LoadMemory(const char *ptr, int length, const char *name ) {
3050  idLexer *script;
3051 
3052  if ( idParser::loaded ) {
3053  idLib::common->FatalError("idParser::loadMemory: another source already loaded");
3054  return false;
3055  }
3056  script = new idLexer( ptr, length, name );
3057  if ( !script->IsLoaded() ) {
3058  delete script;
3059  return false;
3060  }
3061  script->SetFlags( idParser::flags );
3063  script->next = NULL;
3065  idParser::scriptstack = script;
3068  idParser::skip = 0;
3069  idParser::loaded = true;
3070 
3071  if ( !idParser::definehash ) {
3075  }
3076  return true;
3077 }
3078 
3079 /*
3080 ================
3081 idParser::FreeSource
3082 ================
3083 */
3084 void idParser::FreeSource( bool keepDefines ) {
3085  idLexer *script;
3086  idToken *token;
3087  define_t *define;
3088  indent_t *indent;
3089  int i;
3090 
3091  // free all the scripts
3092  while( scriptstack ) {
3093  script = scriptstack;
3095  delete script;
3096  }
3097  // free all the tokens
3098  while( tokens ) {
3099  token = tokens;
3100  tokens = tokens->next;
3101  delete token;
3102  }
3103  // free all indents
3104  while( indentstack ) {
3105  indent = indentstack;
3107  Mem_Free( indent );
3108  }
3109  if ( !keepDefines ) {
3110  // free hash table
3111  if ( definehash ) {
3112  // free defines
3113  for ( i = 0; i < DEFINEHASHSIZE; i++ ) {
3114  while( definehash[i] ) {
3115  define = definehash[i];
3117  FreeDefine(define);
3118  }
3119  }
3120  defines = NULL;
3122  definehash = NULL;
3123  }
3124  }
3125  loaded = false;
3126 }
3127 
3128 /*
3129 ================
3130 idParser::GetPunctuationFromId
3131 ================
3132 */
3133 const char *idParser::GetPunctuationFromId( int id ) {
3134  int i;
3135 
3136  if ( !idParser::punctuations ) {
3137  idLexer lex;
3138  return lex.GetPunctuationFromId( id );
3139  }
3140 
3141  for (i = 0; idParser::punctuations[i].p; i++) {
3142  if ( idParser::punctuations[i].n == id ) {
3143  return idParser::punctuations[i].p;
3144  }
3145  }
3146  return "unkown punctuation";
3147 }
3148 
3149 /*
3150 ================
3151 idParser::GetPunctuationId
3152 ================
3153 */
3154 int idParser::GetPunctuationId( const char *p ) {
3155  int i;
3156 
3157  if ( !idParser::punctuations ) {
3158  idLexer lex;
3159  return lex.GetPunctuationId( p );
3160  }
3161 
3162  for (i = 0; idParser::punctuations[i].p; i++) {
3163  if ( !strcmp(idParser::punctuations[i].p, p) ) {
3164  return idParser::punctuations[i].n;
3165  }
3166  }
3167  return 0;
3168 }
3169 
3170 /*
3171 ================
3172 idParser::idParser
3173 ================
3174 */
3176  this->loaded = false;
3177  this->OSPath = false;
3178  this->punctuations = 0;
3179  this->flags = 0;
3180  this->scriptstack = NULL;
3181  this->indentstack = NULL;
3182  this->definehash = NULL;
3183  this->defines = NULL;
3184  this->tokens = NULL;
3185  this->marker_p = NULL;
3186 }
3187 
3188 /*
3189 ================
3190 idParser::idParser
3191 ================
3192 */
3193 idParser::idParser( int flags ) {
3194  this->loaded = false;
3195  this->OSPath = false;
3196  this->punctuations = 0;
3197  this->flags = flags;
3198  this->scriptstack = NULL;
3199  this->indentstack = NULL;
3200  this->definehash = NULL;
3201  this->defines = NULL;
3202  this->tokens = NULL;
3203  this->marker_p = NULL;
3204 }
3205 
3206 /*
3207 ================
3208 idParser::idParser
3209 ================
3210 */
3211 idParser::idParser( const char *filename, int flags, bool OSPath ) {
3212  this->loaded = false;
3213  this->OSPath = true;
3214  this->punctuations = 0;
3215  this->flags = flags;
3216  this->scriptstack = NULL;
3217  this->indentstack = NULL;
3218  this->definehash = NULL;
3219  this->defines = NULL;
3220  this->tokens = NULL;
3221  this->marker_p = NULL;
3222  LoadFile( filename, OSPath );
3223 }
3224 
3225 /*
3226 ================
3227 idParser::idParser
3228 ================
3229 */
3230 idParser::idParser( const char *ptr, int length, const char *name, int flags ) {
3231  this->loaded = false;
3232  this->OSPath = false;
3233  this->punctuations = 0;
3234  this->flags = flags;
3235  this->scriptstack = NULL;
3236  this->indentstack = NULL;
3237  this->definehash = NULL;
3238  this->defines = NULL;
3239  this->tokens = NULL;
3240  this->marker_p = NULL;
3241  LoadMemory( ptr, length, name );
3242 }
3243 
3244 /*
3245 ================
3246 idParser::~idParser
3247 ================
3248 */
3250  idParser::FreeSource( false );
3251 }
3252 
int type
Definition: Parser.h:69
#define BUILTIN_FILE
Definition: Parser.h:43
#define P_COLON
Definition: Lexer.h:115
void Error(const char *str,...) const id_attribute((format(printf
Definition: Parser.cpp:318
#define P_LOGIC_NOT
Definition: Lexer.h:108
#define strcmp
Definition: Str.h:41
idToken * tokens
Definition: Parser.h:61
const char * whiteSpaceStart_p
Definition: Token.h:103
static define_t * DefineFromString(const char *string)
Definition: Parser.cpp:295
int loaded
Definition: Parser.h:182
int type
Definition: Token.h:77
GLsizei const GLfloat * value
Definition: glext.h:3614
ID_INLINE int PC_NameHash(const char *name)
Definition: Parser.cpp:151
int builtin
Definition: Parser.h:58
int AddDefine(const char *string)
Definition: Parser.cpp:1177
void void static int AddGlobalDefine(const char *string)
Definition: Parser.cpp:54
void UnreadToken(idToken *token)
Definition: Parser.cpp:2745
double floatvalue
Definition: Token.h:102
int GetPunctuationId(const char *p)
Definition: Lexer.cpp:199
int ExpandDefineIntoSource(idToken *deftoken, define_t *define)
Definition: Parser.cpp:890
#define DEFINEHASHSIZE
Definition: Parser.cpp:34
const char * GetFileName(void)
Definition: Lexer.h:282
int MergeTokens(idToken *t1, idToken *t2)
Definition: Parser.cpp:596
#define P_LOGIC_LEQ
Definition: Lexer.h:75
int Parse3DMatrix(int z, int y, int x, float *m)
Definition: Parser.cpp:2880
int DollarDirective_evalfloat(void)
Definition: Parser.cpp:2274
define_t * defines
Definition: Parser.h:190
char * name
Definition: Parser.h:56
#define DEFINE_FIXED
Definition: Parser.h:40
const GLdouble * v
Definition: glext.h:2936
int priority
Definition: Parser.cpp:1290
#define BUILTIN_STDC
Definition: Parser.h:46
int SkipUntilString(const char *string)
Definition: Parser.cpp:2575
#define TT_LONG
Definition: Token.h:53
struct value_s * next
Definition: Parser.cpp:1300
#define TT_NAME
Definition: Token.h:44
int EvaluateTokens(idToken *tokens, signed long int *intvalue, double *floatvalue, int integer)
Definition: Parser.cpp:1368
double floatvalue
Definition: Parser.cpp:1298
int Length(void) const
Definition: Str.h:702
int UnreadSourceToken(idToken *token)
Definition: Parser.cpp:468
~idParser()
Definition: Parser.cpp:3249
#define INDENT_ELSE
Definition: Parser.h:49
const char * script_p
Definition: Lexer.h:249
#define P_BIN_XOR
Definition: Lexer.h:105
#define TT_INTEGER
Definition: Token.h:48
GLenum GLint GLint y
Definition: glext.h:2849
GLenum GLsizei n
Definition: glext.h:3705
void StripTrailing(const char c)
Definition: Str.cpp:515
int Directive_eval(void)
Definition: Parser.cpp:2103
case const int
Definition: Callbacks.cpp:52
#define P_DEC
Definition: Lexer.h:85
#define P_QUESTIONMARK
Definition: Lexer.h:116
int ReadDefineParms(define_t *define, idToken **parms, int maxparms)
Definition: Parser.cpp:482
int subtype
Definition: Token.h:78
#define P_LOGIC_OR
Definition: Lexer.h:73
#define MAX_DEFINEPARMS
Definition: Parser.cpp:33
int ReadDirective(void)
Definition: Parser.cpp:2163
define_t * CopyFirstDefine(void)
Definition: Parser.cpp:658
int Directive_if(void)
Definition: Parser.cpp:2007
int linesCrossed
Definition: Token.h:80
int ExpandDefine(idToken *deftoken, define_t *define, idToken **firsttoken, idToken **lasttoken)
Definition: Parser.cpp:763
#define P_BIN_AND
Definition: Lexer.h:103
float GetFloatValue(void)
Definition: Token.h:138
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glext.h:2878
GLenum GLsizei const GLvoid * string
Definition: glext.h:3472
#define P_LOGIC_UNEQ
Definition: Lexer.h:77
int FindDefineParm(define_t *define, const char *name)
Definition: Parser.cpp:214
int skip
Definition: Parser.h:70
int LoadMemory(const char *ptr, int length, const char *name)
Definition: Parser.cpp:3049
int DollarEvaluate(signed long int *intvalue, double *floatvalue, int integer)
Definition: Parser.cpp:1884
void FreeSource(bool keepDefines=false)
Definition: Parser.cpp:3084
#define P_LOGIC_AND
Definition: Lexer.h:72
#define P_LSHIFT
Definition: Lexer.h:91
idToken * tokens
Definition: Parser.h:189
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
int ExpectTokenString(const char *string)
Definition: Parser.cpp:2402
void SetIncludePath(const char *path)
Definition: Parser.cpp:2967
Definition: Token.h:71
void SetFlags(int flags)
Definition: Lexer.h:298
#define TT_STRING
Definition: Token.h:41
int flags
Definition: Parser.h:187
#define P_LOGIC_GEQ
Definition: Lexer.h:74
GLdouble s
Definition: glext.h:2935
GLuint src
Definition: glext.h:5390
#define AllocOperator(op)
Definition: Parser.cpp:1356
void ClearTokenWhiteSpace(void)
Definition: Token.cpp:175
const char * ParseBracedSection(idStr &out, int tabs=-1)
Definition: Parser.cpp:2655
idToken * parms
Definition: Parser.h:60
#define P_MOD
Definition: Lexer.h:98
GLenum GLint x
Definition: glext.h:2849
int i
Definition: process.py:33
#define TT_DECIMAL
Definition: Token.h:49
#define BUILTIN_LINE
Definition: Parser.h:42
int Icmp(const char *text) const
Definition: Str.h:667
#define P_PARENTHESESCLOSE
Definition: Lexer.h:119
define_t * FindHashedDefine(define_t **definehash, const char *name)
Definition: Parser.cpp:180
int Directive_include(void)
Definition: Parser.cpp:936
#define TT_NUMBER
Definition: Token.h:43
struct operator_s operator_t
idLexer * scriptstack
Definition: Parser.h:188
#define TT_BINARY
Definition: Token.h:52
#define P_SUB
Definition: Lexer.h:100
#define P_BIN_NOT
Definition: Lexer.h:106
int ReadToken(idToken *token)
Definition: Parser.cpp:2338
const int GetLineNum(void)
Definition: Lexer.h:294
#define TT_UNSIGNED
Definition: Token.h:54
int Directive_elif(void)
Definition: Parser.cpp:1985
GLfloat GLfloat GLfloat v2
Definition: glext.h:3608
Definition: Lexer.h:137
bool ParseBool(void)
Definition: Parser.cpp:2797
void Error(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:215
int line
Definition: Token.h:79
int GetFlags(void) const
Definition: Parser.cpp:3004
void GetStringFromMarker(idStr &out, bool clean=false)
Definition: Parser.cpp:2929
int Directive_warning(void)
Definition: Parser.cpp:2054
#define AllocValue(val)
Definition: Parser.cpp:1344
int Directive_pragma(void)
Definition: Parser.cpp:2070
int ParseInt(void)
Definition: Parser.cpp:2775
int Directive_line(void)
Definition: Parser.cpp:2024
int PeekTokenString(const char *string)
Definition: Parser.cpp:2532
#define MAX_STRING_CHARS
Definition: Lib.h:95
#define P_INC
Definition: Lexer.h:84
#define P_DIV
Definition: Lexer.h:97
void Empty(void)
Definition: Str.h:714
int Directive_error(void)
Definition: Parser.cpp:2038
int Parse1DMatrix(int x, float *m)
Definition: Parser.cpp:2834
#define TT_HEX
Definition: Token.h:50
idParser()
Definition: Parser.cpp:3175
int Directive_ifndef(void)
Definition: Parser.cpp:1241
define_t * CopyDefine(define_t *define)
Definition: Parser.cpp:233
static float Fabs(float f)
Definition: Math.h:779
void SetPunctuations(const punctuation_t *p)
Definition: Lexer.cpp:260
#define NULL
Definition: Lib.h:88
static int RemoveGlobalDefine(const char *name)
Definition: Parser.cpp:71
#define P_LOGIC_GREATER
Definition: Lexer.h:109
signed long int intvalue
Definition: Parser.cpp:1297
int Directive_else(void)
Definition: Parser.cpp:1250
virtual void virtual void FatalError(const char *fmt,...) id_attribute((format(printf
struct operator_s * prev
Definition: Parser.cpp:1292
void AddGlobalDefinesToSource(void)
Definition: Parser.cpp:1193
indent_t * indentstack
Definition: Parser.h:192
const char * whiteSpaceEnd_p
Definition: Token.h:104
static void PrintDefine(define_t *define)
Definition: Parser.cpp:120
#define P_LOGIC_LESS
Definition: Lexer.h:110
void PopIndent(int *type, int *skip)
Definition: Parser.cpp:369
int GetPunctuationId(const char *p)
Definition: Parser.cpp:3154
void void Warning(const char *str,...) const id_attribute((format(printf
Definition: Parser.cpp:335
const char * path
Definition: sws.c:117
int GetFlags(void)
Definition: Lexer.h:302
int SkipRestOfLine(void)
Definition: Parser.cpp:2591
float ParseFloat(void)
Definition: Parser.cpp:2812
#define INDENT_IFNDEF
Definition: Parser.h:52
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
void SetFlags(int flags)
Definition: Parser.cpp:2990
const char * GetPunctuationFromId(int id)
Definition: Parser.cpp:3133
void Clear(void)
Definition: Str.h:724
static void FreeDefine(define_t *define)
Definition: Parser.cpp:273
const punctuation_t * punctuations
Definition: Parser.h:186
int Evaluate(signed long int *intvalue, double *floatvalue, int integer)
Definition: Parser.cpp:1793
int Directive_undef(void)
Definition: Parser.cpp:1016
define_t ** definehash
Definition: Parser.h:191
virtual void Printf(const char *fmt,...) id_attribute((format(printf
#define MAX_VALUES
Definition: Parser.cpp:1341
struct operator_s * next
Definition: Parser.cpp:1292
int ExpectAnyToken(idToken *token)
Definition: Parser.cpp:2476
idLexer * script
Definition: Parser.h:71
const char * GetPunctuationFromId(int id)
Definition: Lexer.cpp:183
idLexer * next
Definition: Lexer.h:264
const char * ParseBracedSectionExact(idStr &out, int tabs=-1)
Definition: Parser.cpp:2642
struct indent_s * next
Definition: Parser.h:72
idStr filename
Definition: Parser.h:183
GLfloat GLfloat v1
Definition: glext.h:3607
#define BUILTIN_DATE
Definition: Parser.h:44
#define TT_LITERAL
Definition: Token.h:42
void AddDefineToHash(define_t *define, define_t **definehash)
Definition: Parser.cpp:167
void SetPunctuations(const punctuation_t *p)
Definition: Parser.cpp:2981
int WhiteSpaceBeforeToken(void) const
Definition: Token.h:156
int parentheses
Definition: Parser.cpp:1291
int ReadDollarDirective(void)
Definition: Parser.cpp:2306
#define MAX_OPERATORS
Definition: Parser.cpp:1342
#define TT_VALUESVALID
Definition: Token.h:64
int Directive_if_def(int type)
Definition: Parser.cpp:1207
int ReadSourceToken(idToken *token)
Definition: Parser.cpp:414
bool OSPath
Definition: Parser.h:185
int ExpandBuiltinDefine(idToken *deftoken, define_t *define, idToken **firsttoken, idToken **lasttoken)
Definition: Parser.cpp:674
int DollarDirective_evalint(void)
Definition: Parser.cpp:2242
static define_t * FindDefine(define_t *defines, const char *name)
Definition: Parser.cpp:198
#define P_ADD
Definition: Lexer.h:99
struct define_s * hashnext
Definition: Parser.h:63
void void Warning(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:241
int Directive_define(void)
Definition: Parser.cpp:1060
static void SetBaseFolder(const char *path)
Definition: Lexer.cpp:1785
void UnreadSignToken(void)
Definition: Parser.cpp:2084
int numparms
Definition: Parser.h:59
GLuint id
Definition: glext.h:3103
#define P_MUL
Definition: Lexer.h:96
#define TT_PUNCTUATION
Definition: Token.h:45
idStr includepath
Definition: Parser.h:184
void PushIndent(int type, int skip)
Definition: Parser.cpp:352
void Append(const char a)
Definition: Str.h:729
static void SetBaseFolder(const char *path)
Definition: Parser.cpp:45
int LoadFile(const char *filename, bool OSPath=false)
Definition: Parser.cpp:3013
#define FreeValue(val)
Definition: Parser.cpp:1354
int GetLastWhiteSpace(idStr &whiteSpace) const
Definition: Lexer.cpp:1519
const char * ParseRestOfLine(idStr &out)
Definition: Parser.cpp:2723
#define INDENT_IF
Definition: Parser.h:48
const GLcharARB * name
Definition: glext.h:3629
void PushScript(idLexer *script)
Definition: Parser.cpp:395
int PeekTokenType(int type, int subtype, idToken *token)
Definition: Parser.cpp:2553
int CheckTokenString(const char *string)
Definition: Parser.cpp:2491
#define BUILTIN_TIME
Definition: Parser.h:45
Definition: Str.h:116
int flags
Definition: Token.h:81
GLsizei const GLcharARB const GLint * length
Definition: glext.h:3599
idToken * next
Definition: Token.h:105
void SetMarker(void)
Definition: Parser.cpp:2918
#define INDENT_IFDEF
Definition: Parser.h:51
int SkipBracedSection(bool parseFirstBrace=true)
Definition: Parser.cpp:2611
static define_t * globaldefines
Definition: Parser.h:196
int Directive_ifdef(void)
Definition: Parser.cpp:1232
int vsprintf(idStr &string, const char *fmt, va_list argptr)
Definition: Str.cpp:1549
void * Mem_ClearedAlloc(const int size)
Definition: Heap.cpp:1149
int ReadTokenOnLine(idToken *token)
Definition: Parser.cpp:2754
int GetIntValue(void)
Definition: Token.h:152
const char * c_str(void) const
Definition: Str.h:487
struct value_s value_t
static void RemoveAllGlobalDefines(void)
Definition: Parser.cpp:97
const char * marker_p
Definition: Parser.h:194
#define TT_OCTAL
Definition: Token.h:51
struct value_s * prev
Definition: Parser.cpp:1300
#define P_BIN_OR
Definition: Lexer.h:104
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
int skip
Definition: Parser.h:193
const char * buffer
Definition: Lexer.h:248
GLint * first
Definition: glext.h:3036
int IsLoaded(void)
Definition: Lexer.h:158
#define TT_FLOAT
Definition: Token.h:55
unsigned long intvalue
Definition: Token.h:101
struct define_s * next
Definition: Parser.h:62
#define P_PARENTHESESOPEN
Definition: Lexer.h:118
int parentheses
Definition: Parser.cpp:1299
void AddBuiltinDefines(void)
Definition: Parser.cpp:623
GLfloat GLfloat p
Definition: glext.h:4674
GLdouble GLdouble z
Definition: glext.h:3067
#define P_RSHIFT
Definition: Lexer.h:90
const char * ParseBracedSectionExact(idStr &out, int tabs=-1)
Definition: Lexer.cpp:1376
int flags
Definition: Parser.h:57
const char * p
Definition: Lexer.h:132
int sprintf(idStr &string, const char *fmt,...)
Definition: Str.cpp:1528
int StringizeTokens(idToken *tokens, idToken *token)
Definition: Parser.cpp:578
int Parse2DMatrix(int y, int x, float *m)
Definition: Parser.cpp:2856
#define INDENT_ELIF
Definition: Parser.h:50
idStr & StripFilename(void)
Definition: Str.cpp:864
int PC_OperatorPriority(int op)
Definition: Parser.cpp:1303
#define FreeOperator(op)
Definition: Parser.cpp:1366
int ReadLine(idToken *token)
Definition: Parser.cpp:913
#define TOKEN_FL_RECURSIVE_DEFINE
Definition: Parser.cpp:36
#define P_LOGIC_EQ
Definition: Lexer.h:76
int CheckTokenType(int type, int subtype, idToken *token)
Definition: Parser.cpp:2511
int LoadFile(const char *filename, bool OSPath=false)
Definition: Lexer.cpp:1591
static class idCommon * common
Definition: Lib.h:53
int ExpectTokenType(int type, int subtype, idToken *token)
Definition: Parser.cpp:2422
int Directive_endif(void)
Definition: Parser.cpp:1271
GLdouble GLdouble t
Definition: glext.h:2943
int Directive_evalfloat(void)
Definition: Parser.cpp:2133
int GetLastWhiteSpace(idStr &whiteSpace) const
Definition: Parser.cpp:2904