[project @ 2002-08-06 20:48:44 by unknown_lamer]
[clinton/bobotpp.git] / source / BotInterp.C
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>
30 extern "C"
31 {
32 #include <libguile/regex-posix.h>
33 }
34
35 BotInterp::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
43 void
44 BotInterp::Execute(String command)
45 {
46 Interp::Execute(bot, command);
47 }
48
49 void
50 BotInterp::LoadScript(String filename)
51 {
52 Interp::LoadScript(bot, filename);
53 }
54
55 void
56 BotInterp::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
64 namespace
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
72 bool
73 BotInterp::AddHook(int hooktype, SCM regex, SCM function, int pri, bool fall,
74 String name) {
75 if (scm_string_p(regex) == SCM_BOOL_F)
76 return false;
77 String rx = Utils::scm2String(regex).toUpper();
78 SCM r = scm_make_regexp(regex,
79 scm_listify (gh_lookup("regexp/icase"),
80 SCM_UNDEFINED));
81 scm_gc_protect_object(r);
82 scm_gc_protect_object(function);
83 // First, we check if an hook doesn't exist yet
84 std::list<Hook *>::iterator it = hooksMap[hooktype].begin();
85 std::list<Hook *>::iterator it2 = hooksMap[hooktype].end();
86
87 for ( ; it != it2; ++it)
88 // It exists, we replace it.
89 if ((*it)->regex_str == rx && (*it)->name == name) {
90 scm_gc_unprotect_object((*it)->function);
91 scm_gc_unprotect_object (r);
92 (*it)->function = function;
93 (*it)->priority = pri;
94 (*it)->fallthru = fall;
95 hooksMap[hooktype].sort (hptr_lt);
96 return true;
97 }
98 // It does not exist, we create it
99 hooksMap[hooktype].push_back (new Hook(hooktype, rx, r,
100 function, pri, fall, name));
101 hooksMap[hooktype].sort (hptr_lt);
102 return true;
103 }
104
105 bool
106 BotInterp::RunHooks(int hooktype, String match, SCM args)
107 {
108 SCM result;
109 // We want to execute higher priority hooks first, so we start at
110 // the end of the list instead of the beggining
111 std::list<Hook *>::reverse_iterator it = hooksMap[hooktype].rbegin();
112 std::list<Hook *>::reverse_iterator it2 = hooksMap[hooktype].rend();
113 wrapper_data wd;
114 wd.args = args;
115 for ( ; it != it2; ++it) {
116 if (scm_regexp_exec((*it)->regex, Utils::string2SCM(match),
117 SCM_UNDEFINED, SCM_UNDEFINED) != SCM_BOOL_F)
118 {
119 wd.func = (*it)->function;
120 result = gh_catch(SCM_BOOL_T,
121 (scm_t_catch_body) scm_apply_wrapper,
122 static_cast<void *> (&wd),
123 (scm_t_catch_handler) Interp::ErrorHandler, 0);
124 if (! (*it)->fallthru)
125 break;
126 }
127 }
128 return true;
129 }
130
131 SCM
132 BotInterp::AddTimer(int delay, SCM function)
133 {
134 int when = time(NULL) + delay;
135 int c = ++counter;
136 scm_gc_protect_object(function);
137 Timer *t = new Timer(c, when, function);
138 timersList.push_back(t);
139 return scm_long2num (c);
140 }
141
142 bool
143 BotInterp::DelTimer(SCM timer)
144 {
145 int count = scm_num2long(timer, SCM_ARG1, "BotInterp::DelTimer");
146 std::list<Timer *>::iterator it = timersList.begin();
147 std::list<Timer *>::iterator it2 = timersList.end();
148
149 for ( ; it != it2; ++it) {
150 if ((*it)->count == count) {
151 scm_gc_unprotect_object((*it)->function);
152 delete (*it);
153 timersList.erase(it);
154 return true;
155 }
156 }
157 return false;
158 }
159
160 bool
161 BotInterp::RunTimers(int now)
162 {
163 std::list<Timer *>::iterator it = timersList.begin();
164 std::list<Timer *>::iterator it2 = timersList.end();
165 std::list<Timer *>::iterator it3;
166 Timer *t;
167 struct wrapper_data wd;
168 wd.args = scm_listify (SCM_UNDEFINED);
169
170 while (it != it2) {
171 if ((*it)->when <= now) {
172 wd.func = (*it)->function;
173 gh_catch(SCM_BOOL_T, (scm_t_catch_body) scm_apply_wrapper,
174 (void *)&wd, (scm_t_catch_handler) Interp::ErrorHandler, 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