#include #include #include #include #include #include #include "VarSet.h" #include "DefScript.h" #include "DefScriptTools.h" // --- SECTION FOR SCRIPT PACKAGES --- DefScriptPackage::DefScriptPackage() { functionTable=_GetFunctionTable(); _eventmgr=new DefScript_DynamicEventMgr(this); } DefScriptPackage::~DefScriptPackage() { delete _eventmgr; Clear(); } void DefScriptPackage::SetParentMethod(void *p) { parentMethod = p; } void DefScriptPackage::Clear(void) { for(std::map::iterator i = Script.begin(); i != Script.end(); i++) { delete i->second; // delete each script } Script.empty(); } DefScriptFunctionTable *DefScriptPackage::_GetFunctionTable(void) const { static DefScriptFunctionTable table[] = { // basic functions: {"out",&DefScriptPackage::func_out}, {"set",&DefScriptPackage::func_set}, {"default",&DefScriptPackage::func_default}, {"unset",&DefScriptPackage::func_unset}, {"shdn",&DefScriptPackage::func_shdn}, {"loaddef",&DefScriptPackage::func_loaddef}, {"reloaddef",&DefScriptPackage::func_reloaddef}, {"setscriptpermission",&DefScriptPackage::func_setscriptpermission}, // mathematical functions: {"toint",&DefScriptPackage::func_toint}, {"add",&DefScriptPackage::func_add}, {"sub",&DefScriptPackage::func_sub}, {"mul",&DefScriptPackage::func_mul}, {"div",&DefScriptPackage::func_div}, {"mod",&DefScriptPackage::func_mod}, {"pow",&DefScriptPackage::func_pow}, {"bitor",&DefScriptPackage::func_bitor}, {"bitand",&DefScriptPackage::func_bitand}, {"bitxor",&DefScriptPackage::func_bitxor}, {"addevent",&DefScriptPackage::func_addevent}, {"removeevent",&DefScriptPackage::func_removeevent}, // user functions: {"pause",&DefScriptPackage::SCpause}, {"emote",&DefScriptPackage::SCemote}, //{"follow",&DefScriptPackage::SCfollow}, {"savecache",&DefScriptPackage::SCsavecache}, {"sendchatmessage",&DefScriptPackage::SCSendChatMessage}, {"joinchannel",&DefScriptPackage::SCjoinchannel}, {"leavechannel",&DefScriptPackage::SCleavechannel}, {"loadconf",&DefScriptPackage::SCloadconf}, {"applyconf",&DefScriptPackage::SCapplyconf}, {"applypermissions",&DefScriptPackage::SCapplypermissions}, {"log",&DefScriptPackage::SClog}, {"logdetail",&DefScriptPackage::SClogdetail}, {"logerror",&DefScriptPackage::SClogerror}, {"logdebug",&DefScriptPackage::SClogdebug}, {"castspell", &DefScriptPackage::SCcastspell}, {"queryitem", &DefScriptPackage::SCqueryitem}, {"target", &DefScriptPackage::SCtarget}, {"loadscp", &DefScriptPackage::SCloadscp}, // table termination {NULL,NULL} }; return table; } void DefScriptPackage::SetFunctionTable(DefScriptFunctionTable *tab) { functionTable=tab; } void DefScriptPackage::SetPath(std::string p){ scPath=p; } DefScript *DefScriptPackage::GetScript(std::string scname){ return ScriptExists(scname) ? Script[scname] : NULL; } unsigned int DefScriptPackage::GetScripts(void){ return Script.size(); } DefScript_DynamicEventMgr *DefScriptPackage::GetEventMgr(void) { return _eventmgr; } bool DefScriptPackage::ScriptExists(std::string name) { for (std::map::iterator i = Script.begin();i != Script.end();i++) if(i->first == name && i->second != NULL) return true; for(unsigned int i=0;functionTable[i].func!=NULL;i++) if(name == functionTable[i].name) return true; return false; } bool DefScriptPackage::LoadByName(std::string name){ return LoadScriptFromFile((scPath+name).append(".def"),name); } bool DefScriptPackage::LoadScriptFromFile(std::string fn, std::string sn){ if(fn.empty() || sn.empty()) return false; std::string label, value, line; std::fstream f; bool load_debug=false,load_notify=false, exec=false; char z; f.open(fn.c_str(),std::ios_base::in); if(!f.is_open()) return false; if(GetScript(sn)) delete GetScript(sn); DefScript *newscript = new DefScript(this); Script[sn] = newscript; Script[sn]->SetName(sn); // necessary that the script knows its own name while(!f.eof()){ line.clear(); while (true) { f.get(z); if(z=='\n' || f.eof()) break; line+=z; } if(line.empty()) continue; // line is empty, proceed with next line while( !line.empty() && (line.at(0)==' ' || line.at(0)=='\t') ) line.erase(0,1); if(line.empty()) continue; if(line.at(0)=='/' && line.at(1)=='/') continue; // line is comment, proceed with next line if(line.at(0)=='#') { line.erase(0,1); // remove # label=line.substr(0,line.find('=',0)); value=line.substr(line.find('=',0)+1,line.length()); if(label=="permission") { scriptPermissionMap[sn] = atoi(value.c_str()); } if(line=="load_debug") load_debug=true; if(line=="load_notify") load_notify=true; if(line=="debug") Script[sn]->SetDebug(true); if(line=="onload") exec=true; if(line=="endonload" || line=="/onload") exec=false; //... continue; // line was an option, not script content } if(load_debug) std::cout<<"~LOAD: "<AddLine(line); else { this->RunSingleLineFromScript(line,Script[sn]); } } f.close(); if(load_notify) std::cout << "+> Script '" << sn << "' [" << fn << "] successfully loaded.\n"; // ... return true; } // --- SECTION FOR THE INDIVIDUAL SCRIPTS IN A PACKAGE --- DefScript::DefScript(DefScriptPackage *p) { _parent=p; scriptname="{NONAME}"; debugmode=false; // printf("--> DefScript inited!\n"); } DefScript::~DefScript() { Clear(); } void DefScript::Clear(void) { Line.clear(); } void DefScript::SetDebug(bool d) { debugmode=d; } bool DefScript::GetDebug(void) { return debugmode; } void DefScript::SetName(std::string name) { scriptname=name; } std::string DefScript::GetName(void) { return scriptname; } unsigned int DefScript::GetLines(void) { return Line.size(); } std::string DefScript::GetLine(unsigned int id) { return Line[id]; } bool DefScript::AddLine(std::string l){ if(l.empty()) return false; Line.insert(Line.end(),l); return true; } // --- SECTION FOR COMMAND SETS --- CmdSet::CmdSet(){ Clear(); } CmdSet::~CmdSet(){ Clear(); } void CmdSet::Clear() { for(unsigned int i=0;icaller=pSet->myname; pSet->myname=name; for(unsigned int i=0;iGetLines();i++) { CmdSet mySet; DefXChgResult final=ReplaceVars(sc->GetLine(i),pSet,0); _DEFSC_DEBUG(printf("DefScript: \"%s\"\n",final.str.c_str())); SplitLine(mySet,final.str); mySet.myname=name; mySet.caller=pSet?pSet->myname:""; r=Interpret(mySet); if(r.mustreturn) { r.mustreturn=false; break; } } return r; } DefReturnResult DefScriptPackage::RunSingleLine(std::string line){ DefXChgResult final=ReplaceVars(line,NULL,0); CmdSet Set; SplitLine(Set,final.str); return Interpret(Set); } DefReturnResult DefScriptPackage::RunSingleLineFromScript(std::string line, DefScript *pScript){ CmdSet Set; Set.myname=pScript->GetName(); DefXChgResult final=ReplaceVars(line,&Set,0); SplitLine(Set,final.str); return Interpret(Set); } void DefScriptPackage::SplitLine(CmdSet& Set,std::string line){ unsigned int i=0; unsigned int bracketsOpen=0,curParam=0; bool cmdDefined=false; std::string tempLine; // extract cmd+params and txt for(i=0;i0 && (t[i-1]=='$' || t[i-1]=='?') ) isVar=true; if(!bo) ob=i; bo++; } if(t[i]=='}') { bo--; if(!bo) { 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; } } } return t; } void DefScriptPackage::RemoveBrackets(CmdSet& Set){ std::string t; for(unsigned int a=0;a0 && str[i-1]=='$') { hasVar=true; if(!bracketsOpen) nextVar=DEFSCRIPT_VAR; } if(i>0 && str[i-1]=='?') { hasVar=true; if(!bracketsOpen) nextVar=DEFSCRIPT_FUNC; } bracketsOpen++; } if(str[i]=='}') { if(bracketsOpen) bracketsOpen--; if(!bracketsOpen) { closingBracket=i; if(nextVar==DEFSCRIPT_NONE && VarType!=DEFSCRIPT_NONE && !hasVar) // remove brackets in var names, like ${var{ia}ble} { str.erase(closingBracket,1); str.erase(openingBracket,1); i=openingBracket; // jump to the pos where the opening bracket was continue; } else { bLen=closingBracket-openingBracket-1; subStr=str.substr(openingBracket+1,bLen); //printf("SUBSTR: \"%s\"\n",subStr.c_str()); xchg=ReplaceVars(subStr,pSet,nextVar); if( nextVar==DEFSCRIPT_NONE && hasVar && xchg.changed ) { str.erase(openingBracket+1,subStr.length()); str.insert(openingBracket+1,xchg.str); hasVar=false; i-=(subStr.length()+1); hasChanged=true; } else if( nextVar!=DEFSCRIPT_NONE && hasVar && xchg.changed ) { str.erase(openingBracket-1,bLen+3); // remove ${...} (+3 because of '${}') i-=(bLen+2); // adjust position str.insert(i,xchg.str); hasVar=false; nextVar=DEFSCRIPT_NONE; } } } } // end if '}' } // end for if(!bracketsOpen && VarType!=DEFSCRIPT_NONE) { if(VarType==DEFSCRIPT_VAR) { std::string vname=_NormalizeVarName(str, (pSet==NULL) ? "" : pSet->myname); if(vname[0]=='@') { std::stringstream vns; std::string subs=vname.substr(1,str.length()-1); unsigned int vn=atoi( subs.c_str() ); vns << vn; if(pSet && vns.str()==subs) // resolve arg macros @0 - @99 str=pSet->arg[vn]; else if(pSet && subs=="def") str=pSet->defaultarg; else if(pSet && subs=="myname") str=pSet->myname; else if(pSet && subs=="cmd") str=pSet->cmd; else if(pSet && subs=="caller") str=pSet->caller; else if(subs=="n") str="\n"; else if(variables.Exists(vname)) str=variables.Get(vname); else { // TODO: call custom macro table //... str.clear(); } xchg.changed=true; } else { if(variables.Exists(vname)) { str=variables.Get(vname); xchg.changed=true; } } } else if(VarType==DEFSCRIPT_FUNC) { DefReturnResult res; if(pSet) res=RunSingleLineFromScript(str,GetScript(pSet->myname)); else res=RunSingleLine(str); str=res.ret; // returns empty string on invalid function!! xchg.result.ok=res.ok; if(res.ok) xchg.changed=true; //xchg.result.err += res.err; } } xchg.str = str; if(hasChanged) xchg.changed=true; return xchg; } std::string DefScriptPackage::_NormalizeVarName(std::string vn_in, std::string sn){ std::string vn=vn_in; bool global=false; while(true) { if(sn.empty()) return vn; if(vn.at(0)=='#') global = true; if(vn.at(0)=='#' || vn.at(0)==':') vn.erase(0,1); else break; } if( (!global) && (vn.at(0)!='@') ) vn=sn+"::"+vn; return vn; } DefReturnResult DefScriptPackage::Interpret(CmdSet& Set) { DefReturnResult result; // first search if the script is defined in the internal functions for(unsigned int i=0;;i++) { if(functionTable[i].func==NULL || functionTable[i].name==NULL) // reached the end of the table? { break; } if(Set.cmd==functionTable[i].name) { result=(this->*functionTable[i].func)(Set); return result; } } if(Set.cmd=="return") { result.mustreturn=true; result.ret=Set.defaultarg; return result; } // if nothing has been found its maybe an external script file to run result=RunScript(Set.cmd, &Set); if((!result.ok) /*&& Script[Set.cmd]->GetDebug()*/) std::cout << "Could not execute script command '" << Set.cmd << "'\n"; return result; }