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