OSDN Git Service

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