From 2c2261884c10ecb60b8f314bfbb9b501027b02bd Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 5 Oct 2006 03:30:44 +0000 Subject: [PATCH] SVN r349 (trunk) --- docs/rh-log.txt | 9 +++ src/c_dispatch.cpp | 160 ++++++++++++++++++++++++++++++------------ src/c_dispatch.h | 5 +- src/oplsynth/muslib.h | 64 +++++++++++++++++ src/zstring.cpp | 1 + 5 files changed, 194 insertions(+), 45 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 11fd39fc4..19799c2a4 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index b8b901010..4058c1afa 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -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; } diff --git a/src/c_dispatch.h b/src/c_dispatch.h index e8720fb16..f05cfd718 100644 --- a/src/c_dispatch.h +++ b/src/c_dispatch.h @@ -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; }; diff --git a/src/oplsynth/muslib.h b/src/oplsynth/muslib.h index 6cc71def5..4a6d34e2f 100644 --- a/src/oplsynth/muslib.h +++ b/src/oplsynth/muslib.h @@ -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_ diff --git a/src/zstring.cpp b/src/zstring.cpp index a35443be2..13ec7a405 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -138,6 +138,7 @@ char *FString::LockBuffer() AllocBuffer (old->Len); StrCopy (Chars, old->Chars(), old->Len); old->Release(); + Data()->RefCount = -1; } return Chars; }