SVN r349 (trunk)

This commit is contained in:
Randy Heit 2006-10-05 03:30:44 +00:00
parent 28ea15d8f4
commit 2c2261884c
5 changed files with 194 additions and 45 deletions

View file

@ -1,3 +1,12 @@
October 4, 2006
- Added alias parameter substitution. Instances of %x in the alias command
string will be replaced with parameter x when the alias is executed.
- Fixed: When FString::LockBuffer() had to create a new string because the
RefCount was higher than one, the new string was not actually locked.
- FConsoleAlias now stores the commands in FStrings.
- BuildString() now returns an FString.
- Added the muslib license text to muslib.h.
October 4, 2006 (Changes by Graf Zahl)
- When exiting the level on a damaging floor the player could be in the pain
state and make its pain noise at the start of the next level.

View file

@ -846,53 +846,117 @@ void FConsoleCommand::Run (FCommandLine &argv, APlayerPawn *who, int key)
FConsoleAlias::FConsoleAlias (const char *name, const char *command, bool noSave)
: FConsoleCommand (name, NULL),
bRunning (false), bKill (false)
bRunning(false), bKill(false)
{
m_Command[noSave] = copystring (command);
m_Command[!noSave] = NULL;
m_Command[noSave] = command;
m_Command[!noSave] = FString();
// If the command contains % characters, assume they are parameter markers
// for substitution when the command is executed.
bDoSubstitution = (strchr (command, '%') != NULL);
}
FConsoleAlias::~FConsoleAlias ()
{
for (int i = 0; i < 2; ++i)
{
if (m_Command[i] != NULL)
{
delete[] m_Command[i];
m_Command[i] = NULL;
}
}
m_Command[1] = m_Command[0] = FString();
}
char *BuildString (int argc, char **argv)
FString BuildString (int argc, char **argv)
{
char temp[1024];
char *cur;
int arg;
if (argc == 1)
{
return copystring (*argv);
return *argv;
}
else
{
cur = temp;
FString buf;
int arg;
for (arg = 0; arg < argc; arg++)
{
if (strchr (argv[arg], ' '))
{
cur += sprintf (cur, "\"%s\" ", argv[arg]);
buf.AppendFormat ("\"%s\" ", argv[arg]);
}
else
{
cur += sprintf (cur, "%s ", argv[arg]);
buf.AppendFormat ("%s ", argv[arg]);
}
}
temp[strlen (temp) - 1] = 0;
return copystring (temp);
return buf;
}
}
//===========================================================================
//
// SubstituteAliasParams
//
// Given an command line and a set of arguments, replace instances of
// %x or %{x} in the command line with argument x. If argument x does not
// exist, then the empty string is substituted in its place.
//
// Substitution is not done inside of quoted strings.
//
// To avoid a substitution, use %%. The %% will be replaced by a single %.
//
//===========================================================================
FString SubstituteAliasParams (FString &command, FCommandLine &args)
{
// Do substitution by replacing %x with the argument x.
// If there is no argument x, then %x is simply removed.
// For some reason, strtoul's stop parameter is non-const.
char *p = command.LockBuffer(), *start = p;
unsigned long argnum;
FString buf;
while (*p != '\0')
{
if (*p == '%' && ((p[1] >= '0' && p[1] <= '9') || p[1] == '{' || p[1] == '%'))
{
if (p[1] == '%')
{
// Do not substitute. Just collapse to a single %.
buf.AppendCStrPart (start, p - start + 1);
start = p = p + 2;
continue;
}
// Do a substitution. Output what came before this.
buf.AppendCStrPart (start, p - start);
// Extract the argument number and substitute the corresponding argument.
argnum = strtoul (p + 1 + (p[1] == '{'), &start, 10);
if ((p[1] != '{' || *start == '}') && argnum < args.argc())
{
buf += args[argnum];
}
p = (start += (p[1] == '{' && *start == '}'));
}
else if (*p == '"')
{
// Don't substitute inside quoted strings.
p++;
while (*p != '\0' && (*p != '"' || *(p-1) == '\\'))
p++;
if (*p != '\0')
p++;
}
else
{
p++;
}
}
// Return whatever was after the final substitution.
if (p > start)
{
buf.AppendCStrPart (start, p - start);
}
command.UnlockBuffer();
return buf;
}
static int DumpHash (FConsoleCommand **table, bool aliases, const char *pattern=NULL)
{
int bucket, count;
@ -939,7 +1003,7 @@ void FConsoleAlias::PrintAlias ()
void FConsoleAlias::Archive (FConfigFile *f)
{
if (f != NULL && m_Command[0] != NULL)
if (f != NULL && !m_Command[0].IsEmpty())
{
f->SetValueForKey ("Name", m_Name, true);
f->SetValueForKey ("Command", m_Command[0], true);
@ -1066,7 +1130,7 @@ void C_ExecCmdLineParams ()
{
if (*Args.GetArg (currArg++) == '+')
{
char *cmdString;
FString cmdString;
int cmdlen = 1;
int argstart = currArg - 1;
@ -1078,10 +1142,10 @@ void C_ExecCmdLineParams ()
cmdlen++;
}
if ( (cmdString = BuildString (cmdlen, Args.GetArgList (argstart))) )
cmdString = BuildString (cmdlen, Args.GetArgList (argstart));
if (!cmdString.IsEmpty())
{
C_DoCommand (cmdString + 1);
delete[] cmdString;
C_DoCommand (&cmdString[1]);
}
}
}
@ -1105,19 +1169,29 @@ void FConsoleAlias::Run (FCommandLine &args, APlayerPawn *who, int key)
return;
}
int index = m_Command[1] != NULL;
char *mycommand = m_Command[index];
m_Command[index] = NULL;
bRunning = true;
AddCommandString (mycommand, key);
bRunning = false;
if (m_Command[index] != NULL)
{ // The alias realiased itself, so delete the memory used by this command.
delete[] mycommand;
int index = !m_Command[1].IsEmpty();
FString savedcommand = m_Command[index], mycommand;
m_Command[index] = FString();
if (bDoSubstitution)
{
mycommand = SubstituteAliasParams (savedcommand, args);
}
else
{
mycommand = savedcommand;
}
bRunning = true;
AddCommandString (mycommand.LockBuffer(), key);
mycommand.UnlockBuffer();
bRunning = false;
if (m_Command[index].IsEmpty())
{ // The alias is unchanged, so put the command back so it can be used again.
m_Command[index] = mycommand;
// If the command had been non-empty, then that means that executing this
// alias caused it to realias itself, so the old command will be forgotten
// once this function returns.
m_Command[index] = savedcommand;
}
if (bKill)
{ // The alias wants to remove itself
@ -1127,15 +1201,15 @@ void FConsoleAlias::Run (FCommandLine &args, APlayerPawn *who, int key)
void FConsoleAlias::Realias (const char *command, bool noSave)
{
if (m_Command[1] != NULL)
if (!noSave && !m_Command[1].IsEmpty())
{
noSave = true;
}
if (m_Command[noSave] != NULL)
{
delete[] m_Command[noSave];
}
m_Command[noSave] = copystring (command);
m_Command[noSave] = command;
// If the command contains % characters, assume they are parameter markers
// for substitution when the command is executed.
bDoSubstitution = (strchr (command, '%') != NULL);
bKill = false;
}

View file

@ -58,7 +58,7 @@ void C_ArchiveAliases (FConfigFile *f);
void C_SetAlias (const char *name, const char *cmd);
// build a single string out of multiple strings
char *BuildString (int argc, char **argv);
FString BuildString (int argc, char **argv);
// Class that can parse command lines
class FCommandLine
@ -121,7 +121,8 @@ public:
void Realias (const char *command, bool noSave);
void SafeDelete ();
protected:
char *m_Command[2];
FString m_Command[2]; // Slot 0 is saved to the ini, slot 1 is not.
bool bDoSubstitution;
bool bRunning;
bool bKill;
};

View file

@ -8,6 +8,70 @@
*
*/
/* From muslib175.zip/README.1ST:
1.1 - Disclaimer of Warranties
------------------------------
#ifdef LAWYER
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
#else
Use this software at your own risk.
#endif
1.2 - Terms of Use
------------------
This library may be used in any freeware or shareware product free of
charge. The product may not be sold for profit (except for shareware) and
should be freely available to the public. It would be nice of you if you
credited me in your product and notified me if you use this library.
If you want to use this library in a commercial product, contact me
and we will make an agreement. It is a violation of the law to make money
of this product without prior signing an agreement and paying a license fee.
This licence will allow its holder to sell any products based on MUSLib,
royalty-free. There is no need to buy separate licences for different
products once the licence fee is paid.
1.3 - Contacting the Author
---------------------------
Internet (address valid probably until the end of year 1998):
xarnos00@dcse.fee.vutbr.cz
FIDO:
2:423/36.2
Snail-mail:
Vladimir Arnost
Ceska 921
Chrudim 4
537 01
CZECH REPUBLIC
Voice-mail (Czech language only, not recommended; weekends only):
+42-455-2154
*/
#ifndef __MUSLIB_H_
#define __MUSLIB_H_

View file

@ -138,6 +138,7 @@ char *FString::LockBuffer()
AllocBuffer (old->Len);
StrCopy (Chars, old->Chars(), old->Len);
old->Release();
Data()->RefCount = -1;
}
return Chars;
}