doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Lexer.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 PUNCTABLE
33 
34 //longer punctuations first
36  //binary operators
37  {">>=",P_RSHIFT_ASSIGN},
38  {"<<=",P_LSHIFT_ASSIGN},
39  //
40  {"...",P_PARMS},
41  //define merge operator
42  {"##",P_PRECOMPMERGE}, // pre-compiler
43  //logic operators
44  {"&&",P_LOGIC_AND}, // pre-compiler
45  {"||",P_LOGIC_OR}, // pre-compiler
46  {">=",P_LOGIC_GEQ}, // pre-compiler
47  {"<=",P_LOGIC_LEQ}, // pre-compiler
48  {"==",P_LOGIC_EQ}, // pre-compiler
49  {"!=",P_LOGIC_UNEQ}, // pre-compiler
50  //arithmatic operators
51  {"*=",P_MUL_ASSIGN},
52  {"/=",P_DIV_ASSIGN},
53  {"%=",P_MOD_ASSIGN},
54  {"+=",P_ADD_ASSIGN},
55  {"-=",P_SUB_ASSIGN},
56  {"++",P_INC},
57  {"--",P_DEC},
58  //binary operators
59  {"&=",P_BIN_AND_ASSIGN},
60  {"|=",P_BIN_OR_ASSIGN},
61  {"^=",P_BIN_XOR_ASSIGN},
62  {">>",P_RSHIFT}, // pre-compiler
63  {"<<",P_LSHIFT}, // pre-compiler
64  //reference operators
65  {"->",P_POINTERREF},
66  //C++
67  {"::",P_CPP1},
68  {".*",P_CPP2},
69  //arithmatic operators
70  {"*",P_MUL}, // pre-compiler
71  {"/",P_DIV}, // pre-compiler
72  {"%",P_MOD}, // pre-compiler
73  {"+",P_ADD}, // pre-compiler
74  {"-",P_SUB}, // pre-compiler
75  {"=",P_ASSIGN},
76  //binary operators
77  {"&",P_BIN_AND}, // pre-compiler
78  {"|",P_BIN_OR}, // pre-compiler
79  {"^",P_BIN_XOR}, // pre-compiler
80  {"~",P_BIN_NOT}, // pre-compiler
81  //logic operators
82  {"!",P_LOGIC_NOT}, // pre-compiler
83  {">",P_LOGIC_GREATER}, // pre-compiler
84  {"<",P_LOGIC_LESS}, // pre-compiler
85  //reference operator
86  {".",P_REF},
87  //seperators
88  {",",P_COMMA}, // pre-compiler
89  {";",P_SEMICOLON},
90  //label indication
91  {":",P_COLON}, // pre-compiler
92  //if statement
93  {"?",P_QUESTIONMARK}, // pre-compiler
94  //embracements
95  {"(",P_PARENTHESESOPEN}, // pre-compiler
96  {")",P_PARENTHESESCLOSE}, // pre-compiler
97  {"{",P_BRACEOPEN}, // pre-compiler
98  {"}",P_BRACECLOSE}, // pre-compiler
99  {"[",P_SQBRACKETOPEN},
100  {"]",P_SQBRACKETCLOSE},
101  //
102  {"\\",P_BACKSLASH},
103  //precompiler operator
104  {"#",P_PRECOMP}, // pre-compiler
105  {"$",P_DOLLAR},
106  {NULL, 0}
107 };
108 
112 
113 char idLexer::baseFolder[ 256 ];
114 
115 /*
116 ================
117 idLexer::CreatePunctuationTable
118 ================
119 */
120 void idLexer::CreatePunctuationTable( const punctuation_t *punctuations ) {
121  int i, n, lastp;
122  const punctuation_t *p, *newp;
123 
124  //get memory for the table
125  if ( punctuations == default_punctuations ) {
128  if ( default_setup ) {
129  return;
130  }
131  default_setup = true;
132  i = sizeof(default_punctuations) / sizeof(punctuation_t);
133  }
134  else {
136  idLexer::punctuationtable = (int *) Mem_Alloc(256 * sizeof(int));
137  }
140  }
141  for (i = 0; punctuations[i].p; i++) {
142  }
143  idLexer::nextpunctuation = (int *) Mem_Alloc(i * sizeof(int));
144  }
145  memset(idLexer::punctuationtable, 0xFF, 256 * sizeof(int));
146  memset(idLexer::nextpunctuation, 0xFF, i * sizeof(int));
147  //add the punctuations in the list to the punctuation table
148  for (i = 0; punctuations[i].p; i++) {
149  newp = &punctuations[i];
150  lastp = -1;
151  //sort the punctuations in this table entry on length (longer punctuations first)
152  for (n = idLexer::punctuationtable[(unsigned int) newp->p[0]]; n >= 0; n = idLexer::nextpunctuation[n] ) {
153  p = &punctuations[n];
154  if (strlen(p->p) < strlen(newp->p)) {
156  if (lastp >= 0) {
157  idLexer::nextpunctuation[lastp] = i;
158  }
159  else {
160  idLexer::punctuationtable[(unsigned int) newp->p[0]] = i;
161  }
162  break;
163  }
164  lastp = n;
165  }
166  if (n < 0) {
168  if (lastp >= 0) {
169  idLexer::nextpunctuation[lastp] = i;
170  }
171  else {
172  idLexer::punctuationtable[(unsigned int) newp->p[0]] = i;
173  }
174  }
175  }
176 }
177 
178 /*
179 ================
180 idLexer::GetPunctuationFromId
181 ================
182 */
183 const char *idLexer::GetPunctuationFromId( int id ) {
184  int i;
185 
186  for (i = 0; idLexer::punctuations[i].p; i++) {
187  if ( idLexer::punctuations[i].n == id ) {
188  return idLexer::punctuations[i].p;
189  }
190  }
191  return "unkown punctuation";
192 }
193 
194 /*
195 ================
196 idLexer::GetPunctuationId
197 ================
198 */
199 int idLexer::GetPunctuationId( const char *p ) {
200  int i;
201 
202  for (i = 0; idLexer::punctuations[i].p; i++) {
203  if ( !strcmp(idLexer::punctuations[i].p, p) ) {
204  return idLexer::punctuations[i].n;
205  }
206  }
207  return 0;
208 }
209 
210 /*
211 ================
212 idLexer::Error
213 ================
214 */
215 void idLexer::Error( const char *str, ... ) {
216  char text[MAX_STRING_CHARS];
217  va_list ap;
218 
219  hadError = true;
220 
221  if ( idLexer::flags & LEXFL_NOERRORS ) {
222  return;
223  }
224 
225  va_start(ap, str);
226  vsprintf(text, str, ap);
227  va_end(ap);
228 
230  idLib::common->Warning( "file %s, line %d: %s", idLexer::filename.c_str(), idLexer::line, text );
231  } else {
232  idLib::common->Error( "file %s, line %d: %s", idLexer::filename.c_str(), idLexer::line, text );
233  }
234 }
235 
236 /*
237 ================
238 idLexer::Warning
239 ================
240 */
241 void idLexer::Warning( const char *str, ... ) {
242  char text[MAX_STRING_CHARS];
243  va_list ap;
244 
246  return;
247  }
248 
249  va_start( ap, str );
250  vsprintf( text, str, ap );
251  va_end( ap );
252  idLib::common->Warning( "file %s, line %d: %s", idLexer::filename.c_str(), idLexer::line, text );
253 }
254 
255 /*
256 ================
257 idLexer::SetPunctuations
258 ================
259 */
261 #ifdef PUNCTABLE
262  if (p) {
264  }
265  else {
266  idLexer::CreatePunctuationTable( default_punctuations );
267  }
268 #endif //PUNCTABLE
269  if (p) {
271  }
272  else {
274  }
275 }
276 
277 /*
278 ================
279 idLexer::ReadWhiteSpace
280 
281 Reads spaces, tabs, C-like comments etc.
282 When a newline character is found the scripts line counter is increased.
283 ================
284 */
286  while(1) {
287  // skip white space
288  while(*idLexer::script_p <= ' ') {
289  if (!*idLexer::script_p) {
290  return 0;
291  }
292  if (*idLexer::script_p == '\n') {
293  idLexer::line++;
294  }
296  }
297  // skip comments
298  if (*idLexer::script_p == '/') {
299  // comments //
300  if (*(idLexer::script_p+1) == '/') {
302  do {
304  if ( !*idLexer::script_p ) {
305  return 0;
306  }
307  }
308  while( *idLexer::script_p != '\n' );
309  idLexer::line++;
311  if ( !*idLexer::script_p ) {
312  return 0;
313  }
314  continue;
315  }
316  // comments /* */
317  else if (*(idLexer::script_p+1) == '*') {
319  while( 1 ) {
321  if ( !*idLexer::script_p ) {
322  return 0;
323  }
324  if ( *idLexer::script_p == '\n' ) {
325  idLexer::line++;
326  }
327  else if ( *idLexer::script_p == '/' ) {
328  if ( *(idLexer::script_p-1) == '*' ) {
329  break;
330  }
331  if ( *(idLexer::script_p+1) == '*' ) {
332  idLexer::Warning( "nested comment" );
333  }
334  }
335  }
337  if ( !*idLexer::script_p ) {
338  return 0;
339  }
341  if ( !*idLexer::script_p ) {
342  return 0;
343  }
344  continue;
345  }
346  }
347  break;
348  }
349  return 1;
350 }
351 
352 /*
353 ================
354 idLexer::ReadEscapeCharacter
355 ================
356 */
358  int c, val, i;
359 
360  // step over the leading '\\'
362  // determine the escape character
363  switch(*idLexer::script_p) {
364  case '\\': c = '\\'; break;
365  case 'n': c = '\n'; break;
366  case 'r': c = '\r'; break;
367  case 't': c = '\t'; break;
368  case 'v': c = '\v'; break;
369  case 'b': c = '\b'; break;
370  case 'f': c = '\f'; break;
371  case 'a': c = '\a'; break;
372  case '\'': c = '\''; break;
373  case '\"': c = '\"'; break;
374  case '\?': c = '\?'; break;
375  case 'x':
376  {
378  for (i = 0, val = 0; ; i++, idLexer::script_p++) {
379  c = *idLexer::script_p;
380  if (c >= '0' && c <= '9')
381  c = c - '0';
382  else if (c >= 'A' && c <= 'Z')
383  c = c - 'A' + 10;
384  else if (c >= 'a' && c <= 'z')
385  c = c - 'a' + 10;
386  else
387  break;
388  val = (val << 4) + c;
389  }
391  if (val > 0xFF) {
392  idLexer::Warning( "too large value in escape character" );
393  val = 0xFF;
394  }
395  c = val;
396  break;
397  }
398  default: //NOTE: decimal ASCII code, NOT octal
399  {
400  if (*idLexer::script_p < '0' || *idLexer::script_p > '9') {
401  idLexer::Error("unknown escape char");
402  }
403  for (i = 0, val = 0; ; i++, idLexer::script_p++) {
404  c = *idLexer::script_p;
405  if (c >= '0' && c <= '9')
406  c = c - '0';
407  else
408  break;
409  val = val * 10 + c;
410  }
412  if (val > 0xFF) {
413  idLexer::Warning( "too large value in escape character" );
414  val = 0xFF;
415  }
416  c = val;
417  break;
418  }
419  }
420  // step over the escape character or the last digit of the number
422  // store the escape character
423  *ch = c;
424  // succesfully read escape character
425  return 1;
426 }
427 
428 /*
429 ================
430 idLexer::ReadString
431 
432 Escape characters are interpretted.
433 Reads two strings with only a white space between them as one string.
434 ================
435 */
436 int idLexer::ReadString( idToken *token, int quote ) {
437  int tmpline;
438  const char *tmpscript_p;
439  char ch;
440 
441  if ( quote == '\"' ) {
442  token->type = TT_STRING;
443  } else {
444  token->type = TT_LITERAL;
445  }
446 
447  // leading quote
449 
450  while(1) {
451  // if there is an escape character and escape characters are allowed
453  if ( !idLexer::ReadEscapeCharacter( &ch ) ) {
454  return 0;
455  }
456  token->AppendDirty( ch );
457  }
458  // if a trailing quote
459  else if (*idLexer::script_p == quote) {
460  // step over the quote
462  // if consecutive strings should not be concatenated
464  (!(idLexer::flags & LEXFL_ALLOWBACKSLASHSTRINGCONCAT) || (quote != '\"')) ) {
465  break;
466  }
467 
468  tmpscript_p = idLexer::script_p;
469  tmpline = idLexer::line;
470  // read white space between possible two consecutive strings
471  if ( !idLexer::ReadWhiteSpace() ) {
472  idLexer::script_p = tmpscript_p;
473  idLexer::line = tmpline;
474  break;
475  }
476 
477  if ( idLexer::flags & LEXFL_NOSTRINGCONCAT ) {
478  if ( *idLexer::script_p != '\\' ) {
479  idLexer::script_p = tmpscript_p;
480  idLexer::line = tmpline;
481  break;
482  }
483  // step over the '\\'
485  if ( !idLexer::ReadWhiteSpace() || ( *idLexer::script_p != quote ) ) {
486  idLexer::Error( "expecting string after '\' terminated line" );
487  return 0;
488  }
489  }
490 
491  // if there's no leading qoute
492  if ( *idLexer::script_p != quote ) {
493  idLexer::script_p = tmpscript_p;
494  idLexer::line = tmpline;
495  break;
496  }
497  // step over the new leading quote
499  }
500  else {
501  if (*idLexer::script_p == '\0') {
502  idLexer::Error( "missing trailing quote" );
503  return 0;
504  }
505  if (*idLexer::script_p == '\n') {
506  idLexer::Error( "newline inside string" );
507  return 0;
508  }
509  token->AppendDirty( *idLexer::script_p++ );
510  }
511  }
512  token->data[token->len] = '\0';
513 
514  if ( token->type == TT_LITERAL ) {
516  if ( token->Length() != 1 ) {
517  idLexer::Warning( "literal is not one character long" );
518  }
519  }
520  token->subtype = (*token)[0];
521  }
522  else {
523  // the sub type is the length of the string
524  token->subtype = token->Length();
525  }
526  return 1;
527 }
528 
529 /*
530 ================
531 idLexer::ReadName
532 ================
533 */
534 int idLexer::ReadName( idToken *token ) {
535  char c;
536 
537  token->type = TT_NAME;
538  do {
539  token->AppendDirty( *idLexer::script_p++ );
540  c = *idLexer::script_p;
541  } while ((c >= 'a' && c <= 'z') ||
542  (c >= 'A' && c <= 'Z') ||
543  (c >= '0' && c <= '9') ||
544  c == '_' ||
545  // if treating all tokens as strings, don't parse '-' as a seperate token
546  ((idLexer::flags & LEXFL_ONLYSTRINGS) && (c == '-')) ||
547  // if special path name characters are allowed
548  ((idLexer::flags & LEXFL_ALLOWPATHNAMES) && (c == '/' || c == '\\' || c == ':' || c == '.')) );
549  token->data[token->len] = '\0';
550  //the sub type is the length of the name
551  token->subtype = token->Length();
552  return 1;
553 }
554 
555 /*
556 ================
557 idLexer::CheckString
558 ================
559 */
560 ID_INLINE int idLexer::CheckString( const char *str ) const {
561  int i;
562 
563  for ( i = 0; str[i]; i++ ) {
564  if ( idLexer::script_p[i] != str[i] ) {
565  return false;
566  }
567  }
568  return true;
569 }
570 
571 /*
572 ================
573 idLexer::ReadNumber
574 ================
575 */
577  int i;
578  int dot;
579  char c, c2;
580 
581  token->type = TT_NUMBER;
582  token->subtype = 0;
583  token->intvalue = 0;
584  token->floatvalue = 0;
585 
586  c = *idLexer::script_p;
587  c2 = *(idLexer::script_p + 1);
588 
589  if ( c == '0' && c2 != '.' ) {
590  // check for a hexadecimal number
591  if ( c2 == 'x' || c2 == 'X' ) {
592  token->AppendDirty( *idLexer::script_p++ );
593  token->AppendDirty( *idLexer::script_p++ );
594  c = *idLexer::script_p;
595  while((c >= '0' && c <= '9') ||
596  (c >= 'a' && c <= 'f') ||
597  (c >= 'A' && c <= 'F')) {
598  token->AppendDirty( c );
599  c = *(++idLexer::script_p);
600  }
601  token->subtype = TT_HEX | TT_INTEGER;
602  }
603  // check for a binary number
604  else if ( c2 == 'b' || c2 == 'B' ) {
605  token->AppendDirty( *idLexer::script_p++ );
606  token->AppendDirty( *idLexer::script_p++ );
607  c = *idLexer::script_p;
608  while( c == '0' || c == '1' ) {
609  token->AppendDirty( c );
610  c = *(++idLexer::script_p);
611  }
612  token->subtype = TT_BINARY | TT_INTEGER;
613  }
614  // its an octal number
615  else {
616  token->AppendDirty( *idLexer::script_p++ );
617  c = *idLexer::script_p;
618  while( c >= '0' && c <= '7' ) {
619  token->AppendDirty( c );
620  c = *(++idLexer::script_p);
621  }
622  token->subtype = TT_OCTAL | TT_INTEGER;
623  }
624  }
625  else {
626  // decimal integer or floating point number or ip address
627  dot = 0;
628  while( 1 ) {
629  if ( c >= '0' && c <= '9' ) {
630  }
631  else if ( c == '.' ) {
632  dot++;
633  }
634  else {
635  break;
636  }
637  token->AppendDirty( c );
638  c = *(++idLexer::script_p);
639  }
640  if( c == 'e' && dot == 0) {
641  //We have scientific notation without a decimal point
642  dot++;
643  }
644  // if a floating point number
645  if ( dot == 1 ) {
646  token->subtype = TT_DECIMAL | TT_FLOAT;
647  // check for floating point exponent
648  if ( c == 'e' ) {
649  //Append the e so that GetFloatValue code works
650  token->AppendDirty( c );
651  c = *(++idLexer::script_p);
652  if ( c == '-' ) {
653  token->AppendDirty( c );
654  c = *(++idLexer::script_p);
655  }
656  else if ( c == '+' ) {
657  token->AppendDirty( c );
658  c = *(++idLexer::script_p);
659  }
660  while( c >= '0' && c <= '9' ) {
661  token->AppendDirty( c );
662  c = *(++idLexer::script_p);
663  }
664  }
665  // check for floating point exception infinite 1.#INF or indefinite 1.#IND or NaN
666  else if ( c == '#' ) {
667  c2 = 4;
668  if ( CheckString( "INF" ) ) {
669  token->subtype |= TT_INFINITE;
670  }
671  else if ( CheckString( "IND" ) ) {
672  token->subtype |= TT_INDEFINITE;
673  }
674  else if ( CheckString( "NAN" ) ) {
675  token->subtype |= TT_NAN;
676  }
677  else if ( CheckString( "QNAN" ) ) {
678  token->subtype |= TT_NAN;
679  c2++;
680  }
681  else if ( CheckString( "SNAN" ) ) {
682  token->subtype |= TT_NAN;
683  c2++;
684  }
685  for ( i = 0; i < c2; i++ ) {
686  token->AppendDirty( c );
687  c = *(++idLexer::script_p);
688  }
689  while( c >= '0' && c <= '9' ) {
690  token->AppendDirty( c );
691  c = *(++idLexer::script_p);
692  }
694  token->AppendDirty( 0 ); // zero terminate for c_str
695  idLexer::Error( "parsed %s", token->c_str() );
696  }
697  }
698  }
699  else if ( dot > 1 ) {
700  if ( !( idLexer::flags & LEXFL_ALLOWIPADDRESSES ) ) {
701  idLexer::Error( "more than one dot in number" );
702  return 0;
703  }
704  if ( dot != 3 ) {
705  idLexer::Error( "ip address should have three dots" );
706  return 0;
707  }
708  token->subtype = TT_IPADDRESS;
709  }
710  else {
711  token->subtype = TT_DECIMAL | TT_INTEGER;
712  }
713  }
714 
715  if ( token->subtype & TT_FLOAT ) {
716  if ( c > ' ' ) {
717  // single-precision: float
718  if ( c == 'f' || c == 'F' ) {
719  token->subtype |= TT_SINGLE_PRECISION;
721  }
722  // extended-precision: long double
723  else if ( c == 'l' || c == 'L' ) {
724  token->subtype |= TT_EXTENDED_PRECISION;
726  }
727  // default is double-precision: double
728  else {
729  token->subtype |= TT_DOUBLE_PRECISION;
730  }
731  }
732  else {
733  token->subtype |= TT_DOUBLE_PRECISION;
734  }
735  }
736  else if ( token->subtype & TT_INTEGER ) {
737  if ( c > ' ' ) {
738  // default: signed long
739  for ( i = 0; i < 2; i++ ) {
740  // long integer
741  if ( c == 'l' || c == 'L' ) {
742  token->subtype |= TT_LONG;
743  }
744  // unsigned integer
745  else if ( c == 'u' || c == 'U' ) {
746  token->subtype |= TT_UNSIGNED;
747  }
748  else {
749  break;
750  }
751  c = *(++idLexer::script_p);
752  }
753  }
754  }
755  else if ( token->subtype & TT_IPADDRESS ) {
756  if ( c == ':' ) {
757  token->AppendDirty( c );
758  c = *(++idLexer::script_p);
759  while( c >= '0' && c <= '9' ) {
760  token->AppendDirty( c );
761  c = *(++idLexer::script_p);
762  }
763  token->subtype |= TT_IPPORT;
764  }
765  }
766  token->data[token->len] = '\0';
767  return 1;
768 }
769 
770 /*
771 ================
772 idLexer::ReadPunctuation
773 ================
774 */
776  int l, n, i;
777  const char *p;
778  const punctuation_t *punc;
779 
780 #ifdef PUNCTABLE
781  for (n = idLexer::punctuationtable[(unsigned int)*(idLexer::script_p)]; n >= 0; n = idLexer::nextpunctuation[n])
782  {
783  punc = &(idLexer::punctuations[n]);
784 #else
785  int i;
786 
787  for (i = 0; idLexer::punctuations[i].p; i++) {
788  punc = &idLexer::punctuations[i];
789 #endif
790  p = punc->p;
791  // check for this punctuation in the script
792  for ( l = 0; p[l] && idLexer::script_p[l]; l++ ) {
793  if ( idLexer::script_p[l] != p[l] ) {
794  break;
795  }
796  }
797  if ( !p[l] ) {
798  //
799  token->EnsureAlloced( l+1, false );
800  for ( i = 0; i <= l; i++ ) {
801  token->data[i] = p[i];
802  }
803  token->len = l;
804  //
805  idLexer::script_p += l;
806  token->type = TT_PUNCTUATION;
807  // sub type is the punctuation id
808  token->subtype = punc->n;
809  return 1;
810  }
811  }
812  return 0;
813 }
814 
815 /*
816 ================
817 idLexer::ReadToken
818 ================
819 */
821  int c;
822 
823  if ( !loaded ) {
824  idLib::common->Error( "idLexer::ReadToken: no file loaded" );
825  return 0;
826  }
827 
828  // if there is a token available (from unreadToken)
829  if ( tokenavailable ) {
830  tokenavailable = 0;
831  *token = idLexer::token;
832  return 1;
833  }
834  // save script pointer
836  // save line counter
837  lastline = line;
838  // clear the token stuff
839  token->data[0] = '\0';
840  token->len = 0;
841  // start of the white space
843  token->whiteSpaceStart_p = script_p;
844  // read white space before token
845  if ( !ReadWhiteSpace() ) {
846  return 0;
847  }
848  // end of the white space
850  token->whiteSpaceEnd_p = script_p;
851  // line the token is on
852  token->line = line;
853  // number of lines crossed before token
854  token->linesCrossed = line - lastline;
855  // clear token flags
856  token->flags = 0;
857 
858  c = *idLexer::script_p;
859 
860  // if we're keeping everything as whitespace deliminated strings
862  // if there is a leading quote
863  if ( c == '\"' || c == '\'' ) {
864  if (!idLexer::ReadString( token, c )) {
865  return 0;
866  }
867  } else if ( !idLexer::ReadName( token ) ) {
868  return 0;
869  }
870  }
871  // if there is a number
872  else if ( (c >= '0' && c <= '9') ||
873  (c == '.' && (*(idLexer::script_p + 1) >= '0' && *(idLexer::script_p + 1) <= '9')) ) {
874  if ( !idLexer::ReadNumber( token ) ) {
875  return 0;
876  }
877  // if names are allowed to start with a number
879  c = *idLexer::script_p;
880  if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ) {
881  if ( !idLexer::ReadName( token ) ) {
882  return 0;
883  }
884  }
885  }
886  }
887  // if there is a leading quote
888  else if ( c == '\"' || c == '\'' ) {
889  if (!idLexer::ReadString( token, c )) {
890  return 0;
891  }
892  }
893  // if there is a name
894  else if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ) {
895  if ( !idLexer::ReadName( token ) ) {
896  return 0;
897  }
898  }
899  // names may also start with a slash when pathnames are allowed
900  else if ( ( idLexer::flags & LEXFL_ALLOWPATHNAMES ) && ( (c == '/' || c == '\\') || c == '.' ) ) {
901  if ( !idLexer::ReadName( token ) ) {
902  return 0;
903  }
904  }
905  // check for punctuations
906  else if ( !idLexer::ReadPunctuation( token ) ) {
907  idLexer::Error( "unknown punctuation %c", c );
908  return 0;
909  }
910  // succesfully read a token
911  return 1;
912 }
913 
914 /*
915 ================
916 idLexer::ExpectTokenString
917 ================
918 */
919 int idLexer::ExpectTokenString( const char *string ) {
920  idToken token;
921 
922  if (!idLexer::ReadToken( &token )) {
923  idLexer::Error( "couldn't find expected '%s'", string );
924  return 0;
925  }
926  if ( token != string ) {
927  idLexer::Error( "expected '%s' but found '%s'", string, token.c_str() );
928  return 0;
929  }
930  return 1;
931 }
932 
933 /*
934 ================
935 idLexer::ExpectTokenType
936 ================
937 */
938 int idLexer::ExpectTokenType( int type, int subtype, idToken *token ) {
939  idStr str;
940 
941  if ( !idLexer::ReadToken( token ) ) {
942  idLexer::Error( "couldn't read expected token" );
943  return 0;
944  }
945 
946  if ( token->type != type ) {
947  switch( type ) {
948  case TT_STRING: str = "string"; break;
949  case TT_LITERAL: str = "literal"; break;
950  case TT_NUMBER: str = "number"; break;
951  case TT_NAME: str = "name"; break;
952  case TT_PUNCTUATION: str = "punctuation"; break;
953  default: str = "unknown type"; break;
954  }
955  idLexer::Error( "expected a %s but found '%s'", str.c_str(), token->c_str() );
956  return 0;
957  }
958  if ( token->type == TT_NUMBER ) {
959  if ( (token->subtype & subtype) != subtype ) {
960  str.Clear();
961  if ( subtype & TT_DECIMAL ) str = "decimal ";
962  if ( subtype & TT_HEX ) str = "hex ";
963  if ( subtype & TT_OCTAL ) str = "octal ";
964  if ( subtype & TT_BINARY ) str = "binary ";
965  if ( subtype & TT_UNSIGNED ) str += "unsigned ";
966  if ( subtype & TT_LONG ) str += "long ";
967  if ( subtype & TT_FLOAT ) str += "float ";
968  if ( subtype & TT_INTEGER ) str += "integer ";
969  str.StripTrailing( ' ' );
970  idLexer::Error( "expected %s but found '%s'", str.c_str(), token->c_str() );
971  return 0;
972  }
973  }
974  else if ( token->type == TT_PUNCTUATION ) {
975  if ( subtype < 0 ) {
976  idLexer::Error( "BUG: wrong punctuation subtype" );
977  return 0;
978  }
979  if ( token->subtype != subtype ) {
980  idLexer::Error( "expected '%s' but found '%s'", GetPunctuationFromId( subtype ), token->c_str() );
981  return 0;
982  }
983  }
984  return 1;
985 }
986 
987 /*
988 ================
989 idLexer::ExpectAnyToken
990 ================
991 */
993  if (!idLexer::ReadToken( token )) {
994  idLexer::Error( "couldn't read expected token" );
995  return 0;
996  }
997  else {
998  return 1;
999  }
1000 }
1001 
1002 /*
1003 ================
1004 idLexer::CheckTokenString
1005 ================
1006 */
1007 int idLexer::CheckTokenString( const char *string ) {
1008  idToken tok;
1009 
1010  if ( !ReadToken( &tok ) ) {
1011  return 0;
1012  }
1013  // if the given string is available
1014  if ( tok == string ) {
1015  return 1;
1016  }
1017  // unread token
1019  line = lastline;
1020  return 0;
1021 }
1022 
1023 /*
1024 ================
1025 idLexer::CheckTokenType
1026 ================
1027 */
1028 int idLexer::CheckTokenType( int type, int subtype, idToken *token ) {
1029  idToken tok;
1030 
1031  if ( !ReadToken( &tok ) ) {
1032  return 0;
1033  }
1034  // if the type matches
1035  if (tok.type == type && (tok.subtype & subtype) == subtype) {
1036  *token = tok;
1037  return 1;
1038  }
1039  // unread token
1041  line = lastline;
1042  return 0;
1043 }
1044 
1045 /*
1046 ================
1047 idLexer::PeekTokenString
1048 ================
1049 */
1050 int idLexer::PeekTokenString( const char *string ) {
1051  idToken tok;
1052 
1053  if ( !ReadToken( &tok ) ) {
1054  return 0;
1055  }
1056 
1057  // unread token
1059  line = lastline;
1060 
1061  // if the given string is available
1062  if ( tok == string ) {
1063  return 1;
1064  }
1065  return 0;
1066 }
1067 
1068 /*
1069 ================
1070 idLexer::PeekTokenType
1071 ================
1072 */
1073 int idLexer::PeekTokenType( int type, int subtype, idToken *token ) {
1074  idToken tok;
1075 
1076  if ( !ReadToken( &tok ) ) {
1077  return 0;
1078  }
1079 
1080  // unread token
1082  line = lastline;
1083 
1084  // if the type matches
1085  if ( tok.type == type && ( tok.subtype & subtype ) == subtype ) {
1086  *token = tok;
1087  return 1;
1088  }
1089  return 0;
1090 }
1091 
1092 /*
1093 ================
1094 idLexer::SkipUntilString
1095 ================
1096 */
1097 int idLexer::SkipUntilString( const char *string ) {
1098  idToken token;
1099 
1100  while(idLexer::ReadToken( &token )) {
1101  if ( token == string ) {
1102  return 1;
1103  }
1104  }
1105  return 0;
1106 }
1107 
1108 /*
1109 ================
1110 idLexer::SkipRestOfLine
1111 ================
1112 */
1114  idToken token;
1115 
1116  while(idLexer::ReadToken( &token )) {
1117  if ( token.linesCrossed ) {
1120  return 1;
1121  }
1122  }
1123  return 0;
1124 }
1125 
1126 /*
1127 =================
1128 idLexer::SkipBracedSection
1129 
1130 Skips until a matching close brace is found.
1131 Internal brace depths are properly skipped.
1132 =================
1133 */
1134 int idLexer::SkipBracedSection( bool parseFirstBrace ) {
1135  idToken token;
1136  int depth;
1137 
1138  depth = parseFirstBrace ? 0 : 1;
1139  do {
1140  if ( !ReadToken( &token ) ) {
1141  return false;
1142  }
1143  if ( token.type == TT_PUNCTUATION ) {
1144  if ( token == "{" ) {
1145  depth++;
1146  } else if ( token == "}" ) {
1147  depth--;
1148  }
1149  }
1150  } while( depth );
1151  return true;
1152 }
1153 
1154 /*
1155 ================
1156 idLexer::UnreadToken
1157 ================
1158 */
1159 void idLexer::UnreadToken( const idToken *token ) {
1160  if ( idLexer::tokenavailable ) {
1161  idLib::common->FatalError( "idLexer::unreadToken, unread token twice\n" );
1162  }
1163  idLexer::token = *token;
1165 }
1166 
1167 /*
1168 ================
1169 idLexer::ReadTokenOnLine
1170 ================
1171 */
1173  idToken tok;
1174 
1175  if (!idLexer::ReadToken( &tok )) {
1178  return false;
1179  }
1180  // if no lines were crossed before this token
1181  if ( !tok.linesCrossed ) {
1182  *token = tok;
1183  return true;
1184  }
1185  // restore our position
1188  token->Clear();
1189  return false;
1190 }
1191 
1192 /*
1193 ================
1194 idLexer::ReadRestOfLine
1195 ================
1196 */
1197 const char* idLexer::ReadRestOfLine(idStr& out) {
1198  while(1) {
1199 
1200  if(*idLexer::script_p == '\n') {
1201  idLexer::line++;
1202  break;
1203  }
1204 
1205  if(!*idLexer::script_p) {
1206  break;
1207  }
1208 
1209  if(*idLexer::script_p <= ' ') {
1210  out += " ";
1211  } else {
1212  out += *idLexer::script_p;
1213  }
1215 
1216  }
1217 
1218  out.Strip(' ');
1219  return out.c_str();
1220 }
1221 
1222 /*
1223 ================
1224 idLexer::ParseInt
1225 ================
1226 */
1227 int idLexer::ParseInt( void ) {
1228  idToken token;
1229 
1230  if ( !idLexer::ReadToken( &token ) ) {
1231  idLexer::Error( "couldn't read expected integer" );
1232  return 0;
1233  }
1234  if ( token.type == TT_PUNCTUATION && token == "-" ) {
1236  return -((signed int) token.GetIntValue());
1237  }
1238  else if ( token.type != TT_NUMBER || token.subtype == TT_FLOAT ) {
1239  idLexer::Error( "expected integer value, found '%s'", token.c_str() );
1240  }
1241  return token.GetIntValue();
1242 }
1243 
1244 /*
1245 ================
1246 idLexer::ParseBool
1247 ================
1248 */
1249 bool idLexer::ParseBool( void ) {
1250  idToken token;
1251 
1252  if ( !idLexer::ExpectTokenType( TT_NUMBER, 0, &token ) ) {
1253  idLexer::Error( "couldn't read expected boolean" );
1254  return false;
1255  }
1256  return ( token.GetIntValue() != 0 );
1257 }
1258 
1259 /*
1260 ================
1261 idLexer::ParseFloat
1262 ================
1263 */
1264 float idLexer::ParseFloat( bool *errorFlag ) {
1265  idToken token;
1266 
1267  if ( errorFlag ) {
1268  *errorFlag = false;
1269  }
1270 
1271  if ( !idLexer::ReadToken( &token ) ) {
1272  if ( errorFlag ) {
1273  idLexer::Warning( "couldn't read expected floating point number" );
1274  *errorFlag = true;
1275  } else {
1276  idLexer::Error( "couldn't read expected floating point number" );
1277  }
1278  return 0;
1279  }
1280  if ( token.type == TT_PUNCTUATION && token == "-" ) {
1281  idLexer::ExpectTokenType( TT_NUMBER, 0, &token );
1282  return -token.GetFloatValue();
1283  }
1284  else if ( token.type != TT_NUMBER ) {
1285  if ( errorFlag ) {
1286  idLexer::Warning( "expected float value, found '%s'", token.c_str() );
1287  *errorFlag = true;
1288  } else {
1289  idLexer::Error( "expected float value, found '%s'", token.c_str() );
1290  }
1291  }
1292  return token.GetFloatValue();
1293 }
1294 
1295 /*
1296 ================
1297 idLexer::Parse1DMatrix
1298 ================
1299 */
1300 int idLexer::Parse1DMatrix( int x, float *m ) {
1301  int i;
1302 
1303  if ( !idLexer::ExpectTokenString( "(" ) ) {
1304  return false;
1305  }
1306 
1307  for ( i = 0; i < x; i++ ) {
1308  m[i] = idLexer::ParseFloat();
1309  }
1310 
1311  if ( !idLexer::ExpectTokenString( ")" ) ) {
1312  return false;
1313  }
1314  return true;
1315 }
1316 
1317 /*
1318 ================
1319 idLexer::Parse2DMatrix
1320 ================
1321 */
1322 int idLexer::Parse2DMatrix( int y, int x, float *m ) {
1323  int i;
1324 
1325  if ( !idLexer::ExpectTokenString( "(" ) ) {
1326  return false;
1327  }
1328 
1329  for ( i = 0; i < y; i++ ) {
1330  if ( !idLexer::Parse1DMatrix( x, m + i * x ) ) {
1331  return false;
1332  }
1333  }
1334 
1335  if ( !idLexer::ExpectTokenString( ")" ) ) {
1336  return false;
1337  }
1338  return true;
1339 }
1340 
1341 /*
1342 ================
1343 idLexer::Parse3DMatrix
1344 ================
1345 */
1346 int idLexer::Parse3DMatrix( int z, int y, int x, float *m ) {
1347  int i;
1348 
1349  if ( !idLexer::ExpectTokenString( "(" ) ) {
1350  return false;
1351  }
1352 
1353  for ( i = 0 ; i < z; i++ ) {
1354  if ( !idLexer::Parse2DMatrix( y, x, m + i * x*y ) ) {
1355  return false;
1356  }
1357  }
1358 
1359  if ( !idLexer::ExpectTokenString( ")" ) ) {
1360  return false;
1361  }
1362  return true;
1363 }
1364 
1365 /*
1366 =================
1367 idParser::ParseBracedSection
1368 
1369 The next token should be an open brace.
1370 Parses until a matching close brace is found.
1371 Maintains exact characters between braces.
1372 
1373  FIXME: this should use ReadToken and replace the token white space with correct indents and newlines
1374 =================
1375 */
1376 const char *idLexer::ParseBracedSectionExact( idStr &out, int tabs ) {
1377  int depth;
1378  bool doTabs;
1379  bool skipWhite;
1380 
1381  out.Empty();
1382 
1383  if ( !idLexer::ExpectTokenString( "{" ) ) {
1384  return out.c_str( );
1385  }
1386 
1387  out = "{";
1388  depth = 1;
1389  skipWhite = false;
1390  doTabs = tabs >= 0;
1391 
1392  while( depth && *idLexer::script_p ) {
1393  char c = *(idLexer::script_p++);
1394 
1395  switch ( c ) {
1396  case '\t':
1397  case ' ': {
1398  if ( skipWhite ) {
1399  continue;
1400  }
1401  break;
1402  }
1403  case '\n': {
1404  if ( doTabs ) {
1405  skipWhite = true;
1406  out += c;
1407  continue;
1408  }
1409  break;
1410  }
1411  case '{': {
1412  depth++;
1413  tabs++;
1414  break;
1415  }
1416  case '}': {
1417  depth--;
1418  tabs--;
1419  break;
1420  }
1421  }
1422 
1423  if ( skipWhite ) {
1424  int i = tabs;
1425  if ( c == '{' ) {
1426  i--;
1427  }
1428  skipWhite = false;
1429  for ( ; i > 0; i-- ) {
1430  out += '\t';
1431  }
1432  }
1433  out += c;
1434  }
1435  return out.c_str();
1436 }
1437 
1438 /*
1439 =================
1440 idLexer::ParseBracedSection
1441 
1442 The next token should be an open brace.
1443 Parses until a matching close brace is found.
1444 Internal brace depths are properly skipped.
1445 =================
1446 */
1447 const char *idLexer::ParseBracedSection( idStr &out ) {
1448  idToken token;
1449  int i, depth;
1450 
1451  out.Empty();
1452  if ( !idLexer::ExpectTokenString( "{" ) ) {
1453  return out.c_str();
1454  }
1455  out = "{";
1456  depth = 1;
1457  do {
1458  if ( !idLexer::ReadToken( &token ) ) {
1459  Error( "missing closing brace" );
1460  return out.c_str();
1461  }
1462 
1463  // if the token is on a new line
1464  for ( i = 0; i < token.linesCrossed; i++ ) {
1465  out += "\r\n";
1466  }
1467 
1468  if ( token.type == TT_PUNCTUATION ) {
1469  if ( token[0] == '{' ) {
1470  depth++;
1471  }
1472  else if ( token[0] == '}' ) {
1473  depth--;
1474  }
1475  }
1476 
1477  if ( token.type == TT_STRING ) {
1478  out += "\"" + token + "\"";
1479  }
1480  else {
1481  out += token;
1482  }
1483  out += " ";
1484  } while( depth );
1485 
1486  return out.c_str();
1487 }
1488 
1489 /*
1490 =================
1491 idLexer::ParseRestOfLine
1492 
1493  parse the rest of the line
1494 =================
1495 */
1496 const char *idLexer::ParseRestOfLine( idStr &out ) {
1497  idToken token;
1498 
1499  out.Empty();
1500  while(idLexer::ReadToken( &token )) {
1501  if ( token.linesCrossed ) {
1504  break;
1505  }
1506  if ( out.Length() ) {
1507  out += " ";
1508  }
1509  out += token;
1510  }
1511  return out.c_str();
1512 }
1513 
1514 /*
1515 ================
1516 idLexer::GetLastWhiteSpace
1517 ================
1518 */
1519 int idLexer::GetLastWhiteSpace( idStr &whiteSpace ) const {
1520  whiteSpace.Clear();
1521  for ( const char *p = whiteSpaceStart_p; p < whiteSpaceEnd_p; p++ ) {
1522  whiteSpace.Append( *p );
1523  }
1524  return whiteSpace.Length();
1525 }
1526 
1527 /*
1528 ================
1529 idLexer::GetLastWhiteSpaceStart
1530 ================
1531 */
1533  return whiteSpaceStart_p - buffer;
1534 }
1535 
1536 /*
1537 ================
1538 idLexer::GetLastWhiteSpaceEnd
1539 ================
1540 */
1542  return whiteSpaceEnd_p - buffer;
1543 }
1544 
1545 /*
1546 ================
1547 idLexer::Reset
1548 ================
1549 */
1550 void idLexer::Reset( void ) {
1551  // pointer in script buffer
1553  // pointer in script buffer before reading token
1555  // begin of white space
1557  // end of white space
1559  // set if there's a token available in idLexer::token
1561 
1562  idLexer::line = 1;
1563  idLexer::lastline = 1;
1564  // clear the saved token
1565  idLexer::token = "";
1566 }
1567 
1568 /*
1569 ================
1570 idLexer::EndOfFile
1571 ================
1572 */
1573 int idLexer::EndOfFile( void ) {
1575 }
1576 
1577 /*
1578 ================
1579 idLexer::NumLinesCrossed
1580 ================
1581 */
1584 }
1585 
1586 /*
1587 ================
1588 idLexer::LoadFile
1589 ================
1590 */
1591 int idLexer::LoadFile( const char *filename, bool OSPath ) {
1592  idFile *fp;
1593  idStr pathname;
1594  int length;
1595  char *buf;
1596 
1597  if ( idLexer::loaded ) {
1598  idLib::common->Error("idLexer::LoadFile: another script already loaded");
1599  return false;
1600  }
1601 
1602  if ( !OSPath && ( baseFolder[0] != '\0' ) ) {
1603  pathname = va( "%s/%s", baseFolder, filename );
1604  } else {
1605  pathname = filename;
1606  }
1607  if ( OSPath ) {
1608  fp = idLib::fileSystem->OpenExplicitFileRead( pathname );
1609  } else {
1610  fp = idLib::fileSystem->OpenFileRead( pathname );
1611  }
1612  if ( !fp ) {
1613  return false;
1614  }
1615  length = fp->Length();
1616  buf = (char *) Mem_Alloc( length + 1 );
1617  buf[length] = '\0';
1618  fp->Read( buf, length );
1619  idLexer::fileTime = fp->Timestamp();
1622 
1623  idLexer::buffer = buf;
1625  // pointer in script buffer
1627  // pointer in script buffer before reading token
1629  // pointer to end of script buffer
1631 
1633  idLexer::line = 1;
1634  idLexer::lastline = 1;
1635  idLexer::allocated = true;
1636  idLexer::loaded = true;
1637 
1638  return true;
1639 }
1640 
1641 /*
1642 ================
1643 idLexer::LoadMemory
1644 ================
1645 */
1646 int idLexer::LoadMemory( const char *ptr, int length, const char *name, int startLine ) {
1647  if ( idLexer::loaded ) {
1648  idLib::common->Error("idLexer::LoadMemory: another script already loaded");
1649  return false;
1650  }
1652  idLexer::buffer = ptr;
1653  idLexer::fileTime = 0;
1655  // pointer in script buffer
1657  // pointer in script buffer before reading token
1659  // pointer to end of script buffer
1661 
1663  idLexer::line = startLine;
1664  idLexer::lastline = startLine;
1665  idLexer::allocated = false;
1666  idLexer::loaded = true;
1667 
1668  return true;
1669 }
1670 
1671 /*
1672 ================
1673 idLexer::FreeSource
1674 ================
1675 */
1676 void idLexer::FreeSource( void ) {
1677 #ifdef PUNCTABLE
1679  Mem_Free( (void *) idLexer::punctuationtable );
1681  }
1683  Mem_Free( (void *) idLexer::nextpunctuation );
1685  }
1686 #endif //PUNCTABLE
1687  if ( idLexer::allocated ) {
1688  Mem_Free( (void *) idLexer::buffer );
1690  idLexer::allocated = false;
1691  }
1693  idLexer::token = "";
1694  idLexer::loaded = false;
1695 }
1696 
1697 /*
1698 ================
1699 idLexer::idLexer
1700 ================
1701 */
1703  idLexer::loaded = false;
1704  idLexer::filename = "";
1705  idLexer::flags = 0;
1707  idLexer::allocated = false;
1708  idLexer::fileTime = 0;
1709  idLexer::length = 0;
1710  idLexer::line = 0;
1711  idLexer::lastline = 0;
1713  idLexer::token = "";
1714  idLexer::next = NULL;
1715  idLexer::hadError = false;
1716 }
1717 
1718 /*
1719 ================
1720 idLexer::idLexer
1721 ================
1722 */
1724  idLexer::loaded = false;
1725  idLexer::filename = "";
1728  idLexer::allocated = false;
1729  idLexer::fileTime = 0;
1730  idLexer::length = 0;
1731  idLexer::line = 0;
1732  idLexer::lastline = 0;
1734  idLexer::token = "";
1735  idLexer::next = NULL;
1736  idLexer::hadError = false;
1737 }
1738 
1739 /*
1740 ================
1741 idLexer::idLexer
1742 ================
1743 */
1744 idLexer::idLexer( const char *filename, int flags, bool OSPath ) {
1745  idLexer::loaded = false;
1748  idLexer::allocated = false;
1749  idLexer::token = "";
1750  idLexer::next = NULL;
1751  idLexer::hadError = false;
1752  idLexer::LoadFile( filename, OSPath );
1753 }
1754 
1755 /*
1756 ================
1757 idLexer::idLexer
1758 ================
1759 */
1760 idLexer::idLexer( const char *ptr, int length, const char *name, int flags ) {
1761  idLexer::loaded = false;
1764  idLexer::allocated = false;
1765  idLexer::token = "";
1766  idLexer::next = NULL;
1767  idLexer::hadError = false;
1768  idLexer::LoadMemory( ptr, length, name );
1769 }
1770 
1771 /*
1772 ================
1773 idLexer::~idLexer
1774 ================
1775 */
1778 }
1779 
1780 /*
1781 ================
1782 idLexer::SetBaseFolder
1783 ================
1784 */
1785 void idLexer::SetBaseFolder( const char *path ) {
1786  idStr::Copynz( baseFolder, path, sizeof( baseFolder ) );
1787 }
1788 
1789 /*
1790 ================
1791 idLexer::HadError
1792 ================
1793 */
1794 bool idLexer::HadError( void ) const {
1795  return hadError;
1796 }
1797 
#define P_SQBRACKETCLOSE
Definition: Lexer.h:123
int CheckTokenString(const char *string)
Definition: Lexer.cpp:1007
int flags
Definition: Lexer.h:259
#define P_COLON
Definition: Lexer.h:115
const char * whiteSpaceStart_p
Definition: Lexer.h:252
#define P_LOGIC_NOT
Definition: Lexer.h:108
const char * ReadRestOfLine(idStr &out)
Definition: Lexer.cpp:1197
#define strcmp
Definition: Str.h:41
virtual idFile * OpenFileRead(const char *relativePath, bool allowCopyFiles=true, const char *gamedir=NULL)=0
const char * whiteSpaceStart_p
Definition: Token.h:103
#define P_RSHIFT_ASSIGN
Definition: Lexer.h:67
int type
Definition: Token.h:77
void Reset(void)
Definition: Lexer.cpp:1550
char * data
Definition: Str.h:317
#define TT_INDEFINITE
Definition: Token.h:60
double floatvalue
Definition: Token.h:102
int GetPunctuationId(const char *p)
Definition: Lexer.cpp:199
void void bool HadError(void) const
Definition: Lexer.cpp:1794
#define P_DOLLAR
Definition: Lexer.h:127
#define P_BIN_AND_ASSIGN
Definition: Lexer.h:87
int * nextpunctuation
Definition: Lexer.h:262
int ReadEscapeCharacter(char *ch)
Definition: Lexer.cpp:357
int lastline
Definition: Lexer.h:257
#define P_LOGIC_LEQ
Definition: Lexer.h:75
idStr filename
Definition: Lexer.h:246
int ReadName(idToken *token)
Definition: Lexer.cpp:534
#define P_MUL_ASSIGN
Definition: Lexer.h:79
void FreeSource(void)
Definition: Lexer.cpp:1676
#define TT_LONG
Definition: Token.h:53
int CheckString(const char *str) const
Definition: Lexer.cpp:560
#define TT_NAME
Definition: Token.h:44
const char * lastScript_p
Definition: Lexer.h:251
#define P_BIN_OR_ASSIGN
Definition: Lexer.h:88
int Length(void) const
Definition: Str.h:702
#define P_SEMICOLON
Definition: Lexer.h:114
const char * script_p
Definition: Lexer.h:249
#define P_BIN_XOR_ASSIGN
Definition: Lexer.h:89
int Parse1DMatrix(int x, float *m)
Definition: Lexer.cpp:1300
#define P_BIN_XOR
Definition: Lexer.h:105
#define TT_INTEGER
Definition: Token.h:48
#define P_CPP1
Definition: Lexer.h:94
GLenum GLint GLint y
Definition: glext.h:2849
const char * end_p
Definition: Lexer.h:250
GLenum GLsizei n
Definition: glext.h:3705
void StripTrailing(const char c)
Definition: Str.cpp:515
#define P_PRECOMPMERGE
Definition: Lexer.h:70
case const int
Definition: Callbacks.cpp:52
virtual idFile * OpenExplicitFileRead(const char *OSPath)=0
#define P_DEC
Definition: Lexer.h:85
int GetLastWhiteSpaceStart(void) const
Definition: Lexer.cpp:1532
#define P_QUESTIONMARK
Definition: Lexer.h:116
void Strip(const char c)
Definition: Str.h:915
int subtype
Definition: Token.h:78
#define P_LOGIC_OR
Definition: Lexer.h:73
int SkipBracedSection(bool parseFirstBrace=true)
Definition: Lexer.cpp:1134
int linesCrossed
Definition: Token.h:80
#define P_SQBRACKETOPEN
Definition: Lexer.h:122
#define P_BIN_AND
Definition: Lexer.h:103
bool ParseBool(void)
Definition: Lexer.cpp:1249
float GetFloatValue(void)
Definition: Token.h:138
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glext.h:2878
#define P_LOGIC_UNEQ
Definition: Lexer.h:77
int CheckTokenType(int type, int subtype, idToken *token)
Definition: Lexer.cpp:1028
#define TT_IPPORT
Definition: Token.h:63
#define P_SUB_ASSIGN
Definition: Lexer.h:83
#define P_LOGIC_AND
Definition: Lexer.h:72
#define P_LSHIFT
Definition: Lexer.h:91
#define P_LSHIFT_ASSIGN
Definition: Lexer.h:68
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
ID_TIME_T fileTime
Definition: Lexer.h:254
Definition: Token.h:71
~idLexer()
Definition: Lexer.cpp:1776
int tokenavailable
Definition: Lexer.h:258
#define TT_STRING
Definition: Token.h:41
int default_nextpunctuation[sizeof(default_punctuations)/sizeof(punctuation_t)]
Definition: Lexer.cpp:110
#define P_LOGIC_GEQ
Definition: Lexer.h:74
int PeekTokenString(const char *string)
Definition: Lexer.cpp:1050
float ParseFloat(bool *errorFlag=NULL)
Definition: Lexer.cpp:1264
static char baseFolder[256]
Definition: Lexer.h:267
int ReadTokenOnLine(idToken *token)
Definition: Lexer.cpp:1172
#define P_MOD
Definition: Lexer.h:98
#define P_PRECOMP
Definition: Lexer.h:126
GLenum GLint x
Definition: glext.h:2849
int i
Definition: process.py:33
int default_punctuationtable[256]
Definition: Lexer.cpp:109
#define TT_DECIMAL
Definition: Token.h:49
int ParseInt(void)
Definition: Lexer.cpp:1227
#define P_COMMA
Definition: Lexer.h:113
#define P_BACKSLASH
Definition: Lexer.h:124
#define TT_EXTENDED_PRECISION
Definition: Token.h:58
#define P_PARENTHESESCLOSE
Definition: Lexer.h:119
#define TT_NUMBER
Definition: Token.h:43
list l
Definition: prepare.py:17
int ReadPunctuation(idToken *token)
Definition: Lexer.cpp:775
int ExpectAnyToken(idToken *token)
Definition: Lexer.cpp:992
#define TT_BINARY
Definition: Token.h:52
idLexer()
Definition: Lexer.cpp:1702
#define P_SUB
Definition: Lexer.h:100
#define P_ADD_ASSIGN
Definition: Lexer.h:82
Definition: File.h:50
#define P_BIN_NOT
Definition: Lexer.h:106
#define TT_IPADDRESS
Definition: Token.h:62
#define TT_UNSIGNED
Definition: Token.h:54
void Error(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:215
int line
Definition: Token.h:79
int default_setup
Definition: Lexer.cpp:111
int ExpectTokenType(int type, int subtype, idToken *token)
Definition: Lexer.cpp:938
static class idFileSystem * fileSystem
Definition: Lib.h:55
#define P_POINTERREF
Definition: Lexer.h:93
const GLubyte * c
Definition: glext.h:4677
const char * whiteSpaceEnd_p
Definition: Lexer.h:253
#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
punctuation_t default_punctuations[]
Definition: Lexer.cpp:35
#define TT_HEX
Definition: Token.h:50
int length
Definition: Lexer.h:255
void SetPunctuations(const punctuation_t *p)
Definition: Lexer.cpp:260
#define NULL
Definition: Lib.h:88
#define P_ASSIGN
Definition: Lexer.h:101
void EnsureAlloced(int amount, bool keepold=true)
Definition: Str.h:328
#define P_LOGIC_GREATER
Definition: Lexer.h:109
idToken token
Definition: Lexer.h:263
virtual void virtual void FatalError(const char *fmt,...) id_attribute((format(printf
#define P_DIV_ASSIGN
Definition: Lexer.h:80
virtual int Read(void *buffer, int len)
Definition: File.cpp:179
static void Copynz(char *dest, const char *src, int destsize)
Definition: Str.cpp:1376
#define P_CPP2
Definition: Lexer.h:95
int PeekTokenType(int type, int subtype, idToken *token)
Definition: Lexer.cpp:1073
int allocated
Definition: Lexer.h:247
const char * whiteSpaceEnd_p
Definition: Token.h:104
#define P_LOGIC_LESS
Definition: Lexer.h:110
const char * path
Definition: sws.c:117
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
void Clear(void)
Definition: Str.h:724
void UnreadToken(const idToken *token)
Definition: Lexer.cpp:1159
bool hadError
Definition: Lexer.h:265
int LoadMemory(const char *ptr, int length, const char *name, int startLine=1)
Definition: Lexer.cpp:1646
const char * GetPunctuationFromId(int id)
Definition: Lexer.cpp:183
idLexer * next
Definition: Lexer.h:264
virtual ID_TIME_T Timestamp(void)
Definition: File.cpp:208
int line
Definition: Lexer.h:256
int Parse3DMatrix(int z, int y, int x, float *m)
Definition: Lexer.cpp:1346
int EndOfFile(void)
Definition: Lexer.cpp:1573
#define P_REF
Definition: Lexer.h:112
#define TT_LITERAL
Definition: Token.h:42
#define P_BRACEOPEN
Definition: Lexer.h:120
void CreatePunctuationTable(const punctuation_t *punctuations)
Definition: Lexer.cpp:120
#define P_BRACECLOSE
Definition: Lexer.h:121
#define P_MOD_ASSIGN
Definition: Lexer.h:81
int ExpectTokenString(const char *string)
Definition: Lexer.cpp:919
#define P_ADD
Definition: Lexer.h:99
void void Warning(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:241
static void SetBaseFolder(const char *path)
Definition: Lexer.cpp:1785
int len
Definition: Str.h:316
#define P_MUL
Definition: Lexer.h:96
#define TT_SINGLE_PRECISION
Definition: Token.h:56
#define TT_PUNCTUATION
Definition: Token.h:45
int NumLinesCrossed(void)
Definition: Lexer.cpp:1582
void Append(const char a)
Definition: Str.h:729
int GetLastWhiteSpace(idStr &whiteSpace) const
Definition: Lexer.cpp:1519
#define TT_NAN
Definition: Token.h:61
const GLcharARB * name
Definition: glext.h:3629
int * punctuationtable
Definition: Lexer.h:261
Definition: Str.h:116
#define TT_INFINITE
Definition: Token.h:59
int flags
Definition: Token.h:81
GLsizei const GLcharARB const GLint * length
Definition: glext.h:3599
int GetLastWhiteSpaceEnd(void) const
Definition: Lexer.cpp:1541
int vsprintf(idStr &string, const char *fmt, va_list argptr)
Definition: Str.cpp:1549
int GetIntValue(void)
Definition: Token.h:152
const char * c_str(void) const
Definition: Str.h:487
int SkipUntilString(const char *string)
Definition: Lexer.cpp:1097
#define TT_OCTAL
Definition: Token.h:51
int Parse2DMatrix(int y, int x, float *m)
Definition: Lexer.cpp:1322
#define P_BIN_OR
Definition: Lexer.h:104
void AppendDirty(const char a)
Definition: Token.h:160
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
const char * buffer
Definition: Lexer.h:248
const char * ParseBracedSection(idStr &out)
Definition: Lexer.cpp:1447
float dot(float a[], float b[])
Definition: Model_lwo.cpp:3883
const punctuation_t * punctuations
Definition: Lexer.h:260
#define TT_FLOAT
Definition: Token.h:55
unsigned long intvalue
Definition: Token.h:101
char * va(const char *fmt,...)
Definition: Str.cpp:1568
int ReadString(idToken *token, int quote)
Definition: Lexer.cpp:436
virtual void CloseFile(idFile *f)=0
int ReadNumber(idToken *token)
Definition: Lexer.cpp:576
int loaded
Definition: Lexer.h:245
virtual void Error(const char *fmt,...) id_attribute((format(printf
const char * ParseRestOfLine(idStr &out)
Definition: Lexer.cpp:1496
#define P_PARENTHESESOPEN
Definition: Lexer.h:118
GLfloat GLfloat p
Definition: glext.h:4674
int ReadWhiteSpace(void)
Definition: Lexer.cpp:285
GLdouble GLdouble z
Definition: glext.h:3067
int SkipRestOfLine(void)
Definition: Lexer.cpp:1113
#define P_RSHIFT
Definition: Lexer.h:90
const char * ParseBracedSectionExact(idStr &out, int tabs=-1)
Definition: Lexer.cpp:1376
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
const char * p
Definition: Lexer.h:132
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
#define P_PARMS
Definition: Lexer.h:69
virtual int Length(void)
Definition: File.cpp:199
virtual const char * GetFullPath(void)
Definition: File.cpp:170
#define P_LOGIC_EQ
Definition: Lexer.h:76
#define TT_DOUBLE_PRECISION
Definition: Token.h:57
int LoadFile(const char *filename, bool OSPath=false)
Definition: Lexer.cpp:1591
static class idCommon * common
Definition: Lib.h:53