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
196 { "strparam", TK_STRPARAM_EVAL }, // [FDARI]
\r
197 { "strcpy", TK_STRCPY }, // [FDARI]
\r
200 #define NUM_KEYWORDS (sizeof(Keywords)/sizeof(Keywords[0]))
\r
202 // CODE --------------------------------------------------------------------
\r
204 //==========================================================================
\r
208 //==========================================================================
\r
214 for(i = 0; i < 256; i++)
\r
216 ASCIIToChrCode[i] = CHR_SPECIAL;
\r
217 ASCIIToHexDigit[i] = NON_HEX_DIGIT;
\r
219 for(i = '0'; i <= '9'; i++)
\r
221 ASCIIToChrCode[i] = CHR_NUMBER;
\r
222 ASCIIToHexDigit[i] = i-'0';
\r
224 for(i = 'A'; i <= 'F'; i++)
\r
226 ASCIIToHexDigit[i] = 10+(i-'A');
\r
228 for(i = 'a'; i <= 'f'; i++)
\r
230 ASCIIToHexDigit[i] = 10+(i-'a');
\r
232 for(i = 'A'; i <= 'Z'; i++)
\r
234 ASCIIToChrCode[i] = CHR_LETTER;
\r
236 for(i = 'a'; i <= 'z'; i++)
\r
238 ASCIIToChrCode[i] = CHR_LETTER;
\r
240 ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
\r
241 ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
\r
242 ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
\r
243 tk_String = TokenStringBuffer;
\r
244 IncLineNumber = FALSE;
\r
245 tk_IncludedLines = 0;
\r
246 NumIncludePaths = 1; // the first path is always the parsed file path - Pascal 12/11/08
\r
247 SourceOpen = FALSE;
\r
248 *MasterSourceLine = '\0'; // master line - Ty 07jan2000
\r
249 MasterSourcePos = 0; // master position - Ty 07jan2000
\r
250 ClearMasterSourceLine = TRUE; // clear the line to start
\r
251 qsort (Keywords, NUM_KEYWORDS, sizeof(Keywords[0]), SortKeywords);
\r
252 FileNames = MS_Alloc(4096, ERR_OUT_OF_MEMORY);
\r
254 FileNamesMax = 4096;
\r
257 //==========================================================================
\r
261 //==========================================================================
\r
263 static int SortKeywords(const void *a, const void *b)
\r
265 return strcmp (((struct keyword_s *)a)->name,
\r
266 ((struct keyword_s *)b)->name);
\r
269 //==========================================================================
\r
273 //==========================================================================
\r
275 void TK_OpenSource(char *fileName)
\r
280 size = MS_LoadFile(fileName, &FileStart);
\r
281 tk_SourceName = AddFileName(fileName);
\r
282 SetLocalIncludePath(fileName);
\r
284 FileEnd = FileStart+size;
\r
285 FilePtr = FileStart;
\r
287 tk_Token = TK_NONE;
\r
288 AlreadyGot = FALSE;
\r
293 //==========================================================================
\r
297 //==========================================================================
\r
299 static char *AddFileName(const char *name)
\r
301 size_t len = strlen(name) + 1;
\r
304 if (FileNamesLen + len > FileNamesMax)
\r
306 FileNames = MS_Alloc(FileNamesMax, ERR_OUT_OF_MEMORY);
\r
309 namespot = FileNames + FileNamesLen;
\r
310 memcpy(namespot, name, len);
\r
311 FileNamesLen += len;
\r
315 //==========================================================================
\r
317 // TK_AddIncludePath
\r
318 // This adds an include path with less priority than the ones already added
\r
322 //==========================================================================
\r
324 void TK_AddIncludePath(char *sourcePath)
\r
326 if(NumIncludePaths < MAX_INCLUDE_PATHS)
\r
329 strcpy(IncludePaths[NumIncludePaths], sourcePath);
\r
331 // Not ending with directory delimiter?
\r
332 if(!MS_IsDirectoryDelimiter(*(IncludePaths[NumIncludePaths] + strlen(IncludePaths[NumIncludePaths]) - 1)))
\r
334 // Add a directory delimiter to the include path
\r
335 strcat(IncludePaths[NumIncludePaths], "/");
\r
337 MS_Message(MSG_DEBUG, "Add include path %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);
\r
342 //==========================================================================
\r
344 // TK_AddProgramIncludePath
\r
345 // Adds an include path for the directory of the executable.
\r
347 //==========================================================================
\r
349 void TK_AddProgramIncludePath(char *progname)
\r
351 if(NumIncludePaths < MAX_INCLUDE_PATHS)
\r
355 #if _MSC_VER >= 1300
\r
356 if (_get_pgmptr(&progname) != 0)
\r
361 progname = _pgmptr;
\r
364 char progbuff[1024];
\r
365 GetModuleFileName(0, progbuff, sizeof(progbuff));
\r
366 progbuff[sizeof(progbuff)-1] = '\0';
\r
367 progname = progbuff;
\r
370 char progbuff[PATH_MAX];
\r
371 if (realpath(progname, progbuff) != NULL)
\r
373 progname = progbuff;
\r
376 strcpy(IncludePaths[NumIncludePaths], progname);
\r
377 if(MS_StripFilename(IncludePaths[NumIncludePaths]))
\r
379 MS_Message(MSG_DEBUG, "Program include path is %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);
\r
385 //==========================================================================
\r
387 // SetLocalIncludePath
\r
388 // This sets the first include path
\r
392 //==========================================================================
\r
394 static void SetLocalIncludePath(char *sourceName)
\r
396 strcpy(IncludePaths[0], sourceName);
\r
397 if(MS_StripFilename(IncludePaths[0]) == NO)
\r
399 IncludePaths[0][0] = 0;
\r
404 //==========================================================================
\r
408 //==========================================================================
\r
410 void TK_Include(char *fileName)
\r
412 char sourceName[MAX_FILE_NAME_LENGTH];
\r
415 boolean foundfile = FALSE;
\r
417 MS_Message(MSG_DEBUG, "*Including %s\n", fileName);
\r
418 if(NestDepth == MAX_NESTED_SOURCES)
\r
420 ERR_Exit(ERR_INCL_NESTING_TOO_DEEP, YES, fileName);
\r
422 info = &OpenFiles[NestDepth++];
\r
423 info->name = tk_SourceName;
\r
424 info->start = FileStart;
\r
425 info->end = FileEnd;
\r
426 info->position = FilePtr;
\r
427 info->line = tk_Line;
\r
428 info->incLineNumber = IncLineNumber;
\r
429 info->lastChar = Chr;
\r
430 info->imported = NO;
\r
433 // Handle absolute paths
\r
434 if(MS_IsPathAbsolute(fileName))
\r
436 #if defined(_WIN32) || defined(__MSDOS__)
\r
437 sourceName[0] = '\0';
\r
438 if(MS_IsDirectoryDelimiter(fileName[0]))
\r
440 // The source file is absolute for the drive, but does not
\r
441 // specify a drive. Use the path for the current file to
\r
442 // get the drive letter, if it has one.
\r
443 if(IncludePaths[0][0] != '\0' && IncludePaths[0][1] == ':')
\r
445 sourceName[0] = IncludePaths[0][0];
\r
446 sourceName[1] = ':';
\r
447 sourceName[2] = '\0';
\r
450 strcat(sourceName, fileName);
\r
452 strcpy(sourceName, fileName);
\r
454 foundfile = MS_FileExists(sourceName);
\r
459 // Find the file in the include paths
\r
460 for(i = 0; i < NumIncludePaths; i++)
\r
462 strcpy(sourceName, IncludePaths[i]);
\r
463 strcat(sourceName, fileName);
\r
464 if(MS_FileExists(sourceName))
\r
474 ERR_ErrorAt(tk_SourceName, tk_Line);
\r
475 ERR_Exit(ERR_CANT_FIND_INCLUDE, YES, fileName, tk_SourceName, tk_Line);
\r
478 MS_Message(MSG_DEBUG, "*Include file found at %s\n", sourceName);
\r
480 // Now change the first include path to the file directory
\r
481 SetLocalIncludePath(sourceName);
\r
483 tk_SourceName = AddFileName(sourceName);
\r
484 size = MS_LoadFile(tk_SourceName, &FileStart);
\r
485 FileEnd = FileStart+size;
\r
486 FilePtr = FileStart;
\r
488 IncLineNumber = FALSE;
\r
489 tk_Token = TK_NONE;
\r
490 AlreadyGot = FALSE;
\r
491 BumpMasterSourceLine('x',TRUE); // dummy x
\r
495 //==========================================================================
\r
499 //==========================================================================
\r
501 void TK_Import(char *fileName, enum ImportModes prevMode)
\r
503 TK_Include (fileName);
\r
504 OpenFiles[NestDepth - 1].imported = YES;
\r
505 OpenFiles[NestDepth - 1].prevMode = prevMode;
\r
506 ImportMode = IMPORT_Importing;
\r
509 //==========================================================================
\r
513 //==========================================================================
\r
515 static int PopNestedSource(enum ImportModes *prevMode)
\r
519 MS_Message(MSG_DEBUG, "*Leaving %s\n", tk_SourceName);
\r
521 SY_FreeConstants(NestDepth);
\r
522 tk_IncludedLines += tk_Line;
\r
523 info = &OpenFiles[--NestDepth];
\r
524 tk_SourceName = info->name;
\r
525 FileStart = info->start;
\r
526 FileEnd = info->end;
\r
527 FilePtr = info->position;
\r
528 tk_Line = info->line;
\r
529 IncLineNumber = info->incLineNumber;
\r
530 Chr = info->lastChar;
\r
531 tk_Token = TK_NONE;
\r
532 AlreadyGot = FALSE;
\r
535 // Set the first include path back to this file directory
\r
536 SetLocalIncludePath(tk_SourceName);
\r
538 *prevMode = info->prevMode;
\r
539 return info->imported ? 2 : 0;
\r
542 //==========================================================================
\r
546 //==========================================================================
\r
548 void TK_CloseSource(void)
\r
555 for(i = 0; i < NestDepth; i++)
\r
557 free(OpenFiles[i].start);
\r
559 SourceOpen = FALSE;
\r
563 //==========================================================================
\r
567 //==========================================================================
\r
569 int TK_GetDepth(void)
\r
574 //==========================================================================
\r
578 //==========================================================================
\r
580 tokenType_t TK_NextToken(void)
\r
582 enum ImportModes prevMode;
\r
583 boolean validToken;
\r
585 if(AlreadyGot == TRUE)
\r
587 int t = MasterSourcePos;
\r
588 MasterSourcePos = PrevMasterSourcePos;
\r
589 PrevMasterSourcePos = t;
\r
590 AlreadyGot = FALSE;
\r
594 PrevMasterSourcePos = MasterSourcePos;
\r
597 while(Chr == ASCII_SPACE)
\r
601 switch(ASCIIToChrCode[(byte)Chr])
\r
607 ProcessLetterToken();
\r
610 ProcessNumberToken();
\r
613 ProcessQuoteToken();
\r
616 ProcessSpecialToken();
\r
619 if(tk_Token == TK_STARTCOMMENT)
\r
623 else if(tk_Token == TK_CPPCOMMENT)
\r
627 else if((tk_Token == TK_EOF) && (NestDepth > 0))
\r
629 if (PopNestedSource(&prevMode))
\r
631 ImportMode = prevMode;
\r
632 if(!ExporterFlagged)
\r
634 ERR_Exit(ERR_EXPORTER_NOT_FLAGGED, NO);
\r
643 } while(validToken == NO);
\r
647 //==========================================================================
\r
649 // TK_NextCharacter
\r
651 //==========================================================================
\r
653 int TK_NextCharacter(void)
\r
657 while(Chr == ASCII_SPACE)
\r
662 if(c == EOF_CHARACTER)
\r
670 //==========================================================================
\r
674 //==========================================================================
\r
676 void TK_SkipPast(tokenType_t token)
\r
678 while (tk_Token != token && tk_Token != TK_EOF)
\r
685 //==========================================================================
\r
689 //==========================================================================
\r
691 void TK_SkipTo(tokenType_t token)
\r
693 while (tk_Token != token && tk_Token != TK_EOF)
\r
699 //==========================================================================
\r
701 // TK_NextTokenMustBe
\r
703 //==========================================================================
\r
705 boolean TK_NextTokenMustBe(tokenType_t token, error_t error)
\r
707 if(TK_NextToken() != token)
\r
709 ERR_Error(error, YES);
\r
711 if(skipToken == TK_EOF)
\r
715 else if(skipToken != TK_NONE)
\r
717 TK_SkipPast(skipToken);
\r
726 //==========================================================================
\r
730 //==========================================================================
\r
732 boolean TK_TokenMustBe(tokenType_t token, error_t error)
\r
734 if (token == TK_SEMICOLON && forSemicolonHack)
\r
738 if(tk_Token != token)
\r
740 ERR_Error(error, YES);
\r
742 if(skipToken == TK_EOF)
\r
746 else if(skipToken != TK_NONE)
\r
748 while(tk_Token != skipToken)
\r
760 //==========================================================================
\r
764 //==========================================================================
\r
766 boolean TK_Member(tokenType_t *list)
\r
770 for(i = 0; list[i] != TK_NONE; i++)
\r
772 if(tk_Token == list[i])
\r
780 //==========================================================================
\r
784 //==========================================================================
\r
788 if(tk_Token != TK_NONE)
\r
790 if (AlreadyGot == FALSE)
\r
792 int t = MasterSourcePos;
\r
793 MasterSourcePos = PrevMasterSourcePos;
\r
794 PrevMasterSourcePos = t;
\r
800 //==========================================================================
\r
802 // ProcessLetterToken
\r
804 //==========================================================================
\r
806 static void ProcessLetterToken(void)
\r
812 text = TokenStringBuffer;
\r
813 while (ASCIIToChrCode[(byte)Chr] == CHR_LETTER
\r
814 || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
816 if(++i == MAX_IDENTIFIER_LENGTH)
\r
818 ERR_Error(ERR_IDENTIFIER_TOO_LONG, YES);
\r
820 if(i < MAX_IDENTIFIER_LENGTH)
\r
827 MS_StrLwr(TokenStringBuffer);
\r
828 if(CheckForKeyword() == FALSE
\r
829 && CheckForLineSpecial() == FALSE
\r
830 && CheckForConstant() == FALSE)
\r
832 tk_Token = TK_IDENTIFIER;
\r
836 //==========================================================================
\r
840 //==========================================================================
\r
842 static boolean CheckForKeyword(void)
\r
844 int min, max, probe, lexx;
\r
846 // [RH] Use a binary search
\r
848 max = NUM_KEYWORDS-1;
\r
849 probe = NUM_KEYWORDS/2;
\r
851 while (max - min >= 0)
\r
853 lexx = strcmp(tk_String, Keywords[probe].name);
\r
856 tk_Token = Keywords[probe].token;
\r
867 probe = (max-min)/2+min;
\r
872 //==========================================================================
\r
874 // CheckForLineSpecial
\r
876 //==========================================================================
\r
878 static boolean CheckForLineSpecial(void)
\r
882 sym = SY_FindGlobal(tk_String);
\r
887 if(sym->type != SY_SPECIAL)
\r
891 tk_Token = TK_LINESPECIAL;
\r
892 tk_SpecialValue = sym->info.special.value;
\r
893 tk_SpecialArgCount = sym->info.special.argCount;
\r
897 //==========================================================================
\r
899 // CheckForConstant
\r
901 //==========================================================================
\r
903 static boolean CheckForConstant(void)
\r
907 sym = SY_FindGlobal(tk_String);
\r
912 if(sym->type != SY_CONSTANT)
\r
916 tk_Token = TK_NUMBER;
\r
917 tk_Number = sym->info.constant.value;
\r
921 //==========================================================================
\r
923 // ProcessNumberToken
\r
925 //==========================================================================
\r
927 static void ProcessNumberToken(void)
\r
933 if(c == '0' && (Chr == 'x' || Chr == 'X'))
\r
934 { // Hexadecimal constant
\r
940 while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
942 tk_Number = 10*tk_Number+(Chr-'0');
\r
947 NextChr(); // Skip period
\r
948 EvalFixedConstant(tk_Number);
\r
951 if(Chr == ASCII_UNDERSCORE)
\r
953 NextChr(); // Skip underscore
\r
954 EvalRadixConstant();
\r
957 tk_Token = TK_NUMBER;
\r
960 //==========================================================================
\r
962 // EvalFixedConstant
\r
964 //==========================================================================
\r
966 static void EvalFixedConstant(int whole)
\r
973 while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
975 frac = 10*frac+(Chr-'0');
\r
979 tk_Number = (whole<<16)+(int)(65536.0*frac/divisor);
\r
980 tk_Token = TK_NUMBER;
\r
983 //==========================================================================
\r
987 //==========================================================================
\r
989 static void EvalHexConstant(void)
\r
992 while(ASCIIToHexDigit[(byte)Chr] != NON_HEX_DIGIT)
\r
994 tk_Number = (tk_Number<<4)+ASCIIToHexDigit[(byte)Chr];
\r
997 tk_Token = TK_NUMBER;
\r
1000 //==========================================================================
\r
1002 // EvalRadixConstant
\r
1004 //==========================================================================
\r
1006 static void EvalRadixConstant(void)
\r
1011 radix = tk_Number;
\r
1012 if(radix < 2 || radix > 36)
\r
1014 ERR_Error(ERR_BAD_RADIX_CONSTANT, YES, NULL);
\r
1018 while((digitVal = DigitValue(Chr, radix)) != -1)
\r
1020 tk_Number = radix*tk_Number+digitVal;
\r
1023 tk_Token = TK_NUMBER;
\r
1026 //==========================================================================
\r
1030 // Returns -1 if the digit is not allowed in the specified radix.
\r
1032 //==========================================================================
\r
1034 static int DigitValue(char digit, int radix)
\r
1036 digit = toupper(digit);
\r
1037 if(digit < '0' || (digit > '9' && digit < 'A') || digit > 'Z')
\r
1043 digit = 10+digit-'A';
\r
1049 if(digit >= radix)
\r
1056 //==========================================================================
\r
1058 // ProcessQuoteToken
\r
1060 //==========================================================================
\r
1062 static void ProcessQuoteToken(void)
\r
1070 text = TokenStringBuffer;
\r
1072 while(Chr != EOF_CHARACTER)
\r
1074 if(Chr == ASCII_QUOTE && escaped == 0) // [JB]
\r
1078 if(++i == MAX_QUOTED_LENGTH)
\r
1080 ERR_Error(ERR_STRING_TOO_LONG, YES, NULL);
\r
1082 if(i < MAX_QUOTED_LENGTH)
\r
1086 // escape the character after a backslash [JB]
\r
1088 escaped ^= (Chr == '\\');
\r
1094 if(Chr == ASCII_QUOTE)
\r
1098 tk_Token = TK_STRING;
\r
1101 //==========================================================================
\r
1103 // ProcessSpecialToken
\r
1105 //==========================================================================
\r
1107 static void ProcessSpecialToken(void)
\r
1119 tk_Token = TK_ADDASSIGN;
\r
1123 tk_Token = TK_INC;
\r
1127 tk_Token = TK_PLUS;
\r
1135 tk_Token = TK_SUBASSIGN;
\r
1139 tk_Token = TK_DEC;
\r
1143 tk_Token = TK_MINUS;
\r
1151 tk_Token = TK_MULASSIGN;
\r
1155 tk_Token = TK_ENDCOMMENT;
\r
1159 tk_Token = TK_ASTERISK;
\r
1167 tk_Token = TK_DIVASSIGN;
\r
1171 tk_Token = TK_CPPCOMMENT;
\r
1174 tk_Token = TK_STARTCOMMENT;
\r
1178 tk_Token = TK_SLASH;
\r
1185 tk_Token = TK_MODASSIGN;
\r
1190 tk_Token = TK_PERCENT;
\r
1201 tk_Token = TK_ASSIGN;
\r
1210 else if(Chr == '<')
\r
1215 tk_Token = TK_LSASSIGN;
\r
1220 tk_Token = TK_LSHIFT;
\r
1235 else if(Chr == '>')
\r
1240 tk_Token = TK_RSASSIGN;
\r
1245 tk_Token = TK_RSHIFT;
\r
1261 tk_Token = TK_NOT;
\r
1267 tk_Token = TK_ANDLOGICAL;
\r
1270 else if(Chr == '=')
\r
1272 tk_Token = TK_ANDASSIGN;
\r
1277 tk_Token = TK_ANDBITWISE;
\r
1283 tk_Token = TK_ORLOGICAL;
\r
1286 else if(Chr == '=')
\r
1288 tk_Token = TK_ORASSIGN;
\r
1293 tk_Token = TK_ORBITWISE;
\r
1297 tk_Token = TK_LPAREN;
\r
1300 tk_Token = TK_RPAREN;
\r
1303 tk_Token = TK_LBRACE;
\r
1306 tk_Token = TK_RBRACE;
\r
1309 tk_Token = TK_LBRACKET;
\r
1312 tk_Token = TK_RBRACKET;
\r
1315 tk_Token = TK_COLON;
\r
1318 tk_Token = TK_SEMICOLON;
\r
1321 tk_Token = TK_COMMA;
\r
1324 tk_Token = TK_PERIOD;
\r
1327 tk_Token = TK_NUMBERSIGN;
\r
1332 tk_Token = TK_EORASSIGN;
\r
1337 tk_Token = TK_EORBITWISE;
\r
1341 tk_Token = TK_TILDE;
\r
1349 case '0': case '1': case '2': case '3':
\r
1350 case '4': case '5': case '6': case '7':
\r
1351 tk_Number = OctalChar();
\r
1353 case 'x': case 'X':
\r
1355 EvalHexConstant();
\r
1358 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1388 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1390 tk_Token = TK_NUMBER;
\r
1392 else if(Chr == '\'')
\r
1394 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1399 tk_Token = TK_NUMBER;
\r
1404 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1409 ERR_Exit(ERR_BAD_CHARACTER, YES, NULL);
\r
1414 //==========================================================================
\r
1418 //==========================================================================
\r
1420 static void NextChr(void)
\r
1422 if(FilePtr >= FileEnd)
\r
1424 Chr = EOF_CHARACTER;
\r
1427 if(IncLineNumber == TRUE)
\r
1430 IncLineNumber = FALSE;
\r
1431 BumpMasterSourceLine('x',TRUE); // dummy x
\r
1434 if(Chr < ASCII_SPACE && Chr >= 0) // Allow high ASCII characters
\r
1438 IncLineNumber = TRUE;
\r
1440 Chr = ASCII_SPACE;
\r
1442 BumpMasterSourceLine(Chr,FALSE);
\r
1445 //==========================================================================
\r
1447 // PeekChr // [JB]
\r
1449 //==========================================================================
\r
1451 static int PeekChr(void)
\r
1454 if(FilePtr >= FileEnd)
\r
1456 return EOF_CHARACTER;
\r
1459 if(ch < ASCII_SPACE && ch >= 0) // Allow high ASCII characters
\r
1466 //==========================================================================
\r
1468 // OctalChar // [JB]
\r
1470 //==========================================================================
\r
1472 static int OctalChar()
\r
1475 int code = Chr - '0';
\r
1476 while(digits < 4 && PeekChr() >= '0' && PeekChr() <= '7')
\r
1479 code = (code << 3) + Chr - '0';
\r
1484 //==========================================================================
\r
1488 //==========================================================================
\r
1490 void SkipComment(void)
\r
1495 while(Chr != EOF_CHARACTER)
\r
1497 if(first == TRUE && Chr == '/')
\r
1501 first = (Chr == '*');
\r
1507 //==========================================================================
\r
1511 //==========================================================================
\r
1513 void SkipCPPComment(void)
\r
1515 while(FilePtr < FileEnd)
\r
1517 if(*FilePtr++ == '\n')
\r
1520 BumpMasterSourceLine('x',TRUE); // dummy x
\r
1527 //==========================================================================
\r
1529 // BumpMasterSourceLine
\r
1531 //==========================================================================
\r
1533 void BumpMasterSourceLine(char Chr, boolean clear) // master line - Ty 07jan2000
\r
1535 if (ClearMasterSourceLine) // set to clear last time, clear now for first character
\r
1537 *MasterSourceLine = '\0';
\r
1538 MasterSourcePos = 0;
\r
1539 ClearMasterSourceLine = FALSE;
\r
1543 ClearMasterSourceLine = TRUE;
\r
1547 if (MasterSourcePos < MAX_STATEMENT_LENGTH)
\r
1548 MasterSourceLine[MasterSourcePos++] = Chr;
\r
1552 //==========================================================================
\r
1556 //==========================================================================
\r
1558 void TK_SkipLine(void)
\r
1560 char *sourcenow = tk_SourceName;
\r
1561 int linenow = tk_Line;
\r
1562 do TK_NextToken(); while (tk_Line == linenow && tk_SourceName == sourcenow);
\r