2 //**************************************************************************
\r
6 //**************************************************************************
\r
8 // HEADER FILES ------------------------------------------------------------
\r
10 #if defined(_WIN32) && !defined(_MSC_VER)
\r
11 #define WIN32_LEAN_AND_MEAN
\r
12 #include <windows.h>
\r
35 // MACROS ------------------------------------------------------------------
\r
37 #define NON_HEX_DIGIT 255
\r
38 #define MAX_NESTED_SOURCES 16
\r
40 // TYPES -------------------------------------------------------------------
\r
58 boolean incLineNumber;
\r
60 enum ImportModes prevMode;
\r
64 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
\r
66 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
\r
68 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
\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
91 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
\r
93 // PUBLIC DATA DEFINITIONS -------------------------------------------------
\r
95 tokenType_t tk_Token;
\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
109 // PRIVATE DATA DEFINITIONS ------------------------------------------------
\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
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
132 static struct keyword_s
\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
145 { "else", TK_ELSE },
\r
147 { "goto", TK_GOTO },
\r
149 { "include", TK_INCLUDE },
\r
151 { "open", TK_OPEN },
\r
152 { "print", TK_PRINT },
\r
153 { "printbold", TK_PRINTBOLD },
\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
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
192 { "clientside", TK_CLIENTSIDE }, // [BB]
\r
193 { "disconnect", TK_DISCONNECT },
\r
194 { "unloading", TK_UNLOADING },
\r
195 { "static", TK_STATIC }
\r
198 #define NUM_KEYWORDS (sizeof(Keywords)/sizeof(Keywords[0]))
\r
200 // CODE --------------------------------------------------------------------
\r
202 //==========================================================================
\r
206 //==========================================================================
\r
212 for(i = 0; i < 256; i++)
\r
214 ASCIIToChrCode[i] = CHR_SPECIAL;
\r
215 ASCIIToHexDigit[i] = NON_HEX_DIGIT;
\r
217 for(i = '0'; i <= '9'; i++)
\r
219 ASCIIToChrCode[i] = CHR_NUMBER;
\r
220 ASCIIToHexDigit[i] = i-'0';
\r
222 for(i = 'A'; i <= 'F'; i++)
\r
224 ASCIIToHexDigit[i] = 10+(i-'A');
\r
226 for(i = 'a'; i <= 'f'; i++)
\r
228 ASCIIToHexDigit[i] = 10+(i-'a');
\r
230 for(i = 'A'; i <= 'Z'; i++)
\r
232 ASCIIToChrCode[i] = CHR_LETTER;
\r
234 for(i = 'a'; i <= 'z'; i++)
\r
236 ASCIIToChrCode[i] = CHR_LETTER;
\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
252 FileNamesMax = 4096;
\r
255 //==========================================================================
\r
259 //==========================================================================
\r
261 static int SortKeywords(const void *a, const void *b)
\r
263 return strcmp (((struct keyword_s *)a)->name,
\r
264 ((struct keyword_s *)b)->name);
\r
267 //==========================================================================
\r
271 //==========================================================================
\r
273 void TK_OpenSource(char *fileName)
\r
278 size = MS_LoadFile(fileName, &FileStart);
\r
279 tk_SourceName = AddFileName(fileName);
\r
280 SetLocalIncludePath(fileName);
\r
282 FileEnd = FileStart+size;
\r
283 FilePtr = FileStart;
\r
285 tk_Token = TK_NONE;
\r
286 AlreadyGot = FALSE;
\r
291 //==========================================================================
\r
295 //==========================================================================
\r
297 static char *AddFileName(const char *name)
\r
299 size_t len = strlen(name) + 1;
\r
302 if (FileNamesLen + len > FileNamesMax)
\r
304 FileNames = MS_Alloc(FileNamesMax, ERR_OUT_OF_MEMORY);
\r
307 namespot = FileNames + FileNamesLen;
\r
308 memcpy(namespot, name, len);
\r
309 FileNamesLen += len;
\r
313 //==========================================================================
\r
315 // TK_AddIncludePath
\r
316 // This adds an include path with less priority than the ones already added
\r
320 //==========================================================================
\r
322 void TK_AddIncludePath(char *sourcePath)
\r
324 if(NumIncludePaths < MAX_INCLUDE_PATHS)
\r
327 strcpy(IncludePaths[NumIncludePaths], sourcePath);
\r
329 // Not ending with directory delimiter?
\r
330 if(!MS_IsDirectoryDelimiter(*(IncludePaths[NumIncludePaths] + strlen(IncludePaths[NumIncludePaths]) - 1)))
\r
332 // Add a directory delimiter to the include path
\r
333 strcat(IncludePaths[NumIncludePaths], "/");
\r
335 MS_Message(MSG_DEBUG, "Add include path %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);
\r
340 //==========================================================================
\r
342 // TK_AddProgramIncludePath
\r
343 // Adds an include path for the directory of the executable.
\r
345 //==========================================================================
\r
347 void TK_AddProgramIncludePath(char *progname)
\r
349 if(NumIncludePaths < MAX_INCLUDE_PATHS)
\r
353 #if _MSC_VER >= 1300
\r
354 if (_get_pgmptr(&progname) != 0)
\r
359 progname = _pgmptr;
\r
362 char progbuff[1024];
\r
363 GetModuleFileName(0, progbuff, sizeof(progbuff));
\r
364 progbuff[sizeof(progbuff)-1] = '\0';
\r
365 progname = progbuff;
\r
368 char progbuff[PATH_MAX];
\r
369 if (realpath(progname, progbuff) != NULL)
\r
371 progname = progbuff;
\r
374 strcpy(IncludePaths[NumIncludePaths], progname);
\r
375 if(MS_StripFilename(IncludePaths[NumIncludePaths]))
\r
377 MS_Message(MSG_DEBUG, "Program include path is %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);
\r
383 //==========================================================================
\r
385 // SetLocalIncludePath
\r
386 // This sets the first include path
\r
390 //==========================================================================
\r
392 static void SetLocalIncludePath(char *sourceName)
\r
394 strcpy(IncludePaths[0], sourceName);
\r
395 if(MS_StripFilename(IncludePaths[0]) == NO)
\r
397 IncludePaths[0][0] = 0;
\r
402 //==========================================================================
\r
406 //==========================================================================
\r
408 void TK_Include(char *fileName)
\r
410 char sourceName[MAX_FILE_NAME_LENGTH];
\r
413 boolean foundfile = FALSE;
\r
415 MS_Message(MSG_DEBUG, "*Including %s\n", fileName);
\r
416 if(NestDepth == MAX_NESTED_SOURCES)
\r
418 ERR_Exit(ERR_INCL_NESTING_TOO_DEEP, YES, fileName);
\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
431 // Handle absolute paths
\r
432 if(MS_IsPathAbsolute(fileName))
\r
434 #if defined(_WIN32) || defined(__MSDOS__)
\r
435 sourceName[0] = '\0';
\r
436 if(MS_IsDirectoryDelimiter(fileName[0]))
\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
443 sourceName[0] = IncludePaths[0][0];
\r
444 sourceName[1] = ':';
\r
445 sourceName[2] = '\0';
\r
448 strcat(sourceName, fileName);
\r
450 strcpy(sourceName, fileName);
\r
452 foundfile = MS_FileExists(sourceName);
\r
457 // Find the file in the include paths
\r
458 for(i = 0; i < NumIncludePaths; i++)
\r
460 strcpy(sourceName, IncludePaths[i]);
\r
461 strcat(sourceName, fileName);
\r
462 if(MS_FileExists(sourceName))
\r
472 ERR_ErrorAt(tk_SourceName, tk_Line);
\r
473 ERR_Exit(ERR_CANT_FIND_INCLUDE, YES, fileName, tk_SourceName, tk_Line);
\r
476 MS_Message(MSG_DEBUG, "*Include file found at %s\n", sourceName);
\r
478 // Now change the first include path to the file directory
\r
479 SetLocalIncludePath(sourceName);
\r
481 tk_SourceName = AddFileName(sourceName);
\r
482 size = MS_LoadFile(tk_SourceName, &FileStart);
\r
483 FileEnd = FileStart+size;
\r
484 FilePtr = FileStart;
\r
486 IncLineNumber = FALSE;
\r
487 tk_Token = TK_NONE;
\r
488 AlreadyGot = FALSE;
\r
489 BumpMasterSourceLine('x',TRUE); // dummy x
\r
493 //==========================================================================
\r
497 //==========================================================================
\r
499 void TK_Import(char *fileName, enum ImportModes prevMode)
\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
507 //==========================================================================
\r
511 //==========================================================================
\r
513 static int PopNestedSource(enum ImportModes *prevMode)
\r
517 MS_Message(MSG_DEBUG, "*Leaving %s\n", tk_SourceName);
\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
533 // Set the first include path back to this file directory
\r
534 SetLocalIncludePath(tk_SourceName);
\r
536 *prevMode = info->prevMode;
\r
537 return info->imported ? 2 : 0;
\r
540 //==========================================================================
\r
544 //==========================================================================
\r
546 void TK_CloseSource(void)
\r
553 for(i = 0; i < NestDepth; i++)
\r
555 free(OpenFiles[i].start);
\r
557 SourceOpen = FALSE;
\r
561 //==========================================================================
\r
565 //==========================================================================
\r
567 int TK_GetDepth(void)
\r
572 //==========================================================================
\r
576 //==========================================================================
\r
578 tokenType_t TK_NextToken(void)
\r
580 enum ImportModes prevMode;
\r
581 boolean validToken;
\r
583 if(AlreadyGot == TRUE)
\r
585 int t = MasterSourcePos;
\r
586 MasterSourcePos = PrevMasterSourcePos;
\r
587 PrevMasterSourcePos = t;
\r
588 AlreadyGot = FALSE;
\r
592 PrevMasterSourcePos = MasterSourcePos;
\r
595 while(Chr == ASCII_SPACE)
\r
599 switch(ASCIIToChrCode[(byte)Chr])
\r
605 ProcessLetterToken();
\r
608 ProcessNumberToken();
\r
611 ProcessQuoteToken();
\r
614 ProcessSpecialToken();
\r
617 if(tk_Token == TK_STARTCOMMENT)
\r
621 else if(tk_Token == TK_CPPCOMMENT)
\r
625 else if((tk_Token == TK_EOF) && (NestDepth > 0))
\r
627 if (PopNestedSource(&prevMode))
\r
629 ImportMode = prevMode;
\r
630 if(!ExporterFlagged)
\r
632 ERR_Exit(ERR_EXPORTER_NOT_FLAGGED, NO);
\r
641 } while(validToken == NO);
\r
645 //==========================================================================
\r
647 // TK_NextCharacter
\r
649 //==========================================================================
\r
651 int TK_NextCharacter(void)
\r
655 while(Chr == ASCII_SPACE)
\r
660 if(c == EOF_CHARACTER)
\r
668 //==========================================================================
\r
672 //==========================================================================
\r
674 void TK_SkipPast(tokenType_t token)
\r
676 while (tk_Token != token && tk_Token != TK_EOF)
\r
683 //==========================================================================
\r
687 //==========================================================================
\r
689 void TK_SkipTo(tokenType_t token)
\r
691 while (tk_Token != token && tk_Token != TK_EOF)
\r
697 //==========================================================================
\r
699 // TK_NextTokenMustBe
\r
701 //==========================================================================
\r
703 boolean TK_NextTokenMustBe(tokenType_t token, error_t error)
\r
705 if(TK_NextToken() != token)
\r
707 ERR_Error(error, YES);
\r
709 if(skipToken == TK_EOF)
\r
713 else if(skipToken != TK_NONE)
\r
715 TK_SkipPast(skipToken);
\r
724 //==========================================================================
\r
728 //==========================================================================
\r
730 boolean TK_TokenMustBe(tokenType_t token, error_t error)
\r
732 if (token == TK_SEMICOLON && forSemicolonHack)
\r
736 if(tk_Token != token)
\r
738 ERR_Error(error, YES);
\r
740 if(skipToken == TK_EOF)
\r
744 else if(skipToken != TK_NONE)
\r
746 while(tk_Token != skipToken)
\r
758 //==========================================================================
\r
762 //==========================================================================
\r
764 boolean TK_Member(tokenType_t *list)
\r
768 for(i = 0; list[i] != TK_NONE; i++)
\r
770 if(tk_Token == list[i])
\r
778 //==========================================================================
\r
782 //==========================================================================
\r
786 if(tk_Token != TK_NONE)
\r
788 if (AlreadyGot == FALSE)
\r
790 int t = MasterSourcePos;
\r
791 MasterSourcePos = PrevMasterSourcePos;
\r
792 PrevMasterSourcePos = t;
\r
798 //==========================================================================
\r
800 // ProcessLetterToken
\r
802 //==========================================================================
\r
804 static void ProcessLetterToken(void)
\r
810 text = TokenStringBuffer;
\r
811 while (ASCIIToChrCode[(byte)Chr] == CHR_LETTER
\r
812 || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
814 if(++i == MAX_IDENTIFIER_LENGTH)
\r
816 ERR_Error(ERR_IDENTIFIER_TOO_LONG, YES);
\r
818 if(i < MAX_IDENTIFIER_LENGTH)
\r
825 MS_StrLwr(TokenStringBuffer);
\r
826 if(CheckForKeyword() == FALSE
\r
827 && CheckForLineSpecial() == FALSE
\r
828 && CheckForConstant() == FALSE)
\r
830 tk_Token = TK_IDENTIFIER;
\r
834 //==========================================================================
\r
838 //==========================================================================
\r
840 static boolean CheckForKeyword(void)
\r
842 int min, max, probe, lexx;
\r
844 // [RH] Use a binary search
\r
846 max = NUM_KEYWORDS-1;
\r
847 probe = NUM_KEYWORDS/2;
\r
849 while (max - min >= 0)
\r
851 lexx = strcmp(tk_String, Keywords[probe].name);
\r
854 tk_Token = Keywords[probe].token;
\r
865 probe = (max-min)/2+min;
\r
870 //==========================================================================
\r
872 // CheckForLineSpecial
\r
874 //==========================================================================
\r
876 static boolean CheckForLineSpecial(void)
\r
880 sym = SY_FindGlobal(tk_String);
\r
885 if(sym->type != SY_SPECIAL)
\r
889 tk_Token = TK_LINESPECIAL;
\r
890 tk_SpecialValue = sym->info.special.value;
\r
891 tk_SpecialArgCount = sym->info.special.argCount;
\r
895 //==========================================================================
\r
897 // CheckForConstant
\r
899 //==========================================================================
\r
901 static boolean CheckForConstant(void)
\r
905 sym = SY_FindGlobal(tk_String);
\r
910 if(sym->type != SY_CONSTANT)
\r
914 tk_Token = TK_NUMBER;
\r
915 tk_Number = sym->info.constant.value;
\r
919 //==========================================================================
\r
921 // ProcessNumberToken
\r
923 //==========================================================================
\r
925 static void ProcessNumberToken(void)
\r
931 if(c == '0' && (Chr == 'x' || Chr == 'X'))
\r
932 { // Hexadecimal constant
\r
938 while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
940 tk_Number = 10*tk_Number+(Chr-'0');
\r
945 NextChr(); // Skip period
\r
946 EvalFixedConstant(tk_Number);
\r
949 if(Chr == ASCII_UNDERSCORE)
\r
951 NextChr(); // Skip underscore
\r
952 EvalRadixConstant();
\r
955 tk_Token = TK_NUMBER;
\r
958 //==========================================================================
\r
960 // EvalFixedConstant
\r
962 //==========================================================================
\r
964 static void EvalFixedConstant(int whole)
\r
971 while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
973 frac = 10*frac+(Chr-'0');
\r
977 tk_Number = (whole<<16)+(int)(65536.0*frac/divisor);
\r
978 tk_Token = TK_NUMBER;
\r
981 //==========================================================================
\r
985 //==========================================================================
\r
987 static void EvalHexConstant(void)
\r
990 while(ASCIIToHexDigit[(byte)Chr] != NON_HEX_DIGIT)
\r
992 tk_Number = (tk_Number<<4)+ASCIIToHexDigit[(byte)Chr];
\r
995 tk_Token = TK_NUMBER;
\r
998 //==========================================================================
\r
1000 // EvalRadixConstant
\r
1002 //==========================================================================
\r
1004 static void EvalRadixConstant(void)
\r
1009 radix = tk_Number;
\r
1010 if(radix < 2 || radix > 36)
\r
1012 ERR_Error(ERR_BAD_RADIX_CONSTANT, YES, NULL);
\r
1016 while((digitVal = DigitValue(Chr, radix)) != -1)
\r
1018 tk_Number = radix*tk_Number+digitVal;
\r
1021 tk_Token = TK_NUMBER;
\r
1024 //==========================================================================
\r
1028 // Returns -1 if the digit is not allowed in the specified radix.
\r
1030 //==========================================================================
\r
1032 static int DigitValue(char digit, int radix)
\r
1034 digit = toupper(digit);
\r
1035 if(digit < '0' || (digit > '9' && digit < 'A') || digit > 'Z')
\r
1041 digit = 10+digit-'A';
\r
1047 if(digit >= radix)
\r
1054 //==========================================================================
\r
1056 // ProcessQuoteToken
\r
1058 //==========================================================================
\r
1060 static void ProcessQuoteToken(void)
\r
1068 text = TokenStringBuffer;
\r
1070 while(Chr != EOF_CHARACTER)
\r
1072 if(Chr == ASCII_QUOTE && escaped == 0) // [JB]
\r
1076 if(++i == MAX_QUOTED_LENGTH)
\r
1078 ERR_Error(ERR_STRING_TOO_LONG, YES, NULL);
\r
1080 if(i < MAX_QUOTED_LENGTH)
\r
1084 // escape the character after a backslash [JB]
\r
1086 escaped ^= (Chr == '\\');
\r
1092 if(Chr == ASCII_QUOTE)
\r
1096 tk_Token = TK_STRING;
\r
1099 //==========================================================================
\r
1101 // ProcessSpecialToken
\r
1103 //==========================================================================
\r
1105 static void ProcessSpecialToken(void)
\r
1117 tk_Token = TK_ADDASSIGN;
\r
1121 tk_Token = TK_INC;
\r
1125 tk_Token = TK_PLUS;
\r
1133 tk_Token = TK_SUBASSIGN;
\r
1137 tk_Token = TK_DEC;
\r
1141 tk_Token = TK_MINUS;
\r
1149 tk_Token = TK_MULASSIGN;
\r
1153 tk_Token = TK_ENDCOMMENT;
\r
1157 tk_Token = TK_ASTERISK;
\r
1165 tk_Token = TK_DIVASSIGN;
\r
1169 tk_Token = TK_CPPCOMMENT;
\r
1172 tk_Token = TK_STARTCOMMENT;
\r
1176 tk_Token = TK_SLASH;
\r
1183 tk_Token = TK_MODASSIGN;
\r
1188 tk_Token = TK_PERCENT;
\r
1199 tk_Token = TK_ASSIGN;
\r
1208 else if(Chr == '<')
\r
1213 tk_Token = TK_LSASSIGN;
\r
1218 tk_Token = TK_LSHIFT;
\r
1233 else if(Chr == '>')
\r
1238 tk_Token = TK_RSASSIGN;
\r
1243 tk_Token = TK_RSHIFT;
\r
1259 tk_Token = TK_NOT;
\r
1265 tk_Token = TK_ANDLOGICAL;
\r
1268 else if(Chr == '=')
\r
1270 tk_Token = TK_ANDASSIGN;
\r
1275 tk_Token = TK_ANDBITWISE;
\r
1281 tk_Token = TK_ORLOGICAL;
\r
1284 else if(Chr == '=')
\r
1286 tk_Token = TK_ORASSIGN;
\r
1291 tk_Token = TK_ORBITWISE;
\r
1295 tk_Token = TK_LPAREN;
\r
1298 tk_Token = TK_RPAREN;
\r
1301 tk_Token = TK_LBRACE;
\r
1304 tk_Token = TK_RBRACE;
\r
1307 tk_Token = TK_LBRACKET;
\r
1310 tk_Token = TK_RBRACKET;
\r
1313 tk_Token = TK_COLON;
\r
1316 tk_Token = TK_SEMICOLON;
\r
1319 tk_Token = TK_COMMA;
\r
1322 tk_Token = TK_PERIOD;
\r
1325 tk_Token = TK_NUMBERSIGN;
\r
1330 tk_Token = TK_EORASSIGN;
\r
1335 tk_Token = TK_EORBITWISE;
\r
1339 tk_Token = TK_TILDE;
\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
1351 case 'x': case 'X':
\r
1353 EvalHexConstant();
\r
1356 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1386 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1388 tk_Token = TK_NUMBER;
\r
1390 else if(Chr == '\'')
\r
1392 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1397 tk_Token = TK_NUMBER;
\r
1402 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1407 ERR_Exit(ERR_BAD_CHARACTER, YES, NULL);
\r
1412 //==========================================================================
\r
1416 //==========================================================================
\r
1418 static void NextChr(void)
\r
1420 if(FilePtr >= FileEnd)
\r
1422 Chr = EOF_CHARACTER;
\r
1425 if(IncLineNumber == TRUE)
\r
1428 IncLineNumber = FALSE;
\r
1429 BumpMasterSourceLine('x',TRUE); // dummy x
\r
1432 if(Chr < ASCII_SPACE && Chr >= 0) // Allow high ASCII characters
\r
1436 IncLineNumber = TRUE;
\r
1438 Chr = ASCII_SPACE;
\r
1440 BumpMasterSourceLine(Chr,FALSE);
\r
1443 //==========================================================================
\r
1445 // PeekChr // [JB]
\r
1447 //==========================================================================
\r
1449 static int PeekChr(void)
\r
1452 if(FilePtr >= FileEnd)
\r
1454 return EOF_CHARACTER;
\r
1457 if(ch < ASCII_SPACE && ch >= 0) // Allow high ASCII characters
\r
1464 //==========================================================================
\r
1466 // OctalChar // [JB]
\r
1468 //==========================================================================
\r
1470 static int OctalChar()
\r
1473 int code = Chr - '0';
\r
1474 while(digits < 4 && PeekChr() >= '0' && PeekChr() <= '7')
\r
1477 code = (code << 3) + Chr - '0';
\r
1482 //==========================================================================
\r
1486 //==========================================================================
\r
1488 void SkipComment(void)
\r
1493 while(Chr != EOF_CHARACTER)
\r
1495 if(first == TRUE && Chr == '/')
\r
1499 first = (Chr == '*');
\r
1505 //==========================================================================
\r
1509 //==========================================================================
\r
1511 void SkipCPPComment(void)
\r
1513 while(FilePtr < FileEnd)
\r
1515 if(*FilePtr++ == '\n')
\r
1518 BumpMasterSourceLine('x',TRUE); // dummy x
\r
1525 //==========================================================================
\r
1527 // BumpMasterSourceLine
\r
1529 //==========================================================================
\r
1531 void BumpMasterSourceLine(char Chr, boolean clear) // master line - Ty 07jan2000
\r
1533 if (ClearMasterSourceLine) // set to clear last time, clear now for first character
\r
1535 *MasterSourceLine = '\0';
\r
1536 MasterSourcePos = 0;
\r
1537 ClearMasterSourceLine = FALSE;
\r
1541 ClearMasterSourceLine = TRUE;
\r
1545 if (MasterSourcePos < MAX_STATEMENT_LENGTH)
\r
1546 MasterSourceLine[MasterSourcePos++] = Chr;
\r
1550 //==========================================================================
\r
1554 //==========================================================================
\r
1556 void TK_SkipLine(void)
\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