[project @ 2002-07-28 22:17:32 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
17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
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{
38 logPort = scm_open_file(Utils::string2SCM(fn),
39 Utils::string2SCM("a"));
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
55void
56BotInterp::ScriptLog(SCM throw_args)
57{
58 scm_display_error_message(SCM_CADR (throw_args),
59 SCM_CADDR (throw_args),
60 logPort);
61 scm_flush(logPort);
62}
63
be3612f3 64namespace
65{
66 bool hptr_lt (const Hook* h, const Hook* h1)
67 // Hook Pointer less than
68 // Used to sort the Hooks list
69 { return *h < *h1; }
70}
71
cb21075d 72bool
73BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall) {
74 if (scm_string_p(regex) == SCM_BOOL_F)
75 return false;
76 String rx = Utils::scm2String(regex).toUpper();
77 SCM r = scm_make_regexp(regex,
78 scm_listify (gh_lookup("regexp/icase"),
79 SCM_UNDEFINED));
80 scm_gc_protect_object(r);
81 scm_gc_protect_object(function);
82 // First, we check if an hook doesn't exist yet
83 std::list<Hook *>::iterator it = hooksMap[hooktype].begin();
84 std::list<Hook *>::iterator it2 = hooksMap[hooktype].end();
be3612f3 85
cb21075d 86 for ( ; it != it2; ++it)
87 // It exists, we replace it.
88 if ((*it)->regex_str == rx) {
89 scm_gc_unprotect_object((*it)->function);
90 scm_gc_unprotect_object (r);
91 (*it)->function = function;
92 (*it)->priority = pri;
93 (*it)->fallthru = fall;
be3612f3 94 hooksMap[hooktype].sort (hptr_lt);
cb21075d 95 return true;
96 }
97 // It does not exist, we create it
98 hooksMap[hooktype].push_back (new Hook(hooktype, rx, r,
99 function, pri, fall));
be3612f3 100 hooksMap[hooktype].sort (hptr_lt);
cb21075d 101 return true;
102}
103
104bool
105BotInterp::RunHooks(int hooktype, String match, SCM args)
106{
107 SCM result;
ad529fde 108 // We want to execute higher priority hooks first, so we start at
109 // the end of the list instead of the beggining
110 std::list<Hook *>::reverse_iterator it = hooksMap[hooktype].rbegin();
111 std::list<Hook *>::reverse_iterator it2 = hooksMap[hooktype].rend();
cb21075d 112 wrapper_data wd;
113 wd.args = args;
114 for ( ; it != it2; ++it) {
115 if (scm_regexp_exec((*it)->regex, Utils::string2SCM(match),
116 SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F)
117 {
118 wd.func = (*it)->function;
119 result = gh_catch(SCM_BOOL_T,
120 (scm_t_catch_body) scm_apply_wrapper,
121 static_cast<void *> (&wd),
122 (scm_t_catch_handler) Interp::ErrorHandler, 0);
123 if (! (*it)->fallthru)
124 break;
125 }
126 }
127 return true;
128}
129
130SCM
131BotInterp::AddTimer(int delay, SCM function)
132{
133 int when = time(NULL) + delay;
134 int c = ++counter;
135 scm_gc_protect_object(function);
136 Timer *t = new Timer(c, when, function);
137 timersList.push_back(t);
138 return scm_long2num (c);
139}
140
141bool
142BotInterp::DelTimer(SCM timer)
143{
144 int count = scm_num2long(timer, SCM_ARG1, "BotInterp::DelTimer");
145 std::list<Timer *>::iterator it = timersList.begin();
146 std::list<Timer *>::iterator it2 = timersList.end();
147
148 for ( ; it != it2; ++it) {
149 if ((*it)->count == count) {
150 scm_gc_unprotect_object((*it)->function);
151 delete (*it);
152 timersList.erase(it);
153 return true;
154 }
155 }
156 return false;
157}
158
159bool
160BotInterp::RunTimers(int now)
161{
162 std::list<Timer *>::iterator it = timersList.begin();
163 std::list<Timer *>::iterator it2 = timersList.end();
164 std::list<Timer *>::iterator it3;
165 Timer *t;
166 struct wrapper_data wd;
167 wd.args = scm_listify (SCM_UNDEFINED);
168
169 while (it != it2) {
170 if ((*it)->when <= now) {
171 wd.func = (*it)->function;
172 gh_catch(SCM_BOOL_T, (scm_t_catch_body) scm_apply_wrapper,
173 (void *)&wd, (scm_t_catch_handler) Interp::ErrorHandler, 0);
174 scm_gc_unprotect_object(wd.func);
175 it3 = it;
176 ++it3;
177 delete (*it);
178 timersList.erase(it);
179 it = it3;
180 } else {
181 ++it;
182 }
183 }
184 return true;
185}
186
187#endif