openmohaa/code/qcommon/script.cpp

1188 lines
22 KiB
C++
Raw Normal View History

2016-03-27 11:49:47 +02:00
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA 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.
OpenMoHAA 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// script.cpp :
// C++ implementaion of tokenizing text interpretation. Class accepts filename
// to load or pointer to preloaded text data. Standard tokenizing operations
// such as skip white-space, get string, get integer, get float, get token,
// and skip line are implemented.
//
// Note: all '//', '#', and ';' are treated as comments. Probably should
// make this behaviour toggleable.
//
#include "script.h"
2023-01-29 20:59:31 +01:00
#if defined(GAME_DLL)
#include "g_local.h"
2023-02-04 19:56:06 +01:00
#define FILE_FS_FreeFile gi.FS_FreeFile
#define FILE_FS_ReadFile(a, b) gi.FS_ReadFile(a, b, true)
#define FILE_Malloc gi.Malloc
#define FILE_Free gi.Free
#define FILE_Error gi.Error
2023-01-29 20:59:31 +01:00
#elif defined(CGAME_DLL)
2023-02-04 19:56:06 +01:00
#define FILE_FS_FreeFile cgi.FS_FreeFile
#define FILE_FS_ReadFile(a, b) cgi.FS_ReadFile(a, b, true)
#define FILE_Malloc cgi.Malloc
#define FILE_Free cgi.Free
#define FILE_Error cgi.Error
2023-01-29 20:59:31 +01:00
#else
#include "qcommon.h"
2023-02-04 19:56:06 +01:00
#define FILE_FS_FreeFile FS_FreeFile
#define FILE_FS_ReadFile(a, b) FS_ReadFile(a, b)
#define FILE_Malloc Z_Malloc
#define FILE_Free Z_Free
#define FILE_Error Com_Error
2023-01-29 20:59:31 +01:00
#endif
2016-03-27 11:49:47 +02:00
typedef unsigned char byte;
2023-02-04 19:56:06 +01:00
CLASS_DECLARATION(Class, Script, NULL){
{NULL, NULL}
2016-03-27 11:49:47 +02:00
};
2023-02-04 19:56:06 +01:00
Script::~Script() { Close(); }
2016-03-27 11:49:47 +02:00
Script::Script(const char* filename /*= 0*/)
{
2023-02-04 19:56:06 +01:00
buffer = NULL;
script_p = NULL;
end_p = NULL;
line = 0;
length = 0;
releaseBuffer = false;
tokenready = false;
token[0] = 0;
if (filename != 0) {
LoadFile(filename);
}
2016-03-27 11:49:47 +02:00
}
Script::Script()
{
2023-02-04 19:56:06 +01:00
buffer = NULL;
script_p = NULL;
end_p = NULL;
line = 0;
length = 0;
releaseBuffer = false;
tokenready = false;
token[0] = 0;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
void Script::Close(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (releaseBuffer && buffer) {
FILE_Free((void*)buffer);
}
buffer = NULL;
script_p = NULL;
end_p = NULL;
line = 0;
releaseBuffer = false;
tokenready = false;
token[0] = 0;
// Loop Through the macro container and delete (del33t -hehe) them all
for (int i = 1; i <= macrolist.NumObjects(); i++) {
if (macrolist.ObjectAt(i)) {
delete macrolist.ObjectAt(i);
macrolist.ObjectAt(i) = 0;
}
}
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= Filename
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::Filename(void) { return filename.c_str(); }
2016-03-27 11:49:47 +02:00
/*
==============
=
= GetLineNumber
=
==============
*/
2023-02-04 19:56:06 +01:00
int Script::GetLineNumber(void) { return line; }
2016-03-27 11:49:47 +02:00
/*
==============
=
= Reset
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::Reset(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
script_p = buffer;
line = 1;
tokenready = false;
hasError = false;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= MarkPosition
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::MarkPosition(scriptmarker_t* mark)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
assert(mark);
mark->tokenready = tokenready;
mark->offset = script_p - buffer;
mark->line = line;
strcpy(mark->token, token);
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= RestorePosition
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::RestorePosition(const scriptmarker_t* mark)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
assert(mark);
tokenready = mark->tokenready;
script_p = buffer + mark->offset;
line = mark->line;
strcpy(token, mark->token);
assert(script_p <= end_p);
if (script_p > end_p) {
script_p = end_p;
}
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= SkipToEOL
=
==============
*/
2023-02-04 19:56:06 +01:00
qboolean Script::SkipToEOL(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (script_p >= end_p) {
return true;
}
while (*script_p != TOKENEOL) {
if (script_p >= end_p) {
return true;
}
script_p++;
}
return false;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= CheckOverflow
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::CheckOverflow(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (script_p >= end_p) {
FILE_Error(ERR_DROP,
"End of token file reached prematurely reading %s\n",
filename.c_str());
}
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= SkipWhiteSpace
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::SkipWhiteSpace(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
CheckOverflow();
while (*script_p <= TOKENSPACE) {
if (*script_p++ == TOKENEOL) {
if (!crossline) {
FILE_Error(ERR_DROP, "Line %i is incomplete in file %s\n", line,
filename.c_str());
}
line++;
}
CheckOverflow();
}
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::AtComment(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (script_p >= end_p) {
return false;
}
if (*script_p == TOKENCOMMENT) {
return true;
}
if (*script_p == TOKENCOMMENT2) {
return true;
}
// Two or more character comment specifiers
if ((script_p + 1) >= end_p) {
return false;
}
if ((*script_p == '/') && (*(script_p + 1) == '/')) {
return true;
}
return false;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= SkipNonToken
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::SkipNonToken(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space and comments
//
SkipWhiteSpace(crossline);
while (AtComment()) {
SkipToEOL();
SkipWhiteSpace(crossline);
}
2016-03-27 11:49:47 +02:00
}
/*
=============================================================================
=
= Token section
=
=============================================================================
*/
/*
==============
=
= TokenAvailable
=
==============
*/
2023-02-04 19:56:06 +01:00
qboolean Script::TokenAvailable(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (script_p >= end_p) {
return false;
}
while (1) {
while (*script_p <= TOKENSPACE) {
if (*script_p == TOKENEOL) {
if (!crossline) {
return (false);
}
line++;
}
script_p++;
if (script_p >= end_p) {
return false;
}
}
if (AtComment()) {
qboolean done;
done = SkipToEOL();
if (done) {
return false;
}
} else {
break;
}
}
return true;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= CommentAvailable
=
==============
*/
2023-02-04 19:56:06 +01:00
qboolean Script::CommentAvailable(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
const char* searchptr;
searchptr = script_p;
if (searchptr >= end_p) {
return false;
}
while (*searchptr <= TOKENSPACE) {
if ((*searchptr == TOKENEOL) && (!crossline)) {
return false;
}
searchptr++;
if (searchptr >= end_p) {
return false;
}
}
return true;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= UnGet
=
= Signals that the current token was not used, and should be reported
= for the next GetToken. Note that
GetToken (true);
UnGetToken ();
GetToken (false);
= could cross a line boundary.
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::UnGetToken(void) { tokenready = true; }
2016-03-27 11:49:47 +02:00
/*
==============
=
= Get
=
==============
*/
2023-02-04 19:56:06 +01:00
qboolean Script::AtString(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
SkipNonToken(crossline);
return (*script_p == '"');
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::AtOpenParen(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
SkipNonToken(crossline);
return (*script_p == '(');
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::AtCloseParen(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
SkipNonToken(crossline);
return (*script_p == ')');
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::AtComma(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
SkipNonToken(crossline);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return (*script_p == ',');
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::AtDot(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
SkipNonToken(crossline);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
return (*script_p == '.');
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::AtAssignment(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
//
// skip space
//
SkipNonToken(crossline);
return (*script_p == '=') ||
((*script_p == '+') && (*(script_p + 1) == '=')) ||
((*script_p == '-') && (*(script_p + 1) == '=')) ||
((*script_p == '*') && (*(script_p + 1) == '=')) ||
((*script_p == '/') && (*(script_p + 1) == '='));
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= Get
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::GetToken(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
str token_p = token;
qboolean is_Macro = false;
// is a token already waiting?
if (tokenready) {
tokenready = false;
return token;
}
is_Macro = isMacro();
token_p = GrabNextToken(crossline);
if (is_Macro && (token_p != "$include")) {
// Check to see if we need to add any definitions
while ((token_p == "$define") || (token_p == "$Define")) {
AddMacroDefinition(crossline);
is_Macro = isMacro();
// if ( !is_Macro )
// return "";
token_p = GrabNextToken(crossline);
}
// Check to see if we need return any defines strings
if (is_Macro && (token_p != "$include") &&
(token_p[token_p.length() - 1] == '$')) {
return GetMacroString(token_p);
}
}
return token;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GrabNextToken
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::GrabNextToken(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
char* token_p;
//
// skip space
//
SkipNonToken(crossline);
//
// copy token
//
if (*script_p == '"') {
return GetString(crossline);
}
token_p = token;
while ((*script_p > TOKENSPACE) && !AtComment()) {
if ((*script_p == '\\') && (script_p < (end_p - 1))) {
script_p++;
switch (*script_p) {
case 'n':
*token_p++ = '\n';
break;
case 'r':
*token_p++ = '\n';
break;
case '\'':
*token_p++ = '\'';
break;
case '\"':
*token_p++ = '\"';
break;
case '\\':
*token_p++ = '\\';
break;
default:
*token_p++ = *script_p;
break;
}
script_p++;
} else {
*token_p++ = *script_p++;
}
if (token_p == &token[MAXTOKEN]) {
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n",
line, filename.c_str());
}
if (script_p == end_p) {
break;
}
}
*token_p = 0;
return token;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= AddMacroDefinition
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::AddMacroDefinition(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
macro* theMacro;
// Create a new macro structure. This new macro will be deleted in the
// script close()
theMacro = new macro;
// Grab the macro name
theMacro->macroName = "$";
theMacro->macroName.append(GrabNextToken(crossline));
theMacro->macroName.append(
"$"); //<-- Adding closing ($) to keep formatting consistant
// Grab the macro string
str tmpstr;
tmpstr = GrabNextToken(crossline);
// Check to see if we need return any defines strings
if ((tmpstr != "$include") && (tmpstr[tmpstr.length() - 1] == '$')) {
theMacro->macroText = GetMacroString(tmpstr);
} else {
theMacro->macroText = tmpstr;
}
macrolist.AddObject(theMacro);
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetMacroString
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::GetMacroString(const char* theMacroName)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
macro* theMacro = 0; // Initialize this puppy
for (int i = 1; i <= macrolist.NumObjects(); i++) {
theMacro = macrolist.ObjectAt(i);
if (!theMacro->macroName.cmp(theMacro->macroName.c_str(),
theMacroName)) {
const char* text = theMacro->macroText.c_str();
// If our define value is another define...
if (text[0] == '$') {
return EvaluateMacroString(text);
} else {
return text;
}
}
}
char tmpstr[255], *sptr = tmpstr;
strcpy(tmpstr, theMacroName);
tmpstr[strlen(tmpstr) - 1] = 0;
sptr++;
// We didn't find what we were looking for
FILE_Error(ERR_DROP, "No Macro Text found for %s in file %s\n",
theMacroName, filename.c_str());
return 0;
2016-03-27 11:49:47 +02:00
}
//================================================================
// Name: AddMacro
// Class: Script
//
// Description: Adds a macro to the definitions list.
//
// Parameters: const char *name -- Name of the macro
// const char *value -- Value
//
// Returns: None
//
//================================================================
2023-02-04 19:56:06 +01:00
void Script::AddMacro(const char* name, const char* value) {}
2016-03-27 11:49:47 +02:00
/*
==============
=
= EvaluateMacroString
=
==============
*/
2023-02-04 19:56:06 +01:00
char* Script::EvaluateMacroString(const char* theMacroString)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
static char evalText[255];
char buffer[255], *bufferptr = buffer, oper = '+', newoper = '+';
bool haveoper = false;
int i;
float value = 0.0f, val = 0.0f;
memset(buffer, 0, 255);
for (i = 0; i <= strlen(theMacroString); i++) {
if (theMacroString[i] == '+') {
haveoper = true;
newoper = '+';
}
if (theMacroString[i] == '-') {
haveoper = true;
newoper = '-';
}
if (theMacroString[i] == '*') {
haveoper = true;
newoper = '*';
}
if (theMacroString[i] == '/') {
haveoper = true;
newoper = '/';
}
if (theMacroString[i] == 0) {
haveoper = true;
}
if (haveoper) {
if (buffer[0] == '$') {
val = atof(GetMacroString(buffer));
} else {
val = atof(buffer);
}
value = EvaluateMacroMath(value, val, oper);
oper = newoper;
// Reset everything
haveoper = false;
memset(buffer, 0, 255);
bufferptr = buffer;
continue;
}
*bufferptr = theMacroString[i];
bufferptr++;
}
sprintf(evalText, "%f", value);
return evalText;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= EvaluateMacroMath
=
==============
*/
float Script::EvaluateMacroMath(float value, float newval, char oper)
{
2023-02-04 19:56:06 +01:00
switch (oper) {
case '+':
value += newval;
break;
case '-':
value -= newval;
break;
case '*':
value *= newval;
break;
case '/':
value /= newval;
break;
}
return value;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= isMacro
=
==============
*/
2023-02-04 19:56:06 +01:00
qboolean Script::isMacro(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
if (!TokenAvailable(true)) {
return false;
}
SkipNonToken(true);
if (*script_p == TOKENSPECIAL) {
return true;
}
return false;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetLine
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::GetLine(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
const char* start;
int size;
// is a token already waiting?
if (tokenready) {
tokenready = false;
return token;
}
//
// skip space
//
SkipNonToken(crossline);
//
// copy token
//
start = script_p;
SkipToEOL();
size = script_p - start;
if (size < (MAXTOKEN - 1)) {
memcpy(token, start, size);
token[size] = '\0';
} else {
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n", line,
filename.c_str());
}
return token;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetRaw
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::GetRaw(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
const char* start;
int size;
//
// skip white space
//
SkipWhiteSpace(true);
//
// copy token
//
start = script_p;
SkipToEOL();
size = script_p - start;
if (size < (MAXTOKEN - 1)) {
memset(token, 0, sizeof(token));
memcpy(token, start, size);
} else {
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n", line,
filename.c_str());
}
return token;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetString
=
==============
*/
2023-02-04 19:56:06 +01:00
const char* Script::GetString(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int startline;
char* token_p;
// is a token already waiting?
if (tokenready) {
tokenready = false;
return token;
}
//
// skip space
//
SkipNonToken(crossline);
if (*script_p != '"') {
FILE_Error(ERR_DROP, "Expecting string on line %i in file %s\n", line,
filename.c_str());
}
script_p++;
startline = line;
token_p = token;
while (*script_p != '"') {
if (*script_p == TOKENEOL) {
FILE_Error(
ERR_DROP,
"Line %i is incomplete while reading string in file %s\n", line,
filename.c_str());
}
if ((*script_p == '\\') && (script_p < (end_p - 1))) {
script_p++;
switch (*script_p) {
case 'n':
*token_p++ = '\n';
break;
case 'r':
*token_p++ = '\n';
break;
case '\'':
*token_p++ = '\'';
break;
case '\"':
*token_p++ = '\"';
break;
case '\\':
*token_p++ = '\\';
break;
default:
*token_p++ = *script_p;
break;
}
script_p++;
} else {
*token_p++ = *script_p++;
}
if (script_p >= end_p) {
FILE_Error(ERR_DROP,
"End of token file reached prematurely while reading "
"string on\n"
"line %d in file %s\n",
startline, filename.c_str());
}
if (token_p == &token[MAXTOKEN]) {
FILE_Error(ERR_DROP, "String too large on line %i in file %s\n",
line, filename.c_str());
}
}
*token_p = 0;
// skip last quote
script_p++;
return token;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetSpecific
=
==============
*/
2023-02-04 19:56:06 +01:00
qboolean Script::GetSpecific(const char* string)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
do {
if (!TokenAvailable(true)) {
return false;
}
GetToken(true);
} while (strcmp(token, string));
return true;
2016-03-27 11:49:47 +02:00
}
//===============================================================
// Name: GetBoolean
// Class: Script
//
// Description: Retrieves the next boolean value in the token
// stream. If the next token is either "true"
// or "1", then it returns true. Otherwise, it
// returns false.
2023-02-04 19:56:06 +01:00
//
2016-03-27 11:49:47 +02:00
// Parameters: qboolean -- determines if token parsing can cross newlines
//
// Returns: qboolean -- true if next token was "true" (or "1")
2023-02-04 19:56:06 +01:00
//
2016-03-27 11:49:47 +02:00
//===============================================================
2023-02-04 19:56:06 +01:00
qboolean Script::GetBoolean(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
GetToken(crossline);
if (Q_stricmp(token, "true") == 0) {
return true;
} else if (Q_stricmp(token, "1") == 0) {
return true;
}
return false;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetInteger
=
==============
*/
2023-02-04 19:56:06 +01:00
int Script::GetInteger(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
GetToken(crossline);
return atoi(token);
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetDouble
=
==============
*/
2023-02-04 19:56:06 +01:00
double Script::GetDouble(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
GetToken(crossline);
return atof(token);
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetFloat
=
==============
*/
2023-02-04 19:56:06 +01:00
float Script::GetFloat(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
return (float)GetDouble(crossline);
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= GetVector
=
==============
*/
2023-02-04 19:56:06 +01:00
Vector Script::GetVector(qboolean crossline)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
float x = GetFloat(crossline);
float y = GetFloat(crossline);
float z = GetFloat(crossline);
return Vector(x, y, z);
2016-03-27 11:49:47 +02:00
}
/*
===================
=
= LinesInFile
=
===================
*/
2023-02-04 19:56:06 +01:00
int Script::LinesInFile(void)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
qboolean temp_tokenready;
const char* temp_script_p;
int temp_line;
char temp_token[MAXTOKEN];
int numentries;
temp_tokenready = tokenready;
temp_script_p = script_p;
temp_line = line;
strcpy(temp_token, token);
numentries = 0;
Reset();
while (TokenAvailable(true)) {
GetLine(true);
numentries++;
}
tokenready = temp_tokenready;
script_p = temp_script_p;
line = temp_line;
strcpy(token, temp_token);
return numentries;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= Parse
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::Parse(const char* data, size_t length, const char* name)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
Close();
buffer = data;
Reset();
this->length = length;
end_p = script_p + length;
filename = name;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= Load
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::LoadFile(const char* name)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
int length;
byte* buffer;
byte* tempbuf;
const char* const_buffer;
Close();
length = FILE_FS_ReadFile(name, (void**)&tempbuf);
hasError = false;
if (length < 0) {
hasError = true;
return;
}
// create our own space
buffer = (byte*)FILE_Malloc(length + 1);
// copy the file over to our space
memcpy(buffer, tempbuf, length);
buffer[length] = 0;
// free the file
FILE_FS_FreeFile(tempbuf);
const_buffer = (char*)buffer;
Parse(const_buffer, length, name);
releaseBuffer = true;
2016-03-27 11:49:47 +02:00
}
/*
==============
=
= LoadFile
=
==============
*/
2023-02-04 19:56:06 +01:00
void Script::LoadFile(const char* name, int length, const char* buf)
2016-03-27 11:49:47 +02:00
{
2023-02-04 19:56:06 +01:00
Close();
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
// create our own space
this->buffer = (const char*)FILE_Malloc(length);
this->length = length;
// copy the file over to our space
memcpy((void*)this->buffer, buf, length);
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
Parse(buffer, this->length, name);
releaseBuffer = true;
2016-03-27 11:49:47 +02:00
}
2023-02-04 19:56:06 +01:00
qboolean Script::isValid() { return !hasError; }
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
qboolean Script::EndOfFile(void) { return script_p >= end_p; }
2016-03-27 11:49:47 +02:00
2023-02-04 19:56:06 +01:00
const char* Script::Token(void) { return token; }