gzdoom-gles/src/sc_man.cpp
Randy Heit 6695e255ce - Added actor replacement for DECORATE. This works at a higher level than
using duplicate DoomEdNums and will affect all attempts to spawn the
  replaced actor. However, because this happens for all spawns and not just
  at map load, the replacing actor must be compatible with the replaced
  actor, which means that an actor can only serve as a replacement for one
  of its baseclasses. For example, if you want to use a modified imp, you can
  use this DECORATE:
      actor MyImp : DoomImp replaces DoompImp
      {
          // Put changed properties here
      }
- New: The IWAD dialog now remembers the last IWAD you picked and
  automatically highlights it the next time you run the game. This also
  applies if you check "Don't ask me this again": The IWAD selected will be
  the one that gets automatically loaded, not the one located first. (Using
  the -iwad parameter will not change the default IWAD.) In addition, you
  can now bring the dialog up even if you disable it by holding down SHIFT
  during startup.
- Changed ExtractFilePath() and ExtractFileBase() to return FStrings instead
  of writing to a provided output buffer. ExtractFileBase() can also
  optionally keep the file's extension in the result.
- Removed the -heapsize parameter entirely. The informational message should
  no longer be needed.
- Removed -maxdemo parameter. There's no point to having it around since
  the demo buffer grows automatically.


SVN r238 (trunk)
2006-07-08 02:17:35 +00:00

727 lines
16 KiB
C++

