* 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
This commit is contained in:
False.Genesis 2007-10-28 12:08:55 +00:00
parent 6857827169
commit f84037ad77
7 changed files with 296 additions and 95 deletions

View File

@ -83,10 +83,10 @@ void DefScriptPackage::Clear(void)
void DefScriptPackage::_InitFunctions(void) void DefScriptPackage::_InitFunctions(void)
{ {
AddFunc("out",&DefScriptPackage::func_out); AddFunc("out",&DefScriptPackage::func_out);
AddFunc("set",&DefScriptPackage::func_set); AddFunc("set",&DefScriptPackage::func_set,false);
AddFunc("default",&DefScriptPackage::func_default); AddFunc("default",&DefScriptPackage::func_default,false);
AddFunc("unset",&DefScriptPackage::func_unset); AddFunc("unset",&DefScriptPackage::func_unset);
AddFunc("shdn",&DefScriptPackage::func_shdn); AddFunc("shdn",&DefScriptPackage::func_shdn,false);
AddFunc("loaddef",&DefScriptPackage::func_loaddef); AddFunc("loaddef",&DefScriptPackage::func_loaddef);
AddFunc("reloaddef",&DefScriptPackage::func_reloaddef); AddFunc("reloaddef",&DefScriptPackage::func_reloaddef);
AddFunc("unloaddef",&DefScriptPackage::func_unloaddef); AddFunc("unloaddef",&DefScriptPackage::func_unloaddef);
@ -147,9 +147,9 @@ void DefScriptPackage::_InitFunctions(void)
AddFunc("lsort",&DefScriptPackage::func_lsort); 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); AddFunc(e);
} }
@ -352,7 +352,7 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn){
{ {
if(line[bpos]=='{') if(line[bpos]=='{')
bopen++; bopen++;
if(line[bpos]=='}') else if(line[bpos]=='}')
{ {
if(bpos) if(bpos)
bopen--; bopen--;
@ -362,6 +362,11 @@ bool DefScriptPackage::LoadScriptFromFile(std::string fn){
break; break;
} }
} }
else if(line[bpos]=='\\')
{
bpos++;
continue;
}
} }
if(mismatch || bopen) // no bracket must be left open now 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; return r;
} }
DefReturnResult DefScriptPackage::RunSingleLine(std::string line){ DefReturnResult DefScriptPackage::RunSingleLine(std::string line)
{
DefXChgResult final=ReplaceVars(line,NULL,0,true); DefXChgResult final=ReplaceVars(line,NULL,0,true);
CmdSet Set; CmdSet Set;
SplitLine(Set,final.str); SplitLine(Set,final.str);
return Interpret(Set); return Interpret(Set);
} }
DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript){ DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript)
{
CmdSet Set; CmdSet Set;
Set.myname=pScript->GetName(); Set.myname=pScript->GetName();
DefXChgResult final=ReplaceVars(line,&Set,0,true); DefXChgResult final=ReplaceVars(line,&Set,0,true);
@ -658,7 +665,8 @@ DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefS
return Interpret(Set); 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 i=0;
unsigned int bracketsOpen=0,curParam=0; unsigned int bracketsOpen=0,curParam=0;
@ -670,10 +678,9 @@ void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){
if(line[i]=='{') if(line[i]=='{')
bracketsOpen++; bracketsOpen++;
if(line[i]=='}') else if(line[i]=='}')
bracketsOpen--; bracketsOpen--;
else if( line[i]==',' && !bracketsOpen)
if( line[i]==',' && !bracketsOpen)
{ {
if(!cmdDefined){ if(!cmdDefined){
Set.cmd=tempLine; Set.cmd=tempLine;
@ -698,6 +705,11 @@ void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){
break; break;
} }
else if(line[i]=='\\')
{
i++;
continue;
}
else else
{ {
tempLine+=line[i]; tempLine+=line[i];
@ -710,10 +722,12 @@ void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){
Set.arg[curParam]=tempLine; Set.arg[curParam]=tempLine;
Set.cmd = DefScriptTools::stringToLower(Set.cmd); // lowercase cmd 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! 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()) if(t.empty())
return t; return t;
@ -724,9 +738,8 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){
} }
unsigned int ob=0,bo=0; unsigned int ob=0,bo=0;
bool isVar=false; bool isVar=false;
for(unsigned int i=0;i<t.length();i++){ for(unsigned int i=0; i<t.length(); i++)
{
if(t[i]=='{') if(t[i]=='{')
{ {
if(i>0 && (t[i-1]=='$' || t[i-1]=='?') ) if(i>0 && (t[i-1]=='$' || t[i-1]=='?') )
@ -735,8 +748,7 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){
ob=i; ob=i;
bo++; bo++;
} }
else if(t[i]=='}')
if(t[i]=='}')
{ {
bo--; bo--;
if(!bo) if(!bo)
@ -754,6 +766,12 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){
isVar=false; isVar=false;
} }
} }
else if(t[i]=='\\')
{
i++;
continue;
}
} }
return t; 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 unsigned int
openingBracket=0, // defines the position from where the recursive call is started 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 '?' nextVar=DEFSCRIPT_NONE; // '$' or '?'
bool bool
hasChanged=false, // additional helper. once true, xchg.result will be true later also 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; std::string subStr;
DefXChgResult xchg; DefXChgResult xchg;
for(unsigned int i=0;i<str.length();i++) for(unsigned int i=0;i<str.length();i++)
{ {
if(str[i]=='{') if(escaped)
{
escaped=false;
continue;
}
else if(str[i]=='{')
{ {
if(!bracketsOpen) if(!bracketsOpen)
openingBracket=i; // var starts with $, normal bracket with { openingBracket=i; // var starts with $, normal bracket with {
@ -807,8 +842,7 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsig
} }
bracketsOpen++; bracketsOpen++;
} }
else if(str[i]=='}')
if(str[i]=='}')
{ {
if(bracketsOpen) if(bracketsOpen)
bracketsOpen--; bracketsOpen--;
@ -841,12 +875,19 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsig
str.erase(openingBracket-1,bLen+3); // remove ${...} (+3 because of '${}') str.erase(openingBracket-1,bLen+3); // remove ${...} (+3 because of '${}')
i-=(bLen+2); // adjust position i-=(bLen+2); // adjust position
str.insert(i,xchg.str); str.insert(i,xchg.str);
if(str[i]=='\\') // workaround, since i will be increased 1 too high
escaped=true;
hasVar=false; hasVar=false;
nextVar=DEFSCRIPT_NONE; nextVar=DEFSCRIPT_NONE;
} }
} }
} }
} // end if '}' } // end if '}'
else if(str[i]=='\\') // if escape char \ found, skip parsing next char
{
i++;
continue;
}
} // end for } // end for
if(!bracketsOpen && VarType!=DEFSCRIPT_NONE) if(!bracketsOpen && VarType!=DEFSCRIPT_NONE)
{ {
@ -966,7 +1007,12 @@ DefReturnResult DefScriptPackage::Interpret(CmdSet& Set)
{ {
if(Set.cmd==_functable[i].name) if(Set.cmd==_functable[i].name)
{ {
if(_functable[i].escape) // if we are going to use a C++ function, unescape the whole set, if supposed to do so.
UnescapeSet(Set); // it will not have any bad side effects, we leave the func within this block!
result=(this->*(_functable[i].func))(Set); result=(this->*(_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; return result;
} }
} }
@ -996,7 +1042,6 @@ void DefScriptPackage::_UpdateOrCreateScriptByName(std::string sn)
Script[sn] = newscript; Script[sn] = newscript;
} }
// TODO: add support for safe brackets ( "\{" , "\}" ) and fix the string this way
std::string DefScriptPackage::SecureString(std::string s) std::string DefScriptPackage::SecureString(std::string s)
{ {
std::string out; std::string out;
@ -1011,3 +1056,81 @@ std::string DefScriptPackage::SecureString(std::string s)
} }
return out; 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;
}

View File

@ -8,7 +8,7 @@
#include <fstream> #include <fstream>
#include "VarSet.h" #include "VarSet.h"
#include "DynamicEvent.h" #include "DynamicEvent.h"
#include "ListStorage.h" #include "TypeStorage.h"
#include "DefScriptTools.h" #include "DefScriptTools.h"
class DefScriptPackage; class DefScriptPackage;
@ -62,17 +62,22 @@ class CmdSet {
}; };
struct DefScriptFunctionEntry { struct DefScriptFunctionEntry {
DefScriptFunctionEntry(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set)) DefScriptFunctionEntry(std::string n,DefReturnResult (DefScriptPackage::*f)(CmdSet& Set), bool esc)
{ {
name=n; name=n;
func=f; func=f;
escape=esc;
} }
std::string name; std::string name;
DefReturnResult (DefScriptPackage::*func)(CmdSet& Set); DefReturnResult (DefScriptPackage::*func)(CmdSet& Set);
bool escape;
}; };
typedef std::deque<DefScriptFunctionEntry> DefScriptFunctionTable; typedef std::deque<DefScriptFunctionEntry> DefScriptFunctionTable;
typedef std::deque<std::string> DefList;
typedef std::map<std::string,DefList*> DefListMap;
class DefScript { class DefScript {
public: public:
DefScript(DefScriptPackage *p); DefScript(DefScriptPackage *p);
@ -123,11 +128,13 @@ public:
DefReturnResult RunSingleLineFromScript(std::string line, DefScript *pScript); DefReturnResult RunSingleLineFromScript(std::string line, DefScript *pScript);
DefScript_DynamicEventMgr *GetEventMgr(void); DefScript_DynamicEventMgr *GetEventMgr(void);
void AddFunc(DefScriptFunctionEntry); 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); bool HasFunc(std::string);
void DelFunc(std::string); void DelFunc(std::string);
ListStorage lists; TypeStorage<DefList> lists;
std::string SecureString(std::string s); std::string SecureString(std::string);
std::string EscapeString(std::string);
std::string UnescapeString(std::string);
// own logging functions. default is printf. // own logging functions. default is printf.
// DO NOT USE THEM YET! THEY DO NOT WORK CORRECTLY! // DO NOT USE THEM YET! THEY DO NOT WORK CORRECTLY!
@ -153,8 +160,8 @@ private:
void SplitLine(CmdSet&,std::string); void SplitLine(CmdSet&,std::string);
DefReturnResult Interpret(CmdSet&); DefReturnResult Interpret(CmdSet&);
void RemoveBrackets(CmdSet&); void RemoveBrackets(CmdSet&);
void UnescapeSet(CmdSet&);
std::string RemoveBracketsFromString(std::string); std::string RemoveBracketsFromString(std::string);
unsigned int functions;
void *parentMethod; void *parentMethod;
DefScript_DynamicEventMgr *_eventmgr; DefScript_DynamicEventMgr *_eventmgr;
std::map<std::string,DefScript*> Script; std::map<std::string,DefScript*> Script;

View File

@ -92,14 +92,18 @@ DefReturnResult DefScriptPackage::func_unset(CmdSet& Set){
return r; return r;
} }
DefReturnResult DefScriptPackage::func_set(CmdSet& Set){ DefReturnResult DefScriptPackage::func_set(CmdSet& Set)
{
DefReturnResult r; DefReturnResult r;
if(Set.arg[0].empty()){ if(Set.arg[0].empty())
{
//if(curIsDebug) //if(curIsDebug)
// printf("Can't assign value, no variable name given.\n"); // printf("Can't assign value, no variable name given.\n");
return r; return r;
} }
if(Set.arg[0].at(0)=='@'){ Set.arg[0]=UnescapeString(Set.arg[0]);
if(Set.arg[0].at(0)=='@')
{
//if(curIsDebug) //if(curIsDebug)
// printf("Can't assign value to a macro!\n"); // printf("Can't assign value to a macro!\n");
return r; return r;
@ -120,14 +124,18 @@ DefReturnResult DefScriptPackage::func_set(CmdSet& Set){
return r; return r;
} }
DefReturnResult DefScriptPackage::func_default(CmdSet& Set){ DefReturnResult DefScriptPackage::func_default(CmdSet& Set)
{
DefReturnResult r; DefReturnResult r;
if(Set.arg[0].empty()){ if(Set.arg[0].empty())
{
//if(curIsDebug) //if(curIsDebug)
// printf("Can't assign value, no variable name given.\n"); // printf("Can't assign value, no variable name given.\n");
return r; return r;
} }
if(Set.arg[0].at(0)=='@'){ Set.arg[0]=UnescapeString(Set.arg[0]);
if(Set.arg[0].at(0)=='@')
{
//if(curIsDebug) //if(curIsDebug)
// printf("Can't assign value to a macro!\n"); // printf("Can't assign value to a macro!\n");
return r; return r;

View File

@ -1,27 +0,0 @@
#ifndef DEFSCRIPT_LISTSTORAGE_H
#define DEFSCRIPT_LISTSTORAGE_H
#include <string>
#include <deque>
#include <map>
typedef std::deque<std::string> DefList;
typedef std::map<std::string,DefList*> 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

View File

@ -1,6 +1,6 @@
#include "ListStorage.h" #include "TypeStorage.h"
bool ListStorage::Exists(std::string s) template<class T> bool TypeStorage<T>::Exists(std::string s)
{ {
for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++)
{ {
@ -10,14 +10,14 @@ bool ListStorage::Exists(std::string s)
return false; return false;
} }
DefList *ListStorage::_Create(std::string s) template<class T> T *TypeStorage<T>::_Create(std::string s)
{ {
DefList *l = new DefList(); T *l = new DefList();
_storage[s] = l; _storage[s] = l;
return l; return l;
} }
void ListStorage::Delete(std::string s) template<class T> void TypeStorage<T>::Delete(std::string s)
{ {
for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) 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 <class T> T *TypeStorage<T>::GetNoCreate(std::string s)
{ {
for(DefListMap::iterator it = _storage.begin(); it != _storage.end(); it++) for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++)
if(it->first == s) if(it->first == s)
return it->second; return it->second;
return NULL; return NULL;
} }
DefList *ListStorage::Get(std::string s) template<class T> T *TypeStorage<T>::Get(std::string s)
{ {
DefList *l = GetNoCreate(s); DefList *l = GetNoCreate(s);
return l ? l : _Create(s); return l ? l : _Create(s);
} }
ListStorage::~ListStorage() template<class T> TypeStorage<T>::~TypeStorage()
{ {
for(DefListMap::iterator it = _storage.begin(); it != _storage.end();) for(DefListMap::iterator it = _storage.begin(); it != _storage.end();)
{ {

View File

@ -0,0 +1,84 @@
#ifndef DEFSCRIPT_TYPESTORAGE_H
#define DEFSCRIPT_TYPESTORAGE_H
#include <string>
#include <map>
template <class T> 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<std::string,T*> _storage;
};
template<class T> bool TypeStorage<T>::Exists(std::string s)
{
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++)
{
if(it->first == s)
return true;
}
return false;
}
template<class T> T *TypeStorage<T>::_Create(std::string s)
{
T *elem = new T();
_storage[s] = elem;
return elem;
}
template<class T> void TypeStorage<T>::Delete(std::string s)
{
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++)
{
if(it->first == s)
{
delete it->second;
_storage.erase(it);
return;
}
}
}
template <class T> T *TypeStorage<T>::GetNoCreate(std::string s)
{
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end(); it++)
if(it->first == s)
return it->second;
return NULL;
}
template<class T> T *TypeStorage<T>::Get(std::string s)
{
T *elem = GetNoCreate(s);
return elem ? elem : _Create(s);
}
template<class T> TypeStorage<T>::~TypeStorage()
{
for(std::map<std::string,T*>::iterator it = _storage.begin(); it != _storage.end();)
{
delete it->second;
_storage.erase(it++);
}
}
template<class T> void TypeStorage<T>::Assign(std::string s,T *elem)
{
if(Exists(s))
Delete(s)
_storage[s] = elem;
}
#endif

View File

@ -240,10 +240,16 @@
RelativePath=".\Client\DefScript\DynamicEvent.h"> RelativePath=".\Client\DefScript\DynamicEvent.h">
</File> </File>
<File <File
RelativePath=".\Client\DefScript\ListStorage.cpp"> RelativePath=".\Client\DefScript\TypeStorage.cpp">
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath=".\Client\DefScript\ListStorage.h"> RelativePath=".\Client\DefScript\TypeStorage.h">
</File> </File>
<File <File
RelativePath=".\Client\DefScript\VarSet.cpp"> RelativePath=".\Client\DefScript\VarSet.cpp">