Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

l_script.c (40381B)


      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  * name:		l_script.c
     25  *
     26  * desc:		lexicographical parser
     27  *
     28  * $Archive: /MissionPack/code/botlib/l_script.c $
     29  *
     30  *****************************************************************************/
     31 
     32 //#define SCREWUP
     33 //#define BOTLIB
     34 //#define MEQCC
     35 //#define BSPC
     36 
     37 #ifdef SCREWUP
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <limits.h>
     41 #include <string.h>
     42 #include <stdarg.h>
     43 #include "l_memory.h"
     44 #include "l_script.h"
     45 
     46 typedef enum {qfalse, qtrue}	qboolean;
     47 
     48 #endif //SCREWUP
     49 
     50 #ifdef BOTLIB
     51 //include files for usage in the bot library
     52 #include "../game/q_shared.h"
     53 #include "../game/botlib.h"
     54 #include "be_interface.h"
     55 #include "l_script.h"
     56 #include "l_memory.h"
     57 #include "l_log.h"
     58 #include "l_libvar.h"
     59 #endif //BOTLIB
     60 
     61 #ifdef MEQCC
     62 //include files for usage in MrElusive's QuakeC Compiler
     63 #include "qcc.h"
     64 #include "l_script.h"
     65 #include "l_memory.h"
     66 #include "l_log.h"
     67 
     68 #define qtrue	true
     69 #define qfalse	false
     70 #endif //MEQCC
     71 
     72 #ifdef BSPC
     73 //include files for usage in the BSP Converter
     74 #include "../bspc/qbsp.h"
     75 #include "../bspc/l_log.h"
     76 #include "../bspc/l_mem.h"
     77 
     78 #define qtrue	true
     79 #define qfalse	false
     80 #endif //BSPC
     81 
     82 
     83 #define PUNCTABLE
     84 
     85 //longer punctuations first
     86 punctuation_t default_punctuations[] =
     87 {
     88 	//binary operators
     89 	{">>=",P_RSHIFT_ASSIGN, NULL},
     90 	{"<<=",P_LSHIFT_ASSIGN, NULL},
     91 	//
     92 	{"...",P_PARMS, NULL},
     93 	//define merge operator
     94 	{"##",P_PRECOMPMERGE, NULL},
     95 	//logic operators
     96 	{"&&",P_LOGIC_AND, NULL},
     97 	{"||",P_LOGIC_OR, NULL},
     98 	{">=",P_LOGIC_GEQ, NULL},
     99 	{"<=",P_LOGIC_LEQ, NULL},
    100 	{"==",P_LOGIC_EQ, NULL},
    101 	{"!=",P_LOGIC_UNEQ, NULL},
    102 	//arithmatic operators
    103 	{"*=",P_MUL_ASSIGN, NULL},
    104 	{"/=",P_DIV_ASSIGN, NULL},
    105 	{"%=",P_MOD_ASSIGN, NULL},
    106 	{"+=",P_ADD_ASSIGN, NULL},
    107 	{"-=",P_SUB_ASSIGN, NULL},
    108 	{"++",P_INC, NULL},
    109 	{"--",P_DEC, NULL},
    110 	//binary operators
    111 	{"&=",P_BIN_AND_ASSIGN, NULL},
    112 	{"|=",P_BIN_OR_ASSIGN, NULL},
    113 	{"^=",P_BIN_XOR_ASSIGN, NULL},
    114 	{">>",P_RSHIFT, NULL},
    115 	{"<<",P_LSHIFT, NULL},
    116 	//reference operators
    117 	{"->",P_POINTERREF, NULL},
    118 	//C++
    119 	{"::",P_CPP1, NULL},
    120 	{".*",P_CPP2, NULL},
    121 	//arithmatic operators
    122 	{"*",P_MUL, NULL},
    123 	{"/",P_DIV, NULL},
    124 	{"%",P_MOD, NULL},
    125 	{"+",P_ADD, NULL},
    126 	{"-",P_SUB, NULL},
    127 	{"=",P_ASSIGN, NULL},
    128 	//binary operators
    129 	{"&",P_BIN_AND, NULL},
    130 	{"|",P_BIN_OR, NULL},
    131 	{"^",P_BIN_XOR, NULL},
    132 	{"~",P_BIN_NOT, NULL},
    133 	//logic operators
    134 	{"!",P_LOGIC_NOT, NULL},
    135 	{">",P_LOGIC_GREATER, NULL},
    136 	{"<",P_LOGIC_LESS, NULL},
    137 	//reference operator
    138 	{".",P_REF, NULL},
    139 	//seperators
    140 	{",",P_COMMA, NULL},
    141 	{";",P_SEMICOLON, NULL},
    142 	//label indication
    143 	{":",P_COLON, NULL},
    144 	//if statement
    145 	{"?",P_QUESTIONMARK, NULL},
    146 	//embracements
    147 	{"(",P_PARENTHESESOPEN, NULL},
    148 	{")",P_PARENTHESESCLOSE, NULL},
    149 	{"{",P_BRACEOPEN, NULL},
    150 	{"}",P_BRACECLOSE, NULL},
    151 	{"[",P_SQBRACKETOPEN, NULL},
    152 	{"]",P_SQBRACKETCLOSE, NULL},
    153 	//
    154 	{"\\",P_BACKSLASH, NULL},
    155 	//precompiler operator
    156 	{"#",P_PRECOMP, NULL},
    157 #ifdef DOLLAR
    158 	{"$",P_DOLLAR, NULL},
    159 #endif //DOLLAR
    160 	{NULL, 0}
    161 };
    162 
    163 #ifdef BSPC
    164 char basefolder[MAX_PATH];
    165 #else
    166 char basefolder[MAX_QPATH];
    167 #endif
    168 
    169 //===========================================================================
    170 //
    171 // Parameter:				-
    172 // Returns:					-
    173 // Changes Globals:		-
    174 //===========================================================================
    175 void PS_CreatePunctuationTable(script_t *script, punctuation_t *punctuations)
    176 {
    177 	int i;
    178 	punctuation_t *p, *lastp, *newp;
    179 
    180 	//get memory for the table
    181 	if (!script->punctuationtable) script->punctuationtable = (punctuation_t **)
    182 												GetMemory(256 * sizeof(punctuation_t *));
    183 	Com_Memset(script->punctuationtable, 0, 256 * sizeof(punctuation_t *));
    184 	//add the punctuations in the list to the punctuation table
    185 	for (i = 0; punctuations[i].p; i++)
    186 	{
    187 		newp = &punctuations[i];
    188 		lastp = NULL;
    189 		//sort the punctuations in this table entry on length (longer punctuations first)
    190 		for (p = script->punctuationtable[(unsigned int) newp->p[0]]; p; p = p->next)
    191 		{
    192 			if (strlen(p->p) < strlen(newp->p))
    193 			{
    194 				newp->next = p;
    195 				if (lastp) lastp->next = newp;
    196 				else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
    197 				break;
    198 			} //end if
    199 			lastp = p;
    200 		} //end for
    201 		if (!p)
    202 		{
    203 			newp->next = NULL;
    204 			if (lastp) lastp->next = newp;
    205 			else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
    206 		} //end if
    207 	} //end for
    208 } //end of the function PS_CreatePunctuationTable
    209 //===========================================================================
    210 //
    211 // Parameter:				-
    212 // Returns:					-
    213 // Changes Globals:		-
    214 //===========================================================================
    215 char *PunctuationFromNum(script_t *script, int num)
    216 {
    217 	int i;
    218 
    219 	for (i = 0; script->punctuations[i].p; i++)
    220 	{
    221 		if (script->punctuations[i].n == num) return script->punctuations[i].p;
    222 	} //end for
    223 	return "unkown punctuation";
    224 } //end of the function PunctuationFromNum
    225 //===========================================================================
    226 //
    227 // Parameter:				-
    228 // Returns:					-
    229 // Changes Globals:		-
    230 //===========================================================================
    231 void QDECL ScriptError(script_t *script, char *str, ...)
    232 {
    233 	char text[1024];
    234 	va_list ap;
    235 
    236 	if (script->flags & SCFL_NOERRORS) return;
    237 
    238 	va_start(ap, str);
    239 	vsprintf(text, str, ap);
    240 	va_end(ap);
    241 #ifdef BOTLIB
    242 	botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", script->filename, script->line, text);
    243 #endif //BOTLIB
    244 #ifdef MEQCC
    245 	printf("error: file %s, line %d: %s\n", script->filename, script->line, text);
    246 #endif //MEQCC
    247 #ifdef BSPC
    248 	Log_Print("error: file %s, line %d: %s\n", script->filename, script->line, text);
    249 #endif //BSPC
    250 } //end of the function ScriptError
    251 //===========================================================================
    252 //
    253 // Parameter:				-
    254 // Returns:					-
    255 // Changes Globals:		-
    256 //===========================================================================
    257 void QDECL ScriptWarning(script_t *script, char *str, ...)
    258 {
    259 	char text[1024];
    260 	va_list ap;
    261 
    262 	if (script->flags & SCFL_NOWARNINGS) return;
    263 
    264 	va_start(ap, str);
    265 	vsprintf(text, str, ap);
    266 	va_end(ap);
    267 #ifdef BOTLIB
    268 	botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", script->filename, script->line, text);
    269 #endif //BOTLIB
    270 #ifdef MEQCC
    271 	printf("warning: file %s, line %d: %s\n", script->filename, script->line, text);
    272 #endif //MEQCC
    273 #ifdef BSPC
    274 	Log_Print("warning: file %s, line %d: %s\n", script->filename, script->line, text);
    275 #endif //BSPC
    276 } //end of the function ScriptWarning
    277 //===========================================================================
    278 //
    279 // Parameter:				-
    280 // Returns:					-
    281 // Changes Globals:		-
    282 //===========================================================================
    283 void SetScriptPunctuations(script_t *script, punctuation_t *p)
    284 {
    285 #ifdef PUNCTABLE
    286 	if (p) PS_CreatePunctuationTable(script, p);
    287 	else  PS_CreatePunctuationTable(script, default_punctuations);
    288 #endif //PUNCTABLE
    289 	if (p) script->punctuations = p;
    290 	else script->punctuations = default_punctuations;
    291 } //end of the function SetScriptPunctuations
    292 //============================================================================
    293 // Reads spaces, tabs, C-like comments etc.
    294 // When a newline character is found the scripts line counter is increased.
    295 //
    296 // Parameter:				-
    297 // Returns:					-
    298 // Changes Globals:		-
    299 //============================================================================
    300 int PS_ReadWhiteSpace(script_t *script)
    301 {
    302 	while(1)
    303 	{
    304 		//skip white space
    305 		while(*script->script_p <= ' ')
    306 		{
    307 			if (!*script->script_p) return 0;
    308 			if (*script->script_p == '\n') script->line++;
    309 			script->script_p++;
    310 		} //end while
    311 		//skip comments
    312 		if (*script->script_p == '/')
    313 		{
    314 			//comments //
    315 			if (*(script->script_p+1) == '/')
    316 			{
    317 				script->script_p++;
    318 				do
    319 				{
    320 					script->script_p++;
    321 					if (!*script->script_p) return 0;
    322 				} //end do
    323 				while(*script->script_p != '\n');
    324 				script->line++;
    325 				script->script_p++;
    326 				if (!*script->script_p) return 0;
    327 				continue;
    328 			} //end if
    329 			//comments /* */
    330 			else if (*(script->script_p+1) == '*')
    331 			{
    332 				script->script_p++;
    333 				do
    334 				{
    335 					script->script_p++;
    336 					if (!*script->script_p) return 0;
    337 					if (*script->script_p == '\n') script->line++;
    338 				} //end do
    339 				while(!(*script->script_p == '*' && *(script->script_p+1) == '/'));
    340 				script->script_p++;
    341 				if (!*script->script_p) return 0;
    342 				script->script_p++;
    343 				if (!*script->script_p) return 0;
    344 				continue;
    345 			} //end if
    346 		} //end if
    347 		break;
    348 	} //end while
    349 	return 1;
    350 } //end of the function PS_ReadWhiteSpace
    351 //============================================================================
    352 // Reads an escape character.
    353 //
    354 // Parameter:				script		: script to read from
    355 //								ch				: place to store the read escape character
    356 // Returns:					-
    357 // Changes Globals:		-
    358 //============================================================================
    359 int PS_ReadEscapeCharacter(script_t *script, char *ch)
    360 {
    361 	int c, val, i;
    362 
    363 	//step over the leading '\\'
    364 	script->script_p++;
    365 	//determine the escape character
    366 	switch(*script->script_p)
    367 	{
    368 		case '\\': c = '\\'; break;
    369 		case 'n': c = '\n'; break;
    370 		case 'r': c = '\r'; break;
    371 		case 't': c = '\t'; break;
    372 		case 'v': c = '\v'; break;
    373 		case 'b': c = '\b'; break;
    374 		case 'f': c = '\f'; break;
    375 		case 'a': c = '\a'; break;
    376 		case '\'': c = '\''; break;
    377 		case '\"': c = '\"'; break;
    378 		case '\?': c = '\?'; break;
    379 		case 'x':
    380 		{
    381 			script->script_p++;
    382 			for (i = 0, val = 0; ; i++, script->script_p++)
    383 			{
    384 				c = *script->script_p;
    385 				if (c >= '0' && c <= '9') c = c - '0';
    386 				else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
    387 				else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
    388 				else break;
    389 				val = (val << 4) + c;
    390 			} //end for
    391 			script->script_p--;
    392 			if (val > 0xFF)
    393 			{
    394 				ScriptWarning(script, "too large value in escape character");
    395 				val = 0xFF;
    396 			} //end if
    397 			c = val;
    398 			break;
    399 		} //end case
    400 		default: //NOTE: decimal ASCII code, NOT octal
    401 		{
    402 			if (*script->script_p < '0' || *script->script_p > '9') ScriptError(script, "unknown escape char");
    403 			for (i = 0, val = 0; ; i++, script->script_p++)
    404 			{
    405 				c = *script->script_p;
    406 				if (c >= '0' && c <= '9') c = c - '0';
    407 				else break;
    408 				val = val * 10 + c;
    409 			} //end for
    410 			script->script_p--;
    411 			if (val > 0xFF)
    412 			{
    413 				ScriptWarning(script, "too large value in escape character");
    414 				val = 0xFF;
    415 			} //end if
    416 			c = val;
    417 			break;
    418 		} //end default
    419 	} //end switch
    420 	//step over the escape character or the last digit of the number
    421 	script->script_p++;
    422 	//store the escape character
    423 	*ch = c;
    424 	//succesfully read escape character
    425 	return 1;
    426 } //end of the function PS_ReadEscapeCharacter
    427 //============================================================================
    428 // Reads C-like string. Escape characters are interpretted.
    429 // Quotes are included with the string.
    430 // Reads two strings with a white space between them as one string.
    431 //
    432 // Parameter:				script		: script to read from
    433 //								token			: buffer to store the string
    434 // Returns:					qtrue when a string was read succesfully
    435 // Changes Globals:		-
    436 //============================================================================
    437 int PS_ReadString(script_t *script, token_t *token, int quote)
    438 {
    439 	int len, tmpline;
    440 	char *tmpscript_p;
    441 
    442 	if (quote == '\"') token->type = TT_STRING;
    443 	else token->type = TT_LITERAL;
    444 
    445 	len = 0;
    446 	//leading quote
    447 	token->string[len++] = *script->script_p++;
    448 	//
    449 	while(1)
    450 	{
    451 		//minus 2 because trailing double quote and zero have to be appended
    452 		if (len >= MAX_TOKEN - 2)
    453 		{
    454 			ScriptError(script, "string longer than MAX_TOKEN = %d", MAX_TOKEN);
    455 			return 0;
    456 		} //end if
    457 		//if there is an escape character and
    458 		//if escape characters inside a string are allowed
    459 		if (*script->script_p == '\\' && !(script->flags & SCFL_NOSTRINGESCAPECHARS))
    460 		{
    461 			if (!PS_ReadEscapeCharacter(script, &token->string[len]))
    462 			{
    463 				token->string[len] = 0;
    464 				return 0;
    465 			} //end if
    466 			len++;
    467 		} //end if
    468 		//if a trailing quote
    469 		else if (*script->script_p == quote)
    470 		{
    471 			//step over the double quote
    472 			script->script_p++;
    473 			//if white spaces in a string are not allowed
    474 			if (script->flags & SCFL_NOSTRINGWHITESPACES) break;
    475 			//
    476 			tmpscript_p = script->script_p;
    477 			tmpline = script->line;
    478 			//read unusefull stuff between possible two following strings
    479 			if (!PS_ReadWhiteSpace(script))
    480 			{
    481 				script->script_p = tmpscript_p;
    482 				script->line = tmpline;
    483 				break;
    484 			} //end if
    485 			//if there's no leading double qoute
    486 			if (*script->script_p != quote)
    487 			{
    488 				script->script_p = tmpscript_p;
    489 				script->line = tmpline;
    490 				break;
    491 			} //end if
    492 			//step over the new leading double quote
    493 			script->script_p++;
    494 		} //end if
    495 		else
    496 		{
    497 			if (*script->script_p == '\0')
    498 			{
    499 				token->string[len] = 0;
    500 				ScriptError(script, "missing trailing quote");
    501 				return 0;
    502 			} //end if
    503 	      if (*script->script_p == '\n')
    504 			{
    505 				token->string[len] = 0;
    506 				ScriptError(script, "newline inside string %s", token->string);
    507 				return 0;
    508 			} //end if
    509 			token->string[len++] = *script->script_p++;
    510 		} //end else
    511 	} //end while
    512 	//trailing quote
    513 	token->string[len++] = quote;
    514 	//end string with a zero
    515 	token->string[len] = '\0';
    516 	//the sub type is the length of the string
    517 	token->subtype = len;
    518 	return 1;
    519 } //end of the function PS_ReadString
    520 //============================================================================
    521 //
    522 // Parameter:				-
    523 // Returns:					-
    524 // Changes Globals:		-
    525 //============================================================================
    526 int PS_ReadName(script_t *script, token_t *token)
    527 {
    528 	int len = 0;
    529 	char c;
    530 
    531 	token->type = TT_NAME;
    532 	do
    533 	{
    534 		token->string[len++] = *script->script_p++;
    535 		if (len >= MAX_TOKEN)
    536 		{
    537 			ScriptError(script, "name longer than MAX_TOKEN = %d", MAX_TOKEN);
    538 			return 0;
    539 		} //end if
    540 		c = *script->script_p;
    541    } while ((c >= 'a' && c <= 'z') ||
    542 				(c >= 'A' && c <= 'Z') ||
    543 				(c >= '0' && c <= '9') ||
    544 				c == '_');
    545 	token->string[len] = '\0';
    546 	//the sub type is the length of the name
    547 	token->subtype = len;
    548 	return 1;
    549 } //end of the function PS_ReadName
    550 //============================================================================
    551 //
    552 // Parameter:				-
    553 // Returns:					-
    554 // Changes Globals:		-
    555 //============================================================================
    556 void NumberValue(char *string, int subtype, unsigned long int *intvalue,
    557 															long double *floatvalue)
    558 {
    559 	unsigned long int dotfound = 0;
    560 
    561 	*intvalue = 0;
    562 	*floatvalue = 0;
    563 	//floating point number
    564 	if (subtype & TT_FLOAT)
    565 	{
    566 		while(*string)
    567 		{
    568 			if (*string == '.')
    569 			{
    570 				if (dotfound) return;
    571 				dotfound = 10;
    572 				string++;
    573 			} //end if
    574 			if (dotfound)
    575 			{
    576 				*floatvalue = *floatvalue + (long double) (*string - '0') /
    577 																	(long double) dotfound;
    578 				dotfound *= 10;
    579 			} //end if
    580 			else
    581 			{
    582 				*floatvalue = *floatvalue * 10.0 + (long double) (*string - '0');
    583 			} //end else
    584 			string++;
    585 		} //end while
    586 		*intvalue = (unsigned long) *floatvalue;
    587 	} //end if
    588 	else if (subtype & TT_DECIMAL)
    589 	{
    590 		while(*string) *intvalue = *intvalue * 10 + (*string++ - '0');
    591 		*floatvalue = *intvalue;
    592 	} //end else if
    593 	else if (subtype & TT_HEX)
    594 	{
    595 		//step over the leading 0x or 0X
    596 		string += 2;
    597 		while(*string)
    598 		{
    599 			*intvalue <<= 4;
    600 			if (*string >= 'a' && *string <= 'f') *intvalue += *string - 'a' + 10;
    601 			else if (*string >= 'A' && *string <= 'F') *intvalue += *string - 'A' + 10;
    602 			else *intvalue += *string - '0';
    603 			string++;
    604 		} //end while
    605 		*floatvalue = *intvalue;
    606 	} //end else if
    607 	else if (subtype & TT_OCTAL)
    608 	{
    609 		//step over the first zero
    610 		string += 1;
    611 		while(*string) *intvalue = (*intvalue << 3) + (*string++ - '0');
    612 		*floatvalue = *intvalue;
    613 	} //end else if
    614 	else if (subtype & TT_BINARY)
    615 	{
    616 		//step over the leading 0b or 0B
    617 		string += 2;
    618 		while(*string) *intvalue = (*intvalue << 1) + (*string++ - '0');
    619 		*floatvalue = *intvalue;
    620 	} //end else if
    621 } //end of the function NumberValue
    622 //============================================================================
    623 //
    624 // Parameter:				-
    625 // Returns:					-
    626 // Changes Globals:		-
    627 //============================================================================
    628 int PS_ReadNumber(script_t *script, token_t *token)
    629 {
    630 	int len = 0, i;
    631 	int octal, dot;
    632 	char c;
    633 //	unsigned long int intvalue = 0;
    634 //	long double floatvalue = 0;
    635 
    636 	token->type = TT_NUMBER;
    637 	//check for a hexadecimal number
    638 	if (*script->script_p == '0' &&
    639 		(*(script->script_p + 1) == 'x' ||
    640 		*(script->script_p + 1) == 'X'))
    641 	{
    642 		token->string[len++] = *script->script_p++;
    643 		token->string[len++] = *script->script_p++;
    644 		c = *script->script_p;
    645 		//hexadecimal
    646 		while((c >= '0' && c <= '9') ||
    647 					(c >= 'a' && c <= 'f') ||
    648 					(c >= 'A' && c <= 'A'))
    649 		{
    650 			token->string[len++] = *script->script_p++;
    651 			if (len >= MAX_TOKEN)
    652 			{
    653 				ScriptError(script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN);
    654 				return 0;
    655 			} //end if
    656 			c = *script->script_p;
    657 		} //end while
    658 		token->subtype |= TT_HEX;
    659 	} //end if
    660 #ifdef BINARYNUMBERS
    661 	//check for a binary number
    662 	else if (*script->script_p == '0' &&
    663 		(*(script->script_p + 1) == 'b' ||
    664 		*(script->script_p + 1) == 'B'))
    665 	{
    666 		token->string[len++] = *script->script_p++;
    667 		token->string[len++] = *script->script_p++;
    668 		c = *script->script_p;
    669 		//binary
    670 		while(c == '0' || c == '1')
    671 		{
    672 			token->string[len++] = *script->script_p++;
    673 			if (len >= MAX_TOKEN)
    674 			{
    675 				ScriptError(script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN);
    676 				return 0;
    677 			} //end if
    678 			c = *script->script_p;
    679 		} //end while
    680 		token->subtype |= TT_BINARY;
    681 	} //end if
    682 #endif //BINARYNUMBERS
    683 	else //decimal or octal integer or floating point number
    684 	{
    685 		octal = qfalse;
    686 		dot = qfalse;
    687 		if (*script->script_p == '0') octal = qtrue;
    688 		while(1)
    689 		{
    690 			c = *script->script_p;
    691 			if (c == '.') dot = qtrue;
    692 			else if (c == '8' || c == '9') octal = qfalse;
    693 			else if (c < '0' || c > '9') break;
    694 			token->string[len++] = *script->script_p++;
    695 			if (len >= MAX_TOKEN - 1)
    696 			{
    697 				ScriptError(script, "number longer than MAX_TOKEN = %d", MAX_TOKEN);
    698 				return 0;
    699 			} //end if
    700 		} //end while
    701 		if (octal) token->subtype |= TT_OCTAL;
    702 		else token->subtype |= TT_DECIMAL;
    703 		if (dot) token->subtype |= TT_FLOAT;
    704 	} //end else
    705 	for (i = 0; i < 2; i++)
    706 	{
    707 		c = *script->script_p;
    708 		//check for a LONG number
    709 		if ( (c == 'l' || c == 'L') // bk001204 - brackets 
    710 		     && !(token->subtype & TT_LONG))
    711 		{
    712 			script->script_p++;
    713 			token->subtype |= TT_LONG;
    714 		} //end if
    715 		//check for an UNSIGNED number
    716 		else if ( (c == 'u' || c == 'U') // bk001204 - brackets 
    717 			  && !(token->subtype & (TT_UNSIGNED | TT_FLOAT)))
    718 		{
    719 			script->script_p++;
    720 			token->subtype |= TT_UNSIGNED;
    721 		} //end if
    722 	} //end for
    723 	token->string[len] = '\0';
    724 #ifdef NUMBERVALUE
    725 	NumberValue(token->string, token->subtype, &token->intvalue, &token->floatvalue);
    726 #endif //NUMBERVALUE
    727 	if (!(token->subtype & TT_FLOAT)) token->subtype |= TT_INTEGER;
    728 	return 1;
    729 } //end of the function PS_ReadNumber
    730 //============================================================================
    731 //
    732 // Parameter:				-
    733 // Returns:					-
    734 // Changes Globals:		-
    735 //============================================================================
    736 int PS_ReadLiteral(script_t *script, token_t *token)
    737 {
    738 	token->type = TT_LITERAL;
    739 	//first quote
    740 	token->string[0] = *script->script_p++;
    741 	//check for end of file
    742 	if (!*script->script_p)
    743 	{
    744 		ScriptError(script, "end of file before trailing \'");
    745 		return 0;
    746 	} //end if
    747 	//if it is an escape character
    748 	if (*script->script_p == '\\')
    749 	{
    750 		if (!PS_ReadEscapeCharacter(script, &token->string[1])) return 0;
    751 	} //end if
    752 	else
    753 	{
    754 		token->string[1] = *script->script_p++;
    755 	} //end else
    756 	//check for trailing quote
    757 	if (*script->script_p != '\'')
    758 	{
    759 		ScriptWarning(script, "too many characters in literal, ignored");
    760 		while(*script->script_p &&
    761 				*script->script_p != '\'' &&
    762 				*script->script_p != '\n')
    763 		{
    764 			script->script_p++;
    765 		} //end while
    766 		if (*script->script_p == '\'') script->script_p++;
    767 	} //end if
    768 	//store the trailing quote
    769 	token->string[2] = *script->script_p++;
    770 	//store trailing zero to end the string
    771 	token->string[3] = '\0';
    772 	//the sub type is the integer literal value
    773 	token->subtype = token->string[1];
    774 	//
    775 	return 1;
    776 } //end of the function PS_ReadLiteral
    777 //============================================================================
    778 //
    779 // Parameter:				-
    780 // Returns:					-
    781 // Changes Globals:		-
    782 //============================================================================
    783 int PS_ReadPunctuation(script_t *script, token_t *token)
    784 {
    785 	int len;
    786 	char *p;
    787 	punctuation_t *punc;
    788 
    789 #ifdef PUNCTABLE
    790 	for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next)
    791 	{
    792 #else
    793 	int i;
    794 
    795 	for (i = 0; script->punctuations[i].p; i++)
    796 	{
    797 		punc = &script->punctuations[i];
    798 #endif //PUNCTABLE
    799 		p = punc->p;
    800 		len = strlen(p);
    801 		//if the script contains at least as much characters as the punctuation
    802 		if (script->script_p + len <= script->end_p)
    803 		{
    804 			//if the script contains the punctuation
    805 			if (!strncmp(script->script_p, p, len))
    806 			{
    807 				strncpy(token->string, p, MAX_TOKEN);
    808 				script->script_p += len;
    809 				token->type = TT_PUNCTUATION;
    810 				//sub type is the number of the punctuation
    811 				token->subtype = punc->n;
    812 				return 1;
    813 			} //end if
    814 		} //end if
    815 	} //end for
    816 	return 0;
    817 } //end of the function PS_ReadPunctuation
    818 //============================================================================
    819 //
    820 // Parameter:				-
    821 // Returns:					-
    822 // Changes Globals:		-
    823 //============================================================================
    824 int PS_ReadPrimitive(script_t *script, token_t *token)
    825 {
    826 	int len;
    827 
    828 	len = 0;
    829 	while(*script->script_p > ' ' && *script->script_p != ';')
    830 	{
    831 		if (len >= MAX_TOKEN)
    832 		{
    833 			ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN);
    834 			return 0;
    835 		} //end if
    836 		token->string[len++] = *script->script_p++;
    837 	} //end while
    838 	token->string[len] = 0;
    839 	//copy the token into the script structure
    840 	Com_Memcpy(&script->token, token, sizeof(token_t));
    841 	//primitive reading successfull
    842 	return 1;
    843 } //end of the function PS_ReadPrimitive
    844 //============================================================================
    845 //
    846 // Parameter:				-
    847 // Returns:					-
    848 // Changes Globals:		-
    849 //============================================================================
    850 int PS_ReadToken(script_t *script, token_t *token)
    851 {
    852 	//if there is a token available (from UnreadToken)
    853 	if (script->tokenavailable)
    854 	{
    855 		script->tokenavailable = 0;
    856 		Com_Memcpy(token, &script->token, sizeof(token_t));
    857 		return 1;
    858 	} //end if
    859 	//save script pointer
    860 	script->lastscript_p = script->script_p;
    861 	//save line counter
    862 	script->lastline = script->line;
    863 	//clear the token stuff
    864 	Com_Memset(token, 0, sizeof(token_t));
    865 	//start of the white space
    866 	script->whitespace_p = script->script_p;
    867 	token->whitespace_p = script->script_p;
    868 	//read unusefull stuff
    869 	if (!PS_ReadWhiteSpace(script)) return 0;
    870 	//end of the white space
    871 	script->endwhitespace_p = script->script_p;
    872 	token->endwhitespace_p = script->script_p;
    873 	//line the token is on
    874 	token->line = script->line;
    875 	//number of lines crossed before token
    876 	token->linescrossed = script->line - script->lastline;
    877 	//if there is a leading double quote
    878 	if (*script->script_p == '\"')
    879 	{
    880 		if (!PS_ReadString(script, token, '\"')) return 0;
    881 	} //end if
    882 	//if an literal
    883 	else if (*script->script_p == '\'')
    884 	{
    885 		//if (!PS_ReadLiteral(script, token)) return 0;
    886 		if (!PS_ReadString(script, token, '\'')) return 0;
    887 	} //end if
    888 	//if there is a number
    889 	else if ((*script->script_p >= '0' && *script->script_p <= '9') ||
    890 				(*script->script_p == '.' &&
    891 				(*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9')))
    892 	{
    893 		if (!PS_ReadNumber(script, token)) return 0;
    894 	} //end if
    895 	//if this is a primitive script
    896 	else if (script->flags & SCFL_PRIMITIVE)
    897 	{
    898 		return PS_ReadPrimitive(script, token);
    899 	} //end else if
    900 	//if there is a name
    901 	else if ((*script->script_p >= 'a' && *script->script_p <= 'z') ||
    902 		(*script->script_p >= 'A' && *script->script_p <= 'Z') ||
    903 		*script->script_p == '_')
    904 	{
    905 		if (!PS_ReadName(script, token)) return 0;
    906 	} //end if
    907 	//check for punctuations
    908 	else if (!PS_ReadPunctuation(script, token))
    909 	{
    910 		ScriptError(script, "can't read token");
    911 		return 0;
    912 	} //end if
    913 	//copy the token into the script structure
    914 	Com_Memcpy(&script->token, token, sizeof(token_t));
    915 	//succesfully read a token
    916 	return 1;
    917 } //end of the function PS_ReadToken
    918 //============================================================================
    919 //
    920 // Parameter:				-
    921 // Returns:					-
    922 // Changes Globals:		-
    923 //============================================================================
    924 int PS_ExpectTokenString(script_t *script, char *string)
    925 {
    926 	token_t token;
    927 
    928 	if (!PS_ReadToken(script, &token))
    929 	{
    930 		ScriptError(script, "couldn't find expected %s", string);
    931 		return 0;
    932 	} //end if
    933 
    934 	if (strcmp(token.string, string))
    935 	{
    936 		ScriptError(script, "expected %s, found %s", string, token.string);
    937 		return 0;
    938 	} //end if
    939 	return 1;
    940 } //end of the function PS_ExpectToken
    941 //============================================================================
    942 //
    943 // Parameter:				-
    944 // Returns:					-
    945 // Changes Globals:		-
    946 //============================================================================
    947 int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token)
    948 {
    949 	char str[MAX_TOKEN];
    950 
    951 	if (!PS_ReadToken(script, token))
    952 	{
    953 		ScriptError(script, "couldn't read expected token");
    954 		return 0;
    955 	} //end if
    956 
    957 	if (token->type != type)
    958 	{
    959 		if (type == TT_STRING) strcpy(str, "string");
    960 		if (type == TT_LITERAL) strcpy(str, "literal");
    961 		if (type == TT_NUMBER) strcpy(str, "number");
    962 		if (type == TT_NAME) strcpy(str, "name");
    963 		if (type == TT_PUNCTUATION) strcpy(str, "punctuation");
    964 		ScriptError(script, "expected a %s, found %s", str, token->string);
    965 		return 0;
    966 	} //end if
    967 	if (token->type == TT_NUMBER)
    968 	{
    969 		if ((token->subtype & subtype) != subtype)
    970 		{
    971 			if (subtype & TT_DECIMAL) strcpy(str, "decimal");
    972 			if (subtype & TT_HEX) strcpy(str, "hex");
    973 			if (subtype & TT_OCTAL) strcpy(str, "octal");
    974 			if (subtype & TT_BINARY) strcpy(str, "binary");
    975 			if (subtype & TT_LONG) strcat(str, " long");
    976 			if (subtype & TT_UNSIGNED) strcat(str, " unsigned");
    977 			if (subtype & TT_FLOAT) strcat(str, " float");
    978 			if (subtype & TT_INTEGER) strcat(str, " integer");
    979 			ScriptError(script, "expected %s, found %s", str, token->string);
    980 			return 0;
    981 		} //end if
    982 	} //end if
    983 	else if (token->type == TT_PUNCTUATION)
    984 	{
    985 		if (subtype < 0)
    986 		{
    987 			ScriptError(script, "BUG: wrong punctuation subtype");
    988 			return 0;
    989 		} //end if
    990 		if (token->subtype != subtype)
    991 		{
    992 			ScriptError(script, "expected %s, found %s",
    993 							script->punctuations[subtype], token->string);
    994 			return 0;
    995 		} //end if
    996 	} //end else if
    997 	return 1;
    998 } //end of the function PS_ExpectTokenType
    999 //============================================================================
   1000 //
   1001 // Parameter:				-
   1002 // Returns:					-
   1003 // Changes Globals:		-
   1004 //============================================================================
   1005 int PS_ExpectAnyToken(script_t *script, token_t *token)
   1006 {
   1007 	if (!PS_ReadToken(script, token))
   1008 	{
   1009 		ScriptError(script, "couldn't read expected token");
   1010 		return 0;
   1011 	} //end if
   1012 	else
   1013 	{
   1014 		return 1;
   1015 	} //end else
   1016 } //end of the function PS_ExpectAnyToken
   1017 //============================================================================
   1018 //
   1019 // Parameter:				-
   1020 // Returns:					-
   1021 // Changes Globals:		-
   1022 //============================================================================
   1023 int PS_CheckTokenString(script_t *script, char *string)
   1024 {
   1025 	token_t tok;
   1026 
   1027 	if (!PS_ReadToken(script, &tok)) return 0;
   1028 	//if the token is available
   1029 	if (!strcmp(tok.string, string)) return 1;
   1030 	//token not available
   1031 	script->script_p = script->lastscript_p;
   1032 	return 0;
   1033 } //end of the function PS_CheckTokenString
   1034 //============================================================================
   1035 //
   1036 // Parameter:				-
   1037 // Returns:					-
   1038 // Changes Globals:		-
   1039 //============================================================================
   1040 int PS_CheckTokenType(script_t *script, int type, int subtype, token_t *token)
   1041 {
   1042 	token_t tok;
   1043 
   1044 	if (!PS_ReadToken(script, &tok)) return 0;
   1045 	//if the type matches
   1046 	if (tok.type == type &&
   1047 			(tok.subtype & subtype) == subtype)
   1048 	{
   1049 		Com_Memcpy(token, &tok, sizeof(token_t));
   1050 		return 1;
   1051 	} //end if
   1052 	//token is not available
   1053 	script->script_p = script->lastscript_p;
   1054 	return 0;
   1055 } //end of the function PS_CheckTokenType
   1056 //============================================================================
   1057 //
   1058 // Parameter:				-
   1059 // Returns:					-
   1060 // Changes Globals:		-
   1061 //============================================================================
   1062 int PS_SkipUntilString(script_t *script, char *string)
   1063 {
   1064 	token_t token;
   1065 
   1066 	while(PS_ReadToken(script, &token))
   1067 	{
   1068 		if (!strcmp(token.string, string)) return 1;
   1069 	} //end while
   1070 	return 0;
   1071 } //end of the function PS_SkipUntilString
   1072 //============================================================================
   1073 //
   1074 // Parameter:				-
   1075 // Returns:					-
   1076 // Changes Globals:		-
   1077 //============================================================================
   1078 void PS_UnreadLastToken(script_t *script)
   1079 {
   1080 	script->tokenavailable = 1;
   1081 } //end of the function UnreadLastToken
   1082 //============================================================================
   1083 //
   1084 // Parameter:				-
   1085 // Returns:					-
   1086 // Changes Globals:		-
   1087 //============================================================================
   1088 void PS_UnreadToken(script_t *script, token_t *token)
   1089 {
   1090 	Com_Memcpy(&script->token, token, sizeof(token_t));
   1091 	script->tokenavailable = 1;
   1092 } //end of the function UnreadToken
   1093 //============================================================================
   1094 // returns the next character of the read white space, returns NULL if none
   1095 //
   1096 // Parameter:				-
   1097 // Returns:					-
   1098 // Changes Globals:		-
   1099 //============================================================================
   1100 char PS_NextWhiteSpaceChar(script_t *script)
   1101 {
   1102 	if (script->whitespace_p != script->endwhitespace_p)
   1103 	{
   1104 		return *script->whitespace_p++;
   1105 	} //end if
   1106 	else
   1107 	{
   1108 		return 0;
   1109 	} //end else
   1110 } //end of the function PS_NextWhiteSpaceChar
   1111 //============================================================================
   1112 //
   1113 // Parameter:				-
   1114 // Returns:					-
   1115 // Changes Globals:		-
   1116 //============================================================================
   1117 void StripDoubleQuotes(char *string)
   1118 {
   1119 	if (*string == '\"')
   1120 	{
   1121 		strcpy(string, string+1);
   1122 	} //end if
   1123 	if (string[strlen(string)-1] == '\"')
   1124 	{
   1125 		string[strlen(string)-1] = '\0';
   1126 	} //end if
   1127 } //end of the function StripDoubleQuotes
   1128 //============================================================================
   1129 //
   1130 // Parameter:				-
   1131 // Returns:					-
   1132 // Changes Globals:		-
   1133 //============================================================================
   1134 void StripSingleQuotes(char *string)
   1135 {
   1136 	if (*string == '\'')
   1137 	{
   1138 		strcpy(string, string+1);
   1139 	} //end if
   1140 	if (string[strlen(string)-1] == '\'')
   1141 	{
   1142 		string[strlen(string)-1] = '\0';
   1143 	} //end if
   1144 } //end of the function StripSingleQuotes
   1145 //============================================================================
   1146 //
   1147 // Parameter:				-
   1148 // Returns:					-
   1149 // Changes Globals:		-
   1150 //============================================================================
   1151 long double ReadSignedFloat(script_t *script)
   1152 {
   1153 	token_t token;
   1154 	long double sign = 1;
   1155 
   1156 	PS_ExpectAnyToken(script, &token);
   1157 	if (!strcmp(token.string, "-"))
   1158 	{
   1159 		sign = -1;
   1160 		PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
   1161 	} //end if
   1162 	else if (token.type != TT_NUMBER)
   1163 	{
   1164 		ScriptError(script, "expected float value, found %s\n", token.string);
   1165 	} //end else if
   1166 	return sign * token.floatvalue;
   1167 } //end of the function ReadSignedFloat
   1168 //============================================================================
   1169 //
   1170 // Parameter:				-
   1171 // Returns:					-
   1172 // Changes Globals:		-
   1173 //============================================================================
   1174 signed long int ReadSignedInt(script_t *script)
   1175 {
   1176 	token_t token;
   1177 	signed long int sign = 1;
   1178 
   1179 	PS_ExpectAnyToken(script, &token);
   1180 	if (!strcmp(token.string, "-"))
   1181 	{
   1182 		sign = -1;
   1183 		PS_ExpectTokenType(script, TT_NUMBER, TT_INTEGER, &token);
   1184 	} //end if
   1185 	else if (token.type != TT_NUMBER || token.subtype == TT_FLOAT)
   1186 	{
   1187 		ScriptError(script, "expected integer value, found %s\n", token.string);
   1188 	} //end else if
   1189 	return sign * token.intvalue;
   1190 } //end of the function ReadSignedInt
   1191 //============================================================================
   1192 //
   1193 // Parameter:				-
   1194 // Returns:					-
   1195 // Changes Globals:		-
   1196 //============================================================================
   1197 void SetScriptFlags(script_t *script, int flags)
   1198 {
   1199 	script->flags = flags;
   1200 } //end of the function SetScriptFlags
   1201 //============================================================================
   1202 //
   1203 // Parameter:				-
   1204 // Returns:					-
   1205 // Changes Globals:		-
   1206 //============================================================================
   1207 int GetScriptFlags(script_t *script)
   1208 {
   1209 	return script->flags;
   1210 } //end of the function GetScriptFlags
   1211 //============================================================================
   1212 //
   1213 // Parameter:				-
   1214 // Returns:					-
   1215 // Changes Globals:		-
   1216 //============================================================================
   1217 void ResetScript(script_t *script)
   1218 {
   1219 	//pointer in script buffer
   1220 	script->script_p = script->buffer;
   1221 	//pointer in script buffer before reading token
   1222 	script->lastscript_p = script->buffer;
   1223 	//begin of white space
   1224 	script->whitespace_p = NULL;
   1225 	//end of white space
   1226 	script->endwhitespace_p = NULL;
   1227 	//set if there's a token available in script->token
   1228 	script->tokenavailable = 0;
   1229 	//
   1230 	script->line = 1;
   1231 	script->lastline = 1;
   1232 	//clear the saved token
   1233 	Com_Memset(&script->token, 0, sizeof(token_t));
   1234 } //end of the function ResetScript
   1235 //============================================================================
   1236 // returns true if at the end of the script
   1237 //
   1238 // Parameter:				-
   1239 // Returns:					-
   1240 // Changes Globals:		-
   1241 //============================================================================
   1242 int EndOfScript(script_t *script)
   1243 {
   1244 	return script->script_p >= script->end_p;
   1245 } //end of the function EndOfScript
   1246 //============================================================================
   1247 //
   1248 // Parameter:				-
   1249 // Returns:					-
   1250 // Changes Globals:		-
   1251 //============================================================================
   1252 int NumLinesCrossed(script_t *script)
   1253 {
   1254 	return script->line - script->lastline;
   1255 } //end of the function NumLinesCrossed
   1256 //============================================================================
   1257 //
   1258 // Parameter:				-
   1259 // Returns:					-
   1260 // Changes Globals:		-
   1261 //============================================================================
   1262 int ScriptSkipTo(script_t *script, char *value)
   1263 {
   1264 	int len;
   1265 	char firstchar;
   1266 
   1267 	firstchar = *value;
   1268 	len = strlen(value);
   1269 	do
   1270 	{
   1271 		if (!PS_ReadWhiteSpace(script)) return 0;
   1272 		if (*script->script_p == firstchar)
   1273 		{
   1274 			if (!strncmp(script->script_p, value, len))
   1275 			{
   1276 				return 1;
   1277 			} //end if
   1278 		} //end if
   1279 		script->script_p++;
   1280 	} while(1);
   1281 } //end of the function ScriptSkipTo
   1282 #ifndef BOTLIB
   1283 //============================================================================
   1284 //
   1285 // Parameter:				-
   1286 // Returns:					-
   1287 // Changes Globals:		-
   1288 //============================================================================
   1289 int FileLength(FILE *fp)
   1290 {
   1291 	int pos;
   1292 	int end;
   1293 
   1294 	pos = ftell(fp);
   1295 	fseek(fp, 0, SEEK_END);
   1296 	end = ftell(fp);
   1297 	fseek(fp, pos, SEEK_SET);
   1298 
   1299 	return end;
   1300 } //end of the function FileLength
   1301 #endif
   1302 //============================================================================
   1303 //
   1304 // Parameter:				-
   1305 // Returns:					-
   1306 // Changes Globals:		-
   1307 //============================================================================
   1308 script_t *LoadScriptFile(const char *filename)
   1309 {
   1310 #ifdef BOTLIB
   1311 	fileHandle_t fp;
   1312 	char pathname[MAX_QPATH];
   1313 #else
   1314 	FILE *fp;
   1315 #endif
   1316 	int length;
   1317 	void *buffer;
   1318 	script_t *script;
   1319 
   1320 #ifdef BOTLIB
   1321 	if (strlen(basefolder))
   1322 		Com_sprintf(pathname, sizeof(pathname), "%s/%s", basefolder, filename);
   1323 	else
   1324 		Com_sprintf(pathname, sizeof(pathname), "%s", filename);
   1325 	length = botimport.FS_FOpenFile( pathname, &fp, FS_READ );
   1326 	if (!fp) return NULL;
   1327 #else
   1328 	fp = fopen(filename, "rb");
   1329 	if (!fp) return NULL;
   1330 
   1331 	length = FileLength(fp);
   1332 #endif
   1333 
   1334 	buffer = GetClearedMemory(sizeof(script_t) + length + 1);
   1335 	script = (script_t *) buffer;
   1336 	Com_Memset(script, 0, sizeof(script_t));
   1337 	strcpy(script->filename, filename);
   1338 	script->buffer = (char *) buffer + sizeof(script_t);
   1339 	script->buffer[length] = 0;
   1340 	script->length = length;
   1341 	//pointer in script buffer
   1342 	script->script_p = script->buffer;
   1343 	//pointer in script buffer before reading token
   1344 	script->lastscript_p = script->buffer;
   1345 	//pointer to end of script buffer
   1346 	script->end_p = &script->buffer[length];
   1347 	//set if there's a token available in script->token
   1348 	script->tokenavailable = 0;
   1349 	//
   1350 	script->line = 1;
   1351 	script->lastline = 1;
   1352 	//
   1353 	SetScriptPunctuations(script, NULL);
   1354 	//
   1355 #ifdef BOTLIB
   1356 	botimport.FS_Read(script->buffer, length, fp);
   1357 	botimport.FS_FCloseFile(fp);
   1358 #else
   1359 	if (fread(script->buffer, length, 1, fp) != 1)
   1360 	{
   1361 		FreeMemory(buffer);
   1362 		script = NULL;
   1363 	} //end if
   1364 	fclose(fp);
   1365 #endif
   1366 	//
   1367 	script->length = COM_Compress(script->buffer);
   1368 
   1369 	return script;
   1370 } //end of the function LoadScriptFile
   1371 //============================================================================
   1372 //
   1373 // Parameter:			-
   1374 // Returns:				-
   1375 // Changes Globals:		-
   1376 //============================================================================
   1377 script_t *LoadScriptMemory(char *ptr, int length, char *name)
   1378 {
   1379 	void *buffer;
   1380 	script_t *script;
   1381 
   1382 	buffer = GetClearedMemory(sizeof(script_t) + length + 1);
   1383 	script = (script_t *) buffer;
   1384 	Com_Memset(script, 0, sizeof(script_t));
   1385 	strcpy(script->filename, name);
   1386 	script->buffer = (char *) buffer + sizeof(script_t);
   1387 	script->buffer[length] = 0;
   1388 	script->length = length;
   1389 	//pointer in script buffer
   1390 	script->script_p = script->buffer;
   1391 	//pointer in script buffer before reading token
   1392 	script->lastscript_p = script->buffer;
   1393 	//pointer to end of script buffer
   1394 	script->end_p = &script->buffer[length];
   1395 	//set if there's a token available in script->token
   1396 	script->tokenavailable = 0;
   1397 	//
   1398 	script->line = 1;
   1399 	script->lastline = 1;
   1400 	//
   1401 	SetScriptPunctuations(script, NULL);
   1402 	//
   1403 	Com_Memcpy(script->buffer, ptr, length);
   1404 	//
   1405 	return script;
   1406 } //end of the function LoadScriptMemory
   1407 //============================================================================
   1408 //
   1409 // Parameter:				-
   1410 // Returns:					-
   1411 // Changes Globals:		-
   1412 //============================================================================
   1413 void FreeScript(script_t *script)
   1414 {
   1415 #ifdef PUNCTABLE
   1416 	if (script->punctuationtable) FreeMemory(script->punctuationtable);
   1417 #endif //PUNCTABLE
   1418 	FreeMemory(script);
   1419 } //end of the function FreeScript
   1420 //============================================================================
   1421 //
   1422 // Parameter:				-
   1423 // Returns:					-
   1424 // Changes Globals:		-
   1425 //============================================================================
   1426 void PS_SetBaseFolder(char *path)
   1427 {
   1428 #ifdef BSPC
   1429 	sprintf(basefolder, path);
   1430 #else
   1431 	Com_sprintf(basefolder, sizeof(basefolder), path);
   1432 #endif
   1433 } //end of the function PS_SetBaseFolder