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)
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
# include "../fgame/g_local.h"
|
2023-01-29 20:59:31 +01:00
|
|
|
|
2023-07-05 21:23:39 +02: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-07-05 21:23:39 +02:00
|
|
|
# define FILE_FS_FreeFile cgi.FS_FreeFile
|
|
|
|
# define FILE_FS_ReadFile(a, b) cgi.FS_ReadFile(a, b, qtrue)
|
|
|
|
# define FILE_Malloc cgi.Malloc
|
|
|
|
# define FILE_Free cgi.Free
|
|
|
|
# define FILE_Error cgi.Error
|
2023-01-29 20:59:31 +01:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
# include "qcommon.h"
|
2023-01-29 20:59:31 +01:00
|
|
|
|
2023-07-05 21:23:39 +02: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-07-05 21:23:39 +02:00
|
|
|
CLASS_DECLARATION(Class, Script, NULL) {
|
2023-02-04 19:56:06 +01:00
|
|
|
{NULL, NULL}
|
2016-03-27 11:49:47 +02:00
|
|
|
};
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
Script::~Script()
|
|
|
|
{
|
|
|
|
Close();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
Script::Script(const char *filename /*= 0*/)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
buffer = NULL;
|
|
|
|
script_p = NULL;
|
|
|
|
end_p = NULL;
|
|
|
|
line = 0;
|
|
|
|
length = 0;
|
2023-02-04 19:56:06 +01:00
|
|
|
releaseBuffer = false;
|
2023-07-05 21:23:39 +02:00
|
|
|
tokenready = false;
|
|
|
|
token[0] = 0;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
if (filename != 0) {
|
|
|
|
LoadFile(filename);
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Script::Script()
|
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
buffer = NULL;
|
|
|
|
script_p = NULL;
|
|
|
|
end_p = NULL;
|
|
|
|
line = 0;
|
|
|
|
length = 0;
|
2023-02-04 19:56:06 +01:00
|
|
|
releaseBuffer = false;
|
2023-07-05 21:23:39 +02:00
|
|
|
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) {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Free((void *)buffer);
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
buffer = NULL;
|
|
|
|
script_p = NULL;
|
|
|
|
end_p = NULL;
|
|
|
|
line = 0;
|
2023-02-04 19:56:06 +01:00
|
|
|
releaseBuffer = false;
|
2023-07-05 21:23:39 +02:00
|
|
|
tokenready = false;
|
|
|
|
token[0] = 0;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// 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-07-05 21:23:39 +02:00
|
|
|
const char *Script::Filename(void)
|
|
|
|
{
|
|
|
|
return filename.c_str();
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= GetLineNumber
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02: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-07-05 21:23:39 +02:00
|
|
|
script_p = buffer;
|
|
|
|
line = 1;
|
2023-02-04 19:56:06 +01:00
|
|
|
tokenready = false;
|
2023-07-05 21:23:39 +02:00
|
|
|
hasError = false;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= MarkPosition
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02: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;
|
2023-07-05 21:23:39 +02:00
|
|
|
mark->offset = script_p - buffer;
|
|
|
|
mark->line = line;
|
2024-09-20 21:53:48 +02:00
|
|
|
Q_strncpyz(mark->token, token, sizeof(mark->token));
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= RestorePosition
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02: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;
|
2023-07-05 21:23:39 +02:00
|
|
|
script_p = buffer + mark->offset;
|
|
|
|
line = mark->line;
|
2024-09-20 21:53:48 +02:00
|
|
|
Q_strncpyz(token, mark->token, sizeof(token));
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
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) {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "End of token file reached prematurely reading %s\n", filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
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) {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "Line %i is incomplete in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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-07-05 21:23:39 +02:00
|
|
|
const char *searchptr;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
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-07-05 21:23:39 +02: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);
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
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-07-05 21:23:39 +02:00
|
|
|
const char *Script::GetToken(qboolean crossline)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-08-19 21:17:52 +02:00
|
|
|
const char* token_p = token;
|
|
|
|
qboolean is_Macro = false;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// is a token already waiting?
|
|
|
|
if (tokenready) {
|
|
|
|
tokenready = false;
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
|
|
|
is_Macro = isMacro();
|
|
|
|
|
|
|
|
token_p = GrabNextToken(crossline);
|
|
|
|
|
2023-08-19 21:17:52 +02:00
|
|
|
if (is_Macro && (strcmp(token_p, "$include") != 0)) {
|
2023-02-04 19:56:06 +01:00
|
|
|
// Check to see if we need to add any definitions
|
2023-08-19 21:17:52 +02:00
|
|
|
while ((!strcmp(token_p, "$define")) || (!strcmp(token_p, "$Define"))) {
|
2023-02-04 19:56:06 +01:00
|
|
|
AddMacroDefinition(crossline);
|
|
|
|
is_Macro = isMacro();
|
|
|
|
// if ( !is_Macro )
|
|
|
|
// return "";
|
|
|
|
token_p = GrabNextToken(crossline);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if we need return any defines strings
|
2023-08-19 21:17:52 +02:00
|
|
|
if (is_Macro && (strcmp(token_p, "$include") != 0) && (token_p[strlen(token_p) - 1] == '$')) {
|
2023-02-04 19:56:06 +01:00
|
|
|
return GetMacroString(token_p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return token;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= GrabNextToken
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
2023-07-05 21:23:39 +02:00
|
|
|
const char *Script::GrabNextToken(qboolean crossline)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
char *token_p;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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++;
|
|
|
|
}
|
|
|
|
|
2023-05-21 00:29:26 +02:00
|
|
|
if (token_p == &token[SCRIPT_MAXTOKEN]) {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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-07-05 21:23:39 +02:00
|
|
|
macro *theMacro;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// 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));
|
2023-07-05 21:23:39 +02:00
|
|
|
theMacro->macroName.append("$"); //<-- Adding closing ($) to keep formatting consistant
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// 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-07-05 21:23:39 +02:00
|
|
|
const char *Script::GetMacroString(const char *theMacroName)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
macro *theMacro = 0; // Initialize this puppy
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
for (int i = 1; i <= macrolist.NumObjects(); i++) {
|
|
|
|
theMacro = macrolist.ObjectAt(i);
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
if (!theMacro->macroName.cmp(theMacro->macroName.c_str(), theMacroName)) {
|
|
|
|
const char *text = theMacro->macroText.c_str();
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// If our define value is another define...
|
|
|
|
if (text[0] == '$') {
|
|
|
|
return EvaluateMacroString(text);
|
|
|
|
} else {
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char tmpstr[255], *sptr = tmpstr;
|
2024-09-20 21:53:48 +02:00
|
|
|
Q_strncpyz(tmpstr, theMacroName, sizeof(tmpstr));
|
2023-02-04 19:56:06 +01:00
|
|
|
tmpstr[strlen(tmpstr) - 1] = 0;
|
|
|
|
sptr++;
|
|
|
|
|
|
|
|
// We didn't find what we were looking for
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "No Macro Text found for %s in file %s\n", theMacroName, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
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-07-05 21:23:39 +02:00
|
|
|
void Script::AddMacro(const char *name, const char *value) {}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= EvaluateMacroString
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
2023-07-05 21:23:39 +02: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];
|
2023-07-05 21:23:39 +02:00
|
|
|
char buffer[255], *bufferptr = buffer, oper = '+', newoper = '+';
|
|
|
|
bool haveoper = false;
|
|
|
|
int i;
|
|
|
|
float value = 0.0f, val = 0.0f;
|
2023-02-04 19:56:06 +01:00
|
|
|
memset(buffer, 0, 255);
|
|
|
|
|
|
|
|
for (i = 0; i <= strlen(theMacroString); i++) {
|
|
|
|
if (theMacroString[i] == '+') {
|
|
|
|
haveoper = true;
|
2023-07-05 21:23:39 +02:00
|
|
|
newoper = '+';
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
if (theMacroString[i] == '-') {
|
|
|
|
haveoper = true;
|
2023-07-05 21:23:39 +02:00
|
|
|
newoper = '-';
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
if (theMacroString[i] == '*') {
|
|
|
|
haveoper = true;
|
2023-07-05 21:23:39 +02:00
|
|
|
newoper = '*';
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
if (theMacroString[i] == '/') {
|
|
|
|
haveoper = true;
|
2023-07-05 21:23:39 +02:00
|
|
|
newoper = '/';
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
if (theMacroString[i] == 0) {
|
|
|
|
haveoper = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (haveoper) {
|
|
|
|
if (buffer[0] == '$') {
|
|
|
|
val = atof(GetMacroString(buffer));
|
|
|
|
} else {
|
|
|
|
val = atof(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
value = EvaluateMacroMath(value, val, oper);
|
2023-07-05 21:23:39 +02:00
|
|
|
oper = newoper;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// Reset everything
|
|
|
|
haveoper = false;
|
|
|
|
memset(buffer, 0, 255);
|
|
|
|
bufferptr = buffer;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
*bufferptr = theMacroString[i];
|
|
|
|
bufferptr++;
|
|
|
|
}
|
|
|
|
|
2024-09-20 21:53:48 +02:00
|
|
|
Com_sprintf(evalText, sizeof(evalText), "%f", value);
|
2023-02-04 19:56:06 +01:00
|
|
|
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-07-05 21:23:39 +02:00
|
|
|
const char *Script::GetLine(qboolean crossline)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
const char *start;
|
|
|
|
int size;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// 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;
|
2023-05-21 00:29:26 +02:00
|
|
|
if (size < (SCRIPT_MAXTOKEN - 1)) {
|
2023-02-04 19:56:06 +01:00
|
|
|
memcpy(token, start, size);
|
|
|
|
token[size] = '\0';
|
|
|
|
} else {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return token;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= GetRaw
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
const char *Script::GetRaw(void)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
const char *start;
|
|
|
|
int size;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// skip white space
|
|
|
|
//
|
|
|
|
SkipWhiteSpace(true);
|
|
|
|
|
|
|
|
//
|
|
|
|
// copy token
|
|
|
|
//
|
|
|
|
start = script_p;
|
|
|
|
SkipToEOL();
|
|
|
|
size = script_p - start;
|
2023-05-21 00:29:26 +02:00
|
|
|
if (size < (SCRIPT_MAXTOKEN - 1)) {
|
2023-02-04 19:56:06 +01:00
|
|
|
memset(token, 0, sizeof(token));
|
|
|
|
memcpy(token, start, size);
|
|
|
|
} else {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return token;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= GetString
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
const char *Script::GetString(qboolean crossline)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
int startline;
|
|
|
|
char *token_p;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
// is a token already waiting?
|
|
|
|
if (tokenready) {
|
|
|
|
tokenready = false;
|
|
|
|
return token;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// skip space
|
|
|
|
//
|
|
|
|
SkipNonToken(crossline);
|
|
|
|
|
|
|
|
if (*script_p != '"') {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "Expecting string on line %i in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
script_p++;
|
|
|
|
|
|
|
|
startline = line;
|
2023-07-05 21:23:39 +02:00
|
|
|
token_p = token;
|
2023-02-04 19:56:06 +01:00
|
|
|
while (*script_p != '"') {
|
|
|
|
if (*script_p == TOKENEOL) {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "Line %i is incomplete while reading string in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2023-07-05 21:23:39 +02:00
|
|
|
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()
|
|
|
|
);
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
|
2023-05-21 00:29:26 +02:00
|
|
|
if (token_p == &token[SCRIPT_MAXTOKEN]) {
|
2023-07-05 21:23:39 +02:00
|
|
|
FILE_Error(ERR_DROP, "String too large on line %i in file %s\n", line, filename.c_str());
|
2023-02-04 19:56:06 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*token_p = 0;
|
|
|
|
|
|
|
|
// skip last quote
|
|
|
|
script_p++;
|
|
|
|
|
|
|
|
return token;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= GetSpecific
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02: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-07-05 21:23:39 +02:00
|
|
|
qboolean temp_tokenready;
|
|
|
|
const char *temp_script_p;
|
|
|
|
int temp_line;
|
|
|
|
char temp_token[SCRIPT_MAXTOKEN];
|
|
|
|
int numentries;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
temp_tokenready = tokenready;
|
2023-07-05 21:23:39 +02:00
|
|
|
temp_script_p = script_p;
|
|
|
|
temp_line = line;
|
2024-09-20 21:53:48 +02:00
|
|
|
Q_strncpyz(temp_token, token, sizeof(temp_token));
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
numentries = 0;
|
|
|
|
|
|
|
|
Reset();
|
|
|
|
while (TokenAvailable(true)) {
|
|
|
|
GetLine(true);
|
|
|
|
numentries++;
|
|
|
|
}
|
|
|
|
|
|
|
|
tokenready = temp_tokenready;
|
2023-07-05 21:23:39 +02:00
|
|
|
script_p = temp_script_p;
|
|
|
|
line = temp_line;
|
2024-09-20 21:53:48 +02:00
|
|
|
Q_strncpyz(token, temp_token, sizeof(token));
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
return numentries;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= Parse
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02: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;
|
2023-07-05 21:23:39 +02:00
|
|
|
end_p = script_p + length;
|
|
|
|
filename = name;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= Load
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
void Script::LoadFile(const char *name)
|
2016-03-27 11:49:47 +02:00
|
|
|
{
|
2023-07-05 21:23:39 +02:00
|
|
|
int length;
|
|
|
|
byte *buffer;
|
|
|
|
byte *tempbuf;
|
|
|
|
const char *const_buffer;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
Close();
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
length = FILE_FS_ReadFile(name, (void **)&tempbuf);
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
hasError = false;
|
|
|
|
|
|
|
|
if (length < 0) {
|
|
|
|
hasError = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// create our own space
|
2023-07-05 21:23:39 +02:00
|
|
|
buffer = (byte *)FILE_Malloc(length + 1);
|
2023-02-04 19:56:06 +01:00
|
|
|
// copy the file over to our space
|
|
|
|
memcpy(buffer, tempbuf, length);
|
|
|
|
buffer[length] = 0;
|
|
|
|
// free the file
|
|
|
|
FILE_FS_FreeFile(tempbuf);
|
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
const_buffer = (char *)buffer;
|
2023-02-04 19:56:06 +01:00
|
|
|
|
|
|
|
Parse(const_buffer, length, name);
|
|
|
|
releaseBuffer = true;
|
2016-03-27 11:49:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
=
|
|
|
|
= LoadFile
|
|
|
|
=
|
|
|
|
==============
|
|
|
|
*/
|
|
|
|
|
2023-07-05 21:23:39 +02: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
|
2023-07-05 21:23:39 +02:00
|
|
|
this->buffer = (const char *)FILE_Malloc(length);
|
2023-02-04 19:56:06 +01:00
|
|
|
this->length = length;
|
|
|
|
// copy the file over to our space
|
2023-07-05 21:23:39 +02:00
|
|
|
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-07-05 21:23:39 +02:00
|
|
|
qboolean Script::isValid()
|
|
|
|
{
|
|
|
|
return !hasError;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
qboolean Script::EndOfFile(void)
|
|
|
|
{
|
|
|
|
return script_p >= end_p;
|
|
|
|
}
|
2016-03-27 11:49:47 +02:00
|
|
|
|
2023-07-05 21:23:39 +02:00
|
|
|
const char *Script::Token(void)
|
|
|
|
{
|
|
|
|
return token;
|
|
|
|
}
|