📄 l_precomp.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
//
/*****************************************************************************
* name: l_precomp.c
*
* desc: pre compiler
*
* $Archive: /MissionPack/code/botlib/l_precomp.c $
*
*****************************************************************************/
//Notes: fix: PC_StringizeTokens
//#define SCREWUP
//#define BOTLIB
//#define QUAKE
//#define QUAKEC
//#define MEQCC
#ifdef SCREWUP
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
typedef enum {qfalse, qtrue} qboolean;
#endif //SCREWUP
#ifdef BOTLIB
#include "../game/q_shared.h"
#include "../game/botlib.h"
#include "be_interface.h"
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_log.h"
#endif //BOTLIB
#ifdef MEQCC
#include "qcc.h"
#include "time.h" //time & ctime
#include "math.h" //fabs
#include "l_memory.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_log.h"
#define qtrue true
#define qfalse false
#endif //MEQCC
#ifdef BSPC
//include files for usage in the BSP Converter
#include "../bspc/qbsp.h"
#include "../bspc/l_log.h"
#include "../bspc/l_mem.h"
#include "l_precomp.h"
#define qtrue true
#define qfalse false
#define Q_stricmp stricmp
#endif //BSPC
#if defined(QUAKE) && !defined(BSPC)
#include "l_utils.h"
#endif //QUAKE
//#define DEBUG_EVAL
#define MAX_DEFINEPARMS 128
#define DEFINEHASHING 1
//directive name with parse function
typedef struct directive_s
{
char *name;
int (*func)(source_t *source);
} directive_t;
#define DEFINEHASHSIZE 1024
#define TOKEN_HEAP_SIZE 4096
int numtokens;
/*
int tokenheapinitialized; //true when the token heap is initialized
token_t token_heap[TOKEN_HEAP_SIZE]; //heap with tokens
token_t *freetokens; //free tokens from the heap
*/
//list with global defines added to every source loaded
define_t *globaldefines;
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void QDECL SourceError(source_t *source, char *str, ...)
{
char text[1024];
va_list ap;
va_start(ap, str);
vsprintf(text, str, ap);
va_end(ap);
#ifdef BOTLIB
botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
#endif //BOTLIB
#ifdef MEQCC
printf("error: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
#endif //MEQCC
#ifdef BSPC
Log_Print("error: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
#endif //BSPC
} //end of the function SourceError
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void QDECL SourceWarning(source_t *source, char *str, ...)
{
char text[1024];
va_list ap;
va_start(ap, str);
vsprintf(text, str, ap);
va_end(ap);
#ifdef BOTLIB
botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
#endif //BOTLIB
#ifdef MEQCC
printf("warning: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
#endif //MEQCC
#ifdef BSPC
Log_Print("warning: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
#endif //BSPC
} //end of the function ScriptWarning
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void PC_PushIndent(source_t *source, int type, int skip)
{
indent_t *indent;
indent = (indent_t *) GetMemory(sizeof(indent_t));
indent->type = type;
indent->script = source->scriptstack;
indent->skip = (skip != 0);
source->skip += indent->skip;
indent->next = source->indentstack;
source->indentstack = indent;
} //end of the function PC_PushIndent
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void PC_PopIndent(source_t *source, int *type, int *skip)
{
indent_t *indent;
*type = 0;
*skip = 0;
indent = source->indentstack;
if (!indent) return;
//must be an indent from the current script
if (source->indentstack->script != source->scriptstack) return;
*type = indent->type;
*skip = indent->skip;
source->indentstack = source->indentstack->next;
source->skip -= indent->skip;
FreeMemory(indent);
} //end of the function PC_PopIndent
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void PC_PushScript(source_t *source, script_t *script)
{
script_t *s;
for (s = source->scriptstack; s; s = s->next)
{
if (!Q_stricmp(s->filename, script->filename))
{
SourceError(source, "%s recursively included", script->filename);
return;
} //end if
} //end for
//push the script on the script stack
script->next = source->scriptstack;
source->scriptstack = script;
} //end of the function PC_PushScript
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void PC_InitTokenHeap(void)
{
/*
int i;
if (tokenheapinitialized) return;
freetokens = NULL;
for (i = 0; i < TOKEN_HEAP_SIZE; i++)
{
token_heap[i].next = freetokens;
freetokens = &token_heap[i];
} //end for
tokenheapinitialized = qtrue;
*/
} //end of the function PC_InitTokenHeap
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
token_t *PC_CopyToken(token_t *token)
{
token_t *t;
// t = (token_t *) malloc(sizeof(token_t));
t = (token_t *) GetMemory(sizeof(token_t));
// t = freetokens;
if (!t)
{
#ifdef BSPC
Error("out of token space\n");
#else
Com_Error(ERR_FATAL, "out of token space\n");
#endif
return NULL;
} //end if
// freetokens = freetokens->next;
Com_Memcpy(t, token, sizeof(token_t));
t->next = NULL;
numtokens++;
return t;
} //end of the function PC_CopyToken
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
void PC_FreeToken(token_t *token)
{
//free(token);
FreeMemory(token);
// token->next = freetokens;
// freetokens = token;
numtokens--;
} //end of the function PC_FreeToken
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_ReadSourceToken(source_t *source, token_t *token)
{
token_t *t;
script_t *script;
int type, skip;
//if there's no token already available
while(!source->tokens)
{
//if there's a token to read from the script
if (PS_ReadToken(source->scriptstack, token)) return qtrue;
//if at the end of the script
if (EndOfScript(source->scriptstack))
{
//remove all indents of the script
while(source->indentstack &&
source->indentstack->script == source->scriptstack)
{
SourceWarning(source, "missing #endif");
PC_PopIndent(source, &type, &skip);
} //end if
} //end if
//if this was the initial script
if (!source->scriptstack->next) return qfalse;
//remove the script and return to the last one
script = source->scriptstack;
source->scriptstack = source->scriptstack->next;
FreeScript(script);
} //end while
//copy the already available token
Com_Memcpy(token, source->tokens, sizeof(token_t));
//free the read token
t = source->tokens;
source->tokens = source->tokens->next;
PC_FreeToken(t);
return qtrue;
} //end of the function PC_ReadSourceToken
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_UnreadSourceToken(source_t *source, token_t *token)
{
token_t *t;
t = PC_CopyToken(token);
t->next = source->tokens;
source->tokens = t;
return qtrue;
} //end of the function PC_UnreadSourceToken
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_ReadDefineParms(source_t *source, define_t *define, token_t **parms, int maxparms)
{
token_t token, *t, *last;
int i, done, lastcomma, numparms, indent;
if (!PC_ReadSourceToken(source, &token))
{
SourceError(source, "define %s missing parms", define->name);
return qfalse;
} //end if
//
if (define->numparms > maxparms)
{
SourceError(source, "define with more than %d parameters", maxparms);
return qfalse;
} //end if
//
for (i = 0; i < define->numparms; i++) parms[i] = NULL;
//if no leading "("
if (strcmp(token.string, "("))
{
PC_UnreadSourceToken(source, &token);
SourceError(source, "define %s missing parms", define->name);
return qfalse;
} //end if
//read the define parameters
for (done = 0, numparms = 0, indent = 0; !done;)
{
if (numparms >= maxparms)
{
SourceError(source, "define %s with too many parms", define->name);
return qfalse;
} //end if
if (numparms >= define->numparms)
{
SourceWarning(source, "define %s has too many parms", define->name);
return qfalse;
} //end if
parms[numparms] = NULL;
lastcomma = 1;
last = NULL;
while(!done)
{
//
if (!PC_ReadSourceToken(source, &token))
{
SourceError(source, "define %s incomplete", define->name);
return qfalse;
} //end if
//
if (!strcmp(token.string, ","))
{
if (indent <= 0)
{
if (lastcomma) SourceWarning(source, "too many comma's");
lastcomma = 1;
break;
} //end if
} //end if
lastcomma = 0;
//
if (!strcmp(token.string, "("))
{
indent++;
continue;
} //end if
else if (!strcmp(token.string, ")"))
{
if (--indent <= 0)
{
if (!parms[define->numparms-1])
{
SourceWarning(source, "too few define parms");
} //end if
done = 1;
break;
} //end if
} //end if
//
if (numparms < define->numparms)
{
//
t = PC_CopyToken(&token);
t->next = NULL;
if (last) last->next = t;
else parms[numparms] = t;
last = t;
} //end if
} //end while
numparms++;
} //end for
return qtrue;
} //end of the function PC_ReadDefineParms
//============================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//============================================================================
int PC_StringizeTokens(token_t *tokens, token_t *token)
{
token_t *t;
token->type = TT_STRING;
token->whitespace_p = NULL;
token->endwhitespace_p = NULL;
token->string[0] = '\0';
strcat(token->string, "\"");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -