Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_precomp.c (88624B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 //
     23 
     24 /*****************************************************************************
     25  * name:		l_precomp.c
     26  *
     27  * desc:		pre compiler
     28  *
     29  * $Archive: /MissionPack/code/botlib/l_precomp.c $
     30  *
     31  *****************************************************************************/
     32 
     33 //Notes:			fix: PC_StringizeTokens
     34 
     35 //#define SCREWUP
     36 //#define BOTLIB
     37 //#define QUAKE
     38 //#define QUAKEC
     39 //#define MEQCC
     40 
     41 #ifdef SCREWUP
     42 #include <stdio.h>
     43 #include <stdlib.h>
     44 #include <limits.h>
     45 #include <string.h>
     46 #include <stdarg.h>
     47 #include <time.h>
     48 #include "l_memory.h"
     49 #include "l_script.h"
     50 #include "l_precomp.h"
     51 
     52 typedef enum {qfalse, qtrue}	qboolean;
     53 #endif //SCREWUP
     54 
     55 #ifdef BOTLIB
     56 #include "../game/q_shared.h"
     57 #include "../game/botlib.h"
     58 #include "be_interface.h"
     59 #include "l_memory.h"
     60 #include "l_script.h"
     61 #include "l_precomp.h"
     62 #include "l_log.h"
     63 #endif //BOTLIB
     64 
     65 #ifdef MEQCC
     66 #include "qcc.h"
     67 #include "time.h"   //time & ctime
     68 #include "math.h"   //fabs
     69 #include "l_memory.h"
     70 #include "l_script.h"
     71 #include "l_precomp.h"
     72 #include "l_log.h"
     73 
     74 #define qtrue	true
     75 #define qfalse	false
     76 #endif //MEQCC
     77 
     78 #ifdef BSPC
     79 //include files for usage in the BSP Converter
     80 #include "../bspc/qbsp.h"
     81 #include "../bspc/l_log.h"
     82 #include "../bspc/l_mem.h"
     83 #include "l_precomp.h"
     84 
     85 #define qtrue	true
     86 #define qfalse	false
     87 #define Q_stricmp	stricmp
     88 
     89 #endif //BSPC
     90 
     91 #if defined(QUAKE) && !defined(BSPC)
     92 #include "l_utils.h"
     93 #endif //QUAKE
     94 
     95 //#define DEBUG_EVAL
     96 
     97 #define MAX_DEFINEPARMS			128
     98 
     99 #define DEFINEHASHING			1
    100 
    101 //directive name with parse function
    102 typedef struct directive_s
    103 {
    104 	char *name;
    105 	int (*func)(source_t *source);
    106 } directive_t;
    107 
    108 #define DEFINEHASHSIZE		1024
    109 
    110 #define TOKEN_HEAP_SIZE		4096
    111 
    112 int numtokens;
    113 /*
    114 int tokenheapinitialized;				//true when the token heap is initialized
    115 token_t token_heap[TOKEN_HEAP_SIZE];	//heap with tokens
    116 token_t *freetokens;					//free tokens from the heap
    117 */
    118 
    119 //list with global defines added to every source loaded
    120 define_t *globaldefines;
    121 
    122 //============================================================================
    123 //
    124 // Parameter:				-
    125 // Returns:					-
    126 // Changes Globals:		-
    127 //============================================================================
    128 void QDECL SourceError(source_t *source, char *str, ...)
    129 {
    130 	char text[1024];
    131 	va_list ap;
    132 
    133 	va_start(ap, str);
    134 	vsprintf(text, str, ap);
    135 	va_end(ap);
    136 #ifdef BOTLIB
    137 	botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
    138 #endif	//BOTLIB
    139 #ifdef MEQCC
    140 	printf("error: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
    141 #endif //MEQCC
    142 #ifdef BSPC
    143 	Log_Print("error: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
    144 #endif //BSPC
    145 } //end of the function SourceError
    146 //===========================================================================
    147 //
    148 // Parameter:				-
    149 // Returns:					-
    150 // Changes Globals:		-
    151 //===========================================================================
    152 void QDECL SourceWarning(source_t *source, char *str, ...)
    153 {
    154 	char text[1024];
    155 	va_list ap;
    156 
    157 	va_start(ap, str);
    158 	vsprintf(text, str, ap);
    159 	va_end(ap);
    160 #ifdef BOTLIB
    161 	botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
    162 #endif //BOTLIB
    163 #ifdef MEQCC
    164 	printf("warning: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
    165 #endif //MEQCC
    166 #ifdef BSPC
    167 	Log_Print("warning: file %s, line %d: %s\n", source->scriptstack->filename, source->scriptstack->line, text);
    168 #endif //BSPC
    169 } //end of the function ScriptWarning
    170 //============================================================================
    171 //
    172 // Parameter:				-
    173 // Returns:					-
    174 // Changes Globals:		-
    175 //============================================================================
    176 void PC_PushIndent(source_t *source, int type, int skip)
    177 {
    178 	indent_t *indent;
    179 
    180 	indent = (indent_t *) GetMemory(sizeof(indent_t));
    181 	indent->type = type;
    182 	indent->script = source->scriptstack;
    183 	indent->skip = (skip != 0);
    184 	source->skip += indent->skip;
    185 	indent->next = source->indentstack;
    186 	source->indentstack = indent;
    187 } //end of the function PC_PushIndent
    188 //============================================================================
    189 //
    190 // Parameter:				-
    191 // Returns:					-
    192 // Changes Globals:		-
    193 //============================================================================
    194 void PC_PopIndent(source_t *source, int *type, int *skip)
    195 {
    196 	indent_t *indent;
    197 
    198 	*type = 0;
    199 	*skip = 0;
    200 
    201 	indent = source->indentstack;
    202 	if (!indent) return;
    203 
    204 	//must be an indent from the current script
    205 	if (source->indentstack->script != source->scriptstack) return;
    206 
    207 	*type = indent->type;
    208 	*skip = indent->skip;
    209 	source->indentstack = source->indentstack->next;
    210 	source->skip -= indent->skip;
    211 	FreeMemory(indent);
    212 } //end of the function PC_PopIndent
    213 //============================================================================
    214 //
    215 // Parameter:				-
    216 // Returns:					-
    217 // Changes Globals:		-
    218 //============================================================================
    219 void PC_PushScript(source_t *source, script_t *script)
    220 {
    221 	script_t *s;
    222 
    223 	for (s = source->scriptstack; s; s = s->next)
    224 	{
    225 		if (!Q_stricmp(s->filename, script->filename))
    226 		{
    227 			SourceError(source, "%s recursively included", script->filename);
    228 			return;
    229 		} //end if
    230 	} //end for
    231 	//push the script on the script stack
    232 	script->next = source->scriptstack;
    233 	source->scriptstack = script;
    234 } //end of the function PC_PushScript
    235 //============================================================================
    236 //
    237 // Parameter:			-
    238 // Returns:				-
    239 // Changes Globals:		-
    240 //============================================================================
    241 void PC_InitTokenHeap(void)
    242 {
    243 	/*
    244 	int i;
    245 
    246 	if (tokenheapinitialized) return;
    247 	freetokens = NULL;
    248 	for (i = 0; i < TOKEN_HEAP_SIZE; i++)
    249 	{
    250 		token_heap[i].next = freetokens;
    251 		freetokens = &token_heap[i];
    252 	} //end for
    253 	tokenheapinitialized = qtrue;
    254 	*/
    255 } //end of the function PC_InitTokenHeap
    256 //============================================================================
    257 //
    258 // Parameter:			-
    259 // Returns:				-
    260 // Changes Globals:		-
    261 //============================================================================
    262 token_t *PC_CopyToken(token_t *token)
    263 {
    264 	token_t *t;
    265 
    266 //	t = (token_t *) malloc(sizeof(token_t));
    267 	t = (token_t *) GetMemory(sizeof(token_t));
    268 //	t = freetokens;
    269 	if (!t)
    270 	{
    271 #ifdef BSPC
    272 		Error("out of token space\n");
    273 #else
    274 		Com_Error(ERR_FATAL, "out of token space\n");
    275 #endif
    276 		return NULL;
    277 	} //end if
    278 //	freetokens = freetokens->next;
    279 	Com_Memcpy(t, token, sizeof(token_t));
    280 	t->next = NULL;
    281 	numtokens++;
    282 	return t;
    283 } //end of the function PC_CopyToken
    284 //============================================================================
    285 //
    286 // Parameter:				-
    287 // Returns:					-
    288 // Changes Globals:		-
    289 //============================================================================
    290 void PC_FreeToken(token_t *token)
    291 {
    292 	//free(token);
    293 	FreeMemory(token);
    294 //	token->next = freetokens;
    295 //	freetokens = token;
    296 	numtokens--;
    297 } //end of the function PC_FreeToken
    298 //============================================================================
    299 //
    300 // Parameter:				-
    301 // Returns:					-
    302 // Changes Globals:		-
    303 //============================================================================
    304 int PC_ReadSourceToken(source_t *source, token_t *token)
    305 {
    306 	token_t *t;
    307 	script_t *script;
    308 	int type, skip;
    309 
    310 	//if there's no token already available
    311 	while(!source->tokens)
    312 	{
    313 		//if there's a token to read from the script
    314 		if (PS_ReadToken(source->scriptstack, token)) return qtrue;
    315 		//if at the end of the script
    316 		if (EndOfScript(source->scriptstack))
    317 		{
    318 			//remove all indents of the script
    319 			while(source->indentstack &&
    320 					source->indentstack->script == source->scriptstack)
    321 			{
    322 				SourceWarning(source, "missing #endif");
    323 				PC_PopIndent(source, &type, &skip);
    324 			} //end if
    325 		} //end if
    326 		//if this was the initial script
    327 		if (!source->scriptstack->next) return qfalse;
    328 		//remove the script and return to the last one
    329 		script = source->scriptstack;
    330 		source->scriptstack = source->scriptstack->next;
    331 		FreeScript(script);
    332 	} //end while
    333 	//copy the already available token
    334 	Com_Memcpy(token, source->tokens, sizeof(token_t));
    335 	//free the read token
    336 	t = source->tokens;
    337 	source->tokens = source->tokens->next;
    338 	PC_FreeToken(t);
    339 	return qtrue;
    340 } //end of the function PC_ReadSourceToken
    341 //============================================================================
    342 //
    343 // Parameter:				-
    344 // Returns:					-
    345 // Changes Globals:		-
    346 //============================================================================
    347 int PC_UnreadSourceToken(source_t *source, token_t *token)
    348 {
    349 	token_t *t;
    350 
    351 	t = PC_CopyToken(token);
    352 	t->next = source->tokens;
    353 	source->tokens = t;
    354 	return qtrue;
    355 } //end of the function PC_UnreadSourceToken
    356 //============================================================================
    357 //
    358 // Parameter:				-
    359 // Returns:					-
    360 // Changes Globals:		-
    361 //============================================================================
    362 int PC_ReadDefineParms(source_t *source, define_t *define, token_t **parms, int maxparms)
    363 {
    364 	token_t token, *t, *last;
    365 	int i, done, lastcomma, numparms, indent;
    366 
    367 	if (!PC_ReadSourceToken(source, &token))
    368 	{
    369 		SourceError(source, "define %s missing parms", define->name);
    370 		return qfalse;
    371 	} //end if
    372 	//
    373 	if (define->numparms > maxparms)
    374 	{
    375 		SourceError(source, "define with more than %d parameters", maxparms);
    376 		return qfalse;
    377 	} //end if
    378 	//
    379 	for (i = 0; i < define->numparms; i++) parms[i] = NULL;
    380 	//if no leading "("
    381 	if (strcmp(token.string, "("))
    382 	{
    383 		PC_UnreadSourceToken(source, &token);
    384 		SourceError(source, "define %s missing parms", define->name);
    385 		return qfalse;
    386 	} //end if
    387 	//read the define parameters
    388 	for (done = 0, numparms = 0, indent = 0; !done;)
    389 	{
    390 		if (numparms >= maxparms)
    391 		{
    392 			SourceError(source, "define %s with too many parms", define->name);
    393 			return qfalse;
    394 		} //end if
    395 		if (numparms >= define->numparms)
    396 		{
    397 			SourceWarning(source, "define %s has too many parms", define->name);
    398 			return qfalse;
    399 		} //end if
    400 		parms[numparms] = NULL;
    401 		lastcomma = 1;
    402 		last = NULL;
    403 		while(!done)
    404 		{
    405 			//
    406 			if (!PC_ReadSourceToken(source, &token))
    407 			{
    408 				SourceError(source, "define %s incomplete", define->name);
    409 				return qfalse;
    410 			} //end if
    411 			//
    412 			if (!strcmp(token.string, ","))
    413 			{
    414 				if (indent <= 0)
    415 				{
    416 					if (lastcomma) SourceWarning(source, "too many comma's");
    417 					lastcomma = 1;
    418 					break;
    419 				} //end if
    420 			} //end if
    421 			lastcomma = 0;
    422 			//
    423 			if (!strcmp(token.string, "("))
    424 			{
    425 				indent++;
    426 				continue;
    427 			} //end if
    428 			else if (!strcmp(token.string, ")"))
    429 			{
    430 				if (--indent <= 0)
    431 				{
    432 					if (!parms[define->numparms-1])
    433 					{
    434 						SourceWarning(source, "too few define parms");
    435 					} //end if
    436 					done = 1;
    437 					break;
    438 				} //end if
    439 			} //end if
    440 			//
    441 			if (numparms < define->numparms)
    442 			{
    443 				//
    444 				t = PC_CopyToken(&token);
    445 				t->next = NULL;
    446 				if (last) last->next = t;
    447 				else parms[numparms] = t;
    448 				last = t;
    449 			} //end if
    450 		} //end while
    451 		numparms++;
    452 	} //end for
    453 	return qtrue;
    454 } //end of the function PC_ReadDefineParms
    455 //============================================================================
    456 //
    457 // Parameter:				-
    458 // Returns:					-
    459 // Changes Globals:		-
    460 //============================================================================
    461 int PC_StringizeTokens(token_t *tokens, token_t *token)
    462 {
    463 	token_t *t;
    464 
    465 	token->type = TT_STRING;
    466 	token->whitespace_p = NULL;
    467 	token->endwhitespace_p = NULL;
    468 	token->string[0] = '\0';
    469 	strcat(token->string, "\"");
    470 	for (t = tokens; t; t = t->next)
    471 	{
    472 		strncat(token->string, t->string, MAX_TOKEN - strlen(token->string));
    473 	} //end for
    474 	strncat(token->string, "\"", MAX_TOKEN - strlen(token->string));
    475 	return qtrue;
    476 } //end of the function PC_StringizeTokens
    477 //============================================================================
    478 //
    479 // Parameter:				-
    480 // Returns:					-
    481 // Changes Globals:		-
    482 //============================================================================
    483 int PC_MergeTokens(token_t *t1, token_t *t2)
    484 {
    485 	//merging of a name with a name or number
    486 	if (t1->type == TT_NAME && (t2->type == TT_NAME || t2->type == TT_NUMBER))
    487 	{
    488 		strcat(t1->string, t2->string);
    489 		return qtrue;
    490 	} //end if
    491 	//merging of two strings
    492 	if (t1->type == TT_STRING && t2->type == TT_STRING)
    493 	{
    494 		//remove trailing double quote
    495 		t1->string[strlen(t1->string)-1] = '\0';
    496 		//concat without leading double quote
    497 		strcat(t1->string, &t2->string[1]);
    498 		return qtrue;
    499 	} //end if
    500 	//FIXME: merging of two number of the same sub type
    501 	return qfalse;
    502 } //end of the function PC_MergeTokens
    503 //============================================================================
    504 //
    505 // Parameter:				-
    506 // Returns:					-
    507 // Changes Globals:		-
    508 //============================================================================
    509 /*
    510 void PC_PrintDefine(define_t *define)
    511 {
    512 	printf("define->name = %s\n", define->name);
    513 	printf("define->flags = %d\n", define->flags);
    514 	printf("define->builtin = %d\n", define->builtin);
    515 	printf("define->numparms = %d\n", define->numparms);
    516 //	token_t *parms;					//define parameters
    517 //	token_t *tokens;					//macro tokens (possibly containing parm tokens)
    518 //	struct define_s *next;			//next defined macro in a list
    519 } //end of the function PC_PrintDefine*/
    520 #if DEFINEHASHING
    521 //============================================================================
    522 //
    523 // Parameter:				-
    524 // Returns:					-
    525 // Changes Globals:		-
    526 //============================================================================
    527 void PC_PrintDefineHashTable(define_t **definehash)
    528 {
    529 	int i;
    530 	define_t *d;
    531 
    532 	for (i = 0; i < DEFINEHASHSIZE; i++)
    533 	{
    534 		Log_Write("%4d:", i);
    535 		for (d = definehash[i]; d; d = d->hashnext)
    536 		{
    537 			Log_Write(" %s", d->name);
    538 		} //end for
    539 		Log_Write("\n");
    540 	} //end for
    541 } //end of the function PC_PrintDefineHashTable
    542 //============================================================================
    543 //
    544 // Parameter:				-
    545 // Returns:					-
    546 // Changes Globals:		-
    547 //============================================================================
    548 //char primes[16] = {1, 3, 5, 7, 11, 13, 17, 19, 23, 27, 29, 31, 37, 41, 43, 47};
    549 
    550 int PC_NameHash(char *name)
    551 {
    552 	int register hash, i;
    553 
    554 	hash = 0;
    555 	for (i = 0; name[i] != '\0'; i++)
    556 	{
    557 		hash += name[i] * (119 + i);
    558 		//hash += (name[i] << 7) + i;
    559 		//hash += (name[i] << (i&15));
    560 	} //end while
    561 	hash = (hash ^ (hash >> 10) ^ (hash >> 20)) & (DEFINEHASHSIZE-1);
    562 	return hash;
    563 } //end of the function PC_NameHash
    564 //============================================================================
    565 //
    566 // Parameter:				-
    567 // Returns:					-
    568 // Changes Globals:		-
    569 //============================================================================
    570 void PC_AddDefineToHash(define_t *define, define_t **definehash)
    571 {
    572 	int hash;
    573 
    574 	hash = PC_NameHash(define->name);
    575 	define->hashnext = definehash[hash];
    576 	definehash[hash] = define;
    577 } //end of the function PC_AddDefineToHash
    578 //============================================================================
    579 //
    580 // Parameter:				-
    581 // Returns:					-
    582 // Changes Globals:		-
    583 //============================================================================
    584 define_t *PC_FindHashedDefine(define_t **definehash, char *name)
    585 {
    586 	define_t *d;
    587 	int hash;
    588 
    589 	hash = PC_NameHash(name);
    590 	for (d = definehash[hash]; d; d = d->hashnext)
    591 	{
    592 		if (!strcmp(d->name, name)) return d;
    593 	} //end for
    594 	return NULL;
    595 } //end of the function PC_FindHashedDefine
    596 #endif //DEFINEHASHING
    597 //============================================================================
    598 //
    599 // Parameter:				-
    600 // Returns:					-
    601 // Changes Globals:		-
    602 //============================================================================
    603 define_t *PC_FindDefine(define_t *defines, char *name)
    604 {
    605 	define_t *d;
    606 
    607 	for (d = defines; d; d = d->next)
    608 	{
    609 		if (!strcmp(d->name, name)) return d;
    610 	} //end for
    611 	return NULL;
    612 } //end of the function PC_FindDefine
    613 //============================================================================
    614 //
    615 // Parameter:				-
    616 // Returns:					number of the parm
    617 //								if no parm found with the given name -1 is returned
    618 // Changes Globals:		-
    619 //============================================================================
    620 int PC_FindDefineParm(define_t *define, char *name)
    621 {
    622 	token_t *p;
    623 	int i;
    624 
    625 	i = 0;
    626 	for (p = define->parms; p; p = p->next)
    627 	{
    628 		if (!strcmp(p->string, name)) return i;
    629 		i++;
    630 	} //end for
    631 	return -1;
    632 } //end of the function PC_FindDefineParm
    633 //============================================================================
    634 //
    635 // Parameter:				-
    636 // Returns:					-
    637 // Changes Globals:		-
    638 //============================================================================
    639 void PC_FreeDefine(define_t *define)
    640 {
    641 	token_t *t, *next;
    642 
    643 	//free the define parameters
    644 	for (t = define->parms; t; t = next)
    645 	{
    646 		next = t->next;
    647 		PC_FreeToken(t);
    648 	} //end for
    649 	//free the define tokens
    650 	for (t = define->tokens; t; t = next)
    651 	{
    652 		next = t->next;
    653 		PC_FreeToken(t);
    654 	} //end for
    655 	//free the define
    656 	FreeMemory(define);
    657 } //end of the function PC_FreeDefine
    658 //============================================================================
    659 //
    660 // Parameter:				-
    661 // Returns:					-
    662 // Changes Globals:		-
    663 //============================================================================
    664 void PC_AddBuiltinDefines(source_t *source)
    665 {
    666 	int i;
    667 	define_t *define;
    668 	struct builtin
    669 	{
    670 		char *string;
    671 		int builtin;
    672 	} builtin[] = { // bk001204 - brackets
    673 		{ "__LINE__",	BUILTIN_LINE },
    674 		{ "__FILE__",	BUILTIN_FILE },
    675 		{ "__DATE__",	BUILTIN_DATE },
    676 		{ "__TIME__",	BUILTIN_TIME },
    677 //		{ "__STDC__", BUILTIN_STDC },
    678 		{ NULL, 0 }
    679 	};
    680 
    681 	for (i = 0; builtin[i].string; i++)
    682 	{
    683 		define = (define_t *) GetMemory(sizeof(define_t) + strlen(builtin[i].string) + 1);
    684 		Com_Memset(define, 0, sizeof(define_t));
    685 		define->name = (char *) define + sizeof(define_t);
    686 		strcpy(define->name, builtin[i].string);
    687 		define->flags |= DEFINE_FIXED;
    688 		define->builtin = builtin[i].builtin;
    689 		//add the define to the source
    690 #if DEFINEHASHING
    691 		PC_AddDefineToHash(define, source->definehash);
    692 #else
    693 		define->next = source->defines;
    694 		source->defines = define;
    695 #endif //DEFINEHASHING
    696 	} //end for
    697 } //end of the function PC_AddBuiltinDefines
    698 //============================================================================
    699 //
    700 // Parameter:				-
    701 // Returns:					-
    702 // Changes Globals:		-
    703 //============================================================================
    704 int PC_ExpandBuiltinDefine(source_t *source, token_t *deftoken, define_t *define,
    705 										token_t **firsttoken, token_t **lasttoken)
    706 {
    707 	token_t *token;
    708 	unsigned long t;	//	time_t t; //to prevent LCC warning
    709 	char *curtime;
    710 
    711 	token = PC_CopyToken(deftoken);
    712 	switch(define->builtin)
    713 	{
    714 		case BUILTIN_LINE:
    715 		{
    716 			sprintf(token->string, "%d", deftoken->line);
    717 #ifdef NUMBERVALUE
    718 			token->intvalue = deftoken->line;
    719 			token->floatvalue = deftoken->line;
    720 #endif //NUMBERVALUE
    721 			token->type = TT_NUMBER;
    722 			token->subtype = TT_DECIMAL | TT_INTEGER;
    723 			*firsttoken = token;
    724 			*lasttoken = token;
    725 			break;
    726 		} //end case
    727 		case BUILTIN_FILE:
    728 		{
    729 			strcpy(token->string, source->scriptstack->filename);
    730 			token->type = TT_NAME;
    731 			token->subtype = strlen(token->string);
    732 			*firsttoken = token;
    733 			*lasttoken = token;
    734 			break;
    735 		} //end case
    736 		case BUILTIN_DATE:
    737 		{
    738 			t = time(NULL);
    739 			curtime = ctime(&t);
    740 			strcpy(token->string, "\"");
    741 			strncat(token->string, curtime+4, 7);
    742 			strncat(token->string+7, curtime+20, 4);
    743 			strcat(token->string, "\"");
    744 			free(curtime);
    745 			token->type = TT_NAME;
    746 			token->subtype = strlen(token->string);
    747 			*firsttoken = token;
    748 			*lasttoken = token;
    749 			break;
    750 		} //end case
    751 		case BUILTIN_TIME:
    752 		{
    753 			t = time(NULL);
    754 			curtime = ctime(&t);
    755 			strcpy(token->string, "\"");
    756 			strncat(token->string, curtime+11, 8);
    757 			strcat(token->string, "\"");
    758 			free(curtime);
    759 			token->type = TT_NAME;
    760 			token->subtype = strlen(token->string);
    761 			*firsttoken = token;
    762 			*lasttoken = token;
    763 			break;
    764 		} //end case
    765 		case BUILTIN_STDC:
    766 		default:
    767 		{
    768 			*firsttoken = NULL;
    769 			*lasttoken = NULL;
    770 			break;
    771 		} //end case
    772 	} //end switch
    773 	return qtrue;
    774 } //end of the function PC_ExpandBuiltinDefine
    775 //============================================================================
    776 //
    777 // Parameter:				-
    778 // Returns:					-
    779 // Changes Globals:		-
    780 //============================================================================
    781 int PC_ExpandDefine(source_t *source, token_t *deftoken, define_t *define,
    782 										token_t **firsttoken, token_t **lasttoken)
    783 {
    784 	token_t *parms[MAX_DEFINEPARMS], *dt, *pt, *t;
    785 	token_t *t1, *t2, *first, *last, *nextpt, token;
    786 	int parmnum, i;
    787 
    788 	//if it is a builtin define
    789 	if (define->builtin)
    790 	{
    791 		return PC_ExpandBuiltinDefine(source, deftoken, define, firsttoken, lasttoken);
    792 	} //end if
    793 	//if the define has parameters
    794 	if (define->numparms)
    795 	{
    796 		if (!PC_ReadDefineParms(source, define, parms, MAX_DEFINEPARMS)) return qfalse;
    797 #ifdef DEBUG_EVAL
    798 		for (i = 0; i < define->numparms; i++)
    799 		{
    800 			Log_Write("define parms %d:", i);
    801 			for (pt = parms[i]; pt; pt = pt->next)
    802 			{
    803 				Log_Write("%s", pt->string);
    804 			} //end for
    805 		} //end for
    806 #endif //DEBUG_EVAL
    807 	} //end if
    808 	//empty list at first
    809 	first = NULL;
    810 	last = NULL;
    811 	//create a list with tokens of the expanded define
    812 	for (dt = define->tokens; dt; dt = dt->next)
    813 	{
    814 		parmnum = -1;
    815 		//if the token is a name, it could be a define parameter
    816 		if (dt->type == TT_NAME)
    817 		{
    818 			parmnum = PC_FindDefineParm(define, dt->string);
    819 		} //end if
    820 		//if it is a define parameter
    821 		if (parmnum >= 0)
    822 		{
    823 			for (pt = parms[parmnum]; pt; pt = pt->next)
    824 			{
    825 				t = PC_CopyToken(pt);
    826 				//add the token to the list
    827 				t->next = NULL;
    828 				if (last) last->next = t;
    829 				else first = t;
    830 				last = t;
    831 			} //end for
    832 		} //end if
    833 		else
    834 		{
    835 			//if stringizing operator
    836 			if (dt->string[0] == '#' && dt->string[1] == '\0')
    837 			{
    838 				//the stringizing operator must be followed by a define parameter
    839 				if (dt->next) parmnum = PC_FindDefineParm(define, dt->next->string);
    840 				else parmnum = -1;
    841 				//
    842 				if (parmnum >= 0)
    843 				{
    844 					//step over the stringizing operator
    845 					dt = dt->next;
    846 					//stringize the define parameter tokens
    847 					if (!PC_StringizeTokens(parms[parmnum], &token))
    848 					{
    849 						SourceError(source, "can't stringize tokens");
    850 						return qfalse;
    851 					} //end if
    852 					t = PC_CopyToken(&token);
    853 				} //end if
    854 				else
    855 				{
    856 					SourceWarning(source, "stringizing operator without define parameter");
    857 					continue;
    858 				} //end if
    859 			} //end if
    860 			else
    861 			{
    862 				t = PC_CopyToken(dt);
    863 			} //end else
    864 			//add the token to the list
    865 			t->next = NULL;
    866 			if (last) last->next = t;
    867 			else first = t;
    868 			last = t;
    869 		} //end else
    870 	} //end for
    871 	//check for the merging operator
    872 	for (t = first; t; )
    873 	{
    874 		if (t->next)
    875 		{
    876 			//if the merging operator
    877 			if (t->next->string[0] == '#' && t->next->string[1] == '#')
    878 			{
    879 				t1 = t;
    880 				t2 = t->next->next;
    881 				if (t2)
    882 				{
    883 					if (!PC_MergeTokens(t1, t2))
    884 					{
    885 						SourceError(source, "can't merge %s with %s", t1->string, t2->string);
    886 						return qfalse;
    887 					} //end if
    888 					PC_FreeToken(t1->next);
    889 					t1->next = t2->next;
    890 					if (t2 == last) last = t1;
    891 					PC_FreeToken(t2);
    892 					continue;
    893 				} //end if
    894 			} //end if
    895 		} //end if
    896 		t = t->next;
    897 	} //end for
    898 	//store the first and last token of the list
    899 	*firsttoken = first;
    900 	*lasttoken = last;
    901 	//free all the parameter tokens
    902 	for (i = 0; i < define->numparms; i++)
    903 	{
    904 		for (pt = parms[i]; pt; pt = nextpt)
    905 		{
    906 			nextpt = pt->next;
    907 			PC_FreeToken(pt);
    908 		} //end for
    909 	} //end for
    910 	//
    911 	return qtrue;
    912 } //end of the function PC_ExpandDefine
    913 //============================================================================
    914 //
    915 // Parameter:				-
    916 // Returns:					-
    917 // Changes Globals:		-
    918 //============================================================================
    919 int PC_ExpandDefineIntoSource(source_t *source, token_t *deftoken, define_t *define)
    920 {
    921 	token_t *firsttoken, *lasttoken;
    922 
    923 	if (!PC_ExpandDefine(source, deftoken, define, &firsttoken, &lasttoken)) return qfalse;
    924 
    925 	if (firsttoken && lasttoken)
    926 	{
    927 		lasttoken->next = source->tokens;
    928 		source->tokens = firsttoken;
    929 		return qtrue;
    930 	} //end if
    931 	return qfalse;
    932 } //end of the function PC_ExpandDefineIntoSource
    933 //============================================================================
    934 //
    935 // Parameter:				-
    936 // Returns:					-
    937 // Changes Globals:		-
    938 //============================================================================
    939 void PC_ConvertPath(char *path)
    940 {
    941 	char *ptr;
    942 
    943 	//remove double path seperators
    944 	for (ptr = path; *ptr;)
    945 	{
    946 		if ((*ptr == '\\' || *ptr == '/') &&
    947 				(*(ptr+1) == '\\' || *(ptr+1) == '/'))
    948 		{
    949 			strcpy(ptr, ptr+1);
    950 		} //end if
    951 		else
    952 		{
    953 			ptr++;
    954 		} //end else
    955 	} //end while
    956 	//set OS dependent path seperators
    957 	for (ptr = path; *ptr;)
    958 	{
    959 		if (*ptr == '/' || *ptr == '\\') *ptr = PATHSEPERATOR_CHAR;
    960 		ptr++;
    961 	} //end while
    962 } //end of the function PC_ConvertPath
    963 //============================================================================
    964 //
    965 // Parameter:				-
    966 // Returns:					-
    967 // Changes Globals:		-
    968 //============================================================================
    969 int PC_Directive_include(source_t *source)
    970 {
    971 	script_t *script;
    972 	token_t token;
    973 	char path[MAX_PATH];
    974 #ifdef QUAKE
    975 	foundfile_t file;
    976 #endif //QUAKE
    977 
    978 	if (source->skip > 0) return qtrue;
    979 	//
    980 	if (!PC_ReadSourceToken(source, &token))
    981 	{
    982 		SourceError(source, "#include without file name");
    983 		return qfalse;
    984 	} //end if
    985 	if (token.linescrossed > 0)
    986 	{
    987 		SourceError(source, "#include without file name");
    988 		return qfalse;
    989 	} //end if
    990 	if (token.type == TT_STRING)
    991 	{
    992 		StripDoubleQuotes(token.string);
    993 		PC_ConvertPath(token.string);
    994 		script = LoadScriptFile(token.string);
    995 		if (!script)
    996 		{
    997 			strcpy(path, source->includepath);
    998 			strcat(path, token.string);
    999 			script = LoadScriptFile(path);
   1000 		} //end if
   1001 	} //end if
   1002 	else if (token.type == TT_PUNCTUATION && *token.string == '<')
   1003 	{
   1004 		strcpy(path, source->includepath);
   1005 		while(PC_ReadSourceToken(source, &token))
   1006 		{
   1007 			if (token.linescrossed > 0)
   1008 			{
   1009 				PC_UnreadSourceToken(source, &token);
   1010 				break;
   1011 			} //end if
   1012 			if (token.type == TT_PUNCTUATION && *token.string == '>') break;
   1013 			strncat(path, token.string, MAX_PATH);
   1014 		} //end while
   1015 		if (*token.string != '>')
   1016 		{
   1017 			SourceWarning(source, "#include missing trailing >");
   1018 		} //end if
   1019 		if (!strlen(path))
   1020 		{
   1021 			SourceError(source, "#include without file name between < >");
   1022 			return qfalse;
   1023 		} //end if
   1024 		PC_ConvertPath(path);
   1025 		script = LoadScriptFile(path);
   1026 	} //end if
   1027 	else
   1028 	{
   1029 		SourceError(source, "#include without file name");
   1030 		return qfalse;
   1031 	} //end else
   1032 #ifdef QUAKE
   1033 	if (!script)
   1034 	{
   1035 		Com_Memset(&file, 0, sizeof(foundfile_t));
   1036 		script = LoadScriptFile(path);
   1037 		if (script) strncpy(script->filename, path, MAX_PATH);
   1038 	} //end if
   1039 #endif //QUAKE
   1040 	if (!script)
   1041 	{
   1042 #ifdef SCREWUP
   1043 		SourceWarning(source, "file %s not found", path);
   1044 		return qtrue;
   1045 #else
   1046 		SourceError(source, "file %s not found", path);
   1047 		return qfalse;
   1048 #endif //SCREWUP
   1049 	} //end if
   1050 	PC_PushScript(source, script);
   1051 	return qtrue;
   1052 } //end of the function PC_Directive_include
   1053 //============================================================================
   1054 // reads a token from the current line, continues reading on the next
   1055 // line only if a backslash '\' is encountered.
   1056 //
   1057 // Parameter:				-
   1058 // Returns:					-
   1059 // Changes Globals:		-
   1060 //============================================================================
   1061 int PC_ReadLine(source_t *source, token_t *token)
   1062 {
   1063 	int crossline;
   1064 
   1065 	crossline = 0;
   1066 	do
   1067 	{
   1068 		if (!PC_ReadSourceToken(source, token)) return qfalse;
   1069 		
   1070 		if (token->linescrossed > crossline)
   1071 		{
   1072 			PC_UnreadSourceToken(source, token);
   1073 			return qfalse;
   1074 		} //end if
   1075 		crossline = 1;
   1076 	} while(!strcmp(token->string, "\\"));
   1077 	return qtrue;
   1078 } //end of the function PC_ReadLine
   1079 //============================================================================
   1080 //
   1081 // Parameter:				-
   1082 // Returns:					-
   1083 // Changes Globals:		-
   1084 //============================================================================
   1085 int PC_WhiteSpaceBeforeToken(token_t *token)
   1086 {
   1087 	return token->endwhitespace_p - token->whitespace_p > 0;
   1088 } //end of the function PC_WhiteSpaceBeforeToken
   1089 //============================================================================
   1090 //
   1091 // Parameter:				-
   1092 // Returns:					-
   1093 // Changes Globals:		-
   1094 //============================================================================
   1095 void PC_ClearTokenWhiteSpace(token_t *token)
   1096 {
   1097 	token->whitespace_p = NULL;
   1098 	token->endwhitespace_p = NULL;
   1099 	token->linescrossed = 0;
   1100 } //end of the function PC_ClearTokenWhiteSpace
   1101 //============================================================================
   1102 //
   1103 // Parameter:				-
   1104 // Returns:					-
   1105 // Changes Globals:		-
   1106 //============================================================================
   1107 int PC_Directive_undef(source_t *source)
   1108 {
   1109 	token_t token;
   1110 	define_t *define, *lastdefine;
   1111 	int hash;
   1112 
   1113 	if (source->skip > 0) return qtrue;
   1114 	//
   1115 	if (!PC_ReadLine(source, &token))
   1116 	{
   1117 		SourceError(source, "undef without name");
   1118 		return qfalse;
   1119 	} //end if
   1120 	if (token.type != TT_NAME)
   1121 	{
   1122 		PC_UnreadSourceToken(source, &token);
   1123 		SourceError(source, "expected name, found %s", token.string);
   1124 		return qfalse;
   1125 	} //end if
   1126 #if DEFINEHASHING
   1127 
   1128 	hash = PC_NameHash(token.string);
   1129 	for (lastdefine = NULL, define = source->definehash[hash]; define; define = define->hashnext)
   1130 	{
   1131 		if (!strcmp(define->name, token.string))
   1132 		{
   1133 			if (define->flags & DEFINE_FIXED)
   1134 			{
   1135 				SourceWarning(source, "can't undef %s", token.string);
   1136 			} //end if
   1137 			else
   1138 			{
   1139 				if (lastdefine) lastdefine->hashnext = define->hashnext;
   1140 				else source->definehash[hash] = define->hashnext;
   1141 				PC_FreeDefine(define);
   1142 			} //end else
   1143 			break;
   1144 		} //end if
   1145 		lastdefine = define;
   1146 	} //end for
   1147 #else //DEFINEHASHING
   1148 	for (lastdefine = NULL, define = source->defines; define; define = define->next)
   1149 	{
   1150 		if (!strcmp(define->name, token.string))
   1151 		{
   1152 			if (define->flags & DEFINE_FIXED)
   1153 			{
   1154 				SourceWarning(source, "can't undef %s", token.string);
   1155 			} //end if
   1156 			else
   1157 			{
   1158 				if (lastdefine) lastdefine->next = define->next;
   1159 				else source->defines = define->next;
   1160 				PC_FreeDefine(define);
   1161 			} //end else
   1162 			break;
   1163 		} //end if
   1164 		lastdefine = define;
   1165 	} //end for
   1166 #endif //DEFINEHASHING
   1167 	return qtrue;
   1168 } //end of the function PC_Directive_undef
   1169 //============================================================================
   1170 //
   1171 // Parameter:				-
   1172 // Returns:					-
   1173 // Changes Globals:		-
   1174 //============================================================================
   1175 int PC_Directive_define(source_t *source)
   1176 {
   1177 	token_t token, *t, *last;
   1178 	define_t *define;
   1179 
   1180 	if (source->skip > 0) return qtrue;
   1181 	//
   1182 	if (!PC_ReadLine(source, &token))
   1183 	{
   1184 		SourceError(source, "#define without name");
   1185 		return qfalse;
   1186 	} //end if
   1187 	if (token.type != TT_NAME)
   1188 	{
   1189 		PC_UnreadSourceToken(source, &token);
   1190 		SourceError(source, "expected name after #define, found %s", token.string);
   1191 		return qfalse;
   1192 	} //end if
   1193 	//check if the define already exists
   1194 #if DEFINEHASHING
   1195 	define = PC_FindHashedDefine(source->definehash, token.string);
   1196 #else
   1197 	define = PC_FindDefine(source->defines, token.string);
   1198 #endif //DEFINEHASHING
   1199 	if (define)
   1200 	{
   1201 		if (define->flags & DEFINE_FIXED)
   1202 		{
   1203 			SourceError(source, "can't redefine %s", token.string);
   1204 			return qfalse;
   1205 		} //end if
   1206 		SourceWarning(source, "redefinition of %s", token.string);
   1207 		//unread the define name before executing the #undef directive
   1208 		PC_UnreadSourceToken(source, &token);
   1209 		if (!PC_Directive_undef(source)) return qfalse;
   1210 		//if the define was not removed (define->flags & DEFINE_FIXED)
   1211 #if DEFINEHASHING
   1212 		define = PC_FindHashedDefine(source->definehash, token.string);
   1213 #else
   1214 		define = PC_FindDefine(source->defines, token.string);
   1215 #endif //DEFINEHASHING
   1216 	} //end if
   1217 	//allocate define
   1218 	define = (define_t *) GetMemory(sizeof(define_t) + strlen(token.string) + 1);
   1219 	Com_Memset(define, 0, sizeof(define_t));
   1220 	define->name = (char *) define + sizeof(define_t);
   1221 	strcpy(define->name, token.string);
   1222 	//add the define to the source
   1223 #if DEFINEHASHING
   1224 	PC_AddDefineToHash(define, source->definehash);
   1225 #else //DEFINEHASHING
   1226 	define->next = source->defines;
   1227 	source->defines = define;
   1228 #endif //DEFINEHASHING
   1229 	//if nothing is defined, just return
   1230 	if (!PC_ReadLine(source, &token)) return qtrue;
   1231 	//if it is a define with parameters
   1232 	if (!PC_WhiteSpaceBeforeToken(&token) && !strcmp(token.string, "("))
   1233 	{
   1234 		//read the define parameters
   1235 		last = NULL;
   1236 		if (!PC_CheckTokenString(source, ")"))
   1237 		{
   1238 			while(1)
   1239 			{
   1240 				if (!PC_ReadLine(source, &token))
   1241 				{
   1242 					SourceError(source, "expected define parameter");
   1243 					return qfalse;
   1244 				} //end if
   1245 				//if it isn't a name
   1246 				if (token.type != TT_NAME)
   1247 				{
   1248 					SourceError(source, "invalid define parameter");
   1249 					return qfalse;
   1250 				} //end if
   1251 				//
   1252 				if (PC_FindDefineParm(define, token.string) >= 0)
   1253 				{
   1254 					SourceError(source, "two the same define parameters");
   1255 					return qfalse;
   1256 				} //end if
   1257 				//add the define parm
   1258 				t = PC_CopyToken(&token);
   1259 				PC_ClearTokenWhiteSpace(t);
   1260 				t->next = NULL;
   1261 				if (last) last->next = t;
   1262 				else define->parms = t;
   1263 				last = t;
   1264 				define->numparms++;
   1265 				//read next token
   1266 				if (!PC_ReadLine(source, &token))
   1267 				{
   1268 					SourceError(source, "define parameters not terminated");
   1269 					return qfalse;
   1270 				} //end if
   1271 				//
   1272 				if (!strcmp(token.string, ")")) break;
   1273 				//then it must be a comma
   1274 				if (strcmp(token.string, ","))
   1275 				{
   1276 					SourceError(source, "define not terminated");
   1277 					return qfalse;
   1278 				} //end if
   1279 			} //end while
   1280 		} //end if
   1281 		if (!PC_ReadLine(source, &token)) return qtrue;
   1282 	} //end if
   1283 	//read the defined stuff
   1284 	last = NULL;
   1285 	do
   1286 	{
   1287 		t = PC_CopyToken(&token);
   1288 		if (t->type == TT_NAME && !strcmp(t->string, define->name))
   1289 		{
   1290 			SourceError(source, "recursive define (removed recursion)");
   1291 			continue;
   1292 		} //end if
   1293 		PC_ClearTokenWhiteSpace(t);
   1294 		t->next = NULL;
   1295 		if (last) last->next = t;
   1296 		else define->tokens = t;
   1297 		last = t;
   1298 	} while(PC_ReadLine(source, &token));
   1299 	//
   1300 	if (last)
   1301 	{
   1302 		//check for merge operators at the beginning or end
   1303 		if (!strcmp(define->tokens->string, "##") ||
   1304 				!strcmp(last->string, "##"))
   1305 		{
   1306 			SourceError(source, "define with misplaced ##");
   1307 			return qfalse;
   1308 		} //end if
   1309 	} //end if
   1310 	return qtrue;
   1311 } //end of the function PC_Directive_define
   1312 //============================================================================
   1313 //
   1314 // Parameter:				-
   1315 // Returns:					-
   1316 // Changes Globals:		-
   1317 //============================================================================
   1318 define_t *PC_DefineFromString(char *string)
   1319 {
   1320 	script_t *script;
   1321 	source_t src;
   1322 	token_t *t;
   1323 	int res, i;
   1324 	define_t *def;
   1325 
   1326 	PC_InitTokenHeap();
   1327 
   1328 	script = LoadScriptMemory(string, strlen(string), "*extern");
   1329 	//create a new source
   1330 	Com_Memset(&src, 0, sizeof(source_t));
   1331 	strncpy(src.filename, "*extern", MAX_PATH);
   1332 	src.scriptstack = script;
   1333 #if DEFINEHASHING
   1334 	src.definehash = GetClearedMemory(DEFINEHASHSIZE * sizeof(define_t *));
   1335 #endif //DEFINEHASHING
   1336 	//create a define from the source
   1337 	res = PC_Directive_define(&src);
   1338 	//free any tokens if left
   1339 	for (t = src.tokens; t; t = src.tokens)
   1340 	{
   1341 		src.tokens = src.tokens->next;
   1342 		PC_FreeToken(t);
   1343 	} //end for
   1344 #ifdef DEFINEHASHING
   1345 	def = NULL;
   1346 	for (i = 0; i < DEFINEHASHSIZE; i++)
   1347 	{
   1348 		if (src.definehash[i])
   1349 		{
   1350 			def = src.definehash[i];
   1351 			break;
   1352 		} //end if
   1353 	} //end for
   1354 #else
   1355 	def = src.defines;
   1356 #endif //DEFINEHASHING
   1357 	//
   1358 #if DEFINEHASHING
   1359 	FreeMemory(src.definehash);
   1360 #endif //DEFINEHASHING
   1361 	//
   1362 	FreeScript(script);
   1363 	//if the define was created succesfully
   1364 	if (res > 0) return def;
   1365 	//free the define is created
   1366 	if (src.defines) PC_FreeDefine(def);
   1367 	//
   1368 	return NULL;
   1369 } //end of the function PC_DefineFromString
   1370 //============================================================================
   1371 //
   1372 // Parameter:				-
   1373 // Returns:					-
   1374 // Changes Globals:		-
   1375 //============================================================================
   1376 int PC_AddDefine(source_t *source, char *string)
   1377 {
   1378 	define_t *define;
   1379 
   1380 	define = PC_DefineFromString(string);
   1381 	if (!define) return qfalse;
   1382 #if DEFINEHASHING
   1383 	PC_AddDefineToHash(define, source->definehash);
   1384 #else //DEFINEHASHING
   1385 	define->next = source->defines;
   1386 	source->defines = define;
   1387 #endif //DEFINEHASHING
   1388 	return qtrue;
   1389 } //end of the function PC_AddDefine
   1390 //============================================================================
   1391 // add a globals define that will be added to all opened sources
   1392 //
   1393 // Parameter:				-
   1394 // Returns:					-
   1395 // Changes Globals:		-
   1396 //============================================================================
   1397 int PC_AddGlobalDefine(char *string)
   1398 {
   1399 	define_t *define;
   1400 
   1401 	define = PC_DefineFromString(string);
   1402 	if (!define) return qfalse;
   1403 	define->next = globaldefines;
   1404 	globaldefines = define;
   1405 	return qtrue;
   1406 } //end of the function PC_AddGlobalDefine
   1407 //============================================================================
   1408 // remove the given global define
   1409 //
   1410 // Parameter:				-
   1411 // Returns:					-
   1412 // Changes Globals:		-
   1413 //============================================================================
   1414 int PC_RemoveGlobalDefine(char *name)
   1415 {
   1416 	define_t *define;
   1417 
   1418 	define = PC_FindDefine(globaldefines, name);
   1419 	if (define)
   1420 	{
   1421 		PC_FreeDefine(define);
   1422 		return qtrue;
   1423 	} //end if
   1424 	return qfalse;
   1425 } //end of the function PC_RemoveGlobalDefine
   1426 //============================================================================
   1427 // remove all globals defines
   1428 //
   1429 // Parameter:				-
   1430 // Returns:					-
   1431 // Changes Globals:		-
   1432 //============================================================================
   1433 void PC_RemoveAllGlobalDefines(void)
   1434 {
   1435 	define_t *define;
   1436 
   1437 	for (define = globaldefines; define; define = globaldefines)
   1438 	{
   1439 		globaldefines = globaldefines->next;
   1440 		PC_FreeDefine(define);
   1441 	} //end for
   1442 } //end of the function PC_RemoveAllGlobalDefines
   1443 //============================================================================
   1444 //
   1445 // Parameter:				-
   1446 // Returns:					-
   1447 // Changes Globals:		-
   1448 //============================================================================
   1449 define_t *PC_CopyDefine(source_t *source, define_t *define)
   1450 {
   1451 	define_t *newdefine;
   1452 	token_t *token, *newtoken, *lasttoken;
   1453 
   1454 	newdefine = (define_t *) GetMemory(sizeof(define_t) + strlen(define->name) + 1);
   1455 	//copy the define name
   1456 	newdefine->name = (char *) newdefine + sizeof(define_t);
   1457 	strcpy(newdefine->name, define->name);
   1458 	newdefine->flags = define->flags;
   1459 	newdefine->builtin = define->builtin;
   1460 	newdefine->numparms = define->numparms;
   1461 	//the define is not linked
   1462 	newdefine->next = NULL;
   1463 	newdefine->hashnext = NULL;
   1464 	//copy the define tokens
   1465 	newdefine->tokens = NULL;
   1466 	for (lasttoken = NULL, token = define->tokens; token; token = token->next)
   1467 	{
   1468 		newtoken = PC_CopyToken(token);
   1469 		newtoken->next = NULL;
   1470 		if (lasttoken) lasttoken->next = newtoken;
   1471 		else newdefine->tokens = newtoken;
   1472 		lasttoken = newtoken;
   1473 	} //end for
   1474 	//copy the define parameters
   1475 	newdefine->parms = NULL;
   1476 	for (lasttoken = NULL, token = define->parms; token; token = token->next)
   1477 	{
   1478 		newtoken = PC_CopyToken(token);
   1479 		newtoken->next = NULL;
   1480 		if (lasttoken) lasttoken->next = newtoken;
   1481 		else newdefine->parms = newtoken;
   1482 		lasttoken = newtoken;
   1483 	} //end for
   1484 	return newdefine;
   1485 } //end of the function PC_CopyDefine
   1486 //============================================================================
   1487 //
   1488 // Parameter:				-
   1489 // Returns:					-
   1490 // Changes Globals:		-
   1491 //============================================================================
   1492 void PC_AddGlobalDefinesToSource(source_t *source)
   1493 {
   1494 	define_t *define, *newdefine;
   1495 
   1496 	for (define = globaldefines; define; define = define->next)
   1497 	{
   1498 		newdefine = PC_CopyDefine(source, define);
   1499 #if DEFINEHASHING
   1500 		PC_AddDefineToHash(newdefine, source->definehash);
   1501 #else //DEFINEHASHING
   1502 		newdefine->next = source->defines;
   1503 		source->defines = newdefine;
   1504 #endif //DEFINEHASHING
   1505 	} //end for
   1506 } //end of the function PC_AddGlobalDefinesToSource
   1507 //============================================================================
   1508 //
   1509 // Parameter:				-
   1510 // Returns:					-
   1511 // Changes Globals:		-
   1512 //============================================================================
   1513 int PC_Directive_if_def(source_t *source, int type)
   1514 {
   1515 	token_t token;
   1516 	define_t *d;
   1517 	int skip;
   1518 
   1519 	if (!PC_ReadLine(source, &token))
   1520 	{
   1521 		SourceError(source, "#ifdef without name");
   1522 		return qfalse;
   1523 	} //end if
   1524 	if (token.type != TT_NAME)
   1525 	{
   1526 		PC_UnreadSourceToken(source, &token);
   1527 		SourceError(source, "expected name after #ifdef, found %s", token.string);
   1528 		return qfalse;
   1529 	} //end if
   1530 #if DEFINEHASHING
   1531 	d = PC_FindHashedDefine(source->definehash, token.string);
   1532 #else
   1533 	d = PC_FindDefine(source->defines, token.string);
   1534 #endif //DEFINEHASHING
   1535 	skip = (type == INDENT_IFDEF) == (d == NULL);
   1536 	PC_PushIndent(source, type, skip);
   1537 	return qtrue;
   1538 } //end of the function PC_Directiveif_def
   1539 //============================================================================
   1540 //
   1541 // Parameter:				-
   1542 // Returns:					-
   1543 // Changes Globals:		-
   1544 //============================================================================
   1545 int PC_Directive_ifdef(source_t *source)
   1546 {
   1547 	return PC_Directive_if_def(source, INDENT_IFDEF);
   1548 } //end of the function PC_Directive_ifdef
   1549 //============================================================================
   1550 //
   1551 // Parameter:				-
   1552 // Returns:					-
   1553 // Changes Globals:		-
   1554 //============================================================================
   1555 int PC_Directive_ifndef(source_t *source)
   1556 {
   1557 	return PC_Directive_if_def(source, INDENT_IFNDEF);
   1558 } //end of the function PC_Directive_ifndef
   1559 //============================================================================
   1560 //
   1561 // Parameter:				-
   1562 // Returns:					-
   1563 // Changes Globals:		-
   1564 //============================================================================
   1565 int PC_Directive_else(source_t *source)
   1566 {
   1567 	int type, skip;
   1568 
   1569 	PC_PopIndent(source, &type, &skip);
   1570 	if (!type)
   1571 	{
   1572 		SourceError(source, "misplaced #else");
   1573 		return qfalse;
   1574 	} //end if
   1575 	if (type == INDENT_ELSE)
   1576 	{
   1577 		SourceError(source, "#else after #else");
   1578 		return qfalse;
   1579 	} //end if
   1580 	PC_PushIndent(source, INDENT_ELSE, !skip);
   1581 	return qtrue;
   1582 } //end of the function PC_Directive_else
   1583 //============================================================================
   1584 //
   1585 // Parameter:				-
   1586 // Returns:					-
   1587 // Changes Globals:		-
   1588 //============================================================================
   1589 int PC_Directive_endif(source_t *source)
   1590 {
   1591 	int type, skip;
   1592 
   1593 	PC_PopIndent(source, &type, &skip);
   1594 	if (!type)
   1595 	{
   1596 		SourceError(source, "misplaced #endif");
   1597 		return qfalse;
   1598 	} //end if
   1599 	return qtrue;
   1600 } //end of the function PC_Directive_endif
   1601 //============================================================================
   1602 //
   1603 // Parameter:				-
   1604 // Returns:					-
   1605 // Changes Globals:		-
   1606 //============================================================================
   1607 typedef struct operator_s
   1608 {
   1609 	int operator;
   1610 	int priority;
   1611 	int parentheses;
   1612 	struct operator_s *prev, *next;
   1613 } operator_t;
   1614 
   1615 typedef struct value_s
   1616 {
   1617 	signed long int intvalue;
   1618 	double floatvalue;
   1619 	int parentheses;
   1620 	struct value_s *prev, *next;
   1621 } value_t;
   1622 
   1623 int PC_OperatorPriority(int op)
   1624 {
   1625 	switch(op)
   1626 	{
   1627 		case P_MUL: return 15;
   1628 		case P_DIV: return 15;
   1629 		case P_MOD: return 15;
   1630 		case P_ADD: return 14;
   1631 		case P_SUB: return 14;
   1632 
   1633 		case P_LOGIC_AND: return 7;
   1634 		case P_LOGIC_OR: return 6;
   1635 		case P_LOGIC_GEQ: return 12;
   1636 		case P_LOGIC_LEQ: return 12;
   1637 		case P_LOGIC_EQ: return 11;
   1638 		case P_LOGIC_UNEQ: return 11;
   1639 
   1640 		case P_LOGIC_NOT: return 16;
   1641 		case P_LOGIC_GREATER: return 12;
   1642 		case P_LOGIC_LESS: return 12;
   1643 
   1644 		case P_RSHIFT: return 13;
   1645 		case P_LSHIFT: return 13;
   1646 
   1647 		case P_BIN_AND: return 10;
   1648 		case P_BIN_OR: return 8;
   1649 		case P_BIN_XOR: return 9;
   1650 		case P_BIN_NOT: return 16;
   1651 
   1652 		case P_COLON: return 5;
   1653 		case P_QUESTIONMARK: return 5;
   1654 	} //end switch
   1655 	return qfalse;
   1656 } //end of the function PC_OperatorPriority
   1657 
   1658 //#define AllocValue()			GetClearedMemory(sizeof(value_t));
   1659 //#define FreeValue(val)		FreeMemory(val)
   1660 //#define AllocOperator(op)		op = (operator_t *) GetClearedMemory(sizeof(operator_t));
   1661 //#define FreeOperator(op)		FreeMemory(op);
   1662 
   1663 #define MAX_VALUES		64
   1664 #define MAX_OPERATORS	64
   1665 #define AllocValue(val)									\
   1666 	if (numvalues >= MAX_VALUES) {						\
   1667 		SourceError(source, "out of value space\n");		\
   1668 		error = 1;										\
   1669 		break;											\
   1670 	}													\
   1671 	else												\
   1672 		val = &value_heap[numvalues++];
   1673 #define FreeValue(val)
   1674 //
   1675 #define AllocOperator(op)								\
   1676 	if (numoperators >= MAX_OPERATORS) {				\
   1677 		SourceError(source, "out of operator space\n");	\
   1678 		error = 1;										\
   1679 		break;											\
   1680 	}													\
   1681 	else												\
   1682 		op = &operator_heap[numoperators++];
   1683 #define FreeOperator(op)
   1684 
   1685 int PC_EvaluateTokens(source_t *source, token_t *tokens, signed long int *intvalue,
   1686 																	double *floatvalue, int integer)
   1687 {
   1688 	operator_t *o, *firstoperator, *lastoperator;
   1689 	value_t *v, *firstvalue, *lastvalue, *v1, *v2;
   1690 	token_t *t;
   1691 	int brace = 0;
   1692 	int parentheses = 0;
   1693 	int error = 0;
   1694 	int lastwasvalue = 0;
   1695 	int negativevalue = 0;
   1696 	int questmarkintvalue = 0;
   1697 	double questmarkfloatvalue = 0;
   1698 	int gotquestmarkvalue = qfalse;
   1699 	int lastoperatortype = 0;
   1700 	//
   1701 	operator_t operator_heap[MAX_OPERATORS];
   1702 	int numoperators = 0;
   1703 	value_t value_heap[MAX_VALUES];
   1704 	int numvalues = 0;
   1705 
   1706 	firstoperator = lastoperator = NULL;
   1707 	firstvalue = lastvalue = NULL;
   1708 	if (intvalue) *intvalue = 0;
   1709 	if (floatvalue) *floatvalue = 0;
   1710 	for (t = tokens; t; t = t->next)
   1711 	{
   1712 		switch(t->type)
   1713 		{
   1714 			case TT_NAME:
   1715 			{
   1716 				if (lastwasvalue || negativevalue)
   1717 				{
   1718 					SourceError(source, "syntax error in #if/#elif");
   1719 					error = 1;
   1720 					break;
   1721 				} //end if
   1722 				if (strcmp(t->string, "defined"))
   1723 				{
   1724 					SourceError(source, "undefined name %s in #if/#elif", t->string);
   1725 					error = 1;
   1726 					break;
   1727 				} //end if
   1728 				t = t->next;
   1729 				if (!strcmp(t->string, "("))
   1730 				{
   1731 					brace = qtrue;
   1732 					t = t->next;
   1733 				} //end if
   1734 				if (!t || t->type != TT_NAME)
   1735 				{
   1736 					SourceError(source, "defined without name in #if/#elif");
   1737 					error = 1;
   1738 					break;
   1739 				} //end if
   1740 				//v = (value_t *) GetClearedMemory(sizeof(value_t));
   1741 				AllocValue(v);
   1742 #if DEFINEHASHING
   1743 				if (PC_FindHashedDefine(source->definehash, t->string))
   1744 #else			
   1745 				if (PC_FindDefine(source->defines, t->string))
   1746 #endif //DEFINEHASHING
   1747 				{
   1748 					v->intvalue = 1;
   1749 					v->floatvalue = 1;
   1750 				} //end if
   1751 				else
   1752 				{
   1753 					v->intvalue = 0;
   1754 					v->floatvalue = 0;
   1755 				} //end else
   1756 				v->parentheses = parentheses;
   1757 				v->next = NULL;
   1758 				v->prev = lastvalue;
   1759 				if (lastvalue) lastvalue->next = v;
   1760 				else firstvalue = v;
   1761 				lastvalue = v;
   1762 				if (brace)
   1763 				{
   1764 					t = t->next;
   1765 					if (!t || strcmp(t->string, ")"))
   1766 					{
   1767 						SourceError(source, "defined without ) in #if/#elif");
   1768 						error = 1;
   1769 						break;
   1770 					} //end if
   1771 				} //end if
   1772 				brace = qfalse;
   1773 				// defined() creates a value
   1774 				lastwasvalue = 1;
   1775 				break;
   1776 			} //end case
   1777 			case TT_NUMBER:
   1778 			{
   1779 				if (lastwasvalue)
   1780 				{
   1781 					SourceError(source, "syntax error in #if/#elif");
   1782 					error = 1;
   1783 					break;
   1784 				} //end if
   1785 				//v = (value_t *) GetClearedMemory(sizeof(value_t));
   1786 				AllocValue(v);
   1787 				if (negativevalue)
   1788 				{
   1789 					v->intvalue = - (signed int) t->intvalue;
   1790 					v->floatvalue = - t->floatvalue;
   1791 				} //end if
   1792 				else
   1793 				{
   1794 					v->intvalue = t->intvalue;
   1795 					v->floatvalue = t->floatvalue;
   1796 				} //end else
   1797 				v->parentheses = parentheses;
   1798 				v->next = NULL;
   1799 				v->prev = lastvalue;
   1800 				if (lastvalue) lastvalue->next = v;
   1801 				else firstvalue = v;
   1802 				lastvalue = v;
   1803 				//last token was a value
   1804 				lastwasvalue = 1;
   1805 				//
   1806 				negativevalue = 0;
   1807 				break;
   1808 			} //end case
   1809 			case TT_PUNCTUATION:
   1810 			{
   1811 				if (negativevalue)
   1812 				{
   1813 					SourceError(source, "misplaced minus sign in #if/#elif");
   1814 					error = 1;
   1815 					break;
   1816 				} //end if
   1817 				if (t->subtype == P_PARENTHESESOPEN)
   1818 				{
   1819 					parentheses++;
   1820 					break;
   1821 				} //end if
   1822 				else if (t->subtype == P_PARENTHESESCLOSE)
   1823 				{
   1824 					parentheses--;
   1825 					if (parentheses < 0)
   1826 					{
   1827 						SourceError(source, "too many ) in #if/#elsif");
   1828 						error = 1;
   1829 					} //end if
   1830 					break;
   1831 				} //end else if
   1832 				//check for invalid operators on floating point values
   1833 				if (!integer)
   1834 				{
   1835 					if (t->subtype == P_BIN_NOT || t->subtype == P_MOD ||
   1836 						t->subtype == P_RSHIFT || t->subtype == P_LSHIFT ||
   1837 						t->subtype == P_BIN_AND || t->subtype == P_BIN_OR ||
   1838 						t->subtype == P_BIN_XOR)
   1839 					{
   1840 						SourceError(source, "illigal operator %s on floating point operands\n", t->string);
   1841 						error = 1;
   1842 						break;
   1843 					} //end if
   1844 				} //end if
   1845 				switch(t->subtype)
   1846 				{
   1847 					case P_LOGIC_NOT:
   1848 					case P_BIN_NOT:
   1849 					{
   1850 						if (lastwasvalue)
   1851 						{
   1852 							SourceError(source, "! or ~ after value in #if/#elif");
   1853 							error = 1;
   1854 							break;
   1855 						} //end if
   1856 						break;
   1857 					} //end case
   1858 					case P_INC:
   1859 					case P_DEC:
   1860 					{
   1861 						SourceError(source, "++ or -- used in #if/#elif");
   1862 						break;
   1863 					} //end case
   1864 					case P_SUB:
   1865 					{
   1866 						if (!lastwasvalue)
   1867 						{
   1868 							negativevalue = 1;
   1869 							break;
   1870 						} //end if
   1871 					} //end case
   1872 					
   1873 					case P_MUL:
   1874 					case P_DIV:
   1875 					case P_MOD:
   1876 					case P_ADD:
   1877 
   1878 					case P_LOGIC_AND:
   1879 					case P_LOGIC_OR:
   1880 					case P_LOGIC_GEQ:
   1881 					case P_LOGIC_LEQ:
   1882 					case P_LOGIC_EQ:
   1883 					case P_LOGIC_UNEQ:
   1884 
   1885 					case P_LOGIC_GREATER:
   1886 					case P_LOGIC_LESS:
   1887 
   1888 					case P_RSHIFT:
   1889 					case P_LSHIFT:
   1890 
   1891 					case P_BIN_AND:
   1892 					case P_BIN_OR:
   1893 					case P_BIN_XOR:
   1894 
   1895 					case P_COLON:
   1896 					case P_QUESTIONMARK:
   1897 					{
   1898 						if (!lastwasvalue)
   1899 						{
   1900 							SourceError(source, "operator %s after operator in #if/#elif", t->string);
   1901 							error = 1;
   1902 							break;
   1903 						} //end if
   1904 						break;
   1905 					} //end case
   1906 					default:
   1907 					{
   1908 						SourceError(source, "invalid operator %s in #if/#elif", t->string);
   1909 						error = 1;
   1910 						break;
   1911 					} //end default
   1912 				} //end switch
   1913 				if (!error && !negativevalue)
   1914 				{
   1915 					//o = (operator_t *) GetClearedMemory(sizeof(operator_t));
   1916 					AllocOperator(o);
   1917 					o->operator = t->subtype;
   1918 					o->priority = PC_OperatorPriority(t->subtype);
   1919 					o->parentheses = parentheses;
   1920 					o->next = NULL;
   1921 					o->prev = lastoperator;
   1922 					if (lastoperator) lastoperator->next = o;
   1923 					else firstoperator = o;
   1924 					lastoperator = o;
   1925 					lastwasvalue = 0;
   1926 				} //end if
   1927 				break;
   1928 			} //end case
   1929 			default:
   1930 			{
   1931 				SourceError(source, "unknown %s in #if/#elif", t->string);
   1932 				error = 1;
   1933 				break;
   1934 			} //end default
   1935 		} //end switch
   1936 		if (error) break;
   1937 	} //end for
   1938 	if (!error)
   1939 	{
   1940 		if (!lastwasvalue)
   1941 		{
   1942 			SourceError(source, "trailing operator in #if/#elif");
   1943 			error = 1;
   1944 		} //end if
   1945 		else if (parentheses)
   1946 		{
   1947 			SourceError(source, "too many ( in #if/#elif");
   1948 			error = 1;
   1949 		} //end else if
   1950 	} //end if
   1951 	//
   1952 	gotquestmarkvalue = qfalse;
   1953 	questmarkintvalue = 0;
   1954 	questmarkfloatvalue = 0;
   1955 	//while there are operators
   1956 	while(!error && firstoperator)
   1957 	{
   1958 		v = firstvalue;
   1959 		for (o = firstoperator; o->next; o = o->next)
   1960 		{
   1961 			//if the current operator is nested deeper in parentheses
   1962 			//than the next operator
   1963 			if (o->parentheses > o->next->parentheses) break;
   1964 			//if the current and next operator are nested equally deep in parentheses
   1965 			if (o->parentheses == o->next->parentheses)
   1966 			{
   1967 				//if the priority of the current operator is equal or higher
   1968 				//than the priority of the next operator
   1969 				if (o->priority >= o->next->priority) break;
   1970 			} //end if
   1971 			//if the arity of the operator isn't equal to 1
   1972 			if (o->operator != P_LOGIC_NOT
   1973 					&& o->operator != P_BIN_NOT) v = v->next;
   1974 			//if there's no value or no next value
   1975 			if (!v)
   1976 			{
   1977 				SourceError(source, "mising values in #if/#elif");
   1978 				error = 1;
   1979 				break;
   1980 			} //end if
   1981 		} //end for
   1982 		if (error) break;
   1983 		v1 = v;
   1984 		v2 = v->next;
   1985 #ifdef DEBUG_EVAL
   1986 		if (integer)
   1987 		{
   1988 			Log_Write("operator %s, value1 = %d", PunctuationFromNum(source->scriptstack, o->operator), v1->intvalue);
   1989 			if (v2) Log_Write("value2 = %d", v2->intvalue);
   1990 		} //end if
   1991 		else
   1992 		{
   1993 			Log_Write("operator %s, value1 = %f", PunctuationFromNum(source->scriptstack, o->operator), v1->floatvalue);
   1994 			if (v2) Log_Write("value2 = %f", v2->floatvalue);
   1995 		} //end else
   1996 #endif //DEBUG_EVAL
   1997 		switch(o->operator)
   1998 		{
   1999 			case P_LOGIC_NOT:		v1->intvalue = !v1->intvalue;
   2000 									v1->floatvalue = !v1->floatvalue; break;
   2001 			case P_BIN_NOT:			v1->intvalue = ~v1->intvalue;
   2002 									break;
   2003 			case P_MUL:				v1->intvalue *= v2->intvalue;
   2004 									v1->floatvalue *= v2->floatvalue; break;
   2005 			case P_DIV:				if (!v2->intvalue || !v2->floatvalue)
   2006 									{
   2007 										SourceError(source, "divide by zero in #if/#elif\n");
   2008 										error = 1;
   2009 										break;
   2010 									}
   2011 									v1->intvalue /= v2->intvalue;
   2012 									v1->floatvalue /= v2->floatvalue; break;
   2013 			case P_MOD:				if (!v2->intvalue)
   2014 									{
   2015 										SourceError(source, "divide by zero in #if/#elif\n");
   2016 										error = 1;
   2017 										break;
   2018 									}
   2019 									v1->intvalue %= v2->intvalue; break;
   2020 			case P_ADD:				v1->intvalue += v2->intvalue;
   2021 									v1->floatvalue += v2->floatvalue; break;
   2022 			case P_SUB:				v1->intvalue -= v2->intvalue;
   2023 									v1->floatvalue -= v2->floatvalue; break;
   2024 			case P_LOGIC_AND:		v1->intvalue = v1->intvalue && v2->intvalue;
   2025 									v1->floatvalue = v1->floatvalue && v2->floatvalue; break;
   2026 			case P_LOGIC_OR:		v1->intvalue = v1->intvalue || v2->intvalue;
   2027 									v1->floatvalue = v1->floatvalue || v2->floatvalue; break;
   2028 			case P_LOGIC_GEQ:		v1->intvalue = v1->intvalue >= v2->intvalue;
   2029 									v1->floatvalue = v1->floatvalue >= v2->floatvalue; break;
   2030 			case P_LOGIC_LEQ:		v1->intvalue = v1->intvalue <= v2->intvalue;
   2031 									v1->floatvalue = v1->floatvalue <= v2->floatvalue; break;
   2032 			case P_LOGIC_EQ:		v1->intvalue = v1->intvalue == v2->intvalue;
   2033 									v1->floatvalue = v1->floatvalue == v2->floatvalue; break;
   2034 			case P_LOGIC_UNEQ:		v1->intvalue = v1->intvalue != v2->intvalue;
   2035 									v1->floatvalue = v1->floatvalue != v2->floatvalue; break;
   2036 			case P_LOGIC_GREATER:	v1->intvalue = v1->intvalue > v2->intvalue;
   2037 									v1->floatvalue = v1->floatvalue > v2->floatvalue; break;
   2038 			case P_LOGIC_LESS:		v1->intvalue = v1->intvalue < v2->intvalue;
   2039 									v1->floatvalue = v1->floatvalue < v2->floatvalue; break;
   2040 			case P_RSHIFT:			v1->intvalue >>= v2->intvalue;
   2041 									break;
   2042 			case P_LSHIFT:			v1->intvalue <<= v2->intvalue;
   2043 									break;
   2044 			case P_BIN_AND:			v1->intvalue &= v2->intvalue;
   2045 									break;
   2046 			case P_BIN_OR:			v1->intvalue |= v2->intvalue;
   2047 									break;
   2048 			case P_BIN_XOR:			v1->intvalue ^= v2->intvalue;
   2049 									break;
   2050 			case P_COLON:
   2051 			{
   2052 				if (!gotquestmarkvalue)
   2053 				{
   2054 					SourceError(source, ": without ? in #if/#elif");
   2055 					error = 1;
   2056 					break;
   2057 				} //end if
   2058 				if (integer)
   2059 				{
   2060 					if (!questmarkintvalue) v1->intvalue = v2->intvalue;
   2061 				} //end if
   2062 				else
   2063 				{
   2064 					if (!questmarkfloatvalue) v1->floatvalue = v2->floatvalue;
   2065 				} //end else
   2066 				gotquestmarkvalue = qfalse;
   2067 				break;
   2068 			} //end case
   2069 			case P_QUESTIONMARK:
   2070 			{
   2071 				if (gotquestmarkvalue)
   2072 				{
   2073 					SourceError(source, "? after ? in #if/#elif");
   2074 					error = 1;
   2075 					break;
   2076 				} //end if
   2077 				questmarkintvalue = v1->intvalue;
   2078 				questmarkfloatvalue = v1->floatvalue;
   2079 				gotquestmarkvalue = qtrue;
   2080 				break;
   2081 			} //end if
   2082 		} //end switch
   2083 #ifdef DEBUG_EVAL
   2084 		if (integer) Log_Write("result value = %d", v1->intvalue);
   2085 		else Log_Write("result value = %f", v1->floatvalue);
   2086 #endif //DEBUG_EVAL
   2087 		if (error) break;
   2088 		lastoperatortype = o->operator;
   2089 		//if not an operator with arity 1
   2090 		if (o->operator != P_LOGIC_NOT
   2091 				&& o->operator != P_BIN_NOT)
   2092 		{
   2093 			//remove the second value if not question mark operator
   2094 			if (o->operator != P_QUESTIONMARK) v = v->next;
   2095 			//
   2096 			if (v->prev) v->prev->next = v->next;
   2097 			else firstvalue = v->next;
   2098 			if (v->next) v->next->prev = v->prev;
   2099 			else lastvalue = v->prev;
   2100 			//FreeMemory(v);
   2101 			FreeValue(v);
   2102 		} //end if
   2103 		//remove the operator
   2104 		if (o->prev) o->prev->next = o->next;
   2105 		else firstoperator = o->next;
   2106 		if (o->next) o->next->prev = o->prev;
   2107 		else lastoperator = o->prev;
   2108 		//FreeMemory(o);
   2109 		FreeOperator(o);
   2110 	} //end while
   2111 	if (firstvalue)
   2112 	{
   2113 		if (intvalue) *intvalue = firstvalue->intvalue;
   2114 		if (floatvalue) *floatvalue = firstvalue->floatvalue;
   2115 	} //end if
   2116 	for (o = firstoperator; o; o = lastoperator)
   2117 	{
   2118 		lastoperator = o->next;
   2119 		//FreeMemory(o);
   2120 		FreeOperator(o);
   2121 	} //end for
   2122 	for (v = firstvalue; v; v = lastvalue)
   2123 	{
   2124 		lastvalue = v->next;
   2125 		//FreeMemory(v);
   2126 		FreeValue(v);
   2127 	} //end for
   2128 	if (!error) return qtrue;
   2129 	if (intvalue) *intvalue = 0;
   2130 	if (floatvalue) *floatvalue = 0;
   2131 	return qfalse;
   2132 } //end of the function PC_EvaluateTokens
   2133 //============================================================================
   2134 //
   2135 // Parameter:				-
   2136 // Returns:					-
   2137 // Changes Globals:		-
   2138 //============================================================================
   2139 int PC_Evaluate(source_t *source, signed long int *intvalue,
   2140 												double *floatvalue, int integer)
   2141 {
   2142 	token_t token, *firsttoken, *lasttoken;
   2143 	token_t *t, *nexttoken;
   2144 	define_t *define;
   2145 	int defined = qfalse;
   2146 
   2147 	if (intvalue) *intvalue = 0;
   2148 	if (floatvalue) *floatvalue = 0;
   2149 	//
   2150 	if (!PC_ReadLine(source, &token))
   2151 	{
   2152 		SourceError(source, "no value after #if/#elif");
   2153 		return qfalse;
   2154 	} //end if
   2155 	firsttoken = NULL;
   2156 	lasttoken = NULL;
   2157 	do
   2158 	{
   2159 		//if the token is a name
   2160 		if (token.type == TT_NAME)
   2161 		{
   2162 			if (defined)
   2163 			{
   2164 				defined = qfalse;
   2165 				t = PC_CopyToken(&token);
   2166 				t->next = NULL;
   2167 				if (lasttoken) lasttoken->next = t;
   2168 				else firsttoken = t;
   2169 				lasttoken = t;
   2170 			} //end if
   2171 			else if (!strcmp(token.string, "defined"))
   2172 			{
   2173 				defined = qtrue;
   2174 				t = PC_CopyToken(&token);
   2175 				t->next = NULL;
   2176 				if (lasttoken) lasttoken->next = t;
   2177 				else firsttoken = t;
   2178 				lasttoken = t;
   2179 			} //end if
   2180 			else
   2181 			{
   2182 				//then it must be a define
   2183 #if DEFINEHASHING
   2184 				define = PC_FindHashedDefine(source->definehash, token.string);
   2185 #else
   2186 				define = PC_FindDefine(source->defines, token.string);
   2187 #endif //DEFINEHASHING
   2188 				if (!define)
   2189 				{
   2190 					SourceError(source, "can't evaluate %s, not defined", token.string);
   2191 					return qfalse;
   2192 				} //end if
   2193 				if (!PC_ExpandDefineIntoSource(source, &token, define)) return qfalse;
   2194 			} //end else
   2195 		} //end if
   2196 		//if the token is a number or a punctuation
   2197 		else if (token.type == TT_NUMBER || token.type == TT_PUNCTUATION)
   2198 		{
   2199 			t = PC_CopyToken(&token);
   2200 			t->next = NULL;
   2201 			if (lasttoken) lasttoken->next = t;
   2202 			else firsttoken = t;
   2203 			lasttoken = t;
   2204 		} //end else
   2205 		else //can't evaluate the token
   2206 		{
   2207 			SourceError(source, "can't evaluate %s", token.string);
   2208 			return qfalse;
   2209 		} //end else
   2210 	} while(PC_ReadLine(source, &token));
   2211 	//
   2212 	if (!PC_EvaluateTokens(source, firsttoken, intvalue, floatvalue, integer)) return qfalse;
   2213 	//
   2214 #ifdef DEBUG_EVAL
   2215 	Log_Write("eval:");
   2216 #endif //DEBUG_EVAL
   2217 	for (t = firsttoken; t; t = nexttoken)
   2218 	{
   2219 #ifdef DEBUG_EVAL
   2220 		Log_Write(" %s", t->string);
   2221 #endif //DEBUG_EVAL
   2222 		nexttoken = t->next;
   2223 		PC_FreeToken(t);
   2224 	} //end for
   2225 #ifdef DEBUG_EVAL
   2226 	if (integer) Log_Write("eval result: %d", *intvalue);
   2227 	else Log_Write("eval result: %f", *floatvalue);
   2228 #endif //DEBUG_EVAL
   2229 	//
   2230 	return qtrue;
   2231 } //end of the function PC_Evaluate
   2232 //============================================================================
   2233 //
   2234 // Parameter:				-
   2235 // Returns:					-
   2236 // Changes Globals:		-
   2237 //============================================================================
   2238 int PC_DollarEvaluate(source_t *source, signed long int *intvalue,
   2239 												double *floatvalue, int integer)
   2240 {
   2241 	int indent, defined = qfalse;
   2242 	token_t token, *firsttoken, *lasttoken;
   2243 	token_t *t, *nexttoken;
   2244 	define_t *define;
   2245 
   2246 	if (intvalue) *intvalue = 0;
   2247 	if (floatvalue) *floatvalue = 0;
   2248 	//
   2249 	if (!PC_ReadSourceToken(source, &token))
   2250 	{
   2251 		SourceError(source, "no leading ( after $evalint/$evalfloat");
   2252 		return qfalse;
   2253 	} //end if
   2254 	if (!PC_ReadSourceToken(source, &token))
   2255 	{
   2256 		SourceError(source, "nothing to evaluate");
   2257 		return qfalse;
   2258 	} //end if
   2259 	indent = 1;
   2260 	firsttoken = NULL;
   2261 	lasttoken = NULL;
   2262 	do
   2263 	{
   2264 		//if the token is a name
   2265 		if (token.type == TT_NAME)
   2266 		{
   2267 			if (defined)
   2268 			{
   2269 				defined = qfalse;
   2270 				t = PC_CopyToken(&token);
   2271 				t->next = NULL;
   2272 				if (lasttoken) lasttoken->next = t;
   2273 				else firsttoken = t;
   2274 				lasttoken = t;
   2275 			} //end if
   2276 			else if (!strcmp(token.string, "defined"))
   2277 			{
   2278 				defined = qtrue;
   2279 				t = PC_CopyToken(&token);
   2280 				t->next = NULL;
   2281 				if (lasttoken) lasttoken->next = t;
   2282 				else firsttoken = t;
   2283 				lasttoken = t;
   2284 			} //end if
   2285 			else
   2286 			{
   2287 				//then it must be a define
   2288 #if DEFINEHASHING
   2289 				define = PC_FindHashedDefine(source->definehash, token.string);
   2290 #else
   2291 				define = PC_FindDefine(source->defines, token.string);
   2292 #endif //DEFINEHASHING
   2293 				if (!define)
   2294 				{
   2295 					SourceError(source, "can't evaluate %s, not defined", token.string);
   2296 					return qfalse;
   2297 				} //end if
   2298 				if (!PC_ExpandDefineIntoSource(source, &token, define)) return qfalse;
   2299 			} //end else
   2300 		} //end if
   2301 		//if the token is a number or a punctuation
   2302 		else if (token.type == TT_NUMBER || token.type == TT_PUNCTUATION)
   2303 		{
   2304 			if (*token.string == '(') indent++;
   2305 			else if (*token.string == ')') indent--;
   2306 			if (indent <= 0) break;
   2307 			t = PC_CopyToken(&token);
   2308 			t->next = NULL;
   2309 			if (lasttoken) lasttoken->next = t;
   2310 			else firsttoken = t;
   2311 			lasttoken = t;
   2312 		} //end else
   2313 		else //can't evaluate the token
   2314 		{
   2315 			SourceError(source, "can't evaluate %s", token.string);
   2316 			return qfalse;
   2317 		} //end else
   2318 	} while(PC_ReadSourceToken(source, &token));
   2319 	//
   2320 	if (!PC_EvaluateTokens(source, firsttoken, intvalue, floatvalue, integer)) return qfalse;
   2321 	//
   2322 #ifdef DEBUG_EVAL
   2323 	Log_Write("$eval:");
   2324 #endif //DEBUG_EVAL
   2325 	for (t = firsttoken; t; t = nexttoken)
   2326 	{
   2327 #ifdef DEBUG_EVAL
   2328 		Log_Write(" %s", t->string);
   2329 #endif //DEBUG_EVAL
   2330 		nexttoken = t->next;
   2331 		PC_FreeToken(t);
   2332 	} //end for
   2333 #ifdef DEBUG_EVAL
   2334 	if (integer) Log_Write("$eval result: %d", *intvalue);
   2335 	else Log_Write("$eval result: %f", *floatvalue);
   2336 #endif //DEBUG_EVAL
   2337 	//
   2338 	return qtrue;
   2339 } //end of the function PC_DollarEvaluate
   2340 //============================================================================
   2341 //
   2342 // Parameter:				-
   2343 // Returns:					-
   2344 // Changes Globals:		-
   2345 //============================================================================
   2346 int PC_Directive_elif(source_t *source)
   2347 {
   2348 	signed long int value;
   2349 	int type, skip;
   2350 
   2351 	PC_PopIndent(source, &type, &skip);
   2352 	if (!type || type == INDENT_ELSE)
   2353 	{
   2354 		SourceError(source, "misplaced #elif");
   2355 		return qfalse;
   2356 	} //end if
   2357 	if (!PC_Evaluate(source, &value, NULL, qtrue)) return qfalse;
   2358 	skip = (value == 0);
   2359 	PC_PushIndent(source, INDENT_ELIF, skip);
   2360 	return qtrue;
   2361 } //end of the function PC_Directive_elif
   2362 //============================================================================
   2363 //
   2364 // Parameter:				-
   2365 // Returns:					-
   2366 // Changes Globals:		-
   2367 //============================================================================
   2368 int PC_Directive_if(source_t *source)
   2369 {
   2370 	signed long int value;
   2371 	int skip;
   2372 
   2373 	if (!PC_Evaluate(source, &value, NULL, qtrue)) return qfalse;
   2374 	skip = (value == 0);
   2375 	PC_PushIndent(source, INDENT_IF, skip);
   2376 	return qtrue;
   2377 } //end of the function PC_Directive
   2378 //============================================================================
   2379 //
   2380 // Parameter:				-
   2381 // Returns:					-
   2382 // Changes Globals:		-
   2383 //============================================================================
   2384 int PC_Directive_line(source_t *source)
   2385 {
   2386 	SourceError(source, "#line directive not supported");
   2387 	return qfalse;
   2388 } //end of the function PC_Directive_line
   2389 //============================================================================
   2390 //
   2391 // Parameter:				-
   2392 // Returns:					-
   2393 // Changes Globals:		-
   2394 //============================================================================
   2395 int PC_Directive_error(source_t *source)
   2396 {
   2397 	token_t token;
   2398 
   2399 	strcpy(token.string, "");
   2400 	PC_ReadSourceToken(source, &token);
   2401 	SourceError(source, "#error directive: %s", token.string);
   2402 	return qfalse;
   2403 } //end of the function PC_Directive_error
   2404 //============================================================================
   2405 //
   2406 // Parameter:				-
   2407 // Returns:					-
   2408 // Changes Globals:		-
   2409 //============================================================================
   2410 int PC_Directive_pragma(source_t *source)
   2411 {
   2412 	token_t token;
   2413 
   2414 	SourceWarning(source, "#pragma directive not supported");
   2415 	while(PC_ReadLine(source, &token)) ;
   2416 	return qtrue;
   2417 } //end of the function PC_Directive_pragma
   2418 //============================================================================
   2419 //
   2420 // Parameter:				-
   2421 // Returns:					-
   2422 // Changes Globals:		-
   2423 //============================================================================
   2424 void UnreadSignToken(source_t *source)
   2425 {
   2426 	token_t token;
   2427 
   2428 	token.line = source->scriptstack->line;
   2429 	token.whitespace_p = source->scriptstack->script_p;
   2430 	token.endwhitespace_p = source->scriptstack->script_p;
   2431 	token.linescrossed = 0;
   2432 	strcpy(token.string, "-");
   2433 	token.type = TT_PUNCTUATION;
   2434 	token.subtype = P_SUB;
   2435 	PC_UnreadSourceToken(source, &token);
   2436 } //end of the function UnreadSignToken
   2437 //============================================================================
   2438 //
   2439 // Parameter:				-
   2440 // Returns:					-
   2441 // Changes Globals:		-
   2442 //============================================================================
   2443 int PC_Directive_eval(source_t *source)
   2444 {
   2445 	signed long int value;
   2446 	token_t token;
   2447 
   2448 	if (!PC_Evaluate(source, &value, NULL, qtrue)) return qfalse;
   2449 	//
   2450 	token.line = source->scriptstack->line;
   2451 	token.whitespace_p = source->scriptstack->script_p;
   2452 	token.endwhitespace_p = source->scriptstack->script_p;
   2453 	token.linescrossed = 0;
   2454 	sprintf(token.string, "%d", abs(value));
   2455 	token.type = TT_NUMBER;
   2456 	token.subtype = TT_INTEGER|TT_LONG|TT_DECIMAL;
   2457 	PC_UnreadSourceToken(source, &token);
   2458 	if (value < 0) UnreadSignToken(source);
   2459 	return qtrue;
   2460 } //end of the function PC_Directive_eval
   2461 //============================================================================
   2462 //
   2463 // Parameter:				-
   2464 // Returns:					-
   2465 // Changes Globals:		-
   2466 //============================================================================
   2467 int PC_Directive_evalfloat(source_t *source)
   2468 {
   2469 	double value;
   2470 	token_t token;
   2471 
   2472 	if (!PC_Evaluate(source, NULL, &value, qfalse)) return qfalse;
   2473 	token.line = source->scriptstack->line;
   2474 	token.whitespace_p = source->scriptstack->script_p;
   2475 	token.endwhitespace_p = source->scriptstack->script_p;
   2476 	token.linescrossed = 0;
   2477 	sprintf(token.string, "%1.2f", fabs(value));
   2478 	token.type = TT_NUMBER;
   2479 	token.subtype = TT_FLOAT|TT_LONG|TT_DECIMAL;
   2480 	PC_UnreadSourceToken(source, &token);
   2481 	if (value < 0) UnreadSignToken(source);
   2482 	return qtrue;
   2483 } //end of the function PC_Directive_evalfloat
   2484 //============================================================================
   2485 //
   2486 // Parameter:				-
   2487 // Returns:					-
   2488 // Changes Globals:		-
   2489 //============================================================================
   2490 directive_t directives[20] =
   2491 {
   2492 	{"if", PC_Directive_if},
   2493 	{"ifdef", PC_Directive_ifdef},
   2494 	{"ifndef", PC_Directive_ifndef},
   2495 	{"elif", PC_Directive_elif},
   2496 	{"else", PC_Directive_else},
   2497 	{"endif", PC_Directive_endif},
   2498 	{"include", PC_Directive_include},
   2499 	{"define", PC_Directive_define},
   2500 	{"undef", PC_Directive_undef},
   2501 	{"line", PC_Directive_line},
   2502 	{"error", PC_Directive_error},
   2503 	{"pragma", PC_Directive_pragma},
   2504 	{"eval", PC_Directive_eval},
   2505 	{"evalfloat", PC_Directive_evalfloat},
   2506 	{NULL, NULL}
   2507 };
   2508 
   2509 int PC_ReadDirective(source_t *source)
   2510 {
   2511 	token_t token;
   2512 	int i;
   2513 
   2514 	//read the directive name
   2515 	if (!PC_ReadSourceToken(source, &token))
   2516 	{
   2517 		SourceError(source, "found # without name");
   2518 		return qfalse;
   2519 	} //end if
   2520 	//directive name must be on the same line
   2521 	if (token.linescrossed > 0)
   2522 	{
   2523 		PC_UnreadSourceToken(source, &token);
   2524 		SourceError(source, "found # at end of line");
   2525 		return qfalse;
   2526 	} //end if
   2527 	//if if is a name
   2528 	if (token.type == TT_NAME)
   2529 	{
   2530 		//find the precompiler directive
   2531 		for (i = 0; directives[i].name; i++)
   2532 		{
   2533 			if (!strcmp(directives[i].name, token.string))
   2534 			{
   2535 				return directives[i].func(source);
   2536 			} //end if
   2537 		} //end for
   2538 	} //end if
   2539 	SourceError(source, "unknown precompiler directive %s", token.string);
   2540 	return qfalse;
   2541 } //end of the function PC_ReadDirective
   2542 //============================================================================
   2543 //
   2544 // Parameter:				-
   2545 // Returns:					-
   2546 // Changes Globals:		-
   2547 //============================================================================
   2548 int PC_DollarDirective_evalint(source_t *source)
   2549 {
   2550 	signed long int value;
   2551 	token_t token;
   2552 
   2553 	if (!PC_DollarEvaluate(source, &value, NULL, qtrue)) return qfalse;
   2554 	//
   2555 	token.line = source->scriptstack->line;
   2556 	token.whitespace_p = source->scriptstack->script_p;
   2557 	token.endwhitespace_p = source->scriptstack->script_p;
   2558 	token.linescrossed = 0;
   2559 	sprintf(token.string, "%d", abs(value));
   2560 	token.type = TT_NUMBER;
   2561 	token.subtype = TT_INTEGER|TT_LONG|TT_DECIMAL;
   2562 #ifdef NUMBERVALUE
   2563 	token.intvalue = value;
   2564 	token.floatvalue = value;
   2565 #endif //NUMBERVALUE
   2566 	PC_UnreadSourceToken(source, &token);
   2567 	if (value < 0) UnreadSignToken(source);
   2568 	return qtrue;
   2569 } //end of the function PC_DollarDirective_evalint
   2570 //============================================================================
   2571 //
   2572 // Parameter:				-
   2573 // Returns:					-
   2574 // Changes Globals:		-
   2575 //============================================================================
   2576 int PC_DollarDirective_evalfloat(source_t *source)
   2577 {
   2578 	double value;
   2579 	token_t token;
   2580 
   2581 	if (!PC_DollarEvaluate(source, NULL, &value, qfalse)) return qfalse;
   2582 	token.line = source->scriptstack->line;
   2583 	token.whitespace_p = source->scriptstack->script_p;
   2584 	token.endwhitespace_p = source->scriptstack->script_p;
   2585 	token.linescrossed = 0;
   2586 	sprintf(token.string, "%1.2f", fabs(value));
   2587 	token.type = TT_NUMBER;
   2588 	token.subtype = TT_FLOAT|TT_LONG|TT_DECIMAL;
   2589 #ifdef NUMBERVALUE
   2590 	token.intvalue = (unsigned long) value;
   2591 	token.floatvalue = value;
   2592 #endif //NUMBERVALUE
   2593 	PC_UnreadSourceToken(source, &token);
   2594 	if (value < 0) UnreadSignToken(source);
   2595 	return qtrue;
   2596 } //end of the function PC_DollarDirective_evalfloat
   2597 //============================================================================
   2598 //
   2599 // Parameter:				-
   2600 // Returns:					-
   2601 // Changes Globals:		-
   2602 //============================================================================
   2603 directive_t dollardirectives[20] =
   2604 {
   2605 	{"evalint", PC_DollarDirective_evalint},
   2606 	{"evalfloat", PC_DollarDirective_evalfloat},
   2607 	{NULL, NULL}
   2608 };
   2609 
   2610 int PC_ReadDollarDirective(source_t *source)
   2611 {
   2612 	token_t token;
   2613 	int i;
   2614 
   2615 	//read the directive name
   2616 	if (!PC_ReadSourceToken(source, &token))
   2617 	{
   2618 		SourceError(source, "found $ without name");
   2619 		return qfalse;
   2620 	} //end if
   2621 	//directive name must be on the same line
   2622 	if (token.linescrossed > 0)
   2623 	{
   2624 		PC_UnreadSourceToken(source, &token);
   2625 		SourceError(source, "found $ at end of line");
   2626 		return qfalse;
   2627 	} //end if
   2628 	//if if is a name
   2629 	if (token.type == TT_NAME)
   2630 	{
   2631 		//find the precompiler directive
   2632 		for (i = 0; dollardirectives[i].name; i++)
   2633 		{
   2634 			if (!strcmp(dollardirectives[i].name, token.string))
   2635 			{
   2636 				return dollardirectives[i].func(source);
   2637 			} //end if
   2638 		} //end for
   2639 	} //end if
   2640 	PC_UnreadSourceToken(source, &token);
   2641 	SourceError(source, "unknown precompiler directive %s", token.string);
   2642 	return qfalse;
   2643 } //end of the function PC_ReadDirective
   2644 
   2645 #ifdef QUAKEC
   2646 //============================================================================
   2647 //
   2648 // Parameter:				-
   2649 // Returns:					-
   2650 // Changes Globals:		-
   2651 //============================================================================
   2652 int BuiltinFunction(source_t *source)
   2653 {
   2654 	token_t token;
   2655 
   2656 	if (!PC_ReadSourceToken(source, &token)) return qfalse;
   2657 	if (token.type == TT_NUMBER)
   2658 	{
   2659 		PC_UnreadSourceToken(source, &token);
   2660 		return qtrue;
   2661 	} //end if
   2662 	else
   2663 	{
   2664 		PC_UnreadSourceToken(source, &token);
   2665 		return qfalse;
   2666 	} //end else
   2667 } //end of the function BuiltinFunction
   2668 //============================================================================
   2669 //
   2670 // Parameter:				-
   2671 // Returns:					-
   2672 // Changes Globals:		-
   2673 //============================================================================
   2674 int QuakeCMacro(source_t *source)
   2675 {
   2676 	int i;
   2677 	token_t token;
   2678 
   2679 	if (!PC_ReadSourceToken(source, &token)) return qtrue;
   2680 	if (token.type != TT_NAME)
   2681 	{
   2682 		PC_UnreadSourceToken(source, &token);
   2683 		return qtrue;
   2684 	} //end if
   2685 	//find the precompiler directive
   2686 	for (i = 0; dollardirectives[i].name; i++)
   2687 	{
   2688 		if (!strcmp(dollardirectives[i].name, token.string))
   2689 		{
   2690 			PC_UnreadSourceToken(source, &token);
   2691 			return qfalse;
   2692 		} //end if
   2693 	} //end for
   2694 	PC_UnreadSourceToken(source, &token);
   2695 	return qtrue;
   2696 } //end of the function QuakeCMacro
   2697 #endif //QUAKEC
   2698 //============================================================================
   2699 //
   2700 // Parameter:				-
   2701 // Returns:					-
   2702 // Changes Globals:		-
   2703 //============================================================================
   2704 int PC_ReadToken(source_t *source, token_t *token)
   2705 {
   2706 	define_t *define;
   2707 
   2708 	while(1)
   2709 	{
   2710 		if (!PC_ReadSourceToken(source, token)) return qfalse;
   2711 		//check for precompiler directives
   2712 		if (token->type == TT_PUNCTUATION && *token->string == '#')
   2713 		{
   2714 #ifdef QUAKEC
   2715 			if (!BuiltinFunction(source))
   2716 #endif //QUAKC
   2717 			{
   2718 				//read the precompiler directive
   2719 				if (!PC_ReadDirective(source)) return qfalse;
   2720 				continue;
   2721 			} //end if
   2722 		} //end if
   2723 		if (token->type == TT_PUNCTUATION && *token->string == '$')
   2724 		{
   2725 #ifdef QUAKEC
   2726 			if (!QuakeCMacro(source))
   2727 #endif //QUAKEC
   2728 			{
   2729 				//read the precompiler directive
   2730 				if (!PC_ReadDollarDirective(source)) return qfalse;
   2731 				continue;
   2732 			} //end if
   2733 		} //end if
   2734 		// recursively concatenate strings that are behind each other still resolving defines
   2735 		if (token->type == TT_STRING)
   2736 		{
   2737 			token_t newtoken;
   2738 			if (PC_ReadToken(source, &newtoken))
   2739 			{
   2740 				if (newtoken.type == TT_STRING)
   2741 				{
   2742 					token->string[strlen(token->string)-1] = '\0';
   2743 					if (strlen(token->string) + strlen(newtoken.string+1) + 1 >= MAX_TOKEN)
   2744 					{
   2745 						SourceError(source, "string longer than MAX_TOKEN %d\n", MAX_TOKEN);
   2746 						return qfalse;
   2747 					}
   2748 					strcat(token->string, newtoken.string+1);
   2749 				}
   2750 				else
   2751 				{
   2752 					PC_UnreadToken(source, &newtoken);
   2753 				}
   2754 			}
   2755 		} //end if
   2756 		//if skipping source because of conditional compilation
   2757 		if (source->skip) continue;
   2758 		//if the token is a name
   2759 		if (token->type == TT_NAME)
   2760 		{
   2761 			//check if the name is a define macro
   2762 #if DEFINEHASHING
   2763 			define = PC_FindHashedDefine(source->definehash, token->string);
   2764 #else
   2765 			define = PC_FindDefine(source->defines, token->string);
   2766 #endif //DEFINEHASHING
   2767 			//if it is a define macro
   2768 			if (define)
   2769 			{
   2770 				//expand the defined macro
   2771 				if (!PC_ExpandDefineIntoSource(source, token, define)) return qfalse;
   2772 				continue;
   2773 			} //end if
   2774 		} //end if
   2775 		//copy token for unreading
   2776 		Com_Memcpy(&source->token, token, sizeof(token_t));
   2777 		//found a token
   2778 		return qtrue;
   2779 	} //end while
   2780 } //end of the function PC_ReadToken
   2781 //============================================================================
   2782 //
   2783 // Parameter:				-
   2784 // Returns:					-
   2785 // Changes Globals:		-
   2786 //============================================================================
   2787 int PC_ExpectTokenString(source_t *source, char *string)
   2788 {
   2789 	token_t token;
   2790 
   2791 	if (!PC_ReadToken(source, &token))
   2792 	{
   2793 		SourceError(source, "couldn't find expected %s", string);
   2794 		return qfalse;
   2795 	} //end if
   2796 
   2797 	if (strcmp(token.string, string))
   2798 	{
   2799 		SourceError(source, "expected %s, found %s", string, token.string);
   2800 		return qfalse;
   2801 	} //end if
   2802 	return qtrue;
   2803 } //end of the function PC_ExpectTokenString
   2804 //============================================================================
   2805 //
   2806 // Parameter:				-
   2807 // Returns:					-
   2808 // Changes Globals:		-
   2809 //============================================================================
   2810 int PC_ExpectTokenType(source_t *source, int type, int subtype, token_t *token)
   2811 {
   2812 	char str[MAX_TOKEN];
   2813 
   2814 	if (!PC_ReadToken(source, token))
   2815 	{
   2816 		SourceError(source, "couldn't read expected token");
   2817 		return qfalse;
   2818 	} //end if
   2819 
   2820 	if (token->type != type)
   2821 	{
   2822 		strcpy(str, "");
   2823 		if (type == TT_STRING) strcpy(str, "string");
   2824 		if (type == TT_LITERAL) strcpy(str, "literal");
   2825 		if (type == TT_NUMBER) strcpy(str, "number");
   2826 		if (type == TT_NAME) strcpy(str, "name");
   2827 		if (type == TT_PUNCTUATION) strcpy(str, "punctuation");
   2828 		SourceError(source, "expected a %s, found %s", str, token->string);
   2829 		return qfalse;
   2830 	} //end if
   2831 	if (token->type == TT_NUMBER)
   2832 	{
   2833 		if ((token->subtype & subtype) != subtype)
   2834 		{
   2835 			if (subtype & TT_DECIMAL) strcpy(str, "decimal");
   2836 			if (subtype & TT_HEX) strcpy(str, "hex");
   2837 			if (subtype & TT_OCTAL) strcpy(str, "octal");
   2838 			if (subtype & TT_BINARY) strcpy(str, "binary");
   2839 			if (subtype & TT_LONG) strcat(str, " long");
   2840 			if (subtype & TT_UNSIGNED) strcat(str, " unsigned");
   2841 			if (subtype & TT_FLOAT) strcat(str, " float");
   2842 			if (subtype & TT_INTEGER) strcat(str, " integer");
   2843 			SourceError(source, "expected %s, found %s", str, token->string);
   2844 			return qfalse;
   2845 		} //end if
   2846 	} //end if
   2847 	else if (token->type == TT_PUNCTUATION)
   2848 	{
   2849 		if (token->subtype != subtype)
   2850 		{
   2851 			SourceError(source, "found %s", token->string);
   2852 			return qfalse;
   2853 		} //end if
   2854 	} //end else if
   2855 	return qtrue;
   2856 } //end of the function PC_ExpectTokenType
   2857 //============================================================================
   2858 //
   2859 // Parameter:				-
   2860 // Returns:					-
   2861 // Changes Globals:		-
   2862 //============================================================================
   2863 int PC_ExpectAnyToken(source_t *source, token_t *token)
   2864 {
   2865 	if (!PC_ReadToken(source, token))
   2866 	{
   2867 		SourceError(source, "couldn't read expected token");
   2868 		return qfalse;
   2869 	} //end if
   2870 	else
   2871 	{
   2872 		return qtrue;
   2873 	} //end else
   2874 } //end of the function PC_ExpectAnyToken
   2875 //============================================================================
   2876 //
   2877 // Parameter:				-
   2878 // Returns:					-
   2879 // Changes Globals:		-
   2880 //============================================================================
   2881 int PC_CheckTokenString(source_t *source, char *string)
   2882 {
   2883 	token_t tok;
   2884 
   2885 	if (!PC_ReadToken(source, &tok)) return qfalse;
   2886 	//if the token is available
   2887 	if (!strcmp(tok.string, string)) return qtrue;
   2888 	//
   2889 	PC_UnreadSourceToken(source, &tok);
   2890 	return qfalse;
   2891 } //end of the function PC_CheckTokenString
   2892 //============================================================================
   2893 //
   2894 // Parameter:				-
   2895 // Returns:					-
   2896 // Changes Globals:		-
   2897 //============================================================================
   2898 int PC_CheckTokenType(source_t *source, int type, int subtype, token_t *token)
   2899 {
   2900 	token_t tok;
   2901 
   2902 	if (!PC_ReadToken(source, &tok)) return qfalse;
   2903 	//if the type matches
   2904 	if (tok.type == type &&
   2905 			(tok.subtype & subtype) == subtype)
   2906 	{
   2907 		Com_Memcpy(token, &tok, sizeof(token_t));
   2908 		return qtrue;
   2909 	} //end if
   2910 	//
   2911 	PC_UnreadSourceToken(source, &tok);
   2912 	return qfalse;
   2913 } //end of the function PC_CheckTokenType
   2914 //============================================================================
   2915 //
   2916 // Parameter:				-
   2917 // Returns:					-
   2918 // Changes Globals:		-
   2919 //============================================================================
   2920 int PC_SkipUntilString(source_t *source, char *string)
   2921 {
   2922 	token_t token;
   2923 
   2924 	while(PC_ReadToken(source, &token))
   2925 	{
   2926 		if (!strcmp(token.string, string)) return qtrue;
   2927 	} //end while
   2928 	return qfalse;
   2929 } //end of the function PC_SkipUntilString
   2930 //============================================================================
   2931 //
   2932 // Parameter:				-
   2933 // Returns:					-
   2934 // Changes Globals:		-
   2935 //============================================================================
   2936 void PC_UnreadLastToken(source_t *source)
   2937 {
   2938 	PC_UnreadSourceToken(source, &source->token);
   2939 } //end of the function PC_UnreadLastToken
   2940 //============================================================================
   2941 //
   2942 // Parameter:				-
   2943 // Returns:					-
   2944 // Changes Globals:		-
   2945 //============================================================================
   2946 void PC_UnreadToken(source_t *source, token_t *token)
   2947 {
   2948 	PC_UnreadSourceToken(source, token);
   2949 } //end of the function PC_UnreadToken
   2950 //============================================================================
   2951 //
   2952 // Parameter:				-
   2953 // Returns:					-
   2954 // Changes Globals:		-
   2955 //============================================================================
   2956 void PC_SetIncludePath(source_t *source, char *path)
   2957 {
   2958 	strncpy(source->includepath, path, MAX_PATH);
   2959 	//add trailing path seperator
   2960 	if (source->includepath[strlen(source->includepath)-1] != '\\' &&
   2961 		source->includepath[strlen(source->includepath)-1] != '/')
   2962 	{
   2963 		strcat(source->includepath, PATHSEPERATOR_STR);
   2964 	} //end if
   2965 } //end of the function PC_SetIncludePath
   2966 //============================================================================
   2967 //
   2968 // Parameter:				-
   2969 // Returns:					-
   2970 // Changes Globals:		-
   2971 //============================================================================
   2972 void PC_SetPunctuations(source_t *source, punctuation_t *p)
   2973 {
   2974 	source->punctuations = p;
   2975 } //end of the function PC_SetPunctuations
   2976 //============================================================================
   2977 //
   2978 // Parameter:			-
   2979 // Returns:				-
   2980 // Changes Globals:		-
   2981 //============================================================================
   2982 source_t *LoadSourceFile(const char *filename)
   2983 {
   2984 	source_t *source;
   2985 	script_t *script;
   2986 
   2987 	PC_InitTokenHeap();
   2988 
   2989 	script = LoadScriptFile(filename);
   2990 	if (!script) return NULL;
   2991 
   2992 	script->next = NULL;
   2993 
   2994 	source = (source_t *) GetMemory(sizeof(source_t));
   2995 	Com_Memset(source, 0, sizeof(source_t));
   2996 
   2997 	strncpy(source->filename, filename, MAX_PATH);
   2998 	source->scriptstack = script;
   2999 	source->tokens = NULL;
   3000 	source->defines = NULL;
   3001 	source->indentstack = NULL;
   3002 	source->skip = 0;
   3003 
   3004 #if DEFINEHASHING
   3005 	source->definehash = GetClearedMemory(DEFINEHASHSIZE * sizeof(define_t *));
   3006 #endif //DEFINEHASHING
   3007 	PC_AddGlobalDefinesToSource(source);
   3008 	return source;
   3009 } //end of the function LoadSourceFile
   3010 //============================================================================
   3011 //
   3012 // Parameter:				-
   3013 // Returns:					-
   3014 // Changes Globals:		-
   3015 //============================================================================
   3016 source_t *LoadSourceMemory(char *ptr, int length, char *name)
   3017 {
   3018 	source_t *source;
   3019 	script_t *script;
   3020 
   3021 	PC_InitTokenHeap();
   3022 
   3023 	script = LoadScriptMemory(ptr, length, name);
   3024 	if (!script) return NULL;
   3025 	script->next = NULL;
   3026 
   3027 	source = (source_t *) GetMemory(sizeof(source_t));
   3028 	Com_Memset(source, 0, sizeof(source_t));
   3029 
   3030 	strncpy(source->filename, name, MAX_PATH);
   3031 	source->scriptstack = script;
   3032 	source->tokens = NULL;
   3033 	source->defines = NULL;
   3034 	source->indentstack = NULL;
   3035 	source->skip = 0;
   3036 
   3037 #if DEFINEHASHING
   3038 	source->definehash = GetClearedMemory(DEFINEHASHSIZE * sizeof(define_t *));
   3039 #endif //DEFINEHASHING
   3040 	PC_AddGlobalDefinesToSource(source);
   3041 	return source;
   3042 } //end of the function LoadSourceMemory
   3043 //============================================================================
   3044 //
   3045 // Parameter:				-
   3046 // Returns:					-
   3047 // Changes Globals:		-
   3048 //============================================================================
   3049 void FreeSource(source_t *source)
   3050 {
   3051 	script_t *script;
   3052 	token_t *token;
   3053 	define_t *define;
   3054 	indent_t *indent;
   3055 	int i;
   3056 
   3057 	//PC_PrintDefineHashTable(source->definehash);
   3058 	//free all the scripts
   3059 	while(source->scriptstack)
   3060 	{
   3061 		script = source->scriptstack;
   3062 		source->scriptstack = source->scriptstack->next;
   3063 		FreeScript(script);
   3064 	} //end for
   3065 	//free all the tokens
   3066 	while(source->tokens)
   3067 	{
   3068 		token = source->tokens;
   3069 		source->tokens = source->tokens->next;
   3070 		PC_FreeToken(token);
   3071 	} //end for
   3072 #if DEFINEHASHING
   3073 	for (i = 0; i < DEFINEHASHSIZE; i++)
   3074 	{
   3075 		while(source->definehash[i])
   3076 		{
   3077 			define = source->definehash[i];
   3078 			source->definehash[i] = source->definehash[i]->hashnext;
   3079 			PC_FreeDefine(define);
   3080 		} //end while
   3081 	} //end for
   3082 #else //DEFINEHASHING
   3083 	//free all defines
   3084 	while(source->defines)
   3085 	{
   3086 		define = source->defines;
   3087 		source->defines = source->defines->next;
   3088 		PC_FreeDefine(define);
   3089 	} //end for
   3090 #endif //DEFINEHASHING
   3091 	//free all indents
   3092 	while(source->indentstack)
   3093 	{
   3094 		indent = source->indentstack;
   3095 		source->indentstack = source->indentstack->next;
   3096 		FreeMemory(indent);
   3097 	} //end for
   3098 #if DEFINEHASHING
   3099 	//
   3100 	if (source->definehash) FreeMemory(source->definehash);
   3101 #endif //DEFINEHASHING
   3102 	//free the source itself
   3103 	FreeMemory(source);
   3104 } //end of the function FreeSource
   3105 //============================================================================
   3106 //
   3107 // Parameter:			-
   3108 // Returns:				-
   3109 // Changes Globals:		-
   3110 //============================================================================
   3111 
   3112 #define MAX_SOURCEFILES		64
   3113 
   3114 source_t *sourceFiles[MAX_SOURCEFILES];
   3115 
   3116 int PC_LoadSourceHandle(const char *filename)
   3117 {
   3118 	source_t *source;
   3119 	int i;
   3120 
   3121 	for (i = 1; i < MAX_SOURCEFILES; i++)
   3122 	{
   3123 		if (!sourceFiles[i])
   3124 			break;
   3125 	} //end for
   3126 	if (i >= MAX_SOURCEFILES)
   3127 		return 0;
   3128 	PS_SetBaseFolder("");
   3129 	source = LoadSourceFile(filename);
   3130 	if (!source)
   3131 		return 0;
   3132 	sourceFiles[i] = source;
   3133 	return i;
   3134 } //end of the function PC_LoadSourceHandle
   3135 //============================================================================
   3136 //
   3137 // Parameter:			-
   3138 // Returns:				-
   3139 // Changes Globals:		-
   3140 //============================================================================
   3141 int PC_FreeSourceHandle(int handle)
   3142 {
   3143 	if (handle < 1 || handle >= MAX_SOURCEFILES)
   3144 		return qfalse;
   3145 	if (!sourceFiles[handle])
   3146 		return qfalse;
   3147 
   3148 	FreeSource(sourceFiles[handle]);
   3149 	sourceFiles[handle] = NULL;
   3150 	return qtrue;
   3151 } //end of the function PC_FreeSourceHandle
   3152 //============================================================================
   3153 //
   3154 // Parameter:			-
   3155 // Returns:				-
   3156 // Changes Globals:		-
   3157 //============================================================================
   3158 int PC_ReadTokenHandle(int handle, pc_token_t *pc_token)
   3159 {
   3160 	token_t token;
   3161 	int ret;
   3162 
   3163 	if (handle < 1 || handle >= MAX_SOURCEFILES)
   3164 		return 0;
   3165 	if (!sourceFiles[handle])
   3166 		return 0;
   3167 
   3168 	ret = PC_ReadToken(sourceFiles[handle], &token);
   3169 	strcpy(pc_token->string, token.string);
   3170 	pc_token->type = token.type;
   3171 	pc_token->subtype = token.subtype;
   3172 	pc_token->intvalue = token.intvalue;
   3173 	pc_token->floatvalue = token.floatvalue;
   3174 	if (pc_token->type == TT_STRING)
   3175 		StripDoubleQuotes(pc_token->string);
   3176 	return ret;
   3177 } //end of the function PC_ReadTokenHandle
   3178 //============================================================================
   3179 //
   3180 // Parameter:			-
   3181 // Returns:				-
   3182 // Changes Globals:		-
   3183 //============================================================================
   3184 int PC_SourceFileAndLine(int handle, char *filename, int *line)
   3185 {
   3186 	if (handle < 1 || handle >= MAX_SOURCEFILES)
   3187 		return qfalse;
   3188 	if (!sourceFiles[handle])
   3189 		return qfalse;
   3190 
   3191 	strcpy(filename, sourceFiles[handle]->filename);
   3192 	if (sourceFiles[handle]->scriptstack)
   3193 		*line = sourceFiles[handle]->scriptstack->line;
   3194 	else
   3195 		*line = 0;
   3196 	return qtrue;
   3197 } //end of the function PC_SourceFileAndLine
   3198 //============================================================================
   3199 //
   3200 // Parameter:			-
   3201 // Returns:				-
   3202 // Changes Globals:		-
   3203 //============================================================================
   3204 void PC_SetBaseFolder(char *path)
   3205 {
   3206 	PS_SetBaseFolder(path);
   3207 } //end of the function PC_SetBaseFolder
   3208 //============================================================================
   3209 //
   3210 // Parameter:			-
   3211 // Returns:				-
   3212 // Changes Globals:		-
   3213 //============================================================================
   3214 void PC_CheckOpenSourceHandles(void)
   3215 {
   3216 	int i;
   3217 
   3218 	for (i = 1; i < MAX_SOURCEFILES; i++)
   3219 	{
   3220 		if (sourceFiles[i])
   3221 		{
   3222 #ifdef BOTLIB
   3223 			botimport.Print(PRT_ERROR, "file %s still open in precompiler\n", sourceFiles[i]->scriptstack->filename);
   3224 #endif	//BOTLIB
   3225 		} //end if
   3226 	} //end for
   3227 } //end of the function PC_CheckOpenSourceHandles
   3228