|
danderson@3977
|
1 |
/** |
|
danderson@3977
|
2 |
* vim: set ts=4 sts=4 sw=4 tw=99 noet: |
|
danderson@3977
|
3 |
* ============================================================================= |
|
danderson@3977
|
4 |
* SourceMod |
|
danderson@3977
|
5 |
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. |
|
danderson@3977
|
6 |
* ============================================================================= |
|
danderson@3977
|
7 |
* |
|
danderson@3977
|
8 |
* This program is free software; you can redistribute it and/or modify it under |
|
danderson@3977
|
9 |
* the terms of the GNU General Public License, version 3.0, as published by the |
|
danderson@3977
|
10 |
* Free Software Foundation. |
|
danderson@3977
|
11 |
* |
|
danderson@3977
|
12 |
* This program is distributed in the hope that it will be useful, but WITHOUT |
|
danderson@3977
|
13 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
|
danderson@3977
|
14 |
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
|
danderson@3977
|
15 |
* details. |
|
danderson@3977
|
16 |
* |
|
danderson@3977
|
17 |
* You should have received a copy of the GNU General Public License along with |
|
danderson@3977
|
18 |
* this program. If not, see <http://www.gnu.org/licenses/>. |
|
danderson@3977
|
19 |
* |
|
danderson@3977
|
20 |
* As a special exception, AlliedModders LLC gives you permission to link the |
|
danderson@3977
|
21 |
* code of this program (as well as its derivative works) to "Half-Life 2," the |
|
danderson@3977
|
22 |
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software |
|
danderson@3977
|
23 |
* by the Valve Corporation. You must obey the GNU General Public License in |
|
danderson@3977
|
24 |
* all respects for all other code used. Additionally, AlliedModders LLC grants |
|
danderson@3977
|
25 |
* this exception to all derivative works. AlliedModders LLC defines further |
|
danderson@3977
|
26 |
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), |
|
danderson@3977
|
27 |
* or <http://www.sourcemod.net/license.php>. |
|
danderson@3977
|
28 |
* |
|
danderson@3977
|
29 |
* Version: $Id$ |
|
danderson@3977
|
30 |
*/ |
|
danderson@3977
|
31 |
|
|
danderson@3977
|
32 |
#include <sp_vm_api.h> |
|
danderson@3977
|
33 |
#include <stdlib.h> |
|
danderson@3977
|
34 |
#include <stdarg.h> |
|
danderson@3977
|
35 |
#include "x86/jit_x86.h" |
|
danderson@3977
|
36 |
#include "dll_exports.h" |
|
danderson@3977
|
37 |
#include "sp_vm_engine.h" |
|
danderson@3977
|
38 |
#include "engine2.h" |
|
danderson@3977
|
39 |
|
|
danderson@3977
|
40 |
using namespace SourcePawn; |
|
danderson@3977
|
41 |
|
|
danderson@3977
|
42 |
SourcePawnEngine2 g_engine2; |
|
danderson@3977
|
43 |
|
|
danderson@3977
|
44 |
#ifdef SPSHELL |
|
danderson@3977
|
45 |
template <typename T> class AutoT |
|
danderson@3977
|
46 |
{ |
|
danderson@3977
|
47 |
public: |
|
danderson@3977
|
48 |
AutoT(T *t) |
|
danderson@3977
|
49 |
: t_(t) |
|
danderson@3977
|
50 |
{ |
|
danderson@3977
|
51 |
} |
|
danderson@3977
|
52 |
~AutoT() |
|
danderson@3977
|
53 |
{ |
|
danderson@3977
|
54 |
delete t_; |
|
danderson@3977
|
55 |
} |
|
danderson@3977
|
56 |
|
|
danderson@3977
|
57 |
operator T *() const { |
|
danderson@3977
|
58 |
return t_; |
|
danderson@3977
|
59 |
} |
|
danderson@3977
|
60 |
bool operator !() const { |
|
danderson@3977
|
61 |
return !t_; |
|
danderson@3977
|
62 |
} |
|
danderson@3977
|
63 |
T * operator ->() const { |
|
danderson@3977
|
64 |
return t_; |
|
danderson@3977
|
65 |
} |
|
danderson@3977
|
66 |
private: |
|
danderson@3977
|
67 |
T *t_; |
|
danderson@3977
|
68 |
}; |
|
danderson@3977
|
69 |
|
|
danderson@3977
|
70 |
class ShellDebugListener : public IDebugListener |
|
danderson@3977
|
71 |
{ |
|
danderson@3977
|
72 |
public: |
|
danderson@3977
|
73 |
void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error) { |
|
danderson@3977
|
74 |
int n_err = error->GetErrorCode(); |
|
danderson@3977
|
75 |
|
|
danderson@3977
|
76 |
if (n_err != SP_ERROR_NATIVE) |
|
danderson@3977
|
77 |
{ |
|
danderson@3977
|
78 |
fprintf(stderr, "plugin error: %s\n", error->GetErrorString()); |
|
danderson@3977
|
79 |
} |
|
danderson@3977
|
80 |
|
|
danderson@3977
|
81 |
if (const char *lastname = error->GetLastNative(NULL)) |
|
danderson@3977
|
82 |
{ |
|
danderson@3977
|
83 |
if (const char *custerr = error->GetCustomErrorString()) |
|
danderson@3977
|
84 |
{ |
|
danderson@3977
|
85 |
fprintf(stderr, "Native \"%s\" reported: %s", lastname, custerr); |
|
danderson@3977
|
86 |
} else { |
|
danderson@3977
|
87 |
fprintf(stderr, "Native \"%s\" encountered a generic error.", lastname); |
|
danderson@3977
|
88 |
} |
|
danderson@3977
|
89 |
} |
|
danderson@3977
|
90 |
|
|
danderson@3977
|
91 |
if (!error->DebugInfoAvailable()) |
|
danderson@3977
|
92 |
{ |
|
danderson@3977
|
93 |
fprintf(stderr, "Debug info not available!\n"); |
|
danderson@3977
|
94 |
return; |
|
danderson@3977
|
95 |
} |
|
danderson@3977
|
96 |
|
|
danderson@3977
|
97 |
CallStackInfo stk_info; |
|
danderson@3977
|
98 |
int i = 0; |
|
danderson@3977
|
99 |
fprintf(stderr, "Displaying call stack trace:\n"); |
|
danderson@3977
|
100 |
while (error->GetTraceInfo(&stk_info)) |
|
danderson@3977
|
101 |
{ |
|
danderson@3977
|
102 |
fprintf(stderr, |
|
danderson@3977
|
103 |
" [%d] Line %d, %s::%s()", |
|
danderson@3977
|
104 |
i++, |
|
danderson@3977
|
105 |
stk_info.line, |
|
danderson@3977
|
106 |
stk_info.filename, |
|
danderson@3977
|
107 |
stk_info.function); |
|
danderson@3977
|
108 |
} |
|
danderson@3977
|
109 |
} |
|
danderson@3977
|
110 |
|
|
danderson@3977
|
111 |
void OnDebugSpew(const char *msg, ...) { |
|
danderson@3977
|
112 |
#if !defined(NDEBUG) && defined(DEBUG) |
|
danderson@3977
|
113 |
va_list ap; |
|
danderson@3977
|
114 |
va_start(ap, msg); |
|
danderson@3977
|
115 |
vfprintf(stderr, msg, ap); |
|
danderson@3977
|
116 |
va_end(ap); |
|
danderson@3977
|
117 |
#endif |
|
danderson@3977
|
118 |
} |
|
danderson@3977
|
119 |
}; |
|
danderson@3977
|
120 |
|
|
danderson@3977
|
121 |
static cell_t Print(IPluginContext *cx, const cell_t *params) |
|
danderson@3977
|
122 |
{ |
|
danderson@3977
|
123 |
char *p; |
|
danderson@3977
|
124 |
cx->LocalToString(params[1], &p); |
|
danderson@3977
|
125 |
|
|
danderson@3977
|
126 |
return printf("%s", p); |
|
danderson@3977
|
127 |
} |
|
danderson@3977
|
128 |
|
|
danderson@3977
|
129 |
static cell_t PrintNum(IPluginContext *cx, const cell_t *params) |
|
danderson@3977
|
130 |
{ |
|
danderson@3977
|
131 |
return printf("%d\n", params[1]); |
|
danderson@3977
|
132 |
} |
|
danderson@3977
|
133 |
|
|
danderson@3977
|
134 |
static cell_t PrintNums(IPluginContext *cx, const cell_t *params) |
|
danderson@3977
|
135 |
{ |
|
danderson@3977
|
136 |
for (size_t i = 1; i <= size_t(params[0]); i++) { |
|
danderson@3977
|
137 |
int err; |
|
danderson@3977
|
138 |
cell_t *addr; |
|
danderson@3977
|
139 |
if ((err = cx->LocalToPhysAddr(params[i], &addr)) != SP_ERROR_NONE) |
|
danderson@3977
|
140 |
return cx->ThrowNativeErrorEx(err, "Could not read argument"); |
|
danderson@3977
|
141 |
fprintf(stdout, "%d", *addr); |
|
danderson@3977
|
142 |
if (i != size_t(params[0])) |
|
danderson@3977
|
143 |
fprintf(stdout, ", "); |
|
danderson@3977
|
144 |
} |
|
danderson@3977
|
145 |
fprintf(stdout, "\n"); |
|
danderson@3977
|
146 |
return 1; |
|
danderson@3977
|
147 |
} |
|
danderson@3977
|
148 |
|
|
dvander@3983
|
149 |
static cell_t DoNothing(IPluginContext *cx, const cell_t *params) |
|
dvander@3983
|
150 |
{ |
|
dvander@3983
|
151 |
return 1; |
|
dvander@3983
|
152 |
} |
|
dvander@3983
|
153 |
|
|
danderson@3977
|
154 |
static void BindNative(IPluginRuntime *rt, const char *name, SPVM_NATIVE_FUNC fn) |
|
danderson@3977
|
155 |
{ |
|
danderson@3977
|
156 |
int err; |
|
danderson@3977
|
157 |
uint32_t index; |
|
danderson@3977
|
158 |
if ((err = rt->FindNativeByName(name, &index)) != SP_ERROR_NONE) |
|
danderson@3977
|
159 |
return; |
|
danderson@3977
|
160 |
|
|
danderson@3977
|
161 |
sp_native_t *native; |
|
danderson@3977
|
162 |
if (rt->GetNativeByIndex(index, &native) != SP_ERROR_NONE) |
|
danderson@3977
|
163 |
return; |
|
danderson@3977
|
164 |
|
|
danderson@3977
|
165 |
native->pfn = fn; |
|
danderson@3977
|
166 |
native->status = SP_NATIVE_BOUND; |
|
danderson@3977
|
167 |
} |
|
danderson@3977
|
168 |
|
|
danderson@3977
|
169 |
static cell_t PrintFloat(IPluginContext *cx, const cell_t *params) |
|
danderson@3977
|
170 |
{ |
|
danderson@3977
|
171 |
return printf("%f\n", sp_ctof(params[1])); |
|
danderson@3977
|
172 |
} |
|
danderson@3977
|
173 |
|
|
danderson@3977
|
174 |
static int Execute(const char *file) |
|
danderson@3977
|
175 |
{ |
|
danderson@3977
|
176 |
ICompilation *co = g_engine2.StartCompilation(); |
|
danderson@3977
|
177 |
if (!co) { |
|
danderson@3977
|
178 |
fprintf(stderr, "Could not create a compilation context\n"); |
|
danderson@3977
|
179 |
return 1; |
|
danderson@3977
|
180 |
} |
|
danderson@3977
|
181 |
|
|
danderson@3977
|
182 |
int err; |
|
danderson@3977
|
183 |
AutoT<IPluginRuntime> rt(g_engine2.LoadPlugin(co, file, &err)); |
|
danderson@3977
|
184 |
if (!rt) { |
|
danderson@3977
|
185 |
fprintf(stderr, "Could not load plugin: %s\n", g_engine1.GetErrorString(err)); |
|
danderson@3977
|
186 |
return 1; |
|
danderson@3977
|
187 |
} |
|
danderson@3977
|
188 |
|
|
danderson@3977
|
189 |
BindNative(rt, "print", Print); |
|
danderson@3977
|
190 |
BindNative(rt, "printnum", PrintNum); |
|
danderson@3977
|
191 |
BindNative(rt, "printnums", PrintNums); |
|
danderson@3977
|
192 |
BindNative(rt, "printfloat", PrintFloat); |
|
dvander@3983
|
193 |
BindNative(rt, "donothing", DoNothing); |
|
danderson@3977
|
194 |
|
|
danderson@3977
|
195 |
IPluginFunction *fun = rt->GetFunctionByName("main"); |
|
danderson@3977
|
196 |
if (!fun) |
|
danderson@3977
|
197 |
return 0; |
|
danderson@3977
|
198 |
|
|
danderson@3977
|
199 |
IPluginContext *cx = rt->GetDefaultContext(); |
|
danderson@3977
|
200 |
|
|
danderson@3977
|
201 |
int result = fun->Execute2(cx, &err); |
|
danderson@3977
|
202 |
if (err != SP_ERROR_NONE) { |
|
danderson@3977
|
203 |
fprintf(stderr, "Error executing main(): %s\n", g_engine1.GetErrorString(err)); |
|
danderson@3977
|
204 |
return 1; |
|
danderson@3977
|
205 |
} |
|
danderson@3977
|
206 |
|
|
danderson@3977
|
207 |
return result; |
|
danderson@3977
|
208 |
} |
|
danderson@3977
|
209 |
|
|
danderson@3977
|
210 |
int main(int argc, char **argv) |
|
danderson@3977
|
211 |
{ |
|
danderson@3977
|
212 |
if (argc != 2) { |
|
danderson@3977
|
213 |
fprintf(stderr, "Usage: <file>\n"); |
|
danderson@3977
|
214 |
return 1; |
|
danderson@3977
|
215 |
} |
|
danderson@3977
|
216 |
|
|
danderson@3977
|
217 |
if (!g_engine2.Initialize()) { |
|
danderson@3977
|
218 |
fprintf(stderr, "Could not initialize ISourcePawnEngine2\n"); |
|
danderson@3977
|
219 |
return 1; |
|
danderson@3977
|
220 |
} |
|
danderson@3977
|
221 |
|
|
danderson@3977
|
222 |
ShellDebugListener debug; |
|
danderson@3977
|
223 |
g_engine1.SetDebugListener(&debug); |
|
danderson@3977
|
224 |
|
|
danderson@3977
|
225 |
int errcode = Execute(argv[1]); |
|
danderson@3977
|
226 |
|
|
danderson@3977
|
227 |
g_engine1.SetDebugListener(NULL); |
|
danderson@3977
|
228 |
g_engine2.Shutdown(); |
|
danderson@3977
|
229 |
return errcode; |
|
danderson@3977
|
230 |
} |
|
danderson@3977
|
231 |
|
|
danderson@3977
|
232 |
#else |
|
danderson@3977
|
233 |
EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1() |
|
danderson@3977
|
234 |
{ |
|
danderson@3977
|
235 |
return &g_engine1; |
|
danderson@3977
|
236 |
} |
|
danderson@3977
|
237 |
|
|
danderson@3977
|
238 |
EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2() |
|
danderson@3977
|
239 |
{ |
|
danderson@3977
|
240 |
return &g_engine2; |
|
danderson@3977
|
241 |
} |
|
danderson@3977
|
242 |
#endif |
|
danderson@3977
|
243 |
|
|
danderson@3977
|
244 |
#if defined __linux__ || defined __APPLE__ |
|
danderson@3977
|
245 |
extern "C" void __cxa_pure_virtual(void) |
|
danderson@3977
|
246 |
{ |
|
danderson@3977
|
247 |
} |
|
danderson@3977
|
248 |
|
|
danderson@3977
|
249 |
void *operator new(size_t size) |
|
danderson@3977
|
250 |
{ |
|
danderson@3977
|
251 |
return malloc(size); |
|
danderson@3977
|
252 |
} |
|
danderson@3977
|
253 |
|
|
danderson@3977
|
254 |
void *operator new[](size_t size) |
|
danderson@3977
|
255 |
{ |
|
danderson@3977
|
256 |
return malloc(size); |
|
danderson@3977
|
257 |
} |
|
danderson@3977
|
258 |
|
|
danderson@3977
|
259 |
void operator delete(void *ptr) |
|
danderson@3977
|
260 |
{ |
|
danderson@3977
|
261 |
free(ptr); |
|
danderson@3977
|
262 |
} |
|
danderson@3977
|
263 |
|
|
danderson@3977
|
264 |
void operator delete[](void * ptr) |
|
danderson@3977
|
265 |
{ |
|
danderson@3977
|
266 |
free(ptr); |
|
danderson@3977
|
267 |
} |
|
danderson@3977
|
268 |
#endif |
|
danderson@3977
|
269 |
|