]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/qdata_heretic2/common/token.c
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / tools / quake2 / qdata_heretic2 / common / token.c
1 /*
2    Copyright (C) 1999-2007 id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22
23 //**************************************************************************
24 //**
25 //** token.c
26 //**
27 //**************************************************************************
28
29 // HEADER FILES ------------------------------------------------------------
30
31 #include "token.h"
32 #include "inout.h"
33
34 // MACROS ------------------------------------------------------------------
35
36 // TYPES -------------------------------------------------------------------
37
38 typedef enum
39 {
40         CHR_EOF,
41         CHR_LETTER,
42         CHR_NUMBER,
43         CHR_QUOTE,
44         CHR_SPECIAL
45 } chr_t;
46
47 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
48
49 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
50
51 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
52
53 static void ProcessLetterToken( void );
54 static void ProcessNumberToken( void );
55 static void ProcessQuoteToken( void );
56 static void ProcessSpecialToken( void );
57 static qboolean CheckForKeyword( void );
58 static void NextChr( void );
59
60 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
61
62 // PUBLIC DATA DEFINITIONS -------------------------------------------------
63
64 tokenType_t tk_Token;
65 int tk_Line;
66 int tk_IntNumber;
67 float tk_FloatNumber;
68 char *tk_String;
69 char tk_SourceName[MAX_FILE_NAME_LENGTH];
70
71 // PRIVATE DATA DEFINITIONS ------------------------------------------------
72
73 static char Chr;
74 static char *FileStart;
75 static char *FilePtr;
76 static char *FileEnd;
77 static qboolean SourceOpen;
78 static char ASCIIToChrCode[256];
79 static char TokenStringBuffer[MAX_QUOTED_LENGTH];
80 static qboolean IncLineNumber;
81 static char TempBuffer[2048];
82
83 static struct
84 {
85         char *name;
86         tokenType_t token;
87 } Keywords[] =
88 {
89         "model",            TK_MODEL,
90         "mesh",             TK_MESH,
91         "vertices",         TK_VERTICES,
92         "edges",            TK_EDGES,
93         "position",         TK_POSITION,
94         "polygons",         TK_POLYGONS,
95         "nodes",            TK_NODES,
96         "rotation",         TK_ROTATION,
97         "scaling",          TK_SCALING,
98         "translation",      TK_TRANSLATION,
99         "vertex",           TK_VERTEX,
100         "HRCH",             TK_HRCH,
101         "Softimage",        TK_SOFTIMAGE,
102         "material",         TK_MATERIAL,
103         "spline",           TK_SPLINE,
104
105         "Named",            TK_C_NAMED,
106         "object",           TK_OBJECT,
107         "Tri",              TK_C_TRI,
108         "Vertices",         TK_C_VERTICES,
109         "Faces",            TK_C_FACES,
110         "Vertex",           TK_C_VERTEX,
111         "list",             TK_LIST,
112         "Face",             TK_C_FACE,
113
114         "Hexen",            TK_C_HEXEN,
115         "Triangles",        TK_C_TRIANGLES,
116         "Version",          TK_C_VERSION,
117         "faces",            TK_FACES,
118         "face",             TK_FACE,
119         "origin",           TK_ORIGIN,
120
121         "DK_clusters",      TK_CLUSTERS,
122         "DK_cluster_ncvs",  TK_NUM_CLUSTER_VERTICES,
123         "name",             TK_NAME,
124         "DK_cluster_name",  TK_CLUSTER_NAME,
125         "DK_cluster_state", TK_CLUSTER_STATE,
126
127         "actor_data",       TK_ACTOR_DATA,
128         "uvTexture",        TK_UVTEXTURE,
129
130         NULL,               -1
131 };
132
133 static char *TokenNames[] =
134 {
135         "<nothing>",
136         "<unknown_char>",
137         "<EOF>",
138         "<identifier>",
139         "<string>",
140         "<int_number>",
141         "<float_number>",
142         "(",
143         ")",
144         "{",
145         "}",
146         "[",
147         "]",
148         ":",
149         "mesh",
150         "model",
151         "nodes",
152         "rotation",
153         "scaling",
154         "translation",
155         "polygons",
156         "position",
157         "vertex",
158         "vertices",
159         "HRCH",
160         "Softimage"
161 };
162
163 // CODE --------------------------------------------------------------------
164
165 //==========================================================================
166 //
167 // TK_Init
168 //
169 //==========================================================================
170
171 void TK_Init( void ){
172         int i;
173
174         for ( i = 0; i < 256; i++ )
175         {
176                 ASCIIToChrCode[i] = CHR_SPECIAL;
177         }
178         for ( i = '0'; i <= '9'; i++ )
179         {
180                 ASCIIToChrCode[i] = CHR_NUMBER;
181         }
182         for ( i = 'A'; i <= 'Z'; i++ )
183         {
184                 ASCIIToChrCode[i] = CHR_LETTER;
185         }
186         for ( i = 'a'; i <= 'z'; i++ )
187         {
188                 ASCIIToChrCode[i] = CHR_LETTER;
189         }
190         ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
191         ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
192         ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
193         tk_String = TokenStringBuffer;
194         IncLineNumber = FALSE;
195         SourceOpen = FALSE;
196 }
197
198 //==========================================================================
199 //
200 // TK_OpenSource
201 //
202 //==========================================================================
203
204 void TK_OpenSource( char *fileName ){
205         int size;
206
207         TK_CloseSource();
208         size = LoadFile( fileName, (void **)&FileStart );
209         strcpy( tk_SourceName, fileName );
210         SourceOpen = TRUE;
211         FileEnd = FileStart + size;
212         FilePtr = FileStart;
213         tk_Line = 1;
214         tk_Token = TK_NONE;
215         NextChr();
216 }
217
218 //==========================================================================
219 //
220 // TK_CloseSource
221 //
222 //==========================================================================
223
224 void TK_CloseSource( void ){
225         if ( SourceOpen ) {
226                 free( FileStart );
227                 SourceOpen = FALSE;
228         }
229 }
230
231 //==========================================================================
232 //
233 // TK_Fetch
234 //
235 //==========================================================================
236
237 tokenType_t TK_Fetch( void ){
238         while ( Chr == ASCII_SPACE )
239         {
240                 NextChr();
241         }
242         if ( Chr == '-' ) {
243                 ProcessNumberToken();
244         }
245         else{switch ( ASCIIToChrCode[(byte)Chr] )
246                  {
247                  case CHR_EOF:
248                          tk_Token = TK_EOF;
249                          break;
250                  case CHR_LETTER:
251                          ProcessLetterToken();
252                          break;
253                  case CHR_NUMBER:
254                          ProcessNumberToken();
255                          break;
256                  case CHR_QUOTE:
257                          ProcessQuoteToken();
258                          break;
259                  default:
260                          ProcessSpecialToken();
261                          break;
262                  }}
263         return tk_Token;
264 }
265
266 //==========================================================================
267 //
268 // TK_Require
269 //
270 //==========================================================================
271
272 void TK_Require( tokenType_t tokType ){
273         if ( tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER ) {
274                 tk_FloatNumber = (float)tk_IntNumber;
275                 tk_Token = TK_FLOATNUMBER;
276                 return;
277         }
278         if ( tk_Token != tokType ) {
279                 Error( "File '%s', line %d:\nExpected '%s', found '%s'.\n",
280                            tk_SourceName, tk_Line, TokenNames[tokType],
281                            TokenNames[tk_Token] );
282         }
283 }
284
285 void TK_FetchRequire( tokenType_t tokType ){
286         TK_Fetch();
287         TK_Require( tokType );
288 }
289
290 tokenType_t TK_RequireFetch( tokenType_t tokType ){
291         TK_Require( tokType );
292         return TK_Fetch();
293 }
294
295 tokenType_t TK_FetchRequireFetch( tokenType_t tokType ){
296         TK_Fetch();
297         TK_Require( tokType );
298         return TK_Fetch();
299 }
300
301 tokenType_t TK_Beyond( tokenType_t tokType ){
302         while ( tk_Token != tokType )
303         {
304                 if ( TK_Fetch() == TK_EOF ) {
305                         Error( "File '%s':\nCould not find token '%s'.\n",       // FIXME: TokenNames table not big enuff
306                                    tk_SourceName, TokenNames[tokType] );
307                 }
308         }
309         return TK_Fetch();
310 }
311
312 void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok ){
313         TK_Beyond( bTok );
314         TK_Require( rTok );
315 }
316
317 tokenType_t TK_Search( tokenType_t tokType ){
318         while ( tk_Token != tokType )
319         {
320                 if ( TK_Fetch() == TK_EOF ) {
321                         return TK_EOF;
322                 }
323         }
324         return TK_Fetch();
325 }
326
327 tokenType_t TK_Get( tokenType_t tokType ){
328         while ( tk_Token != tokType )
329         {
330                 if ( TK_Fetch() == TK_EOF ) {
331                         Error( "File '%s':\nCould not find token '%s'.\n",
332                                    tk_SourceName, TokenNames[tokType] );
333                 }
334         }
335         return tk_Token;
336 }
337
338 //==========================================================================
339 //
340 // ProcessLetterToken
341 //
342 //==========================================================================
343
344 static void ProcessLetterToken( void ){
345         int i;
346         char *text;
347
348         i = 0;
349         text = TokenStringBuffer;
350         while ( ASCIIToChrCode[(byte)Chr] == CHR_LETTER
351                         || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
352         {
353                 if ( ++i == MAX_IDENTIFIER_LENGTH ) {
354                         Error( "File '%s', line %d:\nIdentifier too long.\n",
355                                    tk_SourceName, tk_Line );
356                 }
357                 *text++ = Chr;
358                 NextChr();
359         }
360         *text = 0;
361         if ( CheckForKeyword() == FALSE ) {
362                 tk_Token = TK_IDENTIFIER;
363         }
364 }
365
366 //==========================================================================
367 //
368 // CheckForKeyword
369 //
370 //==========================================================================
371
372 static qboolean CheckForKeyword( void ){
373         int i;
374
375         for ( i = 0; Keywords[i].name != NULL; i++ )
376         {
377                 if ( strcmp( tk_String, Keywords[i].name ) == 0 ) {
378                         tk_Token = Keywords[i].token;
379                         return TRUE;
380                 }
381         }
382         return FALSE;
383 }
384
385 //==========================================================================
386 //
387 // ProcessNumberToken
388 //
389 //==========================================================================
390
391 static void ProcessNumberToken( void ){
392         char *buffer;
393
394         buffer = TempBuffer;
395         *buffer++ = Chr;
396         NextChr();
397         while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
398         {
399                 *buffer++ = Chr;
400                 NextChr();
401         }
402         if ( Chr == '.' ) { // Float
403                 *buffer++ = Chr;
404                 NextChr(); // Skip period
405                 while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
406                 {
407                         *buffer++ = Chr;
408                         NextChr();
409                 }
410                 *buffer = 0;
411                 tk_FloatNumber = (float)atof( TempBuffer );
412                 tk_Token = TK_FLOATNUMBER;
413                 return;
414         }
415
416         // Integer
417         *buffer = 0;
418         tk_IntNumber = atoi( TempBuffer );
419         tk_Token = TK_INTNUMBER;
420 }
421
422 //==========================================================================
423 //
424 // ProcessQuoteToken
425 //
426 //==========================================================================
427
428 static void ProcessQuoteToken( void ){
429         int i;
430         char *text;
431
432         i = 0;
433         text = TokenStringBuffer;
434         NextChr();
435         while ( Chr != ASCII_QUOTE )
436         {
437                 if ( Chr == EOF_CHARACTER ) {
438                         Error( "File '%s', line %d:\n<EOF> inside string.\n",
439                                    tk_SourceName, tk_Line );
440                 }
441                 if ( ++i > MAX_QUOTED_LENGTH - 1 ) {
442                         Error( "File '%s', line %d:\nString literal too long.\n",
443                                    tk_SourceName, tk_Line );
444                 }
445                 *text++ = Chr;
446                 NextChr();
447         }
448         *text = 0;
449         NextChr();
450         tk_Token = TK_STRING;
451 }
452
453 //==========================================================================
454 //
455 // ProcessSpecialToken
456 //
457 //==========================================================================
458
459 static void ProcessSpecialToken( void ){
460         char c;
461
462         c = Chr;
463         NextChr();
464         switch ( c )
465         {
466         case '(':
467                 tk_Token = TK_LPAREN;
468                 break;
469         case ')':
470                 tk_Token = TK_RPAREN;
471                 break;
472         case '{':
473                 tk_Token = TK_LBRACE;
474                 break;
475         case '}':
476                 tk_Token = TK_RBRACE;
477                 break;
478         case '[':
479                 tk_Token = TK_LBRACKET;
480                 break;
481         case ']':
482                 tk_Token = TK_RBRACKET;
483                 break;
484         case ':':
485                 tk_Token = TK_COLON;
486                 break;
487         default:
488                 tk_Token = TK_UNKNOWNCHAR;
489                 break;
490         }
491 }
492
493 //==========================================================================
494 //
495 // NextChr
496 //
497 //==========================================================================
498
499 static void NextChr( void ){
500         if ( FilePtr >= FileEnd ) {
501                 Chr = EOF_CHARACTER;
502                 return;
503         }
504         if ( IncLineNumber == TRUE ) {
505                 tk_Line++;
506                 IncLineNumber = FALSE;
507         }
508         Chr = *FilePtr++;
509         if ( Chr < ASCII_SPACE ) {
510                 if ( Chr == '\n' ) {
511                         IncLineNumber = TRUE;
512                 }
513                 Chr = ASCII_SPACE;
514         }
515 }