📄 l_precomp.c
字号:
void PC_ConvertPath(char *path)
{
char *ptr;
//remove double path seperators
for (ptr = path; *ptr;)
{
if ((*ptr == '\\' || *ptr == '/') &&
(*(ptr+1) == '\\' || *(ptr+1) == '/'))
{
strcpy(ptr, ptr+1);
} //end if
else
{
ptr++;
} //end else
} //end while
//set OS dependent path seperators
for (ptr = path; *ptr;)
{
if (*ptr == '/' || *ptr == '\\') *ptr = PATHSEPERATOR_CHAR;
ptr++;
} //end while
} //end of the function PC_ConvertPath
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_Directive_include(source_t *source)
{
script_t *script;
token_t token;
char path[MAX_PATH];
#ifdef QUAKE
foundfile_t file;
#endif //QUAKE
if (source->skip > 0) return qtrue;
//
if (!PC_ReadSourceToken(source, &token))
{
SourceError(source, "#include without file name");
return qfalse;
} //end if
if (token.linescrossed > 0)
{
SourceError(source, "#include without file name");
return qfalse;
} //end if
if (token.type == TT_STRING)
{
StripDoubleQuotes(token.string);
PC_ConvertPath(token.string);
script = LoadScriptFile(token.string);
if (!script)
{
strcpy(path, source->includepath);
strcat(path, token.string);
script = LoadScriptFile(path);
} //end if
} //end if
else if (token.type == TT_PUNCTUATION && *token.string == '<')
{
strcpy(path, source->includepath);
while(PC_ReadSourceToken(source, &token))
{
if (token.linescrossed > 0)
{
PC_UnreadSourceToken(source, &token);
break;
} //end if
if (token.type == TT_PUNCTUATION && *token.string == '>') break;
strncat(path, token.string, MAX_PATH);
} //end while
if (*token.string != '>')
{
SourceWarning(source, "#include missing trailing >");
} //end if
if (!strlen(path))
{
SourceError(source, "#include without file name between < >");
return qfalse;
} //end if
PC_ConvertPath(path);
script = LoadScriptFile(path);
} //end if
else
{
SourceError(source, "#include without file name");
return qfalse;
} //end else
#ifdef QUAKE
if (!script)
{
Com_Memset(&file, 0, sizeof(foundfile_t));
script = LoadScriptFile(path);
if (script) strncpy(script->filename, path, MAX_PATH);
} //end if
#endif //QUAKE
if (!script)
{
#ifdef SCREWUP
SourceWarning(source, "file %s not found", path);
return qtrue;
#else
SourceError(source, "file %s not found", path);
return qfalse;
#endif //SCREWUP
} //end if
PC_PushScript(source, script);
return qtrue;
} //end of the function PC_Directive_include
//============================================================================
// reads a token from the current line, continues reading on the next
// line only if a backslash '\' is encountered.
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_ReadLine(source_t *source, token_t *token)
{
int crossline;
crossline = 0;
do
{
if (!PC_ReadSourceToken(source, token)) return qfalse;
if (token->linescrossed > crossline)
{
PC_UnreadSourceToken(source, token);
return qfalse;
} //end if
crossline = 1;
} while(!strcmp(token->string, "\\"));
return qtrue;
} //end of the function PC_ReadLine
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_WhiteSpaceBeforeToken(token_t *token)
{
return token->endwhitespace_p - token->whitespace_p > 0;
} //end of the function PC_WhiteSpaceBeforeToken
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void PC_ClearTokenWhiteSpace(token_t *token)
{
token->whitespace_p = NULL;
token->endwhitespace_p = NULL;
token->linescrossed = 0;
} //end of the function PC_ClearTokenWhiteSpace
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_Directive_undef(source_t *source)
{
token_t token;
define_t *define, *lastdefine;
int hash;
if (source->skip > 0) return qtrue;
//
if (!PC_ReadLine(source, &token))
{
SourceError(source, "undef without name");
return qfalse;
} //end if
if (token.type != TT_NAME)
{
PC_UnreadSourceToken(source, &token);
SourceError(source, "expected name, found %s", token.string);
return qfalse;
} //end if
#if DEFINEHASHING
hash = PC_NameHash(token.string);
for (lastdefine = NULL, define = source->definehash[hash]; define; define = define->hashnext)
{
if (!strcmp(define->name, token.string))
{
if (define->flags & DEFINE_FIXED)
{
SourceWarning(source, "can't undef %s", token.string);
} //end if
else
{
if (lastdefine) lastdefine->hashnext = define->hashnext;
else source->definehash[hash] = define->hashnext;
PC_FreeDefine(define);
} //end else
break;
} //end if
lastdefine = define;
} //end for
#else //DEFINEHASHING
for (lastdefine = NULL, define = source->defines; define; define = define->next)
{
if (!strcmp(define->name, token.string))
{
if (define->flags & DEFINE_FIXED)
{
SourceWarning(source, "can't undef %s", token.string);
} //end if
else
{
if (lastdefine) lastdefine->next = define->next;
else source->defines = define->next;
PC_FreeDefine(define);
} //end else
break;
} //end if
lastdefine = define;
} //end for
#endif //DEFINEHASHING
return qtrue;
} //end of the function PC_Directive_undef
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_Directive_define(source_t *source)
{
token_t token, *t, *last;
define_t *define;
if (source->skip > 0) return qtrue;
//
if (!PC_ReadLine(source, &token))
{
SourceError(source, "#define without name");
return qfalse;
} //end if
if (token.type != TT_NAME)
{
PC_UnreadSourceToken(source, &token);
SourceError(source, "expected name after #define, found %s", token.string);
return qfalse;
} //end if
//check if the define already exists
#if DEFINEHASHING
define = PC_FindHashedDefine(source->definehash, token.string);
#else
define = PC_FindDefine(source->defines, token.string);
#endif //DEFINEHASHING
if (define)
{
if (define->flags & DEFINE_FIXED)
{
SourceError(source, "can't redefine %s", token.string);
return qfalse;
} //end if
SourceWarning(source, "redefinition of %s", token.string);
//unread the define name before executing the #undef directive
PC_UnreadSourceToken(source, &token);
if (!PC_Directive_undef(source)) return qfalse;
//if the define was not removed (define->flags & DEFINE_FIXED)
#if DEFINEHASHING
define = PC_FindHashedDefine(source->definehash, token.string);
#else
define = PC_FindDefine(source->defines, token.string);
#endif //DEFINEHASHING
} //end if
//allocate define
define = (define_t *) GetMemory(sizeof(define_t) + strlen(token.string) + 1);
Com_Memset(define, 0, sizeof(define_t));
define->name = (char *) define + sizeof(define_t);
strcpy(define->name, token.string);
//add the define to the source
#if DEFINEHASHING
PC_AddDefineToHash(define, source->definehash);
#else //DEFINEHASHING
define->next = source->defines;
source->defines = define;
#endif //DEFINEHASHING
//if nothing is defined, just return
if (!PC_ReadLine(source, &token)) return qtrue;
//if it is a define with parameters
if (!PC_WhiteSpaceBeforeToken(&token) && !strcmp(token.string, "("))
{
//read the define parameters
last = NULL;
if (!PC_CheckTokenString(source, ")"))
{
while(1)
{
if (!PC_ReadLine(source, &token))
{
SourceError(source, "expected define parameter");
return qfalse;
} //end if
//if it isn't a name
if (token.type != TT_NAME)
{
SourceError(source, "invalid define parameter");
return qfalse;
} //end if
//
if (PC_FindDefineParm(define, token.string) >= 0)
{
SourceError(source, "two the same define parameters");
return qfalse;
} //end if
//add the define parm
t = PC_CopyToken(&token);
PC_ClearTokenWhiteSpace(t);
t->next = NULL;
if (last) last->next = t;
else define->parms = t;
last = t;
define->numparms++;
//read next token
if (!PC_ReadLine(source, &token))
{
SourceError(source, "define parameters not terminated");
return qfalse;
} //end if
//
if (!strcmp(token.string, ")")) break;
//then it must be a comma
if (strcmp(token.string, ","))
{
SourceError(source, "define not terminated");
return qfalse;
} //end if
} //end while
} //end if
if (!PC_ReadLine(source, &token)) return qtrue;
} //end if
//read the defined stuff
last = NULL;
do
{
t = PC_CopyToken(&token);
if (t->type == TT_NAME && !strcmp(t->string, define->name))
{
SourceError(source, "recursive define (removed recursion)");
continue;
} //end if
PC_ClearTokenWhiteSpace(t);
t->next = NULL;
if (last) last->next = t;
else define->tokens = t;
last = t;
} while(PC_ReadLine(source, &token));
//
if (last)
{
//check for merge operators at the beginning or end
if (!strcmp(define->tokens->string, "##") ||
!strcmp(last->string, "##"))
{
SourceError(source, "define with misplaced ##");
return qfalse;
} //end if
} //end if
return qtrue;
} //end of the function PC_Directive_define
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
define_t *PC_DefineFromString(char *string)
{
script_t *script;
source_t src;
token_t *t;
int res, i;
define_t *def;
PC_InitTokenHeap();
script = LoadScriptMemory(string, strlen(string), "*extern");
//create a new source
Com_Memset(&src, 0, sizeof(source_t));
strncpy(src.filename, "*extern", MAX_PATH);
src.scriptstack = script;
#if DEFINEHASHING
src.definehash = GetClearedMemory(DEFINEHASHSIZE * sizeof(define_t *));
#endif //DEFINEHASHING
//create a define from the source
res = PC_Directive_define(&src);
//free any tokens if left
for (t = src.tokens; t; t = src.tokens)
{
src.tokens = src.tokens->next;
PC_FreeToken(t);
} //end for
#ifdef DEFINEHASHING
def = NULL;
for (i = 0; i < DEFINEHASHSIZE; i++)
{
if (src.definehash[i])
{
def = src.definehash[i];
break;
} //end if
} //end for
#else
def = src.defines;
#endif //DEFINEHASHING
//
#if DEFINEHASHING
FreeMemory(src.definehash);
#endif //DEFINEHASHING
//
FreeScript(script);
//if the define was created succesfully
if (res > 0) return def;
//free the define is created
if (src.defines) PC_FreeDefine(def);
//
return NULL;
} //end of the function PC_DefineFromString
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_AddDefine(source_t *source, char *string)
{
define_t *define;
define = PC_DefineFromString(string);
if (!define) return qfalse;
#if DEFINEHASHING
PC_AddDefineToHash(define, source->definehash);
#else //DEFINEHASHING
define->next = source->defines;
source->defines = define;
#endif //DEFINEHASHING
return qtrue;
} //end of the function PC_AddDefine
//============================================================================
// add a globals define that will be added to all opened sources
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_AddGlobalDefine(char *string)
{
define_t *define;
define = PC_DefineFromString(string);
if (!define) return qfalse;
define->next = globaldefines;
globaldefines = define;
return qtrue;
} //end of the function PC_AddGlobalDefine
//============================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -