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 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
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 { "disconnect", TK_DISCONNECT },
\r
193 { "unloading", TK_UNLOADING },
\r
194 { "static", TK_STATIC }
\r
197 #define NUM_KEYWORDS (sizeof(Keywords)/sizeof(Keywords[0]))
\r
199 // CODE --------------------------------------------------------------------
\r
201 //==========================================================================
\r
205 //==========================================================================
\r
211 for(i = 0; i < 256; i++)
\r
213 ASCIIToChrCode[i] = CHR_SPECIAL;
\r
214 ASCIIToHexDigit[i] = NON_HEX_DIGIT;
\r
216 for(i = '0'; i <= '9'; i++)
\r
218 ASCIIToChrCode[i] = CHR_NUMBER;
\r
219 ASCIIToHexDigit[i] = i-'0';
\r
221 for(i = 'A'; i <= 'F'; i++)
\r
223 ASCIIToHexDigit[i] = 10+(i-'A');
\r
225 for(i = 'a'; i <= 'f'; i++)
\r
227 ASCIIToHexDigit[i] = 10+(i-'a');
\r
229 for(i = 'A'; i <= 'Z'; i++)
\r
231 ASCIIToChrCode[i] = CHR_LETTER;
\r
233 for(i = 'a'; i <= 'z'; i++)
\r
235 ASCIIToChrCode[i] = CHR_LETTER;
\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
251 FileNamesMax = 4096;
\r
254 //==========================================================================
\r
258 //==========================================================================
\r
260 static int SortKeywords(const void *a, const void *b)
\r
262 return strcmp (((struct keyword_s *)a)->name,
\r
263 ((struct keyword_s *)b)->name);
\r
266 //==========================================================================
\r
270 //==========================================================================
\r
272 void TK_OpenSource(char *fileName)
\r
277 size = MS_LoadFile(fileName, &FileStart);
\r
278 tk_SourceName = AddFileName(fileName);
\r
279 SetLocalIncludePath(fileName);
\r
281 FileEnd = FileStart+size;
\r
282 FilePtr = FileStart;
\r
284 tk_Token = TK_NONE;
\r
285 AlreadyGot = FALSE;
\r
290 //==========================================================================
\r
294 //==========================================================================
\r
296 static char *AddFileName(const char *name)
\r
298 size_t len = strlen(name) + 1;
\r
301 if (FileNamesLen + len > FileNamesMax)
\r
303 FileNames = MS_Alloc(FileNamesMax, ERR_OUT_OF_MEMORY);
\r
306 namespot = FileNames + FileNamesLen;
\r
307 memcpy(namespot, name, len);
\r
308 FileNamesLen += len;
\r
312 //==========================================================================
\r
314 // TK_AddIncludePath
\r
315 // This adds an include path with less priority than the ones already added
\r
319 //==========================================================================
\r
321 void TK_AddIncludePath(char *sourcePath)
\r
323 if(NumIncludePaths < MAX_INCLUDE_PATHS)
\r
326 strcpy(IncludePaths[NumIncludePaths], sourcePath);
\r
328 // Not ending with directory delimiter?
\r
329 if(!MS_IsDirectoryDelimiter(*(IncludePaths[NumIncludePaths] + strlen(IncludePaths[NumIncludePaths]) - 1)))
\r
331 // Add a directory delimiter to the include path
\r
332 strcat(IncludePaths[NumIncludePaths], "/");
\r
338 //==========================================================================
\r
340 // TK_AddProgramIncludePath
\r
341 // Adds an include path for the directory of the executable.
\r
343 //==========================================================================
\r
345 void TK_AddProgramIncludePath(char *progname)
\r
347 if(NumIncludePaths < MAX_INCLUDE_PATHS)
\r
351 if (_get_pgmptr(&progname) != 0)
\r
356 char progbuff[1024];
\r
357 GetModuleFileName(0, progbuff, sizeof(progbuff));
\r
358 progbuff[sizeof(progbuff)-1] = '\0';
\r
359 progname = progbuff;
\r
362 char progbuff[PATH_MAX];
\r
363 if (realpath(progname, progbuff) != NULL)
\r
365 progname = progbuff;
\r
368 strcpy(IncludePaths[NumIncludePaths], progname);
\r
369 if(MS_StripFilename(IncludePaths[NumIncludePaths]))
\r
376 //==========================================================================
\r
378 // SetLocalIncludePath
\r
379 // This sets the first include path
\r
383 //==========================================================================
\r
385 static void SetLocalIncludePath(char *sourceName)
\r
387 strcpy(IncludePaths[0], sourceName);
\r
388 if(MS_StripFilename(IncludePaths[0]) == NO)
\r
390 IncludePaths[0][0] = 0;
\r
395 //==========================================================================
\r
399 //==========================================================================
\r
401 void TK_Include(char *fileName)
\r
403 char sourceName[MAX_FILE_NAME_LENGTH];
\r
406 boolean foundfile = FALSE;
\r
408 MS_Message(MSG_DEBUG, "*Including %s\n", fileName);
\r
409 if(NestDepth == MAX_NESTED_SOURCES)
\r
411 ERR_Exit(ERR_INCL_NESTING_TOO_DEEP, YES, fileName);
\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
424 // Handle absolute paths
\r
425 if(MS_IsPathAbsolute(fileName))
\r
427 #if defined(_WIN32) || defined(__MSDOS__)
\r
428 sourceName[0] = '\0';
\r
429 if(MS_IsDirectoryDelimiter(fileName[0]))
\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
436 sourceName[0] = IncludePaths[0][0];
\r
437 sourceName[1] = ':';
\r
438 sourceName[2] = '\0';
\r
441 strcat(sourceName, fileName);
\r
443 strcpy(sourceName, fileName);
\r
445 foundfile = MS_FileExists(sourceName);
\r
450 // Find the file in the include paths
\r
451 for(i = 0; i < NumIncludePaths; i++)
\r
453 strcpy(sourceName, IncludePaths[i]);
\r
454 strcat(sourceName, fileName);
\r
455 if(MS_FileExists(sourceName))
\r
465 ERR_ErrorAt(tk_SourceName, tk_Line);
\r
466 ERR_Exit(ERR_CANT_FIND_INCLUDE, YES, fileName, tk_SourceName, tk_Line);
\r
469 MS_Message(MSG_DEBUG, "*Include file found at %s\n", sourceName);
\r
471 // Now change the first include path to the file directory
\r
472 SetLocalIncludePath(sourceName);
\r
474 tk_SourceName = AddFileName(sourceName);
\r
475 size = MS_LoadFile(tk_SourceName, &FileStart);
\r
476 FileEnd = FileStart+size;
\r
477 FilePtr = FileStart;
\r
479 IncLineNumber = FALSE;
\r
480 tk_Token = TK_NONE;
\r
481 AlreadyGot = FALSE;
\r
482 BumpMasterSourceLine('x',TRUE); // dummy x
\r
486 //==========================================================================
\r
490 //==========================================================================
\r
492 void TK_Import(char *fileName, enum ImportModes prevMode)
\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
500 //==========================================================================
\r
504 //==========================================================================
\r
506 static int PopNestedSource(enum ImportModes *prevMode)
\r
510 MS_Message(MSG_DEBUG, "*Leaving %s\n", tk_SourceName);
\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
526 // Set the first include path back to this file directory
\r
527 SetLocalIncludePath(tk_SourceName);
\r
529 *prevMode = info->prevMode;
\r
530 return info->imported ? 2 : 0;
\r
533 //==========================================================================
\r
537 //==========================================================================
\r
539 void TK_CloseSource(void)
\r
546 for(i = 0; i < NestDepth; i++)
\r
548 free(OpenFiles[i].start);
\r
550 SourceOpen = FALSE;
\r
554 //==========================================================================
\r
558 //==========================================================================
\r
560 int TK_GetDepth(void)
\r
565 //==========================================================================
\r
569 //==========================================================================
\r
571 tokenType_t TK_NextToken(void)
\r
573 enum ImportModes prevMode;
\r
574 boolean validToken;
\r
576 if(AlreadyGot == TRUE)
\r
578 int t = MasterSourcePos;
\r
579 MasterSourcePos = PrevMasterSourcePos;
\r
580 PrevMasterSourcePos = t;
\r
581 AlreadyGot = FALSE;
\r
585 PrevMasterSourcePos = MasterSourcePos;
\r
588 while(Chr == ASCII_SPACE)
\r
592 switch(ASCIIToChrCode[(byte)Chr])
\r
598 ProcessLetterToken();
\r
601 ProcessNumberToken();
\r
604 ProcessQuoteToken();
\r
607 ProcessSpecialToken();
\r
610 if(tk_Token == TK_STARTCOMMENT)
\r
614 else if(tk_Token == TK_CPPCOMMENT)
\r
618 else if((tk_Token == TK_EOF) && (NestDepth > 0))
\r
620 if (PopNestedSource(&prevMode))
\r
622 ImportMode = prevMode;
\r
623 if(!ExporterFlagged)
\r
625 ERR_Exit(ERR_EXPORTER_NOT_FLAGGED, NO);
\r
634 } while(validToken == NO);
\r
638 //==========================================================================
\r
640 // TK_NextCharacter
\r
642 //==========================================================================
\r
644 int TK_NextCharacter(void)
\r
648 while(Chr == ASCII_SPACE)
\r
653 if(c == EOF_CHARACTER)
\r
661 //==========================================================================
\r
665 //==========================================================================
\r
667 void TK_SkipPast(tokenType_t token)
\r
669 while (tk_Token != token)
\r
676 //==========================================================================
\r
680 //==========================================================================
\r
682 void TK_SkipTo(tokenType_t token)
\r
684 while (tk_Token != token)
\r
690 //==========================================================================
\r
692 // TK_NextTokenMustBe
\r
694 //==========================================================================
\r
696 boolean TK_NextTokenMustBe(tokenType_t token, error_t error)
\r
698 if(TK_NextToken() != token)
\r
700 ERR_Error(error, YES);
\r
702 if(skipToken == TK_EOF)
\r
706 else if(skipToken != TK_NONE)
\r
708 TK_SkipPast(skipToken);
\r
717 //==========================================================================
\r
721 //==========================================================================
\r
723 boolean TK_TokenMustBe(tokenType_t token, error_t error)
\r
725 if (token == TK_SEMICOLON && forSemicolonHack)
\r
729 if(tk_Token != token)
\r
731 ERR_Error(error, YES);
\r
733 if(skipToken == TK_EOF)
\r
737 else if(skipToken != TK_NONE)
\r
739 while(tk_Token != skipToken)
\r
751 //==========================================================================
\r
755 //==========================================================================
\r
757 boolean TK_Member(tokenType_t *list)
\r
761 for(i = 0; list[i] != TK_NONE; i++)
\r
763 if(tk_Token == list[i])
\r
771 //==========================================================================
\r
775 //==========================================================================
\r
779 if(tk_Token != TK_NONE)
\r
781 if (AlreadyGot == FALSE)
\r
783 int t = MasterSourcePos;
\r
784 MasterSourcePos = PrevMasterSourcePos;
\r
785 PrevMasterSourcePos = t;
\r
791 //==========================================================================
\r
793 // ProcessLetterToken
\r
795 //==========================================================================
\r
797 static void ProcessLetterToken(void)
\r
803 text = TokenStringBuffer;
\r
804 while (ASCIIToChrCode[(byte)Chr] == CHR_LETTER
\r
805 || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
807 if(++i == MAX_IDENTIFIER_LENGTH)
\r
809 ERR_Error(ERR_IDENTIFIER_TOO_LONG, YES);
\r
811 if(i < MAX_IDENTIFIER_LENGTH)
\r
818 MS_StrLwr(TokenStringBuffer);
\r
819 if(CheckForKeyword() == FALSE
\r
820 && CheckForLineSpecial() == FALSE
\r
821 && CheckForConstant() == FALSE)
\r
823 tk_Token = TK_IDENTIFIER;
\r
827 //==========================================================================
\r
831 //==========================================================================
\r
833 static boolean CheckForKeyword(void)
\r
835 int min, max, probe, lexx;
\r
837 // [RH] Use a binary search
\r
839 max = NUM_KEYWORDS-1;
\r
840 probe = NUM_KEYWORDS/2;
\r
842 while (max - min >= 0)
\r
844 lexx = strcmp(tk_String, Keywords[probe].name);
\r
847 tk_Token = Keywords[probe].token;
\r
858 probe = (max-min)/2+min;
\r
863 //==========================================================================
\r
865 // CheckForLineSpecial
\r
867 //==========================================================================
\r
869 static boolean CheckForLineSpecial(void)
\r
873 sym = SY_FindGlobal(tk_String);
\r
878 if(sym->type != SY_SPECIAL)
\r
882 tk_Token = TK_LINESPECIAL;
\r
883 tk_SpecialValue = sym->info.special.value;
\r
884 tk_SpecialArgCount = sym->info.special.argCount;
\r
888 //==========================================================================
\r
890 // CheckForConstant
\r
892 //==========================================================================
\r
894 static boolean CheckForConstant(void)
\r
898 sym = SY_FindGlobal(tk_String);
\r
903 if(sym->type != SY_CONSTANT)
\r
907 tk_Token = TK_NUMBER;
\r
908 tk_Number = sym->info.constant.value;
\r
912 //==========================================================================
\r
914 // ProcessNumberToken
\r
916 //==========================================================================
\r
918 static void ProcessNumberToken(void)
\r
924 if(c == '0' && (Chr == 'x' || Chr == 'X'))
\r
925 { // Hexadecimal constant
\r
931 while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
933 tk_Number = 10*tk_Number+(Chr-'0');
\r
938 NextChr(); // Skip period
\r
939 EvalFixedConstant(tk_Number);
\r
942 if(Chr == ASCII_UNDERSCORE)
\r
944 NextChr(); // Skip underscore
\r
945 EvalRadixConstant();
\r
948 tk_Token = TK_NUMBER;
\r
951 //==========================================================================
\r
953 // EvalFixedConstant
\r
955 //==========================================================================
\r
957 static void EvalFixedConstant(int whole)
\r
964 while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
\r
966 frac = 10*frac+(Chr-'0');
\r
970 tk_Number = (whole<<16)+((frac<<16)/divisor);
\r
971 tk_Token = TK_NUMBER;
\r
974 //==========================================================================
\r
978 //==========================================================================
\r
980 static void EvalHexConstant(void)
\r
983 while(ASCIIToHexDigit[(byte)Chr] != NON_HEX_DIGIT)
\r
985 tk_Number = (tk_Number<<4)+ASCIIToHexDigit[(byte)Chr];
\r
988 tk_Token = TK_NUMBER;
\r
991 //==========================================================================
\r
993 // EvalRadixConstant
\r
995 //==========================================================================
\r
997 static void EvalRadixConstant(void)
\r
1002 radix = tk_Number;
\r
1003 if(radix < 2 || radix > 36)
\r
1005 ERR_Error(ERR_BAD_RADIX_CONSTANT, YES, NULL);
\r
1009 while((digitVal = DigitValue(Chr, radix)) != -1)
\r
1011 tk_Number = radix*tk_Number+digitVal;
\r
1014 tk_Token = TK_NUMBER;
\r
1017 //==========================================================================
\r
1021 // Returns -1 if the digit is not allowed in the specified radix.
\r
1023 //==========================================================================
\r
1025 static int DigitValue(char digit, int radix)
\r
1027 digit = toupper(digit);
\r
1028 if(digit < '0' || (digit > '9' && digit < 'A') || digit > 'Z')
\r
1034 digit = 10+digit-'A';
\r
1040 if(digit >= radix)
\r
1047 //==========================================================================
\r
1049 // ProcessQuoteToken
\r
1051 //==========================================================================
\r
1053 static void ProcessQuoteToken(void)
\r
1061 text = TokenStringBuffer;
\r
1063 while(Chr != EOF_CHARACTER)
\r
1065 if(Chr == ASCII_QUOTE && escaped == 0) // [JB]
\r
1069 if(++i == MAX_QUOTED_LENGTH)
\r
1071 ERR_Error(ERR_STRING_TOO_LONG, YES, NULL);
\r
1073 if(i < MAX_QUOTED_LENGTH)
\r
1077 // escape the character after a backslash [JB]
\r
1079 escaped ^= (Chr == '\\');
\r
1085 if(Chr == ASCII_QUOTE)
\r
1089 tk_Token = TK_STRING;
\r
1092 //==========================================================================
\r
1094 // ProcessSpecialToken
\r
1096 //==========================================================================
\r
1098 static void ProcessSpecialToken(void)
\r
1110 tk_Token = TK_ADDASSIGN;
\r
1114 tk_Token = TK_INC;
\r
1118 tk_Token = TK_PLUS;
\r
1126 tk_Token = TK_SUBASSIGN;
\r
1130 tk_Token = TK_DEC;
\r
1134 tk_Token = TK_MINUS;
\r
1142 tk_Token = TK_MULASSIGN;
\r
1146 tk_Token = TK_ENDCOMMENT;
\r
1150 tk_Token = TK_ASTERISK;
\r
1158 tk_Token = TK_DIVASSIGN;
\r
1162 tk_Token = TK_CPPCOMMENT;
\r
1165 tk_Token = TK_STARTCOMMENT;
\r
1169 tk_Token = TK_SLASH;
\r
1176 tk_Token = TK_MODASSIGN;
\r
1181 tk_Token = TK_PERCENT;
\r
1192 tk_Token = TK_ASSIGN;
\r
1201 else if(Chr == '<')
\r
1206 tk_Token = TK_LSASSIGN;
\r
1211 tk_Token = TK_LSHIFT;
\r
1226 else if(Chr == '>')
\r
1231 tk_Token = TK_RSASSIGN;
\r
1236 tk_Token = TK_RSHIFT;
\r
1252 tk_Token = TK_NOT;
\r
1258 tk_Token = TK_ANDLOGICAL;
\r
1261 else if(Chr == '=')
\r
1263 tk_Token = TK_ANDASSIGN;
\r
1268 tk_Token = TK_ANDBITWISE;
\r
1274 tk_Token = TK_ORLOGICAL;
\r
1277 else if(Chr == '=')
\r
1279 tk_Token = TK_ORASSIGN;
\r
1284 tk_Token = TK_ORBITWISE;
\r
1288 tk_Token = TK_LPAREN;
\r
1291 tk_Token = TK_RPAREN;
\r
1294 tk_Token = TK_LBRACE;
\r
1297 tk_Token = TK_RBRACE;
\r
1300 tk_Token = TK_LBRACKET;
\r
1303 tk_Token = TK_RBRACKET;
\r
1306 tk_Token = TK_COLON;
\r
1309 tk_Token = TK_SEMICOLON;
\r
1312 tk_Token = TK_COMMA;
\r
1315 tk_Token = TK_PERIOD;
\r
1318 tk_Token = TK_NUMBERSIGN;
\r
1323 tk_Token = TK_EORASSIGN;
\r
1328 tk_Token = TK_EORBITWISE;
\r
1332 tk_Token = TK_TILDE;
\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
1344 case 'x': case 'X':
\r
1346 EvalHexConstant();
\r
1349 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1378 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1380 tk_Token = TK_NUMBER;
\r
1382 else if(Chr == '\'')
\r
1384 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1389 tk_Token = TK_NUMBER;
\r
1394 ERR_Exit(ERR_BAD_CHARACTER_CONSTANT, YES, NULL);
\r
1399 ERR_Exit(ERR_BAD_CHARACTER, YES, NULL);
\r
1404 //==========================================================================
\r
1408 //==========================================================================
\r
1410 static void NextChr(void)
\r
1412 if(FilePtr >= FileEnd)
\r
1414 Chr = EOF_CHARACTER;
\r
1417 if(IncLineNumber == TRUE)
\r
1420 IncLineNumber = FALSE;
\r
1421 BumpMasterSourceLine('x',TRUE); // dummy x
\r
1424 if(Chr < ASCII_SPACE && Chr >= 0) // Allow high ASCII characters
\r
1428 IncLineNumber = TRUE;
\r
1430 Chr = ASCII_SPACE;
\r
1432 BumpMasterSourceLine(Chr,FALSE);
\r
1435 //==========================================================================
\r
1437 // PeekChr // [JB]
\r
1439 //==========================================================================
\r
1441 static int PeekChr(void)
\r
1444 if(FilePtr >= FileEnd)
\r
1446 return EOF_CHARACTER;
\r
1449 if(ch < ASCII_SPACE && ch >= 0) // Allow high ASCII characters
\r
1456 //==========================================================================
\r
1458 // OctalChar // [JB]
\r
1460 //==========================================================================
\r
1462 static int OctalChar()
\r
1465 int code = Chr - '0';
\r
1466 while(digits < 4 && PeekChr() >= '0' && PeekChr() <= '7')
\r
1469 code = (code << 3) + Chr - '0';
\r
1474 //==========================================================================
\r
1478 //==========================================================================
\r
1480 void SkipComment(void)
\r
1485 while(Chr != EOF_CHARACTER)
\r
1487 if(first == TRUE && Chr == '/')
\r
1491 first = (Chr == '*');
\r
1497 //==========================================================================
\r
1501 //==========================================================================
\r
1503 void SkipCPPComment(void)
\r
1505 while(FilePtr < FileEnd)
\r
1507 if(*FilePtr++ == '\n')
\r
1510 BumpMasterSourceLine('x',TRUE); // dummy x
\r
1517 //==========================================================================
\r
1519 // BumpMasterSourceLine
\r
1521 //==========================================================================
\r
1523 void BumpMasterSourceLine(char Chr, boolean clear) // master line - Ty 07jan2000
\r
1525 if (ClearMasterSourceLine) // set to clear last time, clear now for first character
\r
1527 *MasterSourceLine = '\0';
\r
1528 MasterSourcePos = 0;
\r
1529 ClearMasterSourceLine = FALSE;
\r
1533 ClearMasterSourceLine = TRUE;
\r
1537 if (MasterSourcePos < MAX_STATEMENT_LENGTH)
\r
1538 MasterSourceLine[MasterSourcePos++] = Chr;
\r
1542 //==========================================================================
\r
1546 //==========================================================================
\r
1548 void TK_SkipLine(void)
\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