OSDN Git Service

- added PinkSilver's ACS Checksight submission.
[zandronum/zandronum-acc.git] / token.c
1 \r
2 //**************************************************************************\r
3 //**\r
4 //** token.c\r
5 //**\r
6 //**************************************************************************\r
7 \r
8 // HEADER FILES ------------------------------------------------------------\r
9 \r
10 #if defined(_WIN32) && !defined(_MSC_VER)\r
11 #define WIN32_LEAN_AND_MEAN\r
12 #include <windows.h>\r
13 #endif\r
14 \r
15 #ifdef __NeXT__\r
16 #include <libc.h>\r
17 #else\r
18 #ifndef unix\r
19 #include <io.h>\r
20 #endif\r
21 #include <limits.h>\r
22 #include <fcntl.h>\r
23 #include <stdlib.h>\r
24 #endif\r
25 #include <stdio.h>\r
26 #include <string.h>\r
27 #include <ctype.h>\r
28 #include "common.h"\r
29 #include "token.h"\r
30 #include "error.h"\r
31 #include "misc.h"\r
32 #include "symbol.h"\r
33 #include "parse.h"\r
34 \r
35 // MACROS ------------------------------------------------------------------\r
36 \r
37 #define NON_HEX_DIGIT 255\r
38 #define MAX_NESTED_SOURCES 16\r
39 \r
40 // TYPES -------------------------------------------------------------------\r
41 \r
42 typedef enum\r
43 {\r
44         CHR_EOF,\r
45         CHR_LETTER,\r
46         CHR_NUMBER,\r
47         CHR_QUOTE,\r
48         CHR_SPECIAL\r
49 } chr_t;\r
50 \r
51 typedef struct\r
52 {\r
53         char *name;\r
54         char *start;\r
55         char *end;\r
56         char *position;\r
57         int line;\r
58         boolean incLineNumber;\r
59         boolean imported;\r
60         enum ImportModes prevMode;\r
61         char lastChar;\r
62 } nestInfo_t;\r
63 \r
64 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------\r
65 \r
66 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------\r
67 \r
68 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------\r
69 \r
70 static int SortKeywords(const void *a, const void *b);\r
71 static void SetLocalIncludePath(char *sourceName);\r
72 static int PopNestedSource(enum ImportModes *prevMode);\r
73 static void ProcessLetterToken(void);\r
74 static void ProcessNumberToken(void);\r
75 static void EvalFixedConstant(int whole);\r
76 static void EvalHexConstant(void);\r
77 static void EvalRadixConstant(void);\r
78 static int DigitValue(char digit, int radix);\r
79 static void ProcessQuoteToken(void);\r
80 static void ProcessSpecialToken(void);\r
81 static boolean CheckForKeyword(void);\r
82 static boolean CheckForLineSpecial(void);\r
83 static boolean CheckForConstant(void);\r
84 static void NextChr(void);\r
85 static void SkipComment(void);\r
86 static void SkipCPPComment(void);\r
87 static void BumpMasterSourceLine(char Chr, boolean clear); // master line - Ty 07jan2000\r
88 static char *AddFileName(const char *name);\r
89 static int OctalChar();\r
90 \r
91 // EXTERNAL DATA DECLARATIONS ----------------------------------------------\r
92 \r
93 // PUBLIC DATA DEFINITIONS -------------------------------------------------\r
94 \r
95 tokenType_t tk_Token;\r
96 int tk_Line;\r
97 int tk_Number;\r
98 char *tk_String;\r
99 int tk_SpecialValue;\r
100 int tk_SpecialArgCount;\r
101 char *tk_SourceName;\r
102 int tk_IncludedLines;\r
103 boolean forSemicolonHack;\r
104 char MasterSourceLine[MAX_STATEMENT_LENGTH+1];  // master line - Ty 07jan2000\r
105 int MasterSourcePos;      // master position - Ty 07jan2000\r
106 int PrevMasterSourcePos;        // previous master position - RH 09feb2000\r
107 boolean ClearMasterSourceLine;  // master clear flag - Ty 07jan2000\r
108 \r
109 // PRIVATE DATA DEFINITIONS ------------------------------------------------\r
110 \r
111 static char Chr;\r
112 static char *FileStart;\r
113 static char *FilePtr;\r
114 static char *FileEnd;\r
115 static boolean SourceOpen;\r
116 static char ASCIIToChrCode[256];\r
117 static byte ASCIIToHexDigit[256];\r
118 static char TokenStringBuffer[MAX_QUOTED_LENGTH];\r
119 static nestInfo_t OpenFiles[MAX_NESTED_SOURCES];\r
120 static boolean AlreadyGot;\r
121 static int NestDepth;\r
122 static boolean IncLineNumber;\r
123 static char *FileNames;\r
124 static size_t FileNamesLen, FileNamesMax;\r
125 \r
126 // Pascal 12/11/08\r
127 // Include paths. Lowest is searched first.\r
128 // Include path 0 is always set to the directory of the file being parsed.\r
129 static char IncludePaths[MAX_INCLUDE_PATHS][MAX_FILE_NAME_LENGTH];\r
130 static int NumIncludePaths;\r
131 \r
132 static struct keyword_s\r
133 {\r
134         char *name;\r
135         tokenType_t token;\r
136 } Keywords[] =\r
137 {\r
138         { "break", TK_BREAK },\r
139         { "case", TK_CASE },\r
140         { "const", TK_CONST },\r
141         { "continue", TK_CONTINUE },\r
142         { "default", TK_DEFAULT },\r
143         { "define", TK_DEFINE },\r
144         { "do", TK_DO },\r
145         { "else", TK_ELSE },\r
146         { "for", TK_FOR },\r
147         { "goto", TK_GOTO },\r
148         { "if", TK_IF },\r
149         { "include", TK_INCLUDE },\r
150         { "int", TK_INT },\r
151         { "open", TK_OPEN },\r
152         { "print", TK_PRINT },\r
153         { "printbold", TK_PRINTBOLD },\r
154         { "log", TK_LOG },\r
155         { "hudmessage", TK_HUDMESSAGE },\r
156         { "hudmessagebold", TK_HUDMESSAGEBOLD },\r
157         { "restart", TK_RESTART },\r
158         { "script", TK_SCRIPT },\r
159         { "special", TK_SPECIAL },\r
160         { "str", TK_STR },\r
161         { "suspend", TK_SUSPEND },\r
162         { "switch", TK_SWITCH },\r
163         { "terminate", TK_TERMINATE },\r
164         { "until", TK_UNTIL },\r
165         { "void", TK_VOID },\r
166         { "while", TK_WHILE },\r
167         { "world", TK_WORLD },\r
168         { "global", TK_GLOBAL },\r
169         // [BC] Start Skulltag tokens.\r
170         { "respawn", TK_RESPAWN },\r
171         { "death", TK_DEATH },\r
172         { "enter", TK_ENTER },\r
173         { "pickup", TK_PICKUP },\r
174         { "bluereturn", TK_BLUERETURN },\r
175         { "redreturn", TK_REDRETURN },\r
176         { "whitereturn", TK_WHITERETURN },\r
177         // [BC] End Skulltag tokens.\r
178         { "nocompact", TK_NOCOMPACT },\r
179         { "lightning", TK_LIGHTNING },\r
180         { "createtranslation", TK_CREATETRANSLATION },\r
181         { "function", TK_FUNCTION },\r
182         { "return", TK_RETURN },\r
183         { "wadauthor", TK_WADAUTHOR },\r
184         { "nowadauthor", TK_NOWADAUTHOR },\r
185         { "acs_executewait", TK_ACSEXECUTEWAIT },\r
186         { "encryptstrings", TK_ENCRYPTSTRINGS },\r
187         { "import", TK_IMPORT },\r
188         { "library", TK_LIBRARY },\r
189         { "libdefine", TK_LIBDEFINE },\r
190         { "bool", TK_BOOL },\r
191         { "net", TK_NET },\r
192         { "clientside", TK_CLIENTSIDE }, // [BB]\r
193         { "disconnect", TK_DISCONNECT },\r
194         { "unloading", TK_UNLOADING },\r
195         { "static", TK_STATIC }\r
196 };\r
197 \r
198 #define NUM_KEYWORDS (sizeof(Keywords)/sizeof(Keywords[0]))\r
199 \r
200 // CODE --------------------------------------------------------------------\r
201 \r
202 //==========================================================================\r
203 //\r
204 // TK_Init\r
205 //\r
206 //==========================================================================\r
207 \r
208 void TK_Init(void)\r
209 {\r
210         int i;\r
211 \r
212         for(i = 0; i < 256; i++)\r
213         {\r
214                 ASCIIToChrCode[i] = CHR_SPECIAL;\r
215                 ASCIIToHexDigit[i] = NON_HEX_DIGIT;\r
216         }\r
217         for(i = '0'; i <= '9'; i++)\r
218         {\r
219                 ASCIIToChrCode[i] = CHR_NUMBER;\r
220                 ASCIIToHexDigit[i] = i-'0';\r
221         }\r
222         for(i = 'A'; i <= 'F'; i++)\r
223         {\r
224                 ASCIIToHexDigit[i] = 10+(i-'A');\r
225         }\r
226         for(i = 'a'; i <= 'f'; i++)\r
227         {\r
228                 ASCIIToHexDigit[i] = 10+(i-'a');\r
229         }\r
230         for(i = 'A'; i <= 'Z'; i++)\r
231         {\r
232                 ASCIIToChrCode[i] = CHR_LETTER;\r
233         }\r
234         for(i = 'a'; i <= 'z'; i++)\r
235         {\r
236                 ASCIIToChrCode[i] = CHR_LETTER;\r
237         }\r
238         ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;\r
239         ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;\r
240         ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;\r
241         tk_String = TokenStringBuffer;\r
242         IncLineNumber = FALSE;\r
243         tk_IncludedLines = 0;\r
244         NumIncludePaths = 1;    // the first path is always the parsed file path - Pascal 12/11/08\r
245         SourceOpen = FALSE;\r
246         *MasterSourceLine = '\0'; // master line - Ty 07jan2000\r
247         MasterSourcePos = 0;      // master position - Ty 07jan2000\r
248         ClearMasterSourceLine = TRUE; // clear the line to start\r
249         qsort (Keywords, NUM_KEYWORDS, sizeof(Keywords[0]), SortKeywords);\r
250         FileNames = MS_Alloc(4096, ERR_OUT_OF_MEMORY);\r
251         FileNamesLen = 0;\r
252         FileNamesMax = 4096;\r
253 }\r
254 \r
255 //==========================================================================\r
256 //\r
257 // SortKeywords\r
258 //\r
259 //==========================================================================\r
260 \r
261 static int SortKeywords(const void *a, const void *b)\r
262 {\r
263         return strcmp (((struct keyword_s *)a)->name,\r
264                 ((struct keyword_s *)b)->name);\r
265 }\r
266 \r
267 //==========================================================================\r
268 //\r
269 // TK_OpenSource\r
270 //\r
271 //==========================================================================\r
272 \r
273 void TK_OpenSource(char *fileName)\r
274 {\r
275         int size;\r
276 \r
277         TK_CloseSource();\r
278         size = MS_LoadFile(fileName, &FileStart);\r
279         tk_SourceName = AddFileName(fileName);\r
280         SetLocalIncludePath(fileName);\r
281         SourceOpen = TRUE;\r
282         FileEnd = FileStart+size;\r
283         FilePtr = FileStart;\r
284         tk_Line = 1;\r
285         tk_Token = TK_NONE;\r
286         AlreadyGot = FALSE;\r
287         NestDepth = 0;\r
288         NextChr();\r
289 }\r
290 \r
291 //==========================================================================\r
292 //\r
293 // AddFileName\r
294 //\r
295 //==========================================================================\r
296 \r
297 static char *AddFileName(const char *name)\r
298 {\r
299         size_t len = strlen(name) + 1;\r
300         char *namespot;\r
301 \r
302         if (FileNamesLen + len > FileNamesMax)\r
303         {\r
304                 FileNames = MS_Alloc(FileNamesMax, ERR_OUT_OF_MEMORY);\r
305                 FileNamesLen = 0;\r
306         }\r
307         namespot = FileNames + FileNamesLen;\r
308         memcpy(namespot, name, len);\r
309         FileNamesLen += len;\r
310         return namespot;\r
311 }\r
312 \r
313 //==========================================================================\r
314 //\r
315 // TK_AddIncludePath\r
316 // This adds an include path with less priority than the ones already added\r
317 // \r
318 // Pascal 12/11/08\r
319 //\r
320 //==========================================================================\r
321 \r
322 void TK_AddIncludePath(char *sourcePath)\r
323 {\r
324         if(NumIncludePaths < MAX_INCLUDE_PATHS)\r
325         {\r
326                 // Add to list\r
327                 strcpy(IncludePaths[NumIncludePaths], sourcePath);\r
328                 \r
329                 // Not ending with directory delimiter?\r
330                 if(!MS_IsDirectoryDelimiter(*(IncludePaths[NumIncludePaths] + strlen(IncludePaths[NumIncludePaths]) - 1)))\r
331                 {\r
332                         // Add a directory delimiter to the include path\r
333                         strcat(IncludePaths[NumIncludePaths], "/");\r
334                 }\r
335                 MS_Message(MSG_DEBUG, "Add include path %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);\r
336                 NumIncludePaths++;\r
337         }\r
338 }\r
339 \r
340 //==========================================================================\r
341 //\r
342 // TK_AddProgramIncludePath\r
343 // Adds an include path for the directory of the executable.\r
344 //\r
345 //==========================================================================\r
346 \r
347 void TK_AddProgramIncludePath(char *progname)\r
348 {\r
349         if(NumIncludePaths < MAX_INCLUDE_PATHS)\r
350         {\r
351 #ifdef _WIN32\r
352 #ifdef _MSC_VER\r
353 #if _MSC_VER >= 1300\r
354                 if (_get_pgmptr(&progname) != 0)\r
355                 {\r
356                         return;\r
357                 }\r
358 #else\r
359                 progname = _pgmptr;\r
360 #endif\r
361 #else\r
362                 char progbuff[1024];\r
363                 GetModuleFileName(0, progbuff, sizeof(progbuff));\r
364                 progbuff[sizeof(progbuff)-1] = '\0';\r
365                 progname = progbuff;\r
366 #endif\r
367 #else\r
368                 char progbuff[PATH_MAX];\r
369                 if (realpath(progname, progbuff) != NULL)\r
370                 {\r
371                         progname = progbuff;\r
372                 }\r
373 #endif\r
374                 strcpy(IncludePaths[NumIncludePaths], progname);\r
375                 if(MS_StripFilename(IncludePaths[NumIncludePaths]))\r
376                 {\r
377                         MS_Message(MSG_DEBUG, "Program include path is %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);\r
378                         NumIncludePaths++;\r
379                 }\r
380         }\r
381 }\r
382 \r
383 //==========================================================================\r
384 //\r
385 // SetLocalIncludePath\r
386 // This sets the first include path\r
387 // \r
388 // Pascal 12/11/08\r
389 //\r
390 //==========================================================================\r
391 \r
392 static void SetLocalIncludePath(char *sourceName)\r
393 {\r
394         strcpy(IncludePaths[0], sourceName);\r
395         if(MS_StripFilename(IncludePaths[0]) == NO)\r
396         {\r
397                 IncludePaths[0][0] = 0;\r
398         }\r
399 }\r
400 \r
401 \r
402 //==========================================================================\r
403 //\r
404 // TK_Include\r
405 //\r
406 //==========================================================================\r
407 \r
408 void TK_Include(char *fileName)\r
409 {\r
410         char sourceName[MAX_FILE_NAME_LENGTH];\r
411         int size, i;\r
412         nestInfo_t *info;\r
413         boolean foundfile = FALSE;\r
414         \r
415         MS_Message(MSG_DEBUG, "*Including %s\n", fileName);\r
416         if(NestDepth == MAX_NESTED_SOURCES)\r
417         {\r
418                 ERR_Exit(ERR_INCL_NESTING_TOO_DEEP, YES, fileName);\r
419         }\r
420         info = &OpenFiles[NestDepth++];\r
421         info->name = tk_SourceName;\r
422         info->start = FileStart;\r
423         info->end = FileEnd;\r
424         info->position = FilePtr;\r
425         info->line = tk_Line;\r
426         info->incLineNumber = IncLineNumber;\r
427         info->lastChar = Chr;\r
428         info->imported = NO;\r
429         \r
430         // Pascal 30/11/08\r
431         // Handle absolute paths\r
432         if(MS_IsPathAbsolute(fileName))\r
433         {\r
434 #if defined(_WIN32) || defined(__MSDOS__)\r
435                 sourceName[0] = '\0';\r
436                 if(MS_IsDirectoryDelimiter(fileName[0]))\r
437                 {\r
438                         // The source file is absolute for the drive, but does not\r
439                         // specify a drive. Use the path for the current file to\r
440                         // get the drive letter, if it has one.\r
441                         if(IncludePaths[0][0] != '\0' && IncludePaths[0][1] == ':')\r
442                         {\r
443                                 sourceName[0] = IncludePaths[0][0];\r
444                                 sourceName[1] = ':';\r
445                                 sourceName[2] = '\0';\r
446                         }\r
447                 }\r
448                 strcat(sourceName, fileName);\r
449 #else\r
450                 strcpy(sourceName, fileName);\r
451 #endif\r
452                 foundfile = MS_FileExists(sourceName);\r
453         }\r
454         else\r
455         {\r
456                 // Pascal 12/11/08\r
457                 // Find the file in the include paths\r
458                 for(i = 0; i < NumIncludePaths; i++)\r
459                 {\r
460                         strcpy(sourceName, IncludePaths[i]);\r
461                         strcat(sourceName, fileName);\r
462                         if(MS_FileExists(sourceName))\r
463                         {\r
464                                 foundfile = TRUE;\r
465                                 break;\r
466                         }\r
467                 }\r
468         }\r
469         \r
470         if(!foundfile)\r
471         {\r
472                 ERR_ErrorAt(tk_SourceName, tk_Line);\r
473                 ERR_Exit(ERR_CANT_FIND_INCLUDE, YES, fileName, tk_SourceName, tk_Line);\r
474         }\r
475 \r
476         MS_Message(MSG_DEBUG, "*Include file found at %s\n", sourceName);\r
477 \r
478         // Now change the first include path to the file directory\r
479         SetLocalIncludePath(sourceName);\r
480         \r
481         tk_SourceName = AddFileName(sourceName);\r
482         size = MS_LoadFile(tk_SourceName, &FileStart);\r
483         FileEnd = FileStart+size;\r
484         FilePtr = FileStart;\r
485         tk_Line = 1;\r
486         IncLineNumber = FALSE;\r
487         tk_Token = TK_NONE;\r
488         AlreadyGot = FALSE;\r
489         BumpMasterSourceLine('x',TRUE); // dummy x\r
490         NextChr();\r
491 }\r
492 \r
493 //==========================================================================\r
494 //\r
495 // TK_Import\r
496 //\r
497 //==========================================================================\r
498 \r
499 void TK_Import(char *fileName, enum ImportModes prevMode)\r
500 {\r
501         TK_Include (fileName);\r
502         OpenFiles[NestDepth - 1].imported = YES;\r
503         OpenFiles[NestDepth - 1].prevMode = prevMode;\r
504         ImportMode = IMPORT_Importing;\r
505 }\r
506 \r
507 //==========================================================================\r
508 //\r
509 // PopNestedSource\r
510 //\r
511 //==========================================================================\r
512 \r
513 static int PopNestedSource(enum ImportModes *prevMode)\r
514 {\r
515         nestInfo_t *info;\r
516         \r
517         MS_Message(MSG_DEBUG, "*Leaving %s\n", tk_SourceName);\r
518         free(FileStart);\r
519         SY_FreeConstants(NestDepth);\r
520         tk_IncludedLines += tk_Line;\r
521         info = &OpenFiles[--NestDepth];\r
522         tk_SourceName = info->name;\r
523         FileStart = info->start;\r
524         FileEnd = info->end;\r
525         FilePtr = info->position;\r
526         tk_Line = info->line;\r
527         IncLineNumber = info->incLineNumber;\r
528         Chr = info->lastChar;\r
529         tk_Token = TK_NONE;\r
530         AlreadyGot = FALSE;\r
531         \r
532         // Pascal 12/11/08\r
533         // Set the first include path back to this file directory\r
534         SetLocalIncludePath(tk_SourceName);\r
535         \r
536         *prevMode = info->prevMode;\r
537         return info->imported ? 2 : 0;\r
538 }\r
539 \r
540 //==========================================================================\r
541 //\r
542 // TK_CloseSource\r
543 //\r
544 //==========================================================================\r
545 \r
546 void TK_CloseSource(void)\r
547 {\r
548         int i;\r
549 \r
550         if(SourceOpen)\r
551         {\r
552                 free(FileStart);\r
553                 for(i = 0; i < NestDepth; i++)\r
554                 {\r
555                         free(OpenFiles[i].start);\r
556                 }\r
557                 SourceOpen = FALSE;\r
558         }\r
559 }\r
560 \r
561 //==========================================================================\r
562 //\r
563 // TK_GetDepth\r
564 //\r
565 //==========================================================================\r
566 \r
567 int TK_GetDepth(void)\r
568 {\r
569         return NestDepth;\r
570 }\r
571 \r
572 //==========================================================================\r
573 //\r
574 // TK_NextToken\r
575 //\r
576 //==========================================================================\r
577 \r
578 tokenType_t TK_NextToken(void)\r
579 {\r
580         enum ImportModes prevMode;\r
581         boolean validToken;\r
582 \r
583         if(AlreadyGot == TRUE)\r
584         {\r
585                 int t = MasterSourcePos;\r
586                 MasterSourcePos = PrevMasterSourcePos;\r
587                 PrevMasterSourcePos = t;\r
588                 AlreadyGot = FALSE;\r
589                 return tk_Token;\r
590         }\r
591         validToken = NO;\r
592         PrevMasterSourcePos = MasterSourcePos;\r
593         do\r
594         {\r
595                 while(Chr == ASCII_SPACE)\r
596                 {\r
597                         NextChr();\r
598                 }\r
599                 switch(ASCIIToChrCode[(byte)Chr])\r
600                 {\r
601                 case CHR_EOF:\r
602                         tk_Token = TK_EOF;\r
603                         break;\r
604                 case CHR_LETTER:\r
605                         ProcessLetterToken();\r
606                         break;\r
607                 case CHR_NUMBER:\r
608                         ProcessNumberToken();\r
609                         break;\r
610                 case CHR_QUOTE:\r
611                         ProcessQuoteToken();\r
612                         break;\r
613                 default:\r
614                         ProcessSpecialToken();\r
615                         break;\r
616                 }\r
617                 if(tk_Token == TK_STARTCOMMENT)\r
618                 {\r
619                         SkipComment();\r
620                 }\r
621                 else if(tk_Token == TK_CPPCOMMENT)\r
622                 {\r
623                         SkipCPPComment();\r
624                 }\r
625                 else if((tk_Token == TK_EOF) && (NestDepth > 0))\r
626                 {\r
627                         if (PopNestedSource(&prevMode))\r
628                         {\r
629                                 ImportMode = prevMode;\r
630                                 if(!ExporterFlagged)\r
631                                 {\r
632                                         ERR_Exit(ERR_EXPORTER_NOT_FLAGGED, NO);\r
633                                 }\r
634                                 SY_ClearShared();\r
635                         }\r
636                 }\r
637                 else\r
638                 {\r
639                         validToken = YES;\r
640                 }\r
641         } while(validToken == NO);\r
642         return tk_Token;\r
643 }\r
644 \r
645 //==========================================================================\r
646 //\r
647 // TK_NextCharacter\r
648 //\r
649 //==========================================================================\r
650 \r
651 int TK_NextCharacter(void)\r
652 {\r
653         int c;\r
654 \r
655         while(Chr == ASCII_SPACE)\r
656         {\r
657                 NextChr();\r
658         }\r
659         c = (int)Chr;\r
660         if(c == EOF_CHARACTER)\r
661         {\r
662                 c = -1;\r
663         }\r
664         NextChr();\r
665         return c;\r
666 }\r
667 \r
668 //==========================================================================\r
669 //\r
670 // TK_SkipPast\r
671 //\r
672 //==========================================================================\r
673 \r
674 void TK_SkipPast(tokenType_t token)\r
675 {\r
676         while (tk_Token != token && tk_Token != TK_EOF)\r
677         {\r
678                 TK_NextToken();\r
679         }\r
680         TK_NextToken();\r
681 }\r
682 \r
683 //==========================================================================\r
684 //\r
685 // TK_SkipTo\r
686 //\r
687 //==========================================================================\r
688 \r
689 void TK_SkipTo(tokenType_t token)\r
690 {\r
691         while (tk_Token != token && tk_Token != TK_EOF)\r
692         {\r
693                 TK_NextToken();\r
694         }\r
695 }\r
696 \r
697 //==========================================================================\r
698 //\r
699 // TK_NextTokenMustBe\r
700 //\r
701 //==========================================================================\r
702 \r
703 boolean TK_NextTokenMustBe(tokenType_t token, error_t error)\r
704 {\r
705         if(TK_NextToken() != token)\r
706         {\r
707                 ERR_Error(error, YES);\r
708                 /*\r
709                 if(skipToken == TK_EOF)\r
710                 {\r
711                         ERR_Finish();\r
712                 }\r
713                 else if(skipToken != TK_NONE)\r
714                 {\r
715                         TK_SkipPast(skipToken);\r
716                 }\r
717                 return NO;\r
718                 */\r
719                 ERR_Finish();\r
720         }\r
721         return YES;\r
722 }\r
723 \r
724 //==========================================================================\r
725 //\r
726 // TK_TokenMustBe\r
727 //\r
728 //==========================================================================\r
729 \r
730 boolean TK_TokenMustBe(tokenType_t token, error_t error)\r
731 {\r
732         if (token == TK_SEMICOLON && forSemicolonHack)\r
733         {\r
734                 token = TK_RPAREN;\r
735         }\r
736         if(tk_Token != token)\r
737         {\r
738                 ERR_Error(error, YES);\r
739                 /*\r
740                 if(skipToken == TK_EOF)\r
741                 {\r
742                         ERR_Finish();\r
743                 }\r
744                 else if(skipToken != TK_NONE)\r
745                 {\r
746                         while(tk_Token != skipToken)\r
747                         {\r
748                                 TK_NextToken();\r
749                         }\r
750                 }\r
751                 return NO;\r
752                 */\r
753                 ERR_Finish();\r
754         }\r
755         return YES;\r
756 }\r
757 \r
758 //==========================================================================\r
759 //\r
760 // TK_Member\r
761 //\r
762 //==========================================================================\r
763 \r
764 boolean TK_Member(tokenType_t *list)\r
765 {\r
766         int i;\r
767 \r
768         for(i = 0; list[i] != TK_NONE; i++)\r
769         {\r
770                 if(tk_Token == list[i])\r
771                 {\r
772                         return YES;\r
773                 }\r
774         }\r
775         return NO;\r
776 }\r
777 \r
778 //==========================================================================\r
779 //\r
780 // TK_Undo\r
781 //\r
782 //==========================================================================\r
783 \r
784 void TK_Undo(void)\r
785 {\r
786         if(tk_Token != TK_NONE)\r
787         {\r
788                 if (AlreadyGot == FALSE)\r
789                 {\r
790                         int t = MasterSourcePos;\r
791                         MasterSourcePos = PrevMasterSourcePos;\r
792                         PrevMasterSourcePos = t;\r
793                         AlreadyGot = TRUE;\r
794                 }\r
795         }\r
796 }\r
797 \r
798 //==========================================================================\r
799 //\r
800 // ProcessLetterToken\r
801 //\r
802 //==========================================================================\r
803 \r
804 static void ProcessLetterToken(void)\r
805 {\r
806         int i;\r
807         char *text;\r
808 \r
809         i = 0;\r
810         text = TokenStringBuffer;\r
811         while (ASCIIToChrCode[(byte)Chr] == CHR_LETTER\r
812                 || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)\r
813         {\r
814                 if(++i == MAX_IDENTIFIER_LENGTH)\r
815                 {\r
816                         ERR_Error(ERR_IDENTIFIER_TOO_LONG, YES);\r
817                 }\r
818                 if(i < MAX_IDENTIFIER_LENGTH)\r
819                 {\r
820                         *text++ = Chr;\r
821                 }\r
822                 NextChr();\r
823         }\r
824         *text = 0;\r
825         MS_StrLwr(TokenStringBuffer);\r
826         if(CheckForKeyword() == FALSE\r
827                 && CheckForLineSpecial() == FALSE\r
828                 && CheckForConstant() == FALSE)\r
829         {\r
830                 tk_Token = TK_IDENTIFIER;\r
831         }\r
832 }\r
833 \r
834 //==========================================================================\r
835 //\r
836 // CheckForKeyword\r
837 //\r
838 //==========================================================================\r
839 \r
840 static boolean CheckForKeyword(void)\r
841 {\r
842         int min, max, probe, lexx;\r
843 \r
844         // [RH] Use a binary search\r
845         min = 0;\r
846         max = NUM_KEYWORDS-1;\r
847         probe = NUM_KEYWORDS/2;\r
848 \r
849         while (max - min >= 0)\r
850         {\r
851                 lexx = strcmp(tk_String, Keywords[probe].name);\r
852                 if(lexx == 0)\r
853                 {\r
854                         tk_Token = Keywords[probe].token;\r
855                         return TRUE;\r
856                 }\r
857                 else if(lexx < 0)\r
858                 {\r
859                         max = probe-1;\r
860                 }\r
861                 else\r
862                 {\r
863                         min = probe+1;\r
864                 }\r
865                 probe = (max-min)/2+min;\r
866         }\r
867         return FALSE;\r
868 }\r
869 \r
870 //==========================================================================\r
871 //\r
872 // CheckForLineSpecial\r
873 //\r
874 //==========================================================================\r
875 \r
876 static boolean CheckForLineSpecial(void)\r
877 {\r
878         symbolNode_t *sym;\r
879 \r
880         sym = SY_FindGlobal(tk_String);\r
881         if(sym == NULL)\r
882         {\r
883                 return FALSE;\r
884         }\r
885         if(sym->type != SY_SPECIAL)\r
886         {\r
887                 return FALSE;\r
888         }\r
889         tk_Token = TK_LINESPECIAL;\r
890         tk_SpecialValue = sym->info.special.value;\r
891         tk_SpecialArgCount = sym->info.special.argCount;\r
892         return TRUE;\r
893 }\r
894 \r
895 //==========================================================================\r
896 //\r
897 // CheckForConstant\r
898 //\r
899 //==========================================================================\r
900 \r
901 static boolean CheckForConstant(void)\r
902 {\r
903         symbolNode_t *sym;\r
904 \r
905         sym = SY_FindGlobal(tk_String);\r
906         if(sym == NULL)\r
907         {\r
908                 return FALSE;\r
909         }\r
910         if(sym->type != SY_CONSTANT)\r
911         {\r
912                 return FALSE;\r
913         }\r
914         tk_Token = TK_NUMBER;\r
915         tk_Number = sym->info.constant.value;\r
916         return TRUE;\r
917 }\r
918 \r
919 //==========================================================================\r
920 //\r
921 // ProcessNumberToken\r
922 //\r
923 //==========================================================================\r
924 \r
925 static void ProcessNumberToken(void)\r
926 {\r
927         char c;\r
928 \r
929         c = Chr;\r
930         NextChr();\r
931         if(c == '0' && (Chr == 'x' || Chr == 'X'))\r
932         { // Hexadecimal constant\r
933                 NextChr();\r
934                 EvalHexConstant();\r
935                 return;\r
936         }\r
937         tk_Number = c-'0';\r
938         while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)\r
939         {\r
940                 tk_Number = 10*tk_Number+(Chr-'0');\r
941                 NextChr();\r
942         }\r
943         if(Chr == '.')\r
944         { // Fixed point\r
945                 NextChr(); // Skip period\r
946                 EvalFixedConstant(tk_Number);\r
947                 return;\r
948         }\r
949         if(Chr == ASCII_UNDERSCORE)\r
950         {\r
951                 NextChr(); // Skip underscore\r
952                 EvalRadixConstant();\r
953                 return;\r
954         }\r
955         tk_Token = TK_NUMBER;\r
956 }\r
957 \r
958 //==========================================================================\r
959 //\r
960 // EvalFixedConstant\r
961 //\r
962 //==========================================================================\r
963 \r
964 static void EvalFixedConstant(int whole)\r
965 {\r
966         double frac;\r
967         double divisor;\r
968 \r
969         frac = 0;\r
970         divisor = 1;\r
971         while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)\r
972         {\r
973                 frac = 10*frac+(Chr-'0');\r
974                 divisor *= 10;\r
975                 NextChr();\r
976         }\r
977         tk_Number = (whole<<16)+(int)(65536.0*frac/divisor);\r
978         tk_Token = TK_NUMBER;\r
979 }\r
980 \r
981 //==========================================================================\r
982 //\r
983 // EvalHexConstant\r
984 //\r
985 //==========================================================================\r
986 \r
987 static void EvalHexConstant(void)\r
988 {\r
989         tk_Number = 0;\r
990         while(ASCIIToHexDigit[(byte)Chr] != NON_HEX_DIGIT)\r
991         {\r
992                 tk_Number = (tk_Number<<4)+ASCIIToHexDigit[(byte)Chr];\r
993                 NextChr();\r
994         }\r
995         tk_Token = TK_NUMBER;\r
996 }\r
997 \r
998 //==========================================================================\r
999 //\r
1000 // EvalRadixConstant\r
1001 //\r
1002 //==========================================================================\r
1003 \r
1004 static void EvalRadixConstant(void)\r
1005 {\r
1006         int radix;\r
1007         int digitVal;\r
1008 \r
1009         radix = tk_Number;\r
1010         if(radix < 2 || radix > 36)\r
1011         {\r
1012                 ERR_Error(ERR_BAD_RADIX_CONSTANT, YES, NULL);\r
1013                 radix = 36;\r
1014         }\r
1015         tk_Number = 0;\r
1016         while((digitVal = DigitValue(Chr, radix)) != -1)\r
1017         {\r
1018                 tk_Number = radix*tk_Number+digitVal;\r
1019                 NextChr();\r
1020         }\r
1021         tk_Token = TK_NUMBER;\r
1022 }\r
1023 \r
1024 //==========================================================================\r
1025 //\r
1026 // DigitValue\r
1027 //\r
1028 // Returns -1 if the digit is not allowed in the specified radix.\r
1029 //\r
1030 //==========================================================================\r
1031 \r
1032 static int DigitValue(char digit, int radix)\r
1033 {\r
1034         digit = toupper(digit);\r
1035         if(digit < '0' || (digit > '9' && digit < 'A') || digit > 'Z')\r
1036         {\r
1037                 return -1;\r
1038         }\r
1039         if(digit > '9')\r
1040         {\r
1041                 digit = 10+digit-'A';\r
1042         }\r
1043         else\r
1044         {\r
1045                 digit -= '0';\r
1046         }\r
1047         if(digit >= radix)\r
1048         {\r
1049                 return -1;\r
1050         }\r
1051         return digit;\r
1052 }\r
1053 \r
1054 //==========================================================================\r
1055 //\r
1056 // ProcessQuoteToken\r
1057 //\r
1058 //==========================================================================\r
1059 \r
1060 static void ProcessQuoteToken(void)\r
1061 {\r
1062         int i;\r
1063         char *text;\r
1064         boolean escaped;\r
1065 \r
1066         i = 0;\r
1067         escaped = FALSE;\r
1068         text = TokenStringBuffer;\r
1069         NextChr();\r
1070         while(Chr != EOF_CHARACTER)\r
1071         {\r
1072                 if(Chr == ASCII_QUOTE && escaped == 0) // [JB]\r
1073                 {\r
1074                         break;\r
1075                 }\r
1076                 if(++i == MAX_QUOTED_LENGTH)\r
1077                 {\r
1078                         ERR_Error(ERR_STRING_TOO_LONG, YES, NULL);\r
1079                 }\r
1080                 if(i < MAX_QUOTED_LENGTH)\r
1081                 {\r
1082                         *text++ = Chr;\r
1083                 }\r
1084                 // escape the character after a backslash [JB]\r
1085                 if(Chr == '\\')\r
1086                         escaped ^= (Chr == '\\');\r
1087                 else\r
1088                         escaped = FALSE;\r
1089                 NextChr();\r
1090         }\r
1091         *text = 0;\r
1092         if(Chr == ASCII_QUOTE)\r
1093         {\r
1094                 NextChr();\r
1095         }\r
1096         tk_Token = TK_STRING;\r
1097 }\r
1098 \r
1099 //==========================================================================\r
1100 //\r
1101 // ProcessSpecialToken\r
1102 //\r
1103 //==========================================================================\r
1104 \r
1105 static void ProcessSpecialToken(void)\r
1106 {\r
1107         char c;\r
1108 \r
1109         c = Chr;\r
1110         NextChr();\r
1111         switch(c)\r
1112         {\r
1113                 case '+':\r
1114                         switch(Chr)\r
1115                         {\r
1116                                 case '=':\r
1117                                         tk_Token = TK_ADDASSIGN;\r
1118                                         NextChr();\r
1119                                         break;\r
1120                                 case '+':\r
1121                                         tk_Token = TK_INC;\r
1122                                         NextChr();\r
1123                                         break;\r
1124                                 default:\r
1125                                         tk_Token = TK_PLUS;\r
1126                                         break;\r
1127                         }\r
1128                         break;\r
1129                 case '-':\r
1130                         switch(Chr)\r
1131                         {\r
1132                                 case '=':\r
1133                                         tk_Token = TK_SUBASSIGN;\r
1134                                         NextChr();\r
1135                                         break;\r
1136                                 case '-':\r
1137                                         tk_Token = TK_DEC;\r
1138                                         NextChr();\r
1139                                         break;\r
1140                                 default:\r
1141                                         tk_Token = TK_MINUS;\r
1142                                         break;\r
1143                         }\r
1144                         break;\r
1145                 case '*':\r
1146                         switch(Chr)\r
1147                         {\r
1148                                 case '=':\r
1149                                         tk_Token = TK_MULASSIGN;\r
1150                                         NextChr();\r
1151                                         break;\r
1152                                 case '/':\r
1153                                         tk_Token = TK_ENDCOMMENT;\r
1154                                         NextChr();\r
1155                                         break;\r
1156                                 default:\r
1157                                         tk_Token = TK_ASTERISK;\r
1158                                         break;\r
1159                         }\r
1160                         break;\r
1161                 case '/':\r
1162                         switch(Chr)\r
1163                         {\r
1164                                 case '=':\r
1165                                         tk_Token = TK_DIVASSIGN;\r
1166                                         NextChr();\r
1167                                         break;\r
1168                                 case '/':\r
1169                                         tk_Token = TK_CPPCOMMENT;\r
1170                                         break;\r
1171                                 case '*':\r
1172                                         tk_Token = TK_STARTCOMMENT;\r
1173                                         NextChr();\r
1174                                         break;\r
1175                                 default:\r
1176                                         tk_Token = TK_SLASH;\r
1177                                         break;\r
1178                         }\r
1179                         break;\r
1180                 case '%':\r
1181                         if(Chr == '=')\r
1182                         {\r
1183                                 tk_Token = TK_MODASSIGN;\r
1184                                 NextChr();\r
1185                         }\r
1186                         else\r
1187                         {\r
1188                                 tk_Token = TK_PERCENT;\r
1189                         }\r
1190                         break;\r
1191                 case '=':\r
1192                         if(Chr == '=')\r
1193                         {\r
1194                                 tk_Token = TK_EQ;\r
1195                                 NextChr();\r
1196                         }\r
1197                         else\r
1198                         {\r
1199                                 tk_Token = TK_ASSIGN;\r
1200                         }\r
1201                         break;\r
1202                 case '<':\r
1203                         if(Chr == '=')\r
1204                         {\r
1205                                 tk_Token = TK_LE;\r
1206                                 NextChr();\r
1207                         }\r
1208                         else if(Chr == '<')\r
1209                         {\r
1210                                 NextChr();\r
1211                                 if(Chr == '=')\r
1212                                 {\r
1213                                         tk_Token = TK_LSASSIGN;\r
1214                                         NextChr();\r
1215                                 }\r
1216                                 else\r
1217                                 {\r
1218                                         tk_Token = TK_LSHIFT;\r
1219                                 }\r
1220                                 \r
1221                         }\r
1222                         else\r
1223                         {\r
1224                                 tk_Token = TK_LT;\r
1225                         }\r
1226                         break;\r
1227                 case '>':\r
1228                         if(Chr == '=')\r
1229                         {\r
1230                                 tk_Token = TK_GE;\r
1231                                 NextChr();\r
1232                         }\r
1233                         else if(Chr == '>')\r
1234                         {\r
1235                                 NextChr();\r
1236                                 if(Chr == '=')\r
1237                                 {\r
1238                                         tk_Token = TK_RSASSIGN;\r
1239                                         NextChr();\r
1240                                 }\r
1241                                 else\r
1242                                 {\r
1243                                         tk_Token = TK_RSHIFT;\r
1244                                 }\r
1245                         }\r
1246                         else\r
1247                         {\r
1248                                 tk_Token = TK_GT;\r
1249                         }\r
1250                         break;\r
1251                 case '!':\r
1252                         if(Chr == '=')\r
1253                         {\r
1254                                 tk_Token = TK_NE;\r
1255                                 NextChr();\r
1256                         }\r
1257                         else\r
1258                         {\r
1259                                 tk_Token = TK_NOT;\r
1260                         }\r
1261                         break;\r
1262                 case '&':\r
1263                         if(Chr == '&')\r
1264                         {\r
1265                                 tk_Token = TK_ANDLOGICAL;\r
1266                                 NextChr();\r
1267                         }\r
1268                         else if(Chr == '=')\r
1269                         {\r
1270                                 tk_Token = TK_ANDASSIGN;\r
1271                                 NextChr();\r
1272                         }\r
1273                         else\r
1274                         {\r
1275                                 tk_Token = TK_ANDBITWISE;\r
1276                         }\r
1277                         break;\r
1278                 case '|':\r
1279                         if(Chr == '|')\r
1280                         {\r
1281                                 tk_Token = TK_ORLOGICAL;\r
1282                                 NextChr();\r
1283                         }\r
1284                         else if(Chr == '=')\r
1285                         {\r
1286                                 tk_Token = TK_ORASSIGN;\r
1287                                 NextChr();\r
1288                         }\r
1289                         else\r
1290                         {\r
1291                                 tk_Token = TK_ORBITWISE;\r
1292                         }\r
1293                         break;\r
1294                 case '(':\r
1295                         tk_Token = TK_LPAREN;\r
1296                         break;\r
1297                 case ')':\r
1298                         tk_Token = TK_RPAREN;\r
1299                         break;\r
1300                 case '{':\r
1301                         tk_Token = TK_LBRACE;\r
1302                         break;\r
1303                 case '}':\r
1304                         tk_Token = TK_RBRACE;\r
1305                         break;\r
1306                 case '[':\r
1307                         tk_Token = TK_LBRACKET;\r
1308                         break;\r
1309                 case ']':\r
1310                         tk_Token = TK_RBRACKET;\r
1311                         break;\r
1312                 case ':':\r
1313                         tk_Token = TK_COLON;\r
1314                         break;\r
1315                 case ';':\r
1316                         tk_Token = TK_SEMICOLON;\r
1317                         break;\r
1318                 case ',':\r
1319                         tk_Token = TK_COMMA;\r
1320                         break;\r
1321                 case '.':\r
1322                         tk_Token = TK_PERIOD;\r
1323                         break;\r
1324                 case '#':\r
1325                         tk_Token = TK_NUMBERSIGN;\r
1326                         break;\r
1327                 case '^':\r
1328                         if(Chr == '=')\r
1329                         {\r
1330                                 tk_Token = TK_EORASSIGN;\r
1331                                 NextChr();\r
1332                         }\r
1333                         else\r
1334                         {\r
1335                                 tk_Token = TK_EORBITWISE;\r
1336                         }\r
1337                         break;\r
1338                 case '~':\r
1339                         tk_Token = TK_TILDE;\r
1340                         break;\r
1341                 case '\'':\r
1342                         if(Chr == '\\')\r
1343                         {\r
1344                                 NextChr();\r
1345                                 switch(Chr)\r
1346                                 {\r
1347                                 case '0': case '1': case '2': case '3':\r
1348                                 case '4': case '5': case '6': case '7':\r
1349                                         tk_Number = OctalChar();\r
1350                                         break;\r
1351                                 case 'x': case 'X':\r
1352                                         NextChr();\r
1353                                         EvalHexConstant();\r
1354                                         if(Chr != '\'')\r
1355                                         {\r
1356                                                 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);\r
1357                                         }\r
1358                                         NextChr();\r
1359                                         break;\r
1360                                 case 'a':\r
1361                                         tk_Number = '\a';\r
1362                                         break;\r
1363                                 case 'b':\r
1364                                         tk_Number = '\b';\r
1365                                         break;\r
1366                                 case 't':\r
1367                                         tk_Number = '\t';\r
1368                                         break;\r
1369                                 case 'v':\r
1370                                         tk_Number = '\v';\r
1371                                         break;\r
1372                                 case 'n':\r
1373                                         tk_Number = '\n';\r
1374                                         break;\r
1375                                 case 'f':\r
1376                                         tk_Number = '\f';\r
1377                                         break;\r
1378                                 case 'r':\r
1379                                         tk_Number = '\r';\r
1380                                         break;\r
1381                                 case '\'':\r
1382                                 case '\\':\r
1383                                         tk_Number = Chr;\r
1384                                         break;\r
1385                                 default:\r
1386                                         ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);\r
1387                                 }\r
1388                                 tk_Token = TK_NUMBER;\r
1389                         }\r
1390                         else if(Chr == '\'')\r
1391                         {\r
1392                                 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);\r
1393                         }\r
1394                         else\r
1395                         {\r
1396                                 tk_Number = Chr;\r
1397                                 tk_Token = TK_NUMBER;\r
1398                         }\r
1399                         NextChr();\r
1400                         if(Chr != '\'')\r
1401                         {\r
1402                                 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);\r
1403                         }\r
1404                         NextChr();\r
1405                         break;\r
1406                 default:\r
1407                         ERR_Exit(ERR_BAD_CHARACTER, YES, NULL);\r
1408                         break;\r
1409         }\r
1410 }\r
1411 \r
1412 //==========================================================================\r
1413 //\r
1414 // NextChr\r
1415 //\r
1416 //==========================================================================\r
1417 \r
1418 static void NextChr(void)\r
1419 {\r
1420         if(FilePtr >= FileEnd)\r
1421         {\r
1422                 Chr = EOF_CHARACTER;\r
1423                 return;\r
1424         }\r
1425         if(IncLineNumber == TRUE)\r
1426         {\r
1427                 tk_Line++;\r
1428                 IncLineNumber = FALSE;\r
1429                 BumpMasterSourceLine('x',TRUE); // dummy x\r
1430         }\r
1431         Chr = *FilePtr++;\r
1432         if(Chr < ASCII_SPACE && Chr >= 0)       // Allow high ASCII characters\r
1433         {\r
1434                 if(Chr == '\n')\r
1435                 {\r
1436                         IncLineNumber = TRUE;\r
1437                 }\r
1438                 Chr = ASCII_SPACE;\r
1439         }\r
1440         BumpMasterSourceLine(Chr,FALSE);\r
1441 }\r
1442 \r
1443 //==========================================================================\r
1444 //\r
1445 // PeekChr // [JB]\r
1446 //\r
1447 //==========================================================================\r
1448 \r
1449 static int PeekChr(void)\r
1450 {\r
1451         char ch;\r
1452         if(FilePtr >= FileEnd)\r
1453         {\r
1454                 return EOF_CHARACTER;\r
1455         }\r
1456         ch = *FilePtr-1;\r
1457         if(ch < ASCII_SPACE && ch >= 0) // Allow high ASCII characters\r
1458         {\r
1459                 ch = ASCII_SPACE;\r
1460         }\r
1461         return ch;\r
1462 }\r
1463 \r
1464 //==========================================================================\r
1465 //\r
1466 // OctalChar // [JB]\r
1467 //\r
1468 //==========================================================================\r
1469 \r
1470 static int OctalChar() \r
1471 {\r
1472         int digits = 1;\r
1473         int code = Chr - '0';\r
1474         while(digits < 4 && PeekChr() >= '0' && PeekChr() <= '7')\r
1475         {\r
1476                 NextChr();\r
1477                 code = (code << 3) + Chr - '0';\r
1478         }\r
1479         return code;\r
1480 }\r
1481 \r
1482 //==========================================================================\r
1483 //\r
1484 // SkipComment\r
1485 //\r
1486 //==========================================================================\r
1487 \r
1488 void SkipComment(void)\r
1489 {\r
1490         boolean first;\r
1491 \r
1492         first = FALSE;\r
1493         while(Chr != EOF_CHARACTER)\r
1494         {\r
1495                 if(first == TRUE && Chr == '/')\r
1496                 {\r
1497                         break;\r
1498                 }\r
1499                 first = (Chr == '*');\r
1500                 NextChr();\r
1501         }\r
1502         NextChr();\r
1503 }\r
1504 \r
1505 //==========================================================================\r
1506 //\r
1507 // SkipCPPComment\r
1508 //\r
1509 //==========================================================================\r
1510 \r
1511 void SkipCPPComment(void)\r
1512 {\r
1513         while(FilePtr < FileEnd)\r
1514         {\r
1515                 if(*FilePtr++ == '\n')\r
1516                 {\r
1517                         tk_Line++;\r
1518                         BumpMasterSourceLine('x',TRUE); // dummy x\r
1519                         break;\r
1520                 }\r
1521         }\r
1522         NextChr();\r
1523 }\r
1524 \r
1525 //==========================================================================\r
1526 //\r
1527 // BumpMasterSourceLine\r
1528 //\r
1529 //==========================================================================\r
1530 \r
1531 void BumpMasterSourceLine(char Chr, boolean clear) // master line - Ty 07jan2000\r
1532 {\r
1533         if (ClearMasterSourceLine)  // set to clear last time, clear now for first character\r
1534         {\r
1535                 *MasterSourceLine = '\0';\r
1536                 MasterSourcePos = 0;\r
1537                 ClearMasterSourceLine = FALSE;\r
1538         }\r
1539         if (clear)\r
1540         {\r
1541                 ClearMasterSourceLine = TRUE;\r
1542         }\r
1543         else\r
1544         {\r
1545                 if (MasterSourcePos < MAX_STATEMENT_LENGTH)\r
1546                         MasterSourceLine[MasterSourcePos++] = Chr;\r
1547         }\r
1548 }\r
1549 \r
1550 //==========================================================================\r
1551 //\r
1552 // TK_SkipLine\r
1553 //\r
1554 //==========================================================================\r
1555 \r
1556 void TK_SkipLine(void)\r
1557 {\r
1558         char *sourcenow = tk_SourceName;\r
1559         int linenow = tk_Line;\r
1560         do TK_NextToken(); while (tk_Line == linenow && tk_SourceName == sourcenow);\r
1561 }\r