//**************************************************************************
//**
//** sc_man.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: sc_man.c,v $
//** $Revision: 1.3 $
//** $Date: 96/01/06 03:23:43 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include <string.h>
#include <stdlib.h>
#include "doomtype.h"
#include "i_system.h"
#include "sc_man.h"
#include "w_wad.h"
#include "cmdlib.h"
#include "m_misc.h"
#include "templates.h"
// MACROS ------------------------------------------------------------------
#define MAX_STRING_SIZE 4096
#define ASCII_COMMENT (';')
#define CPP_COMMENT ('/')
#define C_COMMENT ('*')
#define ASCII_QUOTE ('"')
#define LUMP_SCRIPT 1
#define FILE_ZONE_SCRIPT 2
#define NORMAL_STOPCHARS "{}|="
#define CMODE_STOPCHARS "`~!@#$%^&*(){}[]/=\?+|;:<>,."
#define CMODE_STOPCHARS_NODECIMAL "`~!@#$%^&*(){}[]/=\?+|;:<>,"
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void SC_PrepareScript (void);
static void CheckOpen (void);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
char *sc_String;
int sc_StringLen;
int sc_Number;
float sc_Float;
int sc_Line;
BOOL sc_End;
BOOL sc_Crossed;
BOOL sc_FileScripts = false;
char *sc_ScriptsDir = "";
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static FString ScriptName;
static char *ScriptBuffer;
static char *ScriptPtr;
static char *ScriptEndPtr;
static char StringBuffer[MAX_STRING_SIZE];
static bool ScriptOpen = false;
static int ScriptSize;
static bool AlreadyGot = false;
static bool FreeScript = false;
static char *SavedScriptPtr;
static int SavedScriptLine;
static bool CMode;
static bool Escape = true;
static bool AtTermed;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// SC_Open
//
//==========================================================================
void SC_Open (const char *name)
{
int lump = Wads.CheckNumForFullName(name);
if (lump==-1) lump = Wads.GetNumForName(name);
SC_OpenLumpNum(lump, name);
}
//==========================================================================
//
// SC_OpenFile
//
// Loads a script (from a file). Uses the new/delete memory allocator for
// memory allocation and de-allocation.
//
//==========================================================================
void SC_OpenFile (const char *name)
{
byte *filebuf;
SC_Close ();
ScriptSize = M_ReadFile (name, &filebuf);
ScriptBuffer = (char *)filebuf;
ScriptName = name; // This is used for error messages so the full file name is preferable
FreeScript = true;
SC_PrepareScript ();
}
//==========================================================================
//
// SC_OpenMem
//
// Prepares a script that is already in memory for parsing. The caller is
// responsible for freeing it, if needed.
//
//==========================================================================
void SC_OpenMem (const char *name, char *buffer, int size)
{
SC_Close ();
ScriptSize = size;
ScriptBuffer = buffer;
ScriptName = name;
FreeScript = false;
SC_PrepareScript ();
}
//==========================================================================
//
// SC_OpenLumpNum
//
// Loads a script (from the WAD files).
//
//==========================================================================
void SC_OpenLumpNum (int lump, const char *name)
{
SC_Close ();
ScriptSize = Wads.LumpLength (lump);
ScriptBuffer = new char[ScriptSize];
Wads.ReadLump (lump, ScriptBuffer);
ScriptName = name;
FreeScript = true;
SC_PrepareScript ();
}
//==========================================================================
//
// SC_PrepareScript
//
// Prepares a script for parsing.
//
//==========================================================================
static void SC_PrepareScript (void)
{
ScriptPtr = ScriptBuffer;
ScriptEndPtr = ScriptPtr + ScriptSize;
sc_Line = 1;
sc_End = false;
ScriptOpen = true;
sc_String = StringBuffer;
AlreadyGot = false;
SavedScriptPtr = NULL;
CMode = false;
Escape = true;
}
//==========================================================================
//
// SC_Close
//
//==========================================================================
void SC_Close (void)
{
if (ScriptOpen)
{
if (ScriptBuffer)
{
if (FreeScript)
{
delete[] ScriptBuffer;
}
}
ScriptBuffer = NULL;
ScriptOpen = false;
}
}
//==========================================================================
//
// SC_SavePos
//
// Saves the current script location for restoration later
//
//==========================================================================
void SC_SavePos (void)
{
CheckOpen ();
if (sc_End)
{
SavedScriptPtr = NULL;
}
else
{
SavedScriptPtr = ScriptPtr;
SavedScriptLine = sc_Line;
}
}
//==========================================================================
//
// SC_RestorePos
//
// Restores the previously saved script location
//
//==========================================================================
void SC_RestorePos (void)
{
if (SavedScriptPtr)
{
ScriptPtr = SavedScriptPtr;
sc_Line = SavedScriptLine;
sc_End = false;
AlreadyGot = false;
}
}
//==========================================================================
//
// SC_SetCMode
//
// Enables/disables C mode. In C mode, more characters are considered to
// be whole words than in non-C mode.
//
//==========================================================================
void SC_SetCMode (bool cmode)
{
CMode = cmode;
}
//==========================================================================
//
// SC_SetEscape
//
// Turns the escape sequence \" in strings on or off. If it's off, that
// means you can't include quotation marks inside strings.
//
//==========================================================================
void SC_SetEscape (bool esc)
{
Escape = esc;
}
//==========================================================================
//
// SC_GetString
//
//==========================================================================
BOOL SC_GetString ()
{
char *marker, *tok;
CheckOpen();
if (AlreadyGot)
{
AlreadyGot = false;
return true;
}
sc_Crossed = false;
if (ScriptPtr >= ScriptEndPtr)
{
sc_End = true;
return false;
}
// In case the generated scanner does not use marker, avoid compiler warnings.
marker;
#include "sc_man_scanner.h"
}
//==========================================================================
//
// SC_MustGetString
//
//==========================================================================
void SC_MustGetString (void)
{
if (SC_GetString () == false)
{
SC_ScriptError ("Missing string (unexpected end of file).");
}
}
//==========================================================================
//
// SC_MustGetStringName
//
//==========================================================================
void SC_MustGetStringName (const char *name)
{
SC_MustGetString ();
if (SC_Compare (name) == false)
{
SC_ScriptError ("Expected '%s', got '%s'.", name, sc_String);
}
}
//==========================================================================
//
// SC_CheckString
//
// Checks if the next token matches the specified string. Returns true if
// it does. If it doesn't, it ungets it and returns false.
//==========================================================================
bool SC_CheckString (const char *name)
{
if (SC_GetString ())
{
if (SC_Compare (name))
{
return true;
}
SC_UnGet ();
}
return false;
}
//==========================================================================
//
// SC_GetNumber
//
//==========================================================================
BOOL SC_GetNumber (void)
{
char *stopper;
CheckOpen ();
if (SC_GetString())
{
if (strcmp (sc_String, "MAXINT") == 0)
{
sc_Number = INT_MAX;
}
else
{
sc_Number = strtol (sc_String, &stopper, 0);
if (*stopper != 0)
{
SC_ScriptError ("SC_GetNumber: Bad numeric constant \"%s\".", sc_String);
}
}
sc_Float = (float)sc_Number;
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_MustGetNumber
//
//==========================================================================
void SC_MustGetNumber (void)
{
if (SC_GetNumber() == false)
{
SC_ScriptError ("Missing integer (unexpected end of file).");
}
}
//==========================================================================
//
// SC_CheckNumber
// similar to SC_GetNumber but ungets the token if it isn't a number
// and does not print an error
//
//==========================================================================
BOOL SC_CheckNumber (void)
{
char *stopper;
//CheckOpen ();
if (SC_GetString())
{
if (strcmp (sc_String, "MAXINT") == 0)
{
sc_Number = INT_MAX;
}
else
{
sc_Number = strtol (sc_String, &stopper, 0);
if (*stopper != 0)
{
SC_UnGet();
return false;
}
}
sc_Float = (float)sc_Number;
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_CheckFloat
// [GRB] Same as SC_CheckNumber, only for floats
//
//==========================================================================
BOOL SC_CheckFloat (void)
{
char *stopper;
//CheckOpen ();
if (SC_GetString())
{
sc_Float = strtod (sc_String, &stopper);
if (*stopper != 0)
{
SC_UnGet();
return false;
}
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_GetFloat
//
//==========================================================================
BOOL SC_GetFloat (void)
{
char *stopper;
CheckOpen ();
if (SC_GetString())
{
sc_Float = (float)strtod (sc_String, &stopper);
if (*stopper != 0)
{
I_Error ("SC_GetFloat: Bad numeric constant \"%s\".\n"
"Script %s, Line %d\n", sc_String, ScriptName.GetChars(), sc_Line);
}
sc_Number = (int)sc_Float;
return true;
}
else
{
return false;
}
}
//==========================================================================
//
// SC_MustGetFloat
//
//==========================================================================
void SC_MustGetFloat (void)
{
if (SC_GetFloat() == false)
{
SC_ScriptError ("Missing floating-point number (unexpected end of file).");
}
}
//==========================================================================
//
// SC_UnGet
//
// Assumes there is a valid string in sc_String.
//
//==========================================================================
void SC_UnGet (void)
{
AlreadyGot = true;
}
//==========================================================================
//
// SC_Check
//
// Returns true if another token is on the current line.
//
//==========================================================================
/*
BOOL SC_Check(void)
{
char *text;
CheckOpen();
text = ScriptPtr;
if(text >= ScriptEndPtr)
{
return false;
}
while(*text <= 32)
{
if(*text == '\n')
{
return false;
}
text++;
if(text == ScriptEndPtr)
{
return false;
}
}
if(*text == ASCII_COMMENT)
{
return false;
}
return true;
}
*/
//==========================================================================
//
// SC_MatchString
//
// Returns the index of the first match to sc_String from the passed
// array of strings, or -1 if not found.
//
//==========================================================================
int SC_MatchString (const char **strings)
{
int i;
for (i = 0; *strings != NULL; i++)
{
if (SC_Compare (*strings++))
{
return i;
}
}
return -1;
}
//==========================================================================
//
// SC_MustMatchString
//
//==========================================================================
int SC_MustMatchString (const char **strings)
{
int i;
i = SC_MatchString (strings);
if (i == -1)
{
SC_ScriptError (NULL);
}
return i;
}
//==========================================================================
//
// SC_Compare
//
//==========================================================================
BOOL SC_Compare (const char *text)
{
return (stricmp (text, sc_String) == 0);
}
//==========================================================================
//
// SC_ScriptError
//
//==========================================================================
void STACK_ARGS SC_ScriptError (const char *message, ...)
{
FString composed;
if (message == NULL)
{
composed = "Bad syntax.";
}
else
{
va_list arglist;
va_start (arglist, message);
composed.VFormat (message, arglist);
va_end (arglist);
}
I_Error ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(),
sc_Line, composed.GetChars());
}
//==========================================================================
//
// CheckOpen
//
//==========================================================================
static void CheckOpen(void)
{
if (ScriptOpen == false)
{
I_FatalError ("SC_ call before SC_Open().");
}
}
//==========================================================================
//
// Script state saving
// This allows recursive script execution
// This does not save the last token!
//
//==========================================================================
struct SavedScript
{
int sc_Line;
BOOL sc_End;
BOOL sc_Crossed;
BOOL sc_FileScripts;
FString *ScriptName;
char *ScriptBuffer;
char *ScriptPtr;
char *ScriptEndPtr;
bool ScriptOpen;
int ScriptSize;
bool FreeScript;
char *SavedScriptPtr;
int SavedScriptLine;
bool CMode;
bool Escape;
};
static TArray<SavedScript> SavedScripts;
void SC_SaveScriptState()
{
SavedScript ss;
ss.sc_Line = sc_Line;
ss.sc_End = sc_End;
ss.sc_Crossed = sc_Crossed;
ss.sc_FileScripts = sc_FileScripts;
ss.ScriptName = ::new FString(ScriptName);
ss.ScriptBuffer = ScriptBuffer;
ss.ScriptPtr = ScriptPtr;
ss.ScriptEndPtr = ScriptEndPtr;
ss.ScriptOpen = ScriptOpen;
ss.ScriptSize = ScriptSize;
ss.FreeScript = FreeScript;
ss.SavedScriptPtr = SavedScriptPtr;
ss.SavedScriptLine = SavedScriptLine;
ss.CMode = CMode;
ss.Escape = Escape;
SavedScripts.Push(ss);
ScriptOpen = false;
}
void SC_RestoreScriptState()
{
if (SavedScripts.Size()>0)
{
SavedScript ss;
SavedScripts.Pop(ss);
sc_Line = ss.sc_Line;
sc_End = ss.sc_End;
sc_Crossed = ss.sc_Crossed;
sc_FileScripts = ss.sc_FileScripts;
ScriptName = *ss.ScriptName;
::delete ss.ScriptName;
ScriptBuffer = ss.ScriptBuffer;
ScriptPtr = ss.ScriptPtr;
ScriptEndPtr = ss.ScriptEndPtr;
ScriptOpen = ss.ScriptOpen;
ScriptSize = ss.ScriptSize;
FreeScript = ss.FreeScript;
SavedScriptPtr = ss.SavedScriptPtr;
SavedScriptLine = ss.SavedScriptLine;
CMode = ss.CMode;
Escape = ss.Escape;
SavedScripts.ShrinkToFit();
AlreadyGot = false;
}
}