diff options
author | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 17:39:27 +0000 |
---|---|---|
committer | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 17:39:27 +0000 |
commit | 6bf20c78f5b69d40bcc4931df93d29198435ab67 (patch) | |
tree | e3eda937a05d7db42de725b7013bd0344b987f34 /code/botlib/l_script.c | |
parent | 872d4d7f55af706737ffb361bb76ad13e7496770 (diff) | |
download | ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.tar.gz ioquake3-aero-6bf20c78f5b69d40bcc4931df93d29198435ab67.zip |
newlines fixed
git-svn-id: svn://svn.icculus.org/quake3/trunk@6 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'code/botlib/l_script.c')
-rwxr-xr-x | code/botlib/l_script.c | 2866 |
1 files changed, 1433 insertions, 1433 deletions
diff --git a/code/botlib/l_script.c b/code/botlib/l_script.c index 2f1e4fa..e782e7f 100755 --- a/code/botlib/l_script.c +++ b/code/botlib/l_script.c @@ -1,1433 +1,1433 @@ -/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-/*****************************************************************************
- * name: l_script.c
- *
- * desc: lexicographical parser
- *
- * $Archive: /MissionPack/code/botlib/l_script.c $
- *
- *****************************************************************************/
-
-//#define SCREWUP
-//#define BOTLIB
-//#define MEQCC
-//#define BSPC
-
-#ifdef SCREWUP
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-#include <stdarg.h>
-#include "l_memory.h"
-#include "l_script.h"
-
-typedef enum {qfalse, qtrue} qboolean;
-
-#endif //SCREWUP
-
-#ifdef BOTLIB
-//include files for usage in the bot library
-#include "../game/q_shared.h"
-#include "../game/botlib.h"
-#include "be_interface.h"
-#include "l_script.h"
-#include "l_memory.h"
-#include "l_log.h"
-#include "l_libvar.h"
-#endif //BOTLIB
-
-#ifdef MEQCC
-//include files for usage in MrElusive's QuakeC Compiler
-#include "qcc.h"
-#include "l_script.h"
-#include "l_memory.h"
-#include "l_log.h"
-
-#define qtrue true
-#define qfalse false
-#endif //MEQCC
-
-#ifdef BSPC
-//include files for usage in the BSP Converter
-#include "../bspc/qbsp.h"
-#include "../bspc/l_log.h"
-#include "../bspc/l_mem.h"
-
-#define qtrue true
-#define qfalse false
-#endif //BSPC
-
-
-#define PUNCTABLE
-
-//longer punctuations first
-punctuation_t default_punctuations[] =
-{
- //binary operators
- {">>=",P_RSHIFT_ASSIGN, NULL},
- {"<<=",P_LSHIFT_ASSIGN, NULL},
- //
- {"...",P_PARMS, NULL},
- //define merge operator
- {"##",P_PRECOMPMERGE, NULL},
- //logic operators
- {"&&",P_LOGIC_AND, NULL},
- {"||",P_LOGIC_OR, NULL},
- {">=",P_LOGIC_GEQ, NULL},
- {"<=",P_LOGIC_LEQ, NULL},
- {"==",P_LOGIC_EQ, NULL},
- {"!=",P_LOGIC_UNEQ, NULL},
- //arithmatic operators
- {"*=",P_MUL_ASSIGN, NULL},
- {"/=",P_DIV_ASSIGN, NULL},
- {"%=",P_MOD_ASSIGN, NULL},
- {"+=",P_ADD_ASSIGN, NULL},
- {"-=",P_SUB_ASSIGN, NULL},
- {"++",P_INC, NULL},
- {"--",P_DEC, NULL},
- //binary operators
- {"&=",P_BIN_AND_ASSIGN, NULL},
- {"|=",P_BIN_OR_ASSIGN, NULL},
- {"^=",P_BIN_XOR_ASSIGN, NULL},
- {">>",P_RSHIFT, NULL},
- {"<<",P_LSHIFT, NULL},
- //reference operators
- {"->",P_POINTERREF, NULL},
- //C++
- {"::",P_CPP1, NULL},
- {".*",P_CPP2, NULL},
- //arithmatic operators
- {"*",P_MUL, NULL},
- {"/",P_DIV, NULL},
- {"%",P_MOD, NULL},
- {"+",P_ADD, NULL},
- {"-",P_SUB, NULL},
- {"=",P_ASSIGN, NULL},
- //binary operators
- {"&",P_BIN_AND, NULL},
- {"|",P_BIN_OR, NULL},
- {"^",P_BIN_XOR, NULL},
- {"~",P_BIN_NOT, NULL},
- //logic operators
- {"!",P_LOGIC_NOT, NULL},
- {">",P_LOGIC_GREATER, NULL},
- {"<",P_LOGIC_LESS, NULL},
- //reference operator
- {".",P_REF, NULL},
- //seperators
- {",",P_COMMA, NULL},
- {";",P_SEMICOLON, NULL},
- //label indication
- {":",P_COLON, NULL},
- //if statement
- {"?",P_QUESTIONMARK, NULL},
- //embracements
- {"(",P_PARENTHESESOPEN, NULL},
- {")",P_PARENTHESESCLOSE, NULL},
- {"{",P_BRACEOPEN, NULL},
- {"}",P_BRACECLOSE, NULL},
- {"[",P_SQBRACKETOPEN, NULL},
- {"]",P_SQBRACKETCLOSE, NULL},
- //
- {"\\",P_BACKSLASH, NULL},
- //precompiler operator
- {"#",P_PRECOMP, NULL},
-#ifdef DOLLAR
- {"$",P_DOLLAR, NULL},
-#endif //DOLLAR
- {NULL, 0}
-};
-
-#ifdef BSPC
-char basefolder[MAX_PATH];
-#else
-char basefolder[MAX_QPATH];
-#endif
-
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void PS_CreatePunctuationTable(script_t *script, punctuation_t *punctuations)
-{
- int i;
- punctuation_t *p, *lastp, *newp;
-
- //get memory for the table
- if (!script->punctuationtable) script->punctuationtable = (punctuation_t **)
- GetMemory(256 * sizeof(punctuation_t *));
- Com_Memset(script->punctuationtable, 0, 256 * sizeof(punctuation_t *));
- //add the punctuations in the list to the punctuation table
- for (i = 0; punctuations[i].p; i++)
- {
- newp = &punctuations[i];
- lastp = NULL;
- //sort the punctuations in this table entry on length (longer punctuations first)
- for (p = script->punctuationtable[(unsigned int) newp->p[0]]; p; p = p->next)
- {
- if (strlen(p->p) < strlen(newp->p))
- {
- newp->next = p;
- if (lastp) lastp->next = newp;
- else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
- break;
- } //end if
- lastp = p;
- } //end for
- if (!p)
- {
- newp->next = NULL;
- if (lastp) lastp->next = newp;
- else script->punctuationtable[(unsigned int) newp->p[0]] = newp;
- } //end if
- } //end for
-} //end of the function PS_CreatePunctuationTable
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-char *PunctuationFromNum(script_t *script, int num)
-{
- int i;
-
- for (i = 0; script->punctuations[i].p; i++)
- {
- if (script->punctuations[i].n == num) return script->punctuations[i].p;
- } //end for
- return "unkown punctuation";
-} //end of the function PunctuationFromNum
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void QDECL ScriptError(script_t *script, char *str, ...)
-{
- char text[1024];
- va_list ap;
-
- if (script->flags & SCFL_NOERRORS) return;
-
- va_start(ap, str);
- vsprintf(text, str, ap);
- va_end(ap);
-#ifdef BOTLIB
- botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", script->filename, script->line, text);
-#endif //BOTLIB
-#ifdef MEQCC
- printf("error: file %s, line %d: %s\n", script->filename, script->line, text);
-#endif //MEQCC
-#ifdef BSPC
- Log_Print("error: file %s, line %d: %s\n", script->filename, script->line, text);
-#endif //BSPC
-} //end of the function ScriptError
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void QDECL ScriptWarning(script_t *script, char *str, ...)
-{
- char text[1024];
- va_list ap;
-
- if (script->flags & SCFL_NOWARNINGS) return;
-
- va_start(ap, str);
- vsprintf(text, str, ap);
- va_end(ap);
-#ifdef BOTLIB
- botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", script->filename, script->line, text);
-#endif //BOTLIB
-#ifdef MEQCC
- printf("warning: file %s, line %d: %s\n", script->filename, script->line, text);
-#endif //MEQCC
-#ifdef BSPC
- Log_Print("warning: file %s, line %d: %s\n", script->filename, script->line, text);
-#endif //BSPC
-} //end of the function ScriptWarning
-//===========================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//===========================================================================
-void SetScriptPunctuations(script_t *script, punctuation_t *p)
-{
-#ifdef PUNCTABLE
- if (p) PS_CreatePunctuationTable(script, p);
- else PS_CreatePunctuationTable(script, default_punctuations);
-#endif //PUNCTABLE
- if (p) script->punctuations = p;
- else script->punctuations = default_punctuations;
-} //end of the function SetScriptPunctuations
-//============================================================================
-// Reads spaces, tabs, C-like comments etc.
-// When a newline character is found the scripts line counter is increased.
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadWhiteSpace(script_t *script)
-{
- while(1)
- {
- //skip white space
- while(*script->script_p <= ' ')
- {
- if (!*script->script_p) return 0;
- if (*script->script_p == '\n') script->line++;
- script->script_p++;
- } //end while
- //skip comments
- if (*script->script_p == '/')
- {
- //comments //
- if (*(script->script_p+1) == '/')
- {
- script->script_p++;
- do
- {
- script->script_p++;
- if (!*script->script_p) return 0;
- } //end do
- while(*script->script_p != '\n');
- script->line++;
- script->script_p++;
- if (!*script->script_p) return 0;
- continue;
- } //end if
- //comments /* */
- else if (*(script->script_p+1) == '*')
- {
- script->script_p++;
- do
- {
- script->script_p++;
- if (!*script->script_p) return 0;
- if (*script->script_p == '\n') script->line++;
- } //end do
- while(!(*script->script_p == '*' && *(script->script_p+1) == '/'));
- script->script_p++;
- if (!*script->script_p) return 0;
- script->script_p++;
- if (!*script->script_p) return 0;
- continue;
- } //end if
- } //end if
- break;
- } //end while
- return 1;
-} //end of the function PS_ReadWhiteSpace
-//============================================================================
-// Reads an escape character.
-//
-// Parameter: script : script to read from
-// ch : place to store the read escape character
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadEscapeCharacter(script_t *script, char *ch)
-{
- int c, val, i;
-
- //step over the leading '\\'
- script->script_p++;
- //determine the escape character
- switch(*script->script_p)
- {
- case '\\': c = '\\'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case 'v': c = '\v'; break;
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'a': c = '\a'; break;
- case '\'': c = '\''; break;
- case '\"': c = '\"'; break;
- case '\?': c = '\?'; break;
- case 'x':
- {
- script->script_p++;
- for (i = 0, val = 0; ; i++, script->script_p++)
- {
- c = *script->script_p;
- if (c >= '0' && c <= '9') c = c - '0';
- else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10;
- else if (c >= 'a' && c <= 'z') c = c - 'a' + 10;
- else break;
- val = (val << 4) + c;
- } //end for
- script->script_p--;
- if (val > 0xFF)
- {
- ScriptWarning(script, "too large value in escape character");
- val = 0xFF;
- } //end if
- c = val;
- break;
- } //end case
- default: //NOTE: decimal ASCII code, NOT octal
- {
- if (*script->script_p < '0' || *script->script_p > '9') ScriptError(script, "unknown escape char");
- for (i = 0, val = 0; ; i++, script->script_p++)
- {
- c = *script->script_p;
- if (c >= '0' && c <= '9') c = c - '0';
- else break;
- val = val * 10 + c;
- } //end for
- script->script_p--;
- if (val > 0xFF)
- {
- ScriptWarning(script, "too large value in escape character");
- val = 0xFF;
- } //end if
- c = val;
- break;
- } //end default
- } //end switch
- //step over the escape character or the last digit of the number
- script->script_p++;
- //store the escape character
- *ch = c;
- //succesfully read escape character
- return 1;
-} //end of the function PS_ReadEscapeCharacter
-//============================================================================
-// Reads C-like string. Escape characters are interpretted.
-// Quotes are included with the string.
-// Reads two strings with a white space between them as one string.
-//
-// Parameter: script : script to read from
-// token : buffer to store the string
-// Returns: qtrue when a string was read succesfully
-// Changes Globals: -
-//============================================================================
-int PS_ReadString(script_t *script, token_t *token, int quote)
-{
- int len, tmpline;
- char *tmpscript_p;
-
- if (quote == '\"') token->type = TT_STRING;
- else token->type = TT_LITERAL;
-
- len = 0;
- //leading quote
- token->string[len++] = *script->script_p++;
- //
- while(1)
- {
- //minus 2 because trailing double quote and zero have to be appended
- if (len >= MAX_TOKEN - 2)
- {
- ScriptError(script, "string longer than MAX_TOKEN = %d", MAX_TOKEN);
- return 0;
- } //end if
- //if there is an escape character and
- //if escape characters inside a string are allowed
- if (*script->script_p == '\\' && !(script->flags & SCFL_NOSTRINGESCAPECHARS))
- {
- if (!PS_ReadEscapeCharacter(script, &token->string[len]))
- {
- token->string[len] = 0;
- return 0;
- } //end if
- len++;
- } //end if
- //if a trailing quote
- else if (*script->script_p == quote)
- {
- //step over the double quote
- script->script_p++;
- //if white spaces in a string are not allowed
- if (script->flags & SCFL_NOSTRINGWHITESPACES) break;
- //
- tmpscript_p = script->script_p;
- tmpline = script->line;
- //read unusefull stuff between possible two following strings
- if (!PS_ReadWhiteSpace(script))
- {
- script->script_p = tmpscript_p;
- script->line = tmpline;
- break;
- } //end if
- //if there's no leading double qoute
- if (*script->script_p != quote)
- {
- script->script_p = tmpscript_p;
- script->line = tmpline;
- break;
- } //end if
- //step over the new leading double quote
- script->script_p++;
- } //end if
- else
- {
- if (*script->script_p == '\0')
- {
- token->string[len] = 0;
- ScriptError(script, "missing trailing quote");
- return 0;
- } //end if
- if (*script->script_p == '\n')
- {
- token->string[len] = 0;
- ScriptError(script, "newline inside string %s", token->string);
- return 0;
- } //end if
- token->string[len++] = *script->script_p++;
- } //end else
- } //end while
- //trailing quote
- token->string[len++] = quote;
- //end string with a zero
- token->string[len] = '\0';
- //the sub type is the length of the string
- token->subtype = len;
- return 1;
-} //end of the function PS_ReadString
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadName(script_t *script, token_t *token)
-{
- int len = 0;
- char c;
-
- token->type = TT_NAME;
- do
- {
- token->string[len++] = *script->script_p++;
- if (len >= MAX_TOKEN)
- {
- ScriptError(script, "name longer than MAX_TOKEN = %d", MAX_TOKEN);
- return 0;
- } //end if
- c = *script->script_p;
- } while ((c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- c == '_');
- token->string[len] = '\0';
- //the sub type is the length of the name
- token->subtype = len;
- return 1;
-} //end of the function PS_ReadName
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void NumberValue(char *string, int subtype, unsigned long int *intvalue,
- long double *floatvalue)
-{
- unsigned long int dotfound = 0;
-
- *intvalue = 0;
- *floatvalue = 0;
- //floating point number
- if (subtype & TT_FLOAT)
- {
- while(*string)
- {
- if (*string == '.')
- {
- if (dotfound) return;
- dotfound = 10;
- string++;
- } //end if
- if (dotfound)
- {
- *floatvalue = *floatvalue + (long double) (*string - '0') /
- (long double) dotfound;
- dotfound *= 10;
- } //end if
- else
- {
- *floatvalue = *floatvalue * 10.0 + (long double) (*string - '0');
- } //end else
- string++;
- } //end while
- *intvalue = (unsigned long) *floatvalue;
- } //end if
- else if (subtype & TT_DECIMAL)
- {
- while(*string) *intvalue = *intvalue * 10 + (*string++ - '0');
- *floatvalue = *intvalue;
- } //end else if
- else if (subtype & TT_HEX)
- {
- //step over the leading 0x or 0X
- string += 2;
- while(*string)
- {
- *intvalue <<= 4;
- if (*string >= 'a' && *string <= 'f') *intvalue += *string - 'a' + 10;
- else if (*string >= 'A' && *string <= 'F') *intvalue += *string - 'A' + 10;
- else *intvalue += *string - '0';
- string++;
- } //end while
- *floatvalue = *intvalue;
- } //end else if
- else if (subtype & TT_OCTAL)
- {
- //step over the first zero
- string += 1;
- while(*string) *intvalue = (*intvalue << 3) + (*string++ - '0');
- *floatvalue = *intvalue;
- } //end else if
- else if (subtype & TT_BINARY)
- {
- //step over the leading 0b or 0B
- string += 2;
- while(*string) *intvalue = (*intvalue << 1) + (*string++ - '0');
- *floatvalue = *intvalue;
- } //end else if
-} //end of the function NumberValue
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadNumber(script_t *script, token_t *token)
-{
- int len = 0, i;
- int octal, dot;
- char c;
-// unsigned long int intvalue = 0;
-// long double floatvalue = 0;
-
- token->type = TT_NUMBER;
- //check for a hexadecimal number
- if (*script->script_p == '0' &&
- (*(script->script_p + 1) == 'x' ||
- *(script->script_p + 1) == 'X'))
- {
- token->string[len++] = *script->script_p++;
- token->string[len++] = *script->script_p++;
- c = *script->script_p;
- //hexadecimal
- while((c >= '0' && c <= '9') ||
- (c >= 'a' && c <= 'f') ||
- (c >= 'A' && c <= 'A'))
- {
- token->string[len++] = *script->script_p++;
- if (len >= MAX_TOKEN)
- {
- ScriptError(script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN);
- return 0;
- } //end if
- c = *script->script_p;
- } //end while
- token->subtype |= TT_HEX;
- } //end if
-#ifdef BINARYNUMBERS
- //check for a binary number
- else if (*script->script_p == '0' &&
- (*(script->script_p + 1) == 'b' ||
- *(script->script_p + 1) == 'B'))
- {
- token->string[len++] = *script->script_p++;
- token->string[len++] = *script->script_p++;
- c = *script->script_p;
- //binary
- while(c == '0' || c == '1')
- {
- token->string[len++] = *script->script_p++;
- if (len >= MAX_TOKEN)
- {
- ScriptError(script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN);
- return 0;
- } //end if
- c = *script->script_p;
- } //end while
- token->subtype |= TT_BINARY;
- } //end if
-#endif //BINARYNUMBERS
- else //decimal or octal integer or floating point number
- {
- octal = qfalse;
- dot = qfalse;
- if (*script->script_p == '0') octal = qtrue;
- while(1)
- {
- c = *script->script_p;
- if (c == '.') dot = qtrue;
- else if (c == '8' || c == '9') octal = qfalse;
- else if (c < '0' || c > '9') break;
- token->string[len++] = *script->script_p++;
- if (len >= MAX_TOKEN - 1)
- {
- ScriptError(script, "number longer than MAX_TOKEN = %d", MAX_TOKEN);
- return 0;
- } //end if
- } //end while
- if (octal) token->subtype |= TT_OCTAL;
- else token->subtype |= TT_DECIMAL;
- if (dot) token->subtype |= TT_FLOAT;
- } //end else
- for (i = 0; i < 2; i++)
- {
- c = *script->script_p;
- //check for a LONG number
- if ( (c == 'l' || c == 'L') // bk001204 - brackets
- && !(token->subtype & TT_LONG))
- {
- script->script_p++;
- token->subtype |= TT_LONG;
- } //end if
- //check for an UNSIGNED number
- else if ( (c == 'u' || c == 'U') // bk001204 - brackets
- && !(token->subtype & (TT_UNSIGNED | TT_FLOAT)))
- {
- script->script_p++;
- token->subtype |= TT_UNSIGNED;
- } //end if
- } //end for
- token->string[len] = '\0';
-#ifdef NUMBERVALUE
- NumberValue(token->string, token->subtype, &token->intvalue, &token->floatvalue);
-#endif //NUMBERVALUE
- if (!(token->subtype & TT_FLOAT)) token->subtype |= TT_INTEGER;
- return 1;
-} //end of the function PS_ReadNumber
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadLiteral(script_t *script, token_t *token)
-{
- token->type = TT_LITERAL;
- //first quote
- token->string[0] = *script->script_p++;
- //check for end of file
- if (!*script->script_p)
- {
- ScriptError(script, "end of file before trailing \'");
- return 0;
- } //end if
- //if it is an escape character
- if (*script->script_p == '\\')
- {
- if (!PS_ReadEscapeCharacter(script, &token->string[1])) return 0;
- } //end if
- else
- {
- token->string[1] = *script->script_p++;
- } //end else
- //check for trailing quote
- if (*script->script_p != '\'')
- {
- ScriptWarning(script, "too many characters in literal, ignored");
- while(*script->script_p &&
- *script->script_p != '\'' &&
- *script->script_p != '\n')
- {
- script->script_p++;
- } //end while
- if (*script->script_p == '\'') script->script_p++;
- } //end if
- //store the trailing quote
- token->string[2] = *script->script_p++;
- //store trailing zero to end the string
- token->string[3] = '\0';
- //the sub type is the integer literal value
- token->subtype = token->string[1];
- //
- return 1;
-} //end of the function PS_ReadLiteral
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadPunctuation(script_t *script, token_t *token)
-{
- int len;
- char *p;
- punctuation_t *punc;
-
-#ifdef PUNCTABLE
- for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next)
- {
-#else
- int i;
-
- for (i = 0; script->punctuations[i].p; i++)
- {
- punc = &script->punctuations[i];
-#endif //PUNCTABLE
- p = punc->p;
- len = strlen(p);
- //if the script contains at least as much characters as the punctuation
- if (script->script_p + len <= script->end_p)
- {
- //if the script contains the punctuation
- if (!strncmp(script->script_p, p, len))
- {
- strncpy(token->string, p, MAX_TOKEN);
- script->script_p += len;
- token->type = TT_PUNCTUATION;
- //sub type is the number of the punctuation
- token->subtype = punc->n;
- return 1;
- } //end if
- } //end if
- } //end for
- return 0;
-} //end of the function PS_ReadPunctuation
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadPrimitive(script_t *script, token_t *token)
-{
- int len;
-
- len = 0;
- while(*script->script_p > ' ' && *script->script_p != ';')
- {
- if (len >= MAX_TOKEN)
- {
- ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN);
- return 0;
- } //end if
- token->string[len++] = *script->script_p++;
- } //end while
- token->string[len] = 0;
- //copy the token into the script structure
- Com_Memcpy(&script->token, token, sizeof(token_t));
- //primitive reading successfull
- return 1;
-} //end of the function PS_ReadPrimitive
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ReadToken(script_t *script, token_t *token)
-{
- //if there is a token available (from UnreadToken)
- if (script->tokenavailable)
- {
- script->tokenavailable = 0;
- Com_Memcpy(token, &script->token, sizeof(token_t));
- return 1;
- } //end if
- //save script pointer
- script->lastscript_p = script->script_p;
- //save line counter
- script->lastline = script->line;
- //clear the token stuff
- Com_Memset(token, 0, sizeof(token_t));
- //start of the white space
- script->whitespace_p = script->script_p;
- token->whitespace_p = script->script_p;
- //read unusefull stuff
- if (!PS_ReadWhiteSpace(script)) return 0;
- //end of the white space
- script->endwhitespace_p = script->script_p;
- token->endwhitespace_p = script->script_p;
- //line the token is on
- token->line = script->line;
- //number of lines crossed before token
- token->linescrossed = script->line - script->lastline;
- //if there is a leading double quote
- if (*script->script_p == '\"')
- {
- if (!PS_ReadString(script, token, '\"')) return 0;
- } //end if
- //if an literal
- else if (*script->script_p == '\'')
- {
- //if (!PS_ReadLiteral(script, token)) return 0;
- if (!PS_ReadString(script, token, '\'')) return 0;
- } //end if
- //if there is a number
- else if ((*script->script_p >= '0' && *script->script_p <= '9') ||
- (*script->script_p == '.' &&
- (*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9')))
- {
- if (!PS_ReadNumber(script, token)) return 0;
- } //end if
- //if this is a primitive script
- else if (script->flags & SCFL_PRIMITIVE)
- {
- return PS_ReadPrimitive(script, token);
- } //end else if
- //if there is a name
- else if ((*script->script_p >= 'a' && *script->script_p <= 'z') ||
- (*script->script_p >= 'A' && *script->script_p <= 'Z') ||
- *script->script_p == '_')
- {
- if (!PS_ReadName(script, token)) return 0;
- } //end if
- //check for punctuations
- else if (!PS_ReadPunctuation(script, token))
- {
- ScriptError(script, "can't read token");
- return 0;
- } //end if
- //copy the token into the script structure
- Com_Memcpy(&script->token, token, sizeof(token_t));
- //succesfully read a token
- return 1;
-} //end of the function PS_ReadToken
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ExpectTokenString(script_t *script, char *string)
-{
- token_t token;
-
- if (!PS_ReadToken(script, &token))
- {
- ScriptError(script, "couldn't find expected %s", string);
- return 0;
- } //end if
-
- if (strcmp(token.string, string))
- {
- ScriptError(script, "expected %s, found %s", string, token.string);
- return 0;
- } //end if
- return 1;
-} //end of the function PS_ExpectToken
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token)
-{
- char str[MAX_TOKEN];
-
- if (!PS_ReadToken(script, token))
- {
- ScriptError(script, "couldn't read expected token");
- return 0;
- } //end if
-
- if (token->type != type)
- {
- if (type == TT_STRING) strcpy(str, "string");
- if (type == TT_LITERAL) strcpy(str, "literal");
- if (type == TT_NUMBER) strcpy(str, "number");
- if (type == TT_NAME) strcpy(str, "name");
- if (type == TT_PUNCTUATION) strcpy(str, "punctuation");
- ScriptError(script, "expected a %s, found %s", str, token->string);
- return 0;
- } //end if
- if (token->type == TT_NUMBER)
- {
- if ((token->subtype & subtype) != subtype)
- {
- if (subtype & TT_DECIMAL) strcpy(str, "decimal");
- if (subtype & TT_HEX) strcpy(str, "hex");
- if (subtype & TT_OCTAL) strcpy(str, "octal");
- if (subtype & TT_BINARY) strcpy(str, "binary");
- if (subtype & TT_LONG) strcat(str, " long");
- if (subtype & TT_UNSIGNED) strcat(str, " unsigned");
- if (subtype & TT_FLOAT) strcat(str, " float");
- if (subtype & TT_INTEGER) strcat(str, " integer");
- ScriptError(script, "expected %s, found %s", str, token->string);
- return 0;
- } //end if
- } //end if
- else if (token->type == TT_PUNCTUATION)
- {
- if (subtype < 0)
- {
- ScriptError(script, "BUG: wrong punctuation subtype");
- return 0;
- } //end if
- if (token->subtype != subtype)
- {
- ScriptError(script, "expected %s, found %s",
- script->punctuations[subtype], token->string);
- return 0;
- } //end if
- } //end else if
- return 1;
-} //end of the function PS_ExpectTokenType
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_ExpectAnyToken(script_t *script, token_t *token)
-{
- if (!PS_ReadToken(script, token))
- {
- ScriptError(script, "couldn't read expected token");
- return 0;
- } //end if
- else
- {
- return 1;
- } //end else
-} //end of the function PS_ExpectAnyToken
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_CheckTokenString(script_t *script, char *string)
-{
- token_t tok;
-
- if (!PS_ReadToken(script, &tok)) return 0;
- //if the token is available
- if (!strcmp(tok.string, string)) return 1;
- //token not available
- script->script_p = script->lastscript_p;
- return 0;
-} //end of the function PS_CheckTokenString
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_CheckTokenType(script_t *script, int type, int subtype, token_t *token)
-{
- token_t tok;
-
- if (!PS_ReadToken(script, &tok)) return 0;
- //if the type matches
- if (tok.type == type &&
- (tok.subtype & subtype) == subtype)
- {
- Com_Memcpy(token, &tok, sizeof(token_t));
- return 1;
- } //end if
- //token is not available
- script->script_p = script->lastscript_p;
- return 0;
-} //end of the function PS_CheckTokenType
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int PS_SkipUntilString(script_t *script, char *string)
-{
- token_t token;
-
- while(PS_ReadToken(script, &token))
- {
- if (!strcmp(token.string, string)) return 1;
- } //end while
- return 0;
-} //end of the function PS_SkipUntilString
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void PS_UnreadLastToken(script_t *script)
-{
- script->tokenavailable = 1;
-} //end of the function UnreadLastToken
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void PS_UnreadToken(script_t *script, token_t *token)
-{
- Com_Memcpy(&script->token, token, sizeof(token_t));
- script->tokenavailable = 1;
-} //end of the function UnreadToken
-//============================================================================
-// returns the next character of the read white space, returns NULL if none
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-char PS_NextWhiteSpaceChar(script_t *script)
-{
- if (script->whitespace_p != script->endwhitespace_p)
- {
- return *script->whitespace_p++;
- } //end if
- else
- {
- return 0;
- } //end else
-} //end of the function PS_NextWhiteSpaceChar
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void StripDoubleQuotes(char *string)
-{
- if (*string == '\"')
- {
- strcpy(string, string+1);
- } //end if
- if (string[strlen(string)-1] == '\"')
- {
- string[strlen(string)-1] = '\0';
- } //end if
-} //end of the function StripDoubleQuotes
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void StripSingleQuotes(char *string)
-{
- if (*string == '\'')
- {
- strcpy(string, string+1);
- } //end if
- if (string[strlen(string)-1] == '\'')
- {
- string[strlen(string)-1] = '\0';
- } //end if
-} //end of the function StripSingleQuotes
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-long double ReadSignedFloat(script_t *script)
-{
- token_t token;
- long double sign = 1;
-
- PS_ExpectAnyToken(script, &token);
- if (!strcmp(token.string, "-"))
- {
- sign = -1;
- PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
- } //end if
- else if (token.type != TT_NUMBER)
- {
- ScriptError(script, "expected float value, found %s\n", token.string);
- } //end else if
- return sign * token.floatvalue;
-} //end of the function ReadSignedFloat
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-signed long int ReadSignedInt(script_t *script)
-{
- token_t token;
- signed long int sign = 1;
-
- PS_ExpectAnyToken(script, &token);
- if (!strcmp(token.string, "-"))
- {
- sign = -1;
- PS_ExpectTokenType(script, TT_NUMBER, TT_INTEGER, &token);
- } //end if
- else if (token.type != TT_NUMBER || token.subtype == TT_FLOAT)
- {
- ScriptError(script, "expected integer value, found %s\n", token.string);
- } //end else if
- return sign * token.intvalue;
-} //end of the function ReadSignedInt
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void SetScriptFlags(script_t *script, int flags)
-{
- script->flags = flags;
-} //end of the function SetScriptFlags
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int GetScriptFlags(script_t *script)
-{
- return script->flags;
-} //end of the function GetScriptFlags
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void ResetScript(script_t *script)
-{
- //pointer in script buffer
- script->script_p = script->buffer;
- //pointer in script buffer before reading token
- script->lastscript_p = script->buffer;
- //begin of white space
- script->whitespace_p = NULL;
- //end of white space
- script->endwhitespace_p = NULL;
- //set if there's a token available in script->token
- script->tokenavailable = 0;
- //
- script->line = 1;
- script->lastline = 1;
- //clear the saved token
- Com_Memset(&script->token, 0, sizeof(token_t));
-} //end of the function ResetScript
-//============================================================================
-// returns true if at the end of the script
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int EndOfScript(script_t *script)
-{
- return script->script_p >= script->end_p;
-} //end of the function EndOfScript
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int NumLinesCrossed(script_t *script)
-{
- return script->line - script->lastline;
-} //end of the function NumLinesCrossed
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int ScriptSkipTo(script_t *script, char *value)
-{
- int len;
- char firstchar;
-
- firstchar = *value;
- len = strlen(value);
- do
- {
- if (!PS_ReadWhiteSpace(script)) return 0;
- if (*script->script_p == firstchar)
- {
- if (!strncmp(script->script_p, value, len))
- {
- return 1;
- } //end if
- } //end if
- script->script_p++;
- } while(1);
-} //end of the function ScriptSkipTo
-#ifndef BOTLIB
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-int FileLength(FILE *fp)
-{
- int pos;
- int end;
-
- pos = ftell(fp);
- fseek(fp, 0, SEEK_END);
- end = ftell(fp);
- fseek(fp, pos, SEEK_SET);
-
- return end;
-} //end of the function FileLength
-#endif
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-script_t *LoadScriptFile(const char *filename)
-{
-#ifdef BOTLIB
- fileHandle_t fp;
- char pathname[MAX_QPATH];
-#else
- FILE *fp;
-#endif
- int length;
- void *buffer;
- script_t *script;
-
-#ifdef BOTLIB
- if (strlen(basefolder))
- Com_sprintf(pathname, sizeof(pathname), "%s/%s", basefolder, filename);
- else
- Com_sprintf(pathname, sizeof(pathname), "%s", filename);
- length = botimport.FS_FOpenFile( pathname, &fp, FS_READ );
- if (!fp) return NULL;
-#else
- fp = fopen(filename, "rb");
- if (!fp) return NULL;
-
- length = FileLength(fp);
-#endif
-
- buffer = GetClearedMemory(sizeof(script_t) + length + 1);
- script = (script_t *) buffer;
- Com_Memset(script, 0, sizeof(script_t));
- strcpy(script->filename, filename);
- script->buffer = (char *) buffer + sizeof(script_t);
- script->buffer[length] = 0;
- script->length = length;
- //pointer in script buffer
- script->script_p = script->buffer;
- //pointer in script buffer before reading token
- script->lastscript_p = script->buffer;
- //pointer to end of script buffer
- script->end_p = &script->buffer[length];
- //set if there's a token available in script->token
- script->tokenavailable = 0;
- //
- script->line = 1;
- script->lastline = 1;
- //
- SetScriptPunctuations(script, NULL);
- //
-#ifdef BOTLIB
- botimport.FS_Read(script->buffer, length, fp);
- botimport.FS_FCloseFile(fp);
-#else
- if (fread(script->buffer, length, 1, fp) != 1)
- {
- FreeMemory(buffer);
- script = NULL;
- } //end if
- fclose(fp);
-#endif
- //
- script->length = COM_Compress(script->buffer);
-
- return script;
-} //end of the function LoadScriptFile
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-script_t *LoadScriptMemory(char *ptr, int length, char *name)
-{
- void *buffer;
- script_t *script;
-
- buffer = GetClearedMemory(sizeof(script_t) + length + 1);
- script = (script_t *) buffer;
- Com_Memset(script, 0, sizeof(script_t));
- strcpy(script->filename, name);
- script->buffer = (char *) buffer + sizeof(script_t);
- script->buffer[length] = 0;
- script->length = length;
- //pointer in script buffer
- script->script_p = script->buffer;
- //pointer in script buffer before reading token
- script->lastscript_p = script->buffer;
- //pointer to end of script buffer
- script->end_p = &script->buffer[length];
- //set if there's a token available in script->token
- script->tokenavailable = 0;
- //
- script->line = 1;
- script->lastline = 1;
- //
- SetScriptPunctuations(script, NULL);
- //
- Com_Memcpy(script->buffer, ptr, length);
- //
- return script;
-} //end of the function LoadScriptMemory
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void FreeScript(script_t *script)
-{
-#ifdef PUNCTABLE
- if (script->punctuationtable) FreeMemory(script->punctuationtable);
-#endif //PUNCTABLE
- FreeMemory(script);
-} //end of the function FreeScript
-//============================================================================
-//
-// Parameter: -
-// Returns: -
-// Changes Globals: -
-//============================================================================
-void PS_SetBaseFolder(char *path)
-{
-#ifdef BSPC
- sprintf(basefolder, path);
-#else
- Com_sprintf(basefolder, sizeof(basefolder), path);
-#endif
-} //end of the function PS_SetBaseFolder
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +/***************************************************************************** + * name: l_script.c + * + * desc: lexicographical parser + * + * $Archive: /MissionPack/code/botlib/l_script.c $ + * + *****************************************************************************/ + +//#define SCREWUP +//#define BOTLIB +//#define MEQCC +//#define BSPC + +#ifdef SCREWUP +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <stdarg.h> +#include "l_memory.h" +#include "l_script.h" + +typedef enum {qfalse, qtrue} qboolean; + +#endif //SCREWUP + +#ifdef BOTLIB +//include files for usage in the bot library +#include "../game/q_shared.h" +#include "../game/botlib.h" +#include "be_interface.h" +#include "l_script.h" +#include "l_memory.h" +#include "l_log.h" +#include "l_libvar.h" +#endif //BOTLIB + +#ifdef MEQCC +//include files for usage in MrElusive's QuakeC Compiler +#include "qcc.h" +#include "l_script.h" +#include "l_memory.h" +#include "l_log.h" + +#define qtrue true +#define qfalse false +#endif //MEQCC + +#ifdef BSPC +//include files for usage in the BSP Converter +#include "../bspc/qbsp.h" +#include "../bspc/l_log.h" +#include "../bspc/l_mem.h" + +#define qtrue true +#define qfalse false +#endif //BSPC + + +#define PUNCTABLE + +//longer punctuations first +punctuation_t default_punctuations[] = +{ + //binary operators + {">>=",P_RSHIFT_ASSIGN, NULL}, + {"<<=",P_LSHIFT_ASSIGN, NULL}, + // + {"...",P_PARMS, NULL}, + //define merge operator + {"##",P_PRECOMPMERGE, NULL}, + //logic operators + {"&&",P_LOGIC_AND, NULL}, + {"||",P_LOGIC_OR, NULL}, + {">=",P_LOGIC_GEQ, NULL}, + {"<=",P_LOGIC_LEQ, NULL}, + {"==",P_LOGIC_EQ, NULL}, + {"!=",P_LOGIC_UNEQ, NULL}, + //arithmatic operators + {"*=",P_MUL_ASSIGN, NULL}, + {"/=",P_DIV_ASSIGN, NULL}, + {"%=",P_MOD_ASSIGN, NULL}, + {"+=",P_ADD_ASSIGN, NULL}, + {"-=",P_SUB_ASSIGN, NULL}, + {"++",P_INC, NULL}, + {"--",P_DEC, NULL}, + //binary operators + {"&=",P_BIN_AND_ASSIGN, NULL}, + {"|=",P_BIN_OR_ASSIGN, NULL}, + {"^=",P_BIN_XOR_ASSIGN, NULL}, + {">>",P_RSHIFT, NULL}, + {"<<",P_LSHIFT, NULL}, + //reference operators + {"->",P_POINTERREF, NULL}, + //C++ + {"::",P_CPP1, NULL}, + {".*",P_CPP2, NULL}, + //arithmatic operators + {"*",P_MUL, NULL}, + {"/",P_DIV, NULL}, + {"%",P_MOD, NULL}, + {"+",P_ADD, NULL}, + {"-",P_SUB, NULL}, + {"=",P_ASSIGN, NULL}, + //binary operators + {"&",P_BIN_AND, NULL}, + {"|",P_BIN_OR, NULL}, + {"^",P_BIN_XOR, NULL}, + {"~",P_BIN_NOT, NULL}, + //logic operators + {"!",P_LOGIC_NOT, NULL}, + {">",P_LOGIC_GREATER, NULL}, + {"<",P_LOGIC_LESS, NULL}, + //reference operator + {".",P_REF, NULL}, + //seperators + {",",P_COMMA, NULL}, + {";",P_SEMICOLON, NULL}, + //label indication + {":",P_COLON, NULL}, + //if statement + {"?",P_QUESTIONMARK, NULL}, + //embracements + {"(",P_PARENTHESESOPEN, NULL}, + {")",P_PARENTHESESCLOSE, NULL}, + {"{",P_BRACEOPEN, NULL}, + {"}",P_BRACECLOSE, NULL}, + {"[",P_SQBRACKETOPEN, NULL}, + {"]",P_SQBRACKETCLOSE, NULL}, + // + {"\\",P_BACKSLASH, NULL}, + //precompiler operator + {"#",P_PRECOMP, NULL}, +#ifdef DOLLAR + {"$",P_DOLLAR, NULL}, +#endif //DOLLAR + {NULL, 0} +}; + +#ifdef BSPC +char basefolder[MAX_PATH]; +#else +char basefolder[MAX_QPATH]; +#endif + +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void PS_CreatePunctuationTable(script_t *script, punctuation_t *punctuations) +{ + int i; + punctuation_t *p, *lastp, *newp; + + //get memory for the table + if (!script->punctuationtable) script->punctuationtable = (punctuation_t **) + GetMemory(256 * sizeof(punctuation_t *)); + Com_Memset(script->punctuationtable, 0, 256 * sizeof(punctuation_t *)); + //add the punctuations in the list to the punctuation table + for (i = 0; punctuations[i].p; i++) + { + newp = &punctuations[i]; + lastp = NULL; + //sort the punctuations in this table entry on length (longer punctuations first) + for (p = script->punctuationtable[(unsigned int) newp->p[0]]; p; p = p->next) + { + if (strlen(p->p) < strlen(newp->p)) + { + newp->next = p; + if (lastp) lastp->next = newp; + else script->punctuationtable[(unsigned int) newp->p[0]] = newp; + break; + } //end if + lastp = p; + } //end for + if (!p) + { + newp->next = NULL; + if (lastp) lastp->next = newp; + else script->punctuationtable[(unsigned int) newp->p[0]] = newp; + } //end if + } //end for +} //end of the function PS_CreatePunctuationTable +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +char *PunctuationFromNum(script_t *script, int num) +{ + int i; + + for (i = 0; script->punctuations[i].p; i++) + { + if (script->punctuations[i].n == num) return script->punctuations[i].p; + } //end for + return "unkown punctuation"; +} //end of the function PunctuationFromNum +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void QDECL ScriptError(script_t *script, char *str, ...) +{ + char text[1024]; + va_list ap; + + if (script->flags & SCFL_NOERRORS) return; + + va_start(ap, str); + vsprintf(text, str, ap); + va_end(ap); +#ifdef BOTLIB + botimport.Print(PRT_ERROR, "file %s, line %d: %s\n", script->filename, script->line, text); +#endif //BOTLIB +#ifdef MEQCC + printf("error: file %s, line %d: %s\n", script->filename, script->line, text); +#endif //MEQCC +#ifdef BSPC + Log_Print("error: file %s, line %d: %s\n", script->filename, script->line, text); +#endif //BSPC +} //end of the function ScriptError +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void QDECL ScriptWarning(script_t *script, char *str, ...) +{ + char text[1024]; + va_list ap; + + if (script->flags & SCFL_NOWARNINGS) return; + + va_start(ap, str); + vsprintf(text, str, ap); + va_end(ap); +#ifdef BOTLIB + botimport.Print(PRT_WARNING, "file %s, line %d: %s\n", script->filename, script->line, text); +#endif //BOTLIB +#ifdef MEQCC + printf("warning: file %s, line %d: %s\n", script->filename, script->line, text); +#endif //MEQCC +#ifdef BSPC + Log_Print("warning: file %s, line %d: %s\n", script->filename, script->line, text); +#endif //BSPC +} //end of the function ScriptWarning +//=========================================================================== +// +// Parameter: - +// Returns: - +// Changes Globals: - +//=========================================================================== +void SetScriptPunctuations(script_t *script, punctuation_t *p) +{ +#ifdef PUNCTABLE + if (p) PS_CreatePunctuationTable(script, p); + else PS_CreatePunctuationTable(script, default_punctuations); +#endif //PUNCTABLE + if (p) script->punctuations = p; + else script->punctuations = default_punctuations; +} //end of the function SetScriptPunctuations +//============================================================================ +// Reads spaces, tabs, C-like comments etc. +// When a newline character is found the scripts line counter is increased. +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadWhiteSpace(script_t *script) +{ + while(1) + { + //skip white space + while(*script->script_p <= ' ') + { + if (!*script->script_p) return 0; + if (*script->script_p == '\n') script->line++; + script->script_p++; + } //end while + //skip comments + if (*script->script_p == '/') + { + //comments // + if (*(script->script_p+1) == '/') + { + script->script_p++; + do + { + script->script_p++; + if (!*script->script_p) return 0; + } //end do + while(*script->script_p != '\n'); + script->line++; + script->script_p++; + if (!*script->script_p) return 0; + continue; + } //end if + //comments /* */ + else if (*(script->script_p+1) == '*') + { + script->script_p++; + do + { + script->script_p++; + if (!*script->script_p) return 0; + if (*script->script_p == '\n') script->line++; + } //end do + while(!(*script->script_p == '*' && *(script->script_p+1) == '/')); + script->script_p++; + if (!*script->script_p) return 0; + script->script_p++; + if (!*script->script_p) return 0; + continue; + } //end if + } //end if + break; + } //end while + return 1; +} //end of the function PS_ReadWhiteSpace +//============================================================================ +// Reads an escape character. +// +// Parameter: script : script to read from +// ch : place to store the read escape character +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadEscapeCharacter(script_t *script, char *ch) +{ + int c, val, i; + + //step over the leading '\\' + script->script_p++; + //determine the escape character + switch(*script->script_p) + { + case '\\': c = '\\'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'a': c = '\a'; break; + case '\'': c = '\''; break; + case '\"': c = '\"'; break; + case '\?': c = '\?'; break; + case 'x': + { + script->script_p++; + for (i = 0, val = 0; ; i++, script->script_p++) + { + c = *script->script_p; + if (c >= '0' && c <= '9') c = c - '0'; + else if (c >= 'A' && c <= 'Z') c = c - 'A' + 10; + else if (c >= 'a' && c <= 'z') c = c - 'a' + 10; + else break; + val = (val << 4) + c; + } //end for + script->script_p--; + if (val > 0xFF) + { + ScriptWarning(script, "too large value in escape character"); + val = 0xFF; + } //end if + c = val; + break; + } //end case + default: //NOTE: decimal ASCII code, NOT octal + { + if (*script->script_p < '0' || *script->script_p > '9') ScriptError(script, "unknown escape char"); + for (i = 0, val = 0; ; i++, script->script_p++) + { + c = *script->script_p; + if (c >= '0' && c <= '9') c = c - '0'; + else break; + val = val * 10 + c; + } //end for + script->script_p--; + if (val > 0xFF) + { + ScriptWarning(script, "too large value in escape character"); + val = 0xFF; + } //end if + c = val; + break; + } //end default + } //end switch + //step over the escape character or the last digit of the number + script->script_p++; + //store the escape character + *ch = c; + //succesfully read escape character + return 1; +} //end of the function PS_ReadEscapeCharacter +//============================================================================ +// Reads C-like string. Escape characters are interpretted. +// Quotes are included with the string. +// Reads two strings with a white space between them as one string. +// +// Parameter: script : script to read from +// token : buffer to store the string +// Returns: qtrue when a string was read succesfully +// Changes Globals: - +//============================================================================ +int PS_ReadString(script_t *script, token_t *token, int quote) +{ + int len, tmpline; + char *tmpscript_p; + + if (quote == '\"') token->type = TT_STRING; + else token->type = TT_LITERAL; + + len = 0; + //leading quote + token->string[len++] = *script->script_p++; + // + while(1) + { + //minus 2 because trailing double quote and zero have to be appended + if (len >= MAX_TOKEN - 2) + { + ScriptError(script, "string longer than MAX_TOKEN = %d", MAX_TOKEN); + return 0; + } //end if + //if there is an escape character and + //if escape characters inside a string are allowed + if (*script->script_p == '\\' && !(script->flags & SCFL_NOSTRINGESCAPECHARS)) + { + if (!PS_ReadEscapeCharacter(script, &token->string[len])) + { + token->string[len] = 0; + return 0; + } //end if + len++; + } //end if + //if a trailing quote + else if (*script->script_p == quote) + { + //step over the double quote + script->script_p++; + //if white spaces in a string are not allowed + if (script->flags & SCFL_NOSTRINGWHITESPACES) break; + // + tmpscript_p = script->script_p; + tmpline = script->line; + //read unusefull stuff between possible two following strings + if (!PS_ReadWhiteSpace(script)) + { + script->script_p = tmpscript_p; + script->line = tmpline; + break; + } //end if + //if there's no leading double qoute + if (*script->script_p != quote) + { + script->script_p = tmpscript_p; + script->line = tmpline; + break; + } //end if + //step over the new leading double quote + script->script_p++; + } //end if + else + { + if (*script->script_p == '\0') + { + token->string[len] = 0; + ScriptError(script, "missing trailing quote"); + return 0; + } //end if + if (*script->script_p == '\n') + { + token->string[len] = 0; + ScriptError(script, "newline inside string %s", token->string); + return 0; + } //end if + token->string[len++] = *script->script_p++; + } //end else + } //end while + //trailing quote + token->string[len++] = quote; + //end string with a zero + token->string[len] = '\0'; + //the sub type is the length of the string + token->subtype = len; + return 1; +} //end of the function PS_ReadString +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadName(script_t *script, token_t *token) +{ + int len = 0; + char c; + + token->type = TT_NAME; + do + { + token->string[len++] = *script->script_p++; + if (len >= MAX_TOKEN) + { + ScriptError(script, "name longer than MAX_TOKEN = %d", MAX_TOKEN); + return 0; + } //end if + c = *script->script_p; + } while ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '_'); + token->string[len] = '\0'; + //the sub type is the length of the name + token->subtype = len; + return 1; +} //end of the function PS_ReadName +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void NumberValue(char *string, int subtype, unsigned long int *intvalue, + long double *floatvalue) +{ + unsigned long int dotfound = 0; + + *intvalue = 0; + *floatvalue = 0; + //floating point number + if (subtype & TT_FLOAT) + { + while(*string) + { + if (*string == '.') + { + if (dotfound) return; + dotfound = 10; + string++; + } //end if + if (dotfound) + { + *floatvalue = *floatvalue + (long double) (*string - '0') / + (long double) dotfound; + dotfound *= 10; + } //end if + else + { + *floatvalue = *floatvalue * 10.0 + (long double) (*string - '0'); + } //end else + string++; + } //end while + *intvalue = (unsigned long) *floatvalue; + } //end if + else if (subtype & TT_DECIMAL) + { + while(*string) *intvalue = *intvalue * 10 + (*string++ - '0'); + *floatvalue = *intvalue; + } //end else if + else if (subtype & TT_HEX) + { + //step over the leading 0x or 0X + string += 2; + while(*string) + { + *intvalue <<= 4; + if (*string >= 'a' && *string <= 'f') *intvalue += *string - 'a' + 10; + else if (*string >= 'A' && *string <= 'F') *intvalue += *string - 'A' + 10; + else *intvalue += *string - '0'; + string++; + } //end while + *floatvalue = *intvalue; + } //end else if + else if (subtype & TT_OCTAL) + { + //step over the first zero + string += 1; + while(*string) *intvalue = (*intvalue << 3) + (*string++ - '0'); + *floatvalue = *intvalue; + } //end else if + else if (subtype & TT_BINARY) + { + //step over the leading 0b or 0B + string += 2; + while(*string) *intvalue = (*intvalue << 1) + (*string++ - '0'); + *floatvalue = *intvalue; + } //end else if +} //end of the function NumberValue +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadNumber(script_t *script, token_t *token) +{ + int len = 0, i; + int octal, dot; + char c; +// unsigned long int intvalue = 0; +// long double floatvalue = 0; + + token->type = TT_NUMBER; + //check for a hexadecimal number + if (*script->script_p == '0' && + (*(script->script_p + 1) == 'x' || + *(script->script_p + 1) == 'X')) + { + token->string[len++] = *script->script_p++; + token->string[len++] = *script->script_p++; + c = *script->script_p; + //hexadecimal + while((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'A')) + { + token->string[len++] = *script->script_p++; + if (len >= MAX_TOKEN) + { + ScriptError(script, "hexadecimal number longer than MAX_TOKEN = %d", MAX_TOKEN); + return 0; + } //end if + c = *script->script_p; + } //end while + token->subtype |= TT_HEX; + } //end if +#ifdef BINARYNUMBERS + //check for a binary number + else if (*script->script_p == '0' && + (*(script->script_p + 1) == 'b' || + *(script->script_p + 1) == 'B')) + { + token->string[len++] = *script->script_p++; + token->string[len++] = *script->script_p++; + c = *script->script_p; + //binary + while(c == '0' || c == '1') + { + token->string[len++] = *script->script_p++; + if (len >= MAX_TOKEN) + { + ScriptError(script, "binary number longer than MAX_TOKEN = %d", MAX_TOKEN); + return 0; + } //end if + c = *script->script_p; + } //end while + token->subtype |= TT_BINARY; + } //end if +#endif //BINARYNUMBERS + else //decimal or octal integer or floating point number + { + octal = qfalse; + dot = qfalse; + if (*script->script_p == '0') octal = qtrue; + while(1) + { + c = *script->script_p; + if (c == '.') dot = qtrue; + else if (c == '8' || c == '9') octal = qfalse; + else if (c < '0' || c > '9') break; + token->string[len++] = *script->script_p++; + if (len >= MAX_TOKEN - 1) + { + ScriptError(script, "number longer than MAX_TOKEN = %d", MAX_TOKEN); + return 0; + } //end if + } //end while + if (octal) token->subtype |= TT_OCTAL; + else token->subtype |= TT_DECIMAL; + if (dot) token->subtype |= TT_FLOAT; + } //end else + for (i = 0; i < 2; i++) + { + c = *script->script_p; + //check for a LONG number + if ( (c == 'l' || c == 'L') // bk001204 - brackets + && !(token->subtype & TT_LONG)) + { + script->script_p++; + token->subtype |= TT_LONG; + } //end if + //check for an UNSIGNED number + else if ( (c == 'u' || c == 'U') // bk001204 - brackets + && !(token->subtype & (TT_UNSIGNED | TT_FLOAT))) + { + script->script_p++; + token->subtype |= TT_UNSIGNED; + } //end if + } //end for + token->string[len] = '\0'; +#ifdef NUMBERVALUE + NumberValue(token->string, token->subtype, &token->intvalue, &token->floatvalue); +#endif //NUMBERVALUE + if (!(token->subtype & TT_FLOAT)) token->subtype |= TT_INTEGER; + return 1; +} //end of the function PS_ReadNumber +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadLiteral(script_t *script, token_t *token) +{ + token->type = TT_LITERAL; + //first quote + token->string[0] = *script->script_p++; + //check for end of file + if (!*script->script_p) + { + ScriptError(script, "end of file before trailing \'"); + return 0; + } //end if + //if it is an escape character + if (*script->script_p == '\\') + { + if (!PS_ReadEscapeCharacter(script, &token->string[1])) return 0; + } //end if + else + { + token->string[1] = *script->script_p++; + } //end else + //check for trailing quote + if (*script->script_p != '\'') + { + ScriptWarning(script, "too many characters in literal, ignored"); + while(*script->script_p && + *script->script_p != '\'' && + *script->script_p != '\n') + { + script->script_p++; + } //end while + if (*script->script_p == '\'') script->script_p++; + } //end if + //store the trailing quote + token->string[2] = *script->script_p++; + //store trailing zero to end the string + token->string[3] = '\0'; + //the sub type is the integer literal value + token->subtype = token->string[1]; + // + return 1; +} //end of the function PS_ReadLiteral +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadPunctuation(script_t *script, token_t *token) +{ + int len; + char *p; + punctuation_t *punc; + +#ifdef PUNCTABLE + for (punc = script->punctuationtable[(unsigned int)*script->script_p]; punc; punc = punc->next) + { +#else + int i; + + for (i = 0; script->punctuations[i].p; i++) + { + punc = &script->punctuations[i]; +#endif //PUNCTABLE + p = punc->p; + len = strlen(p); + //if the script contains at least as much characters as the punctuation + if (script->script_p + len <= script->end_p) + { + //if the script contains the punctuation + if (!strncmp(script->script_p, p, len)) + { + strncpy(token->string, p, MAX_TOKEN); + script->script_p += len; + token->type = TT_PUNCTUATION; + //sub type is the number of the punctuation + token->subtype = punc->n; + return 1; + } //end if + } //end if + } //end for + return 0; +} //end of the function PS_ReadPunctuation +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadPrimitive(script_t *script, token_t *token) +{ + int len; + + len = 0; + while(*script->script_p > ' ' && *script->script_p != ';') + { + if (len >= MAX_TOKEN) + { + ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN); + return 0; + } //end if + token->string[len++] = *script->script_p++; + } //end while + token->string[len] = 0; + //copy the token into the script structure + Com_Memcpy(&script->token, token, sizeof(token_t)); + //primitive reading successfull + return 1; +} //end of the function PS_ReadPrimitive +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ReadToken(script_t *script, token_t *token) +{ + //if there is a token available (from UnreadToken) + if (script->tokenavailable) + { + script->tokenavailable = 0; + Com_Memcpy(token, &script->token, sizeof(token_t)); + return 1; + } //end if + //save script pointer + script->lastscript_p = script->script_p; + //save line counter + script->lastline = script->line; + //clear the token stuff + Com_Memset(token, 0, sizeof(token_t)); + //start of the white space + script->whitespace_p = script->script_p; + token->whitespace_p = script->script_p; + //read unusefull stuff + if (!PS_ReadWhiteSpace(script)) return 0; + //end of the white space + script->endwhitespace_p = script->script_p; + token->endwhitespace_p = script->script_p; + //line the token is on + token->line = script->line; + //number of lines crossed before token + token->linescrossed = script->line - script->lastline; + //if there is a leading double quote + if (*script->script_p == '\"') + { + if (!PS_ReadString(script, token, '\"')) return 0; + } //end if + //if an literal + else if (*script->script_p == '\'') + { + //if (!PS_ReadLiteral(script, token)) return 0; + if (!PS_ReadString(script, token, '\'')) return 0; + } //end if + //if there is a number + else if ((*script->script_p >= '0' && *script->script_p <= '9') || + (*script->script_p == '.' && + (*(script->script_p + 1) >= '0' && *(script->script_p + 1) <= '9'))) + { + if (!PS_ReadNumber(script, token)) return 0; + } //end if + //if this is a primitive script + else if (script->flags & SCFL_PRIMITIVE) + { + return PS_ReadPrimitive(script, token); + } //end else if + //if there is a name + else if ((*script->script_p >= 'a' && *script->script_p <= 'z') || + (*script->script_p >= 'A' && *script->script_p <= 'Z') || + *script->script_p == '_') + { + if (!PS_ReadName(script, token)) return 0; + } //end if + //check for punctuations + else if (!PS_ReadPunctuation(script, token)) + { + ScriptError(script, "can't read token"); + return 0; + } //end if + //copy the token into the script structure + Com_Memcpy(&script->token, token, sizeof(token_t)); + //succesfully read a token + return 1; +} //end of the function PS_ReadToken +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ExpectTokenString(script_t *script, char *string) +{ + token_t token; + + if (!PS_ReadToken(script, &token)) + { + ScriptError(script, "couldn't find expected %s", string); + return 0; + } //end if + + if (strcmp(token.string, string)) + { + ScriptError(script, "expected %s, found %s", string, token.string); + return 0; + } //end if + return 1; +} //end of the function PS_ExpectToken +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token) +{ + char str[MAX_TOKEN]; + + if (!PS_ReadToken(script, token)) + { + ScriptError(script, "couldn't read expected token"); + return 0; + } //end if + + if (token->type != type) + { + if (type == TT_STRING) strcpy(str, "string"); + if (type == TT_LITERAL) strcpy(str, "literal"); + if (type == TT_NUMBER) strcpy(str, "number"); + if (type == TT_NAME) strcpy(str, "name"); + if (type == TT_PUNCTUATION) strcpy(str, "punctuation"); + ScriptError(script, "expected a %s, found %s", str, token->string); + return 0; + } //end if + if (token->type == TT_NUMBER) + { + if ((token->subtype & subtype) != subtype) + { + if (subtype & TT_DECIMAL) strcpy(str, "decimal"); + if (subtype & TT_HEX) strcpy(str, "hex"); + if (subtype & TT_OCTAL) strcpy(str, "octal"); + if (subtype & TT_BINARY) strcpy(str, "binary"); + if (subtype & TT_LONG) strcat(str, " long"); + if (subtype & TT_UNSIGNED) strcat(str, " unsigned"); + if (subtype & TT_FLOAT) strcat(str, " float"); + if (subtype & TT_INTEGER) strcat(str, " integer"); + ScriptError(script, "expected %s, found %s", str, token->string); + return 0; + } //end if + } //end if + else if (token->type == TT_PUNCTUATION) + { + if (subtype < 0) + { + ScriptError(script, "BUG: wrong punctuation subtype"); + return 0; + } //end if + if (token->subtype != subtype) + { + ScriptError(script, "expected %s, found %s", + script->punctuations[subtype], token->string); + return 0; + } //end if + } //end else if + return 1; +} //end of the function PS_ExpectTokenType +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_ExpectAnyToken(script_t *script, token_t *token) +{ + if (!PS_ReadToken(script, token)) + { + ScriptError(script, "couldn't read expected token"); + return 0; + } //end if + else + { + return 1; + } //end else +} //end of the function PS_ExpectAnyToken +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_CheckTokenString(script_t *script, char *string) +{ + token_t tok; + + if (!PS_ReadToken(script, &tok)) return 0; + //if the token is available + if (!strcmp(tok.string, string)) return 1; + //token not available + script->script_p = script->lastscript_p; + return 0; +} //end of the function PS_CheckTokenString +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_CheckTokenType(script_t *script, int type, int subtype, token_t *token) +{ + token_t tok; + + if (!PS_ReadToken(script, &tok)) return 0; + //if the type matches + if (tok.type == type && + (tok.subtype & subtype) == subtype) + { + Com_Memcpy(token, &tok, sizeof(token_t)); + return 1; + } //end if + //token is not available + script->script_p = script->lastscript_p; + return 0; +} //end of the function PS_CheckTokenType +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int PS_SkipUntilString(script_t *script, char *string) +{ + token_t token; + + while(PS_ReadToken(script, &token)) + { + if (!strcmp(token.string, string)) return 1; + } //end while + return 0; +} //end of the function PS_SkipUntilString +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void PS_UnreadLastToken(script_t *script) +{ + script->tokenavailable = 1; +} //end of the function UnreadLastToken +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void PS_UnreadToken(script_t *script, token_t *token) +{ + Com_Memcpy(&script->token, token, sizeof(token_t)); + script->tokenavailable = 1; +} //end of the function UnreadToken +//============================================================================ +// returns the next character of the read white space, returns NULL if none +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +char PS_NextWhiteSpaceChar(script_t *script) +{ + if (script->whitespace_p != script->endwhitespace_p) + { + return *script->whitespace_p++; + } //end if + else + { + return 0; + } //end else +} //end of the function PS_NextWhiteSpaceChar +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void StripDoubleQuotes(char *string) +{ + if (*string == '\"') + { + strcpy(string, string+1); + } //end if + if (string[strlen(string)-1] == '\"') + { + string[strlen(string)-1] = '\0'; + } //end if +} //end of the function StripDoubleQuotes +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void StripSingleQuotes(char *string) +{ + if (*string == '\'') + { + strcpy(string, string+1); + } //end if + if (string[strlen(string)-1] == '\'') + { + string[strlen(string)-1] = '\0'; + } //end if +} //end of the function StripSingleQuotes +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +long double ReadSignedFloat(script_t *script) +{ + token_t token; + long double sign = 1; + + PS_ExpectAnyToken(script, &token); + if (!strcmp(token.string, "-")) + { + sign = -1; + PS_ExpectTokenType(script, TT_NUMBER, 0, &token); + } //end if + else if (token.type != TT_NUMBER) + { + ScriptError(script, "expected float value, found %s\n", token.string); + } //end else if + return sign * token.floatvalue; +} //end of the function ReadSignedFloat +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +signed long int ReadSignedInt(script_t *script) +{ + token_t token; + signed long int sign = 1; + + PS_ExpectAnyToken(script, &token); + if (!strcmp(token.string, "-")) + { + sign = -1; + PS_ExpectTokenType(script, TT_NUMBER, TT_INTEGER, &token); + } //end if + else if (token.type != TT_NUMBER || token.subtype == TT_FLOAT) + { + ScriptError(script, "expected integer value, found %s\n", token.string); + } //end else if + return sign * token.intvalue; +} //end of the function ReadSignedInt +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void SetScriptFlags(script_t *script, int flags) +{ + script->flags = flags; +} //end of the function SetScriptFlags +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int GetScriptFlags(script_t *script) +{ + return script->flags; +} //end of the function GetScriptFlags +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void ResetScript(script_t *script) +{ + //pointer in script buffer + script->script_p = script->buffer; + //pointer in script buffer before reading token + script->lastscript_p = script->buffer; + //begin of white space + script->whitespace_p = NULL; + //end of white space + script->endwhitespace_p = NULL; + //set if there's a token available in script->token + script->tokenavailable = 0; + // + script->line = 1; + script->lastline = 1; + //clear the saved token + Com_Memset(&script->token, 0, sizeof(token_t)); +} //end of the function ResetScript +//============================================================================ +// returns true if at the end of the script +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int EndOfScript(script_t *script) +{ + return script->script_p >= script->end_p; +} //end of the function EndOfScript +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int NumLinesCrossed(script_t *script) +{ + return script->line - script->lastline; +} //end of the function NumLinesCrossed +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int ScriptSkipTo(script_t *script, char *value) +{ + int len; + char firstchar; + + firstchar = *value; + len = strlen(value); + do + { + if (!PS_ReadWhiteSpace(script)) return 0; + if (*script->script_p == firstchar) + { + if (!strncmp(script->script_p, value, len)) + { + return 1; + } //end if + } //end if + script->script_p++; + } while(1); +} //end of the function ScriptSkipTo +#ifndef BOTLIB +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +int FileLength(FILE *fp) +{ + int pos; + int end; + + pos = ftell(fp); + fseek(fp, 0, SEEK_END); + end = ftell(fp); + fseek(fp, pos, SEEK_SET); + + return end; +} //end of the function FileLength +#endif +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +script_t *LoadScriptFile(const char *filename) +{ +#ifdef BOTLIB + fileHandle_t fp; + char pathname[MAX_QPATH]; +#else + FILE *fp; +#endif + int length; + void *buffer; + script_t *script; + +#ifdef BOTLIB + if (strlen(basefolder)) + Com_sprintf(pathname, sizeof(pathname), "%s/%s", basefolder, filename); + else + Com_sprintf(pathname, sizeof(pathname), "%s", filename); + length = botimport.FS_FOpenFile( pathname, &fp, FS_READ ); + if (!fp) return NULL; +#else + fp = fopen(filename, "rb"); + if (!fp) return NULL; + + length = FileLength(fp); +#endif + + buffer = GetClearedMemory(sizeof(script_t) + length + 1); + script = (script_t *) buffer; + Com_Memset(script, 0, sizeof(script_t)); + strcpy(script->filename, filename); + script->buffer = (char *) buffer + sizeof(script_t); + script->buffer[length] = 0; + script->length = length; + //pointer in script buffer + script->script_p = script->buffer; + //pointer in script buffer before reading token + script->lastscript_p = script->buffer; + //pointer to end of script buffer + script->end_p = &script->buffer[length]; + //set if there's a token available in script->token + script->tokenavailable = 0; + // + script->line = 1; + script->lastline = 1; + // + SetScriptPunctuations(script, NULL); + // +#ifdef BOTLIB + botimport.FS_Read(script->buffer, length, fp); + botimport.FS_FCloseFile(fp); +#else + if (fread(script->buffer, length, 1, fp) != 1) + { + FreeMemory(buffer); + script = NULL; + } //end if + fclose(fp); +#endif + // + script->length = COM_Compress(script->buffer); + + return script; +} //end of the function LoadScriptFile +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +script_t *LoadScriptMemory(char *ptr, int length, char *name) +{ + void *buffer; + script_t *script; + + buffer = GetClearedMemory(sizeof(script_t) + length + 1); + script = (script_t *) buffer; + Com_Memset(script, 0, sizeof(script_t)); + strcpy(script->filename, name); + script->buffer = (char *) buffer + sizeof(script_t); + script->buffer[length] = 0; + script->length = length; + //pointer in script buffer + script->script_p = script->buffer; + //pointer in script buffer before reading token + script->lastscript_p = script->buffer; + //pointer to end of script buffer + script->end_p = &script->buffer[length]; + //set if there's a token available in script->token + script->tokenavailable = 0; + // + script->line = 1; + script->lastline = 1; + // + SetScriptPunctuations(script, NULL); + // + Com_Memcpy(script->buffer, ptr, length); + // + return script; +} //end of the function LoadScriptMemory +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void FreeScript(script_t *script) +{ +#ifdef PUNCTABLE + if (script->punctuationtable) FreeMemory(script->punctuationtable); +#endif //PUNCTABLE + FreeMemory(script); +} //end of the function FreeScript +//============================================================================ +// +// Parameter: - +// Returns: - +// Changes Globals: - +//============================================================================ +void PS_SetBaseFolder(char *path) +{ +#ifdef BSPC + sprintf(basefolder, path); +#else + Com_sprintf(basefolder, sizeof(basefolder), path); +#endif +} //end of the function PS_SetBaseFolder |