// BotInterp.C -*- C++ -*- // Copyright (c) 1998 Etienne BERNARD // Copyright (C) 2002 Clinton Ebadi // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "Utils.H" #include "Bot.H" #include "BotInterp.H" #ifdef USESCRIPTS #include extern "C" { #include } BotInterp::BotInterp(Bot *b, String fn) : bot(b), counter(0) { logPort = scm_open_file(Utils::str2scm (fn), Utils::str2scm ("a")); scm_gc_protect_object(logPort); } void BotInterp::Execute(String command) { Interp::Execute(bot, command); } void BotInterp::LoadScript(String filename) { Interp::LoadScript(bot, filename); } SCM BotInterp::ScriptLog() { return logPort; } namespace { bool hptr_lt (const Hook* h, const Hook* h1) // Hook Pointer less than // Used to sort the Hooks list { return *h < *h1; } } bool BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall, String name) { if (scm_string_p(regex) == SCM_BOOL_F) return false; String rx = Utils::to_upper (Utils::scm2str (regex)); SCM r = scm_make_regexp(regex, scm_listify (gh_lookup("regexp/icase"), SCM_UNDEFINED)); scm_gc_protect_object(r); scm_gc_protect_object(function); // First, we check if an hook doesn't exist yet std::list::iterator it = hooksMap[hooktype].begin(); std::list::iterator it2 = hooksMap[hooktype].end(); for ( ; it != it2; ++it) // It exists, we replace it. if ((*it)->regex_str == rx && (*it)->name == name) { scm_gc_unprotect_object((*it)->function); scm_gc_unprotect_object (r); (*it)->function = function; (*it)->priority = pri; (*it)->fallthru = fall; hooksMap[hooktype].sort (hptr_lt); return true; } // It does not exist, we create it hooksMap[hooktype].push_back (new Hook(hooktype, rx, r, function, pri, fall, name)); hooksMap[hooktype].sort (hptr_lt); return true; } bool BotInterp::RunHooks(int hooktype, String match, SCM args) { SCM result; // We want to execute higher priority hooks first, so we start at // the end of the list instead of the beggining std::list::reverse_iterator it = hooksMap[hooktype].rbegin(); std::list::reverse_iterator it2 = hooksMap[hooktype].rend(); wrapper_data wd; wd.args = args; for ( ; it != it2; ++it) { if (scm_regexp_exec((*it)->regex, Utils::str2scm (match), SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F) { wd.func = (*it)->function; result = scm_internal_catch(SCM_BOOL_T, (scm_t_catch_body) lazy_apply_wrapper, static_cast (&wd), (scm_t_catch_handler) empty_handler, 0); if (! (*it)->fallthru) break; } } return true; } SCM BotInterp::AddTimer(int delay, SCM function) { int when = time(NULL) + delay; int c = ++counter; scm_gc_protect_object(function); Timer *t = new Timer(c, when, function); timersList.push_back(t); return scm_long2num (c); } bool BotInterp::DelTimer(SCM timer) { int count = scm_num2long(timer, SCM_ARG1, "BotInterp::DelTimer"); std::list::iterator it = timersList.begin(); std::list::iterator it2 = timersList.end(); for ( ; it != it2; ++it) { if ((*it)->count == count) { scm_gc_unprotect_object((*it)->function); delete (*it); timersList.erase(it); return true; } } return false; } bool BotInterp::RunTimers(int now) { std::list::iterator it = timersList.begin(); std::list::iterator it2 = timersList.end(); std::list::iterator it3; struct wrapper_data wd; wd.args = scm_listify (SCM_UNDEFINED); while (it != it2) { if ((*it)->when <= now) { wd.func = (*it)->function; scm_internal_catch(SCM_BOOL_T, (scm_t_catch_body) lazy_apply_wrapper, (void *)&wd, (scm_t_catch_handler) empty_handler, 0); scm_gc_unprotect_object(wd.func); it3 = it; ++it3; delete (*it); timersList.erase(it); it = it3; } else { ++it; } } return true; } #endif