From f84037ad77b60eee06dd3d34e1f3248ce82ca7ab Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Sun, 28 Oct 2007 12:08:55 +0000 Subject: [PATCH] * DefScript: added initial support for escape sequences "\{ \} \x0A \n \t \\". please report any bugs with this! note: variables MUST be stored unchanged! * changed ListStorage class to TypeStorage template class --- src/Client/DefScript/DefScript.cpp | 213 ++++++++++++++---- src/Client/DefScript/DefScript.h | 19 +- src/Client/DefScript/DefScriptFunctions.cpp | 20 +- src/Client/DefScript/ListStorage.h | 27 --- .../{ListStorage.cpp => TypeStorage.cpp} | 18 +- src/Client/DefScript/TypeStorage.h | 84 +++++++ src/PseuWoW.vcproj | 10 +- 7 files changed, 296 insertions(+), 95 deletions(-) delete mode 100644 src/Client/DefScript/ListStorage.h rename src/Client/DefScript/{ListStorage.cpp => TypeStorage.cpp} (56%) create mode 100644 src/Client/DefScript/TypeStorage.h diff --git a/src/Client/DefScript/DefScript.cpp b/src/Client/DefScript/DefScript.cpp index f095d2d..895b7d1 100644 --- a/src/Client/DefScript/DefScript.cpp +++ b/src/Client/DefScript/DefScript.cpp @@ -83,10 +83,10 @@ void DefScriptPackage::Clear(void) void DefScriptPackage::_InitFunctions(void) { AddFunc("out",&DefScriptPackage::func_out); - AddFunc("set",&DefScriptPackage::func_set); - AddFunc("default",&DefScriptPackage::func_default); + AddFunc("set",&DefScriptPackage::func_set,false); + AddFunc("default",&DefScriptPackage::func_default,false); AddFunc("unset",&DefScriptPackage::func_unset); - AddFunc("shdn",&DefScriptPackage::func_shdn); + AddFunc("shdn",&DefScriptPackage::func_shdn,false); AddFunc("loaddef",&DefScriptPackage::func_loaddef); AddFunc("reloaddef",&DefScriptPackage::func_reloaddef); AddFunc("unloaddef",&DefScriptPackage::func_unloaddef); @@ -147,9 +147,9 @@ void DefScriptPackage::_InitFunctions(void) AddFunc("lsort",&DefScriptPackage::func_lsort); } -void DefScriptPackage::AddFunc(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set)) +void DefScriptPackage::AddFunc(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set), bool esc) { - DefScriptFunctionEntry e(n,f); + DefScriptFunctionEntry e(n,f,esc); AddFunc(e); } @@ -352,7 +352,7 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn){ { if(line[bpos]=='{') bopen++; - if(line[bpos]=='}') + else if(line[bpos]=='}') { if(bpos) bopen--; @@ -362,6 +362,11 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn){ break; } } + else if(line[bpos]=='\\') + { + bpos++; + continue; + } } if(mismatch || bopen) // no bracket must be left open now { @@ -643,14 +648,16 @@ DefReturnResult DefScriptPackage::RunScript(std::string name, CmdSet *pSet,std:: return r; } -DefReturnResult DefScriptPackage::RunSingleLine(std::string line){ +DefReturnResult DefScriptPackage::RunSingleLine(std::string line) +{ DefXChgResult final=ReplaceVars(line,NULL,0,true); CmdSet Set; SplitLine(Set,final.str); return Interpret(Set); } -DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript){ +DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript) +{ CmdSet Set; Set.myname=pScript->GetName(); DefXChgResult final=ReplaceVars(line,&Set,0,true); @@ -658,7 +665,8 @@ DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefS return Interpret(Set); } -void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){ +void DefScriptPackage::SplitLine(CmdSet& Set,std::string line) +{ unsigned int i=0; unsigned int bracketsOpen=0,curParam=0; @@ -670,10 +678,9 @@ void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){ if(line[i]=='{') bracketsOpen++; - if(line[i]=='}') + else if(line[i]=='}') bracketsOpen--; - - if( line[i]==',' && !bracketsOpen) + else if( line[i]==',' && !bracketsOpen) { if(!cmdDefined){ Set.cmd=tempLine; @@ -698,6 +705,11 @@ void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){ break; } + else if(line[i]=='\\') + { + i++; + continue; + } else { tempLine+=line[i]; @@ -710,10 +722,12 @@ void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){ Set.arg[curParam]=tempLine; Set.cmd = DefScriptTools::stringToLower(Set.cmd); // lowercase cmd + Set.cmd = UnescapeString(Set.cmd); // always unescape the cmd! RemoveBrackets(Set); // TODO: call this somewhere else as soon as IF and LOOP statements are implemented! } -std::string DefScriptPackage::RemoveBracketsFromString(std::string t){ +std::string DefScriptPackage::RemoveBracketsFromString(std::string t) +{ if(t.empty()) return t; @@ -724,37 +738,41 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){ } unsigned int ob=0,bo=0; bool isVar=false; - for(unsigned int i=0;i0 && (t[i-1]=='$' || t[i-1]=='?') ) + isVar=true; + if(!bo) + ob=i; + bo++; + } + else if(t[i]=='}') + { + bo--; + if(!bo) { - if(i>0 && (t[i-1]=='$' || t[i-1]=='?') ) - isVar=true; - if(!bo) - ob=i; - bo++; - } - - if(t[i]=='}') - { - bo--; - if(!bo) + if(!isVar) { - if(!isVar) - { - unsigned int blen=i-ob+1; - std::string subStr=t.substr(ob,blen); - std::string retStr=RemoveBracketsFromString(subStr); - t.erase(ob,blen); - t.insert(ob,retStr); - i=ob-1; - - } - isVar=false; + unsigned int blen=i-ob+1; + std::string subStr=t.substr(ob,blen); + std::string retStr=RemoveBracketsFromString(subStr); + t.erase(ob,blen); + t.insert(ob,retStr); + i=ob-1; + } + isVar=false; } } + else if(t[i]=='\\') + { + i++; + continue; + } + + } return t; } @@ -769,8 +787,19 @@ void DefScriptPackage::RemoveBrackets(CmdSet& Set) } } +void DefScriptPackage::UnescapeSet(CmdSet& Set) +{ + Set.defaultarg=UnescapeString(Set.defaultarg); + //Set.cmd=UnescapeString(Set.cmd); // this is done already in SplitLine() ! + for(_CmdSetArgMap::iterator i=Set.arg.begin(); i!=Set.arg.end(); i++) + { + i->second=UnescapeString(i->second); + } +} -DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsigned char VarType, bool run_embedded){ + +DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsigned char VarType, bool run_embedded) +{ unsigned int openingBracket=0, // defines the position from where the recursive call is started @@ -782,14 +811,20 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsig nextVar=DEFSCRIPT_NONE; // '$' or '?' bool hasChanged=false, // additional helper. once true, xchg.result will be true later also - hasVar=false; // true if openingBracket (= the first bracket) was preceded by '$' or '?' + hasVar=false, // true if openingBracket (= the first bracket) was preceded by '$' or '?' + escaped=false; std::string subStr; DefXChgResult xchg; for(unsigned int i=0;i*(_functable[i].func))(Set); + if(_functable[i].escape) + result.ret = EscapeString(result.ret); // and since we are returning a string into the engine, escape it again, if set. return result; } } @@ -996,7 +1042,6 @@ void DefScriptPackage::_UpdateOrCreateScriptByName(std::string sn) Script[sn] = newscript; } -// TODO: add support for safe brackets ( "\{" , "\}" ) and fix the string this way std::string DefScriptPackage::SecureString(std::string s) { std::string out; @@ -1011,3 +1056,81 @@ std::string DefScriptPackage::SecureString(std::string s) } return out; } + +// escapes whole string, which can no longer be parsed & interpreted +std::string DefScriptPackage::EscapeString(std::string s) +{ + std::string out; + out.reserve(s.length()+8); + for(unsigned int i = 0; i < s.length(); i++) + { + switch(s[i]) + { + case '{': + case '}': + case '\\': + out += '\\'; + out += s[i]; + break; + + case '\n': + out += "\\n"; + break; + + case '\t': + out += "\\t"; + break; + + default: + out += s[i]; + } + + } + return out; +} + +// converts a string into a printable form, with all escape sequences resolved +std::string DefScriptPackage::UnescapeString(std::string s) +{ + std::string out; + out.reserve(s.length()); + for(unsigned int i = 0; i < s.length(); i++) + { + if(s[i] == '\\' && i+1 < s.length()) + { + switch(s[i+1]) + { // if any of these are found, append to output string and skip this byte + case '{': + case '}': + case '\\': + out += s[++i]; + break; + + case 'n': + out += '\n'; + i++; + break; + + case 't': + out += '\t'; + i++; + break; + + case 'x': + if(i+4 <= s.length()) + { + std::string xd = s.substr(i+2,2); + char c = (char)strtoul(s.substr(i+2,2).c_str(),NULL,16); + out += c; + i += 3; + } + } + } + else + { + out += s[i]; + } + } + return out; +} + diff --git a/src/Client/DefScript/DefScript.h b/src/Client/DefScript/DefScript.h index 7e76966..1babb86 100644 --- a/src/Client/DefScript/DefScript.h +++ b/src/Client/DefScript/DefScript.h @@ -8,7 +8,7 @@ #include #include "VarSet.h" #include "DynamicEvent.h" -#include "ListStorage.h" +#include "TypeStorage.h" #include "DefScriptTools.h" class DefScriptPackage; @@ -62,17 +62,22 @@ class CmdSet { }; struct DefScriptFunctionEntry { - DefScriptFunctionEntry(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set)) + DefScriptFunctionEntry(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set), bool esc) { name=n; func=f; + escape=esc; } std::string name; DefReturnResult (DefScriptPackage::*func)(CmdSet& Set); + bool escape; }; typedef std::deque DefScriptFunctionTable; +typedef std::deque DefList; +typedef std::map DefListMap; + class DefScript { public: DefScript(DefScriptPackage *p); @@ -123,11 +128,13 @@ public: DefReturnResult RunSingleLineFromScript(std::string line, DefScript *pScript); DefScript_DynamicEventMgr *GetEventMgr(void); void AddFunc(DefScriptFunctionEntry); - void AddFunc(std::string n,DefReturnResult (DefScriptPackage::*)(CmdSet& Set)); + void AddFunc(std::string n,DefReturnResult (DefScriptPackage::*)(CmdSet& Set), bool esc=true); bool HasFunc(std::string); void DelFunc(std::string); - ListStorage lists; - std::string SecureString(std::string s); + TypeStorage lists; + std::string SecureString(std::string); + std::string EscapeString(std::string); + std::string UnescapeString(std::string); // own logging functions. default is printf. // DO NOT USE THEM YET! THEY DO NOT WORK CORRECTLY! @@ -153,8 +160,8 @@ private: void SplitLine(CmdSet&,std::string); DefReturnResult Interpret(CmdSet&); void RemoveBrackets(CmdSet&); + void UnescapeSet(CmdSet&); std::string RemoveBracketsFromString(std::string); - unsigned int functions; void *parentMethod; DefScript_DynamicEventMgr *_eventmgr; std::map Script; diff --git a/src/Client/DefScript/DefScriptFunctions.cpp b/src/Client/DefScript/DefScriptFunctions.cpp index 65d77c9..f1e10ce 100644 --- a/src/Client/DefScript/DefScriptFunctions.cpp +++ b/src/Client/DefScript/DefScriptFunctions.cpp @@ -92,14 +92,18 @@ DefReturnResult DefScriptPackage::func_unset(CmdSet& Set){ return r; } -DefReturnResult DefScriptPackage::func_set(CmdSet& Set){ +DefReturnResult DefScriptPackage::func_set(CmdSet& Set) +{ DefReturnResult r; - if(Set.arg[0].empty()){ + if(Set.arg[0].empty()) + { //if(curIsDebug) // printf("Can't assign value, no variable name given.\n"); return r; } - if(Set.arg[0].at(0)=='@'){ + Set.arg[0]=UnescapeString(Set.arg[0]); + if(Set.arg[0].at(0)=='@') + { //if(curIsDebug) // printf("Can't assign value to a macro!\n"); return r; @@ -120,14 +124,18 @@ DefReturnResult DefScriptPackage::func_set(CmdSet& Set){ return r; } -DefReturnResult DefScriptPackage::func_default(CmdSet& Set){ +DefReturnResult DefScriptPackage::func_default(CmdSet& Set) +{ DefReturnResult r; - if(Set.arg[0].empty()){ + if(Set.arg[0].empty()) + { //if(curIsDebug) // printf("Can't assign value, no variable name given.\n"); return r; } - if(Set.arg[0].at(0)=='@'){ + Set.arg[0]=UnescapeString(Set.arg[0]); + if(Set.arg[0].at(0)=='@') + { //if(curIsDebug) // printf("Can't assign value to a macro!\n"); return r; diff --git a/src/Client/DefScript/ListStorage.h b/src/Client/DefScript/ListStorage.h deleted file mode 100644 index c6c42a7..0000000 --- a/src/Client/DefScript/ListStorage.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef DEFSCRIPT_LISTSTORAGE_H -#define DEFSCRIPT_LISTSTORAGE_H - -#include -#include -#include - -typedef std::deque DefList; -typedef std::map DefListMap; - -class ListStorage -{ -public: - ~ListStorage(); - - bool Exists(std::string); - void Delete(std::string); - DefList *Get(std::string); - DefList *GetNoCreate(std::string); - inline void Assign(std::string s,DefList *l) { _storage[s] = l; } - -private: - DefList *_Create(std::string); - DefListMap _storage; -}; - -#endif diff --git a/src/Client/DefScript/ListStorage.cpp b/src/Client/DefScript/TypeStorage.cpp similarity index 56% rename from src/Client/DefScript/ListStorage.cpp rename to src/Client/DefScript/TypeStorage.cpp index d443115..fe9cdae 100644 --- a/src/Client/DefScript/ListStorage.cpp +++ b/src/Client/DefScript/TypeStorage.cpp @@ -1,6 +1,6 @@ -#include "ListStorage.h" +#include "TypeStorage.h" -bool ListStorage::Exists(std::string s) +template bool TypeStorage::Exists(std::string s) { for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) { @@ -10,14 +10,14 @@ bool ListStorage::Exists(std::string s) return false; } -DefList *ListStorage::_Create(std::string s) +template T *TypeStorage::_Create(std::string s) { - DefList *l = new DefList(); + T *l = new DefList(); _storage[s] = l; return l; } -void ListStorage::Delete(std::string s) +template void TypeStorage::Delete(std::string s) { for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) { @@ -30,21 +30,21 @@ void ListStorage::Delete(std::string s) } } -DefList *ListStorage::GetNoCreate(std::string s) +template T *TypeStorage::GetNoCreate(std::string s) { - for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) + for(std::map::iterator it = _storage.begin(); it != _storage.end(); it++) if(it->first == s) return it->second; return NULL; } -DefList *ListStorage::Get(std::string s) +template T *TypeStorage::Get(std::string s) { DefList *l = GetNoCreate(s); return l ? l : _Create(s); } -ListStorage::~ListStorage() +template TypeStorage::~TypeStorage() { for(DefListMap::iterator it = _storage.begin(); it != _storage.end();) { diff --git a/src/Client/DefScript/TypeStorage.h b/src/Client/DefScript/TypeStorage.h new file mode 100644 index 0000000..40d1c5e --- /dev/null +++ b/src/Client/DefScript/TypeStorage.h @@ -0,0 +1,84 @@ +#ifndef DEFSCRIPT_TYPESTORAGE_H +#define DEFSCRIPT_TYPESTORAGE_H + +#include +#include + +template class TypeStorage +{ +public: + ~TypeStorage(); + bool Exists(std::string); + void Delete(std::string); + T *Get(std::string); + T *GetNoCreate(std::string); + void Assign(std::string,T*); + +private: + T *_Create(std::string); + std::map _storage; +}; + + +template bool TypeStorage::Exists(std::string s) +{ + for(std::map::iterator it = _storage.begin(); it != _storage.end(); it++) + { + if(it->first == s) + return true; + } + return false; +} + +template T *TypeStorage::_Create(std::string s) +{ + T *elem = new T(); + _storage[s] = elem; + return elem; +} + +template void TypeStorage::Delete(std::string s) +{ + for(std::map::iterator it = _storage.begin(); it != _storage.end(); it++) + { + if(it->first == s) + { + delete it->second; + _storage.erase(it); + return; + } + } +} + +template T *TypeStorage::GetNoCreate(std::string s) +{ + for(std::map::iterator it = _storage.begin(); it != _storage.end(); it++) + if(it->first == s) + return it->second; + return NULL; +} + +template T *TypeStorage::Get(std::string s) +{ + T *elem = GetNoCreate(s); + return elem ? elem : _Create(s); +} + +template TypeStorage::~TypeStorage() +{ + for(std::map::iterator it = _storage.begin(); it != _storage.end();) + { + delete it->second; + _storage.erase(it++); + } +} + +template void TypeStorage::Assign(std::string s,T *elem) +{ + if(Exists(s)) + Delete(s) + _storage[s] = elem; +} + + +#endif diff --git a/src/PseuWoW.vcproj b/src/PseuWoW.vcproj index 2af157a..a2b17f4 100644 --- a/src/PseuWoW.vcproj +++ b/src/PseuWoW.vcproj @@ -240,10 +240,16 @@ RelativePath=".\Client\DefScript\DynamicEvent.h"> + RelativePath=".\Client\DefScript\TypeStorage.cpp"> + + + + RelativePath=".\Client\DefScript\TypeStorage.h">