\r
// HEADER FILES ------------------------------------------------------------\r
\r
+#if defined(_WIN32) && !defined(_MSC_VER)\r
+#define WIN32_LEAN_AND_MEAN\r
+#include <windows.h>\r
+#endif\r
+\r
#ifdef __NeXT__\r
#include <libc.h>\r
#else\r
#ifndef unix\r
#include <io.h>\r
#endif\r
+#include <limits.h>\r
#include <fcntl.h>\r
#include <stdlib.h>\r
#endif\r
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------\r
\r
static int SortKeywords(const void *a, const void *b);\r
-static void MakeIncludePath(char *sourceName);\r
+static void SetLocalIncludePath(char *sourceName);\r
static int PopNestedSource(enum ImportModes *prevMode);\r
static void ProcessLetterToken(void);\r
static void ProcessNumberToken(void);\r
int tk_Line;\r
int tk_Number;\r
char *tk_String;\r
-U_BYTE tk_SpecialValue;\r
+int tk_SpecialValue;\r
int tk_SpecialArgCount;\r
char *tk_SourceName;\r
int tk_IncludedLines;\r
static boolean AlreadyGot;\r
static int NestDepth;\r
static boolean IncLineNumber;\r
-static char IncludePath[MAX_FILE_NAME_LENGTH];\r
static char *FileNames;\r
static size_t FileNamesLen, FileNamesMax;\r
\r
+// Pascal 12/11/08\r
+// Include paths. Lowest is searched first.\r
+// Include path 0 is always set to the directory of the file being parsed.\r
+static char IncludePaths[MAX_INCLUDE_PATHS][MAX_FILE_NAME_LENGTH];\r
+static int NumIncludePaths;\r
+\r
static struct keyword_s\r
{\r
char *name;\r
{ "libdefine", TK_LIBDEFINE },\r
{ "bool", TK_BOOL },\r
{ "net", TK_NET },\r
+ { "clientside", TK_CLIENTSIDE }, // [BB]\r
{ "disconnect", TK_DISCONNECT },\r
{ "unloading", TK_UNLOADING },\r
{ "static", TK_STATIC }\r
tk_String = TokenStringBuffer;\r
IncLineNumber = FALSE;\r
tk_IncludedLines = 0;\r
+ NumIncludePaths = 1; // the first path is always the parsed file path - Pascal 12/11/08\r
SourceOpen = FALSE;\r
*MasterSourceLine = '\0'; // master line - Ty 07jan2000\r
MasterSourcePos = 0; // master position - Ty 07jan2000\r
TK_CloseSource();\r
size = MS_LoadFile(fileName, &FileStart);\r
tk_SourceName = AddFileName(fileName);\r
- MakeIncludePath(fileName);\r
+ SetLocalIncludePath(fileName);\r
SourceOpen = TRUE;\r
FileEnd = FileStart+size;\r
FilePtr = FileStart;\r
\r
//==========================================================================\r
//\r
-// MakeIncludePath\r
+// TK_AddIncludePath\r
+// This adds an include path with less priority than the ones already added\r
+// \r
+// Pascal 12/11/08\r
//\r
//==========================================================================\r
\r
-static void MakeIncludePath(char *sourceName)\r
+void TK_AddIncludePath(char *sourcePath)\r
{\r
- strcpy(IncludePath, sourceName);\r
- if(MS_StripFilename(IncludePath) == NO)\r
+ if(NumIncludePaths < MAX_INCLUDE_PATHS)\r
{\r
- IncludePath[0] = 0;\r
+ // Add to list\r
+ strcpy(IncludePaths[NumIncludePaths], sourcePath);\r
+ \r
+ // Not ending with directory delimiter?\r
+ if(!MS_IsDirectoryDelimiter(*(IncludePaths[NumIncludePaths] + strlen(IncludePaths[NumIncludePaths]) - 1)))\r
+ {\r
+ // Add a directory delimiter to the include path\r
+ strcat(IncludePaths[NumIncludePaths], "/");\r
+ }\r
+ MS_Message(MSG_DEBUG, "Add include path %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);\r
+ NumIncludePaths++;\r
}\r
- else\r
- { // Add a directory delimiter to the include path\r
- strcat(IncludePath, DIRECTORY_DELIMITER);\r
+}\r
+\r
+//==========================================================================\r
+//\r
+// TK_AddProgramIncludePath\r
+// Adds an include path for the directory of the executable.\r
+//\r
+//==========================================================================\r
+\r
+void TK_AddProgramIncludePath(char *progname)\r
+{\r
+ if(NumIncludePaths < MAX_INCLUDE_PATHS)\r
+ {\r
+#ifdef _WIN32\r
+#ifdef _MSC_VER\r
+#if _MSC_VER >= 1300\r
+ if (_get_pgmptr(&progname) != 0)\r
+ {\r
+ return;\r
+ }\r
+#else\r
+ progname = _pgmptr;\r
+#endif\r
+#else\r
+ char progbuff[1024];\r
+ GetModuleFileName(0, progbuff, sizeof(progbuff));\r
+ progbuff[sizeof(progbuff)-1] = '\0';\r
+ progname = progbuff;\r
+#endif\r
+#else\r
+ char progbuff[PATH_MAX];\r
+ if (realpath(progname, progbuff) != NULL)\r
+ {\r
+ progname = progbuff;\r
+ }\r
+#endif\r
+ strcpy(IncludePaths[NumIncludePaths], progname);\r
+ if(MS_StripFilename(IncludePaths[NumIncludePaths]))\r
+ {\r
+ MS_Message(MSG_DEBUG, "Program include path is %d: \"%s\"\n", NumIncludePaths, IncludePaths[NumIncludePaths]);\r
+ NumIncludePaths++;\r
+ }\r
+ }\r
+}\r
+\r
+//==========================================================================\r
+//\r
+// SetLocalIncludePath\r
+// This sets the first include path\r
+// \r
+// Pascal 12/11/08\r
+//\r
+//==========================================================================\r
+\r
+static void SetLocalIncludePath(char *sourceName)\r
+{\r
+ strcpy(IncludePaths[0], sourceName);\r
+ if(MS_StripFilename(IncludePaths[0]) == NO)\r
+ {\r
+ IncludePaths[0][0] = 0;\r
}\r
}\r
\r
+\r
//==========================================================================\r
//\r
// TK_Include\r
void TK_Include(char *fileName)\r
{\r
char sourceName[MAX_FILE_NAME_LENGTH];\r
- int size;\r
+ int size, i;\r
nestInfo_t *info;\r
-\r
+ boolean foundfile = FALSE;\r
+ \r
MS_Message(MSG_DEBUG, "*Including %s\n", fileName);\r
if(NestDepth == MAX_NESTED_SOURCES)\r
{\r
info->incLineNumber = IncLineNumber;\r
info->lastChar = Chr;\r
info->imported = NO;\r
- strcpy(sourceName, IncludePath);\r
- strcat(sourceName, fileName);\r
+ \r
+ // Pascal 30/11/08\r
+ // Handle absolute paths\r
+ if(MS_IsPathAbsolute(fileName))\r
+ {\r
+#if defined(_WIN32) || defined(__MSDOS__)\r
+ sourceName[0] = '\0';\r
+ if(MS_IsDirectoryDelimiter(fileName[0]))\r
+ {\r
+ // The source file is absolute for the drive, but does not\r
+ // specify a drive. Use the path for the current file to\r
+ // get the drive letter, if it has one.\r
+ if(IncludePaths[0][0] != '\0' && IncludePaths[0][1] == ':')\r
+ {\r
+ sourceName[0] = IncludePaths[0][0];\r
+ sourceName[1] = ':';\r
+ sourceName[2] = '\0';\r
+ }\r
+ }\r
+ strcat(sourceName, fileName);\r
+#else\r
+ strcpy(sourceName, fileName);\r
+#endif\r
+ foundfile = MS_FileExists(sourceName);\r
+ }\r
+ else\r
+ {\r
+ // Pascal 12/11/08\r
+ // Find the file in the include paths\r
+ for(i = 0; i < NumIncludePaths; i++)\r
+ {\r
+ strcpy(sourceName, IncludePaths[i]);\r
+ strcat(sourceName, fileName);\r
+ if(MS_FileExists(sourceName))\r
+ {\r
+ foundfile = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ if(!foundfile)\r
+ {\r
+ ERR_ErrorAt(tk_SourceName, tk_Line);\r
+ ERR_Exit(ERR_CANT_FIND_INCLUDE, YES, fileName, tk_SourceName, tk_Line);\r
+ }\r
+\r
+ MS_Message(MSG_DEBUG, "*Include file found at %s\n", sourceName);\r
+\r
+ // Now change the first include path to the file directory\r
+ SetLocalIncludePath(sourceName);\r
+ \r
tk_SourceName = AddFileName(sourceName);\r
size = MS_LoadFile(tk_SourceName, &FileStart);\r
FileEnd = FileStart+size;\r
static int PopNestedSource(enum ImportModes *prevMode)\r
{\r
nestInfo_t *info;\r
-\r
+ \r
MS_Message(MSG_DEBUG, "*Leaving %s\n", tk_SourceName);\r
free(FileStart);\r
SY_FreeConstants(NestDepth);\r
Chr = info->lastChar;\r
tk_Token = TK_NONE;\r
AlreadyGot = FALSE;\r
+ \r
+ // Pascal 12/11/08\r
+ // Set the first include path back to this file directory\r
+ SetLocalIncludePath(tk_SourceName);\r
+ \r
*prevMode = info->prevMode;\r
return info->imported ? 2 : 0;\r
}\r
\r
void TK_SkipPast(tokenType_t token)\r
{\r
- while (tk_Token != token)\r
+ while (tk_Token != token && tk_Token != TK_EOF)\r
{\r
TK_NextToken();\r
}\r
\r
void TK_SkipTo(tokenType_t token)\r
{\r
- while (tk_Token != token)\r
+ while (tk_Token != token && tk_Token != TK_EOF)\r
{\r
TK_NextToken();\r
}\r
\r
static void EvalFixedConstant(int whole)\r
{\r
- int frac;\r
- int divisor;\r
+ double frac;\r
+ double divisor;\r
\r
frac = 0;\r
divisor = 1;\r
divisor *= 10;\r
NextChr();\r
}\r
- tk_Number = (whole<<16)+((frac<<16)/divisor);\r
+ tk_Number = (whole<<16)+(int)(65536.0*frac/divisor);\r
tk_Token = TK_NUMBER;\r
}\r
\r
*text++ = Chr;\r
}\r
// escape the character after a backslash [JB]\r
- if(Chr == ASCII_BACKSLASH)\r
- escaped ^= (Chr == ASCII_BACKSLASH);\r
+ if(Chr == '\\')\r
+ escaped ^= (Chr == '\\');\r
else\r
escaped = FALSE;\r
NextChr();\r
tk_Number = '\r';\r
break;\r
case '\'':\r
+ case '\\':\r
tk_Number = Chr;\r
break;\r
default:\r