[project @ 2005-07-04 01:48:38 by unknown_lamer]
[clinton/bobotpp.git] / source / BotInterp.C
1 // BotInterp.C -*- C++ -*-
2 // Copyright (c) 1998 Etienne BERNARD
3 // Copyright (C) 2002,2005 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., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301, USA.
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "Utils.H"
25 #include "Bot.H"
26 #include "BotInterp.H"
27
28 #ifdef USESCRIPTS
29
30 #include <libguile.h>
31 extern "C"
32 {
33 #include <libguile/regex-posix.h>
34 }
35
36 BotInterp::BotInterp(Bot *b, String fn)
37 : bot(b), counter(0)
38 {
39 logPort = scm_open_file(Utils::str2scm (fn),
40 Utils::str2scm ("a"));
41 scm_gc_protect_object(logPort);
42 }
43
44 void
45 BotInterp::Execute(String command)
46 {
47 Interp::Execute(bot, command);
48 }
49
50 void
51 BotInterp::LoadScript(String filename)
52 {
53 Interp::LoadScript(bot, filename);
54 }
55
56 SCM
57 BotInterp::ScriptLog()
58 {
59 return logPort;
60 }
61
62 namespace
63 {
64 bool hptr_lt (const Hook* h, const Hook* h1)
65 // Hook Pointer less than
66 // Used to sort the Hooks list
67 { return *h < *h1; }
68 }
69
70 bool
71 BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall,
72 String name) {
73 if (scm_string_p(regex) == SCM_BOOL_F)
74 return false;
75 String rx = Utils::to_upper (Utils::scm2str (regex));
76 SCM r = scm_make_regexp(regex,
77 scm_listify (gh_lookup("regexp/icase"),
78 SCM_UNDEFINED));
79 scm_gc_protect_object(r);
80 scm_gc_protect_object(function);
81 // First, we check if an hook doesn't exist yet
82 std::list<Hook *>::iterator it = hooksMap[hooktype].begin();
83 std::list<Hook *>::iterator it2 = hooksMap[hooktype].end();
84
85 for ( ; it != it2; ++it)
86 // It exists, we replace it.
87 if ((*it)->regex_str == rx && (*it)->name == name) {
88 scm_gc_unprotect_object((*it)->function);
89 scm_gc_unprotect_object (r);
90 (*it)->function = function;
91 (*it)->priority = pri;
92 (*it)->fallthru = fall;
93 hooksMap[hooktype].sort (hptr_lt);
94 return true;
95 }
96 // It does not exist, we create it
97 hooksMap[hooktype].push_back (new Hook(hooktype, rx, r,
98 function, pri, fall, name));
99 hooksMap[hooktype].sort (hptr_lt);
100 return true;
101 }
102
103 bool
104 BotInterp::RunHooks(int hooktype, String match, SCM args)
105 {
106 SCM result;
107 // We want to execute higher priority hooks first, so we start at
108 // the end of the list instead of the beggining
109 std::list<Hook *>::reverse_iterator it = hooksMap[hooktype].rbegin();
110 std::list<Hook *>::reverse_iterator it2 = hooksMap[hooktype].rend();
111 wrapper_data wd;
112 wd.args = args;
113 for ( ; it != it2; ++it) {
114 if (scm_regexp_exec((*it)->regex, Utils::str2scm (match),
115 SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F)
116 {
117 wd.func = (*it)->function;
118 result = scm_internal_catch(SCM_BOOL_T,
119 (scm_t_catch_body)
120 Interp::LazyApplyWrapper,
121 static_cast<void *> (&wd),
122 (scm_t_catch_handler) Interp::EmptyHandler, 0);
123 if (! (*it)->fallthru)
124 break;
125 }
126 }
127 return true;
128 }
129
130 SCM
131 BotInterp::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
141 bool
142 BotInterp::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
159 bool
160 BotInterp::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
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 scm_internal_catch(SCM_BOOL_T,
173 (scm_t_catch_body) Interp::LazyApplyWrapper, (void *)&wd,
174 (scm_t_catch_handler) Interp::EmptyHandler, 0);
175 scm_gc_unprotect_object(wd.func);
176 it3 = it;
177 ++it3;
178 delete (*it);
179 timersList.erase(it);
180 it = it3;
181 } else {
182 ++it;
183 }
184 }
185 return true;
186 }
187
188 #endif