* 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)
{
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,9 +738,8 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){
}
unsigned int ob=0,bo=0;
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(i>0 && (t[i-1]=='$' || t[i-1]=='?') )
@ -735,8 +748,7 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){
ob=i;
bo++;
}
if(t[i]=='}')
else if(t[i]=='}')
{
bo--;
if(!bo)
@ -754,6 +766,12 @@ std::string DefScriptPackage::RemoveBracketsFromString(std::string t){
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<str.length();i++)
{
if(str[i]=='{')
if(escaped)
{
escaped=false;
continue;
}
else if(str[i]=='{')
{
if(!bracketsOpen)
openingBracket=i; // var starts with $, normal bracket with {
@ -807,8 +842,7 @@ DefXChgResult DefScriptPackage::ReplaceVars(std::string str, CmdSet *pSet, unsig
}
bracketsOpen++;
}
if(str[i]=='}')
else if(str[i]=='}')
{
if(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 '${}')
i-=(bLen+2); // adjust position
str.insert(i,xchg.str);
if(str[i]=='\\') // workaround, since i will be increased 1 too high
escaped=true;
hasVar=false;
nextVar=DEFSCRIPT_NONE;
}
}
}
} // end if '}'
else if(str[i]=='\\') // if escape char \ found, skip parsing next char
{
i++;
continue;
}
} // end for
if(!bracketsOpen && VarType!=DEFSCRIPT_NONE)
{
@ -966,7 +1007,12 @@ DefReturnResult DefScriptPackage::Interpret(CmdSet& Set)
{
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);
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;
}

View File

@ -8,7 +8,7 @@
#include <fstream>
#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<DefScriptFunctionEntry> DefScriptFunctionTable;
typedef std::deque<std::string> DefList;
typedef std::map<std::string,DefList*> 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<DefList> 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<std::string,DefScript*> Script;

View File

@ -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;

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++)
{
@ -10,14 +10,14 @@ bool ListStorage::Exists(std::string s)
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;
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++)
{
@ -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)
return it->second;
return NULL;
}
DefList *ListStorage::Get(std::string s)
template<class T> T *TypeStorage<T>::Get(std::string s)
{
DefList *l = GetNoCreate(s);
return l ? l : _Create(s);
}
ListStorage::~ListStorage()
template<class T> TypeStorage<T>::~TypeStorage()
{
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">
</File>
<File
RelativePath=".\Client\DefScript\ListStorage.cpp">
RelativePath=".\Client\DefScript\TypeStorage.cpp">
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="TRUE">
<Tool
Name="VCCLCompilerTool"/>
</FileConfiguration>
</File>
<File
RelativePath=".\Client\DefScript\ListStorage.h">
RelativePath=".\Client\DefScript\TypeStorage.h">
</File>
<File
RelativePath=".\Client\DefScript\VarSet.cpp">