[project @ 2005-06-28 10:08:45 by unknown_lamer]
[clinton/bobotpp.git] / source / BotInterp.C
CommitLineData
cb21075d 1// BotInterp.C -*- C++ -*-
2// Copyright (c) 1998 Etienne BERNARD
3// Copyright (C) 2002 Clinton Ebadi
4
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
39b022cb 17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
cb21075d 18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "Utils.H"
24#include "Bot.H"
25#include "BotInterp.H"
26
27#ifdef USESCRIPTS
28
29#include <libguile.h>
30extern "C"
31{
32#include <libguile/regex-posix.h>
33}
34
35BotInterp::BotInterp(Bot *b, String fn)
36 : bot(b), counter(0)
37{
a6339323 38 logPort = scm_open_file(Utils::str2scm (fn),
39 Utils::str2scm ("a"));
cb21075d 40 scm_gc_protect_object(logPort);
41}
42
43void
44BotInterp::Execute(String command)
45{
46 Interp::Execute(bot, command);
47}
48
49void
50BotInterp::LoadScript(String filename)
51{
52 Interp::LoadScript(bot, filename);
53}
54
d56bdd22 55SCM
56BotInterp::ScriptLog()
cb21075d 57{
d56bdd22 58 return logPort;
cb21075d 59}
60
be3612f3 61namespace
62{
63 bool hptr_lt (const Hook* h, const Hook* h1)
64 // Hook Pointer less than
65 // Used to sort the Hooks list
66 { return *h < *h1; }
67}
68
cb21075d 69bool
fd7440f1 70BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall,
71 String name) {
cb21075d 72 if (scm_string_p(regex) == SCM_BOOL_F)
73 return false;
a6339323 74 String rx = Utils::to_upper (Utils::scm2str (regex));
cb21075d 75 SCM r = scm_make_regexp(regex,
76 scm_listify (gh_lookup("regexp/icase"),
77 SCM_UNDEFINED));
78 scm_gc_protect_object(r);
79 scm_gc_protect_object(function);
80 // First, we check if an hook doesn't exist yet
81 std::list<Hook *>::iterator it = hooksMap[hooktype].begin();
82 std::list<Hook *>::iterator it2 = hooksMap[hooktype].end();
be3612f3 83
cb21075d 84 for ( ; it != it2; ++it)
85 // It exists, we replace it.
fd7440f1 86 if ((*it)->regex_str == rx && (*it)->name == name) {
cb21075d 87 scm_gc_unprotect_object((*it)->function);
88 scm_gc_unprotect_object (r);
89 (*it)->function = function;
90 (*it)->priority = pri;
91 (*it)->fallthru = fall;
be3612f3 92 hooksMap[hooktype].sort (hptr_lt);
cb21075d 93 return true;
94 }
95 // It does not exist, we create it
96 hooksMap[hooktype].push_back (new Hook(hooktype, rx, r,
fd7440f1 97 function, pri, fall, name));
be3612f3 98 hooksMap[hooktype].sort (hptr_lt);
cb21075d 99 return true;
100}
101
102bool
103BotInterp::RunHooks(int hooktype, String match, SCM args)
104{
105 SCM result;
ad529fde 106 // We want to execute higher priority hooks first, so we start at
107 // the end of the list instead of the beggining
108 std::list<Hook *>::reverse_iterator it = hooksMap[hooktype].rbegin();
109 std::list<Hook *>::reverse_iterator it2 = hooksMap[hooktype].rend();
cb21075d 110 wrapper_data wd;
111 wd.args = args;
112 for ( ; it != it2; ++it) {
a6339323 113 if (scm_regexp_exec((*it)->regex, Utils::str2scm (match),
cb21075d 114 SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F)
115 {
116 wd.func = (*it)->function;
d56bdd22 117 result = scm_internal_catch(SCM_BOOL_T,
118 (scm_t_catch_body) lazy_apply_wrapper,
119 static_cast<void *> (&wd),
120 (scm_t_catch_handler) empty_handler, 0);
cb21075d 121 if (! (*it)->fallthru)
122 break;
123 }
124 }
125 return true;
126}
127
128SCM
129BotInterp::AddTimer(int delay, SCM function)
130{
131 int when = time(NULL) + delay;
132 int c = ++counter;
133 scm_gc_protect_object(function);
134 Timer *t = new Timer(c, when, function);
135 timersList.push_back(t);
136 return scm_long2num (c);
137}
138
139bool
140BotInterp::DelTimer(SCM timer)
141{
142 int count = scm_num2long(timer, SCM_ARG1, "BotInterp::DelTimer");
143 std::list<Timer *>::iterator it = timersList.begin();
144 std::list<Timer *>::iterator it2 = timersList.end();
145
146 for ( ; it != it2; ++it) {
147 if ((*it)->count == count) {
148 scm_gc_unprotect_object((*it)->function);
149 delete (*it);
150 timersList.erase(it);
151 return true;
152 }
153 }
154 return false;
155}
156
157bool
158BotInterp::RunTimers(int now)
159{
160 std::list<Timer *>::iterator it = timersList.begin();
161 std::list<Timer *>::iterator it2 = timersList.end();
162 std::list<Timer *>::iterator it3;
cf8ea873 163
cb21075d 164 struct wrapper_data wd;
165 wd.args = scm_listify (SCM_UNDEFINED);
166
167 while (it != it2) {
168 if ((*it)->when <= now) {
169 wd.func = (*it)->function;
d56bdd22 170 scm_internal_catch(SCM_BOOL_T,
171 (scm_t_catch_body) lazy_apply_wrapper, (void *)&wd,
172 (scm_t_catch_handler) empty_handler, 0);
cb21075d 173 scm_gc_unprotect_object(wd.func);
174 it3 = it;
175 ++it3;
176 delete (*it);
177 timersList.erase(it);
178 it = it3;
179 } else {
180 ++it;
181 }
182 }
183 return true;
184}
185
186#endif