// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "Utils.H" #include "Bot.H" #include "BotInterp.H" #ifdef USESCRIPTS #include extern "C" { #include // SCM scm_regexp_p(SCM); } BotInterp::BotInterp(Bot *b, String fn) : bot(b), counter(0) { logPort = scm_open_file(Utils::string2SCM(fn), Utils::string2SCM("a")); scm_gc_protect_object(logPort); } void BotInterp::Execute(String command) { Interp::Execute(bot, command); } void BotInterp::LoadScript(String filename) { Interp::LoadScript(bot, filename); } void BotInterp::ScriptLog(SCM throw_args) { scm_display_error_message(SCM_CADR (throw_args), SCM_CADDR (throw_args), logPort); scm_flush(logPort); } bool BotInterp::AddHook(int hooktype, SCM regex, SCM function) { if (scm_string_p(regex) == SCM_BOOL_F) return false; String rx = Utils::scm2String(regex).toUpper(); 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) { scm_gc_unprotect_object((*it)->function); (*it)->function = function; return true; } // It does not exist, we create it hooksMap[hooktype].push_back (new Hook(hooktype, rx, r, function)); return true; } bool BotInterp::RunHooks(int hooktype, String match, SCM args) { SCM result; std::list::iterator it = hooksMap[hooktype].begin(); std::list::iterator it2 = hooksMap[hooktype].end(); struct wrapper_data wd; wd.args = args; for ( ; it != it2; ++it) { wd.func = (*it)->function; if (scm_regexp_exec((*it)->regex, Utils::string2SCM(match), SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F) { result = gh_catch(SCM_BOOL_T, (scm_t_catch_body) scm_apply_wrapper, (void *)&wd, (scm_t_catch_handler) Interp::ErrorHandler, 0); // TODO: add tf like hooks system... // break; //if (result != SCM_BOOL_T) 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; Timer *t; struct wrapper_data wd; wd.args = scm_listify (SCM_UNDEFINED); while (it != it2) { if ((*it)->when <= now) { wd.func = (*it)->function; gh_catch(SCM_BOOL_T, (scm_t_catch_body) scm_apply_wrapper, (void *)&wd, (scm_t_catch_handler) Interp::ErrorHandler, 0); scm_gc_unprotect_object(wd.func); it3 = it; ++it3; delete (*it); timersList.erase(it); it = it3; } else { ++it; } } return true; } #endif