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