danderson@3977: /**
danderson@3977: * vim: set ts=4 sts=4 sw=4 tw=99 noet:
danderson@3977: * =============================================================================
danderson@3977: * SourceMod
danderson@3977: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
danderson@3977: * =============================================================================
danderson@3977: *
danderson@3977: * This program is free software; you can redistribute it and/or modify it under
danderson@3977: * the terms of the GNU General Public License, version 3.0, as published by the
danderson@3977: * Free Software Foundation.
danderson@3977: *
danderson@3977: * This program is distributed in the hope that it will be useful, but WITHOUT
danderson@3977: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
danderson@3977: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
danderson@3977: * details.
danderson@3977: *
danderson@3977: * You should have received a copy of the GNU General Public License along with
danderson@3977: * this program. If not, see .
danderson@3977: *
danderson@3977: * As a special exception, AlliedModders LLC gives you permission to link the
danderson@3977: * code of this program (as well as its derivative works) to "Half-Life 2," the
danderson@3977: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
danderson@3977: * by the Valve Corporation. You must obey the GNU General Public License in
danderson@3977: * all respects for all other code used. Additionally, AlliedModders LLC grants
danderson@3977: * this exception to all derivative works. AlliedModders LLC defines further
danderson@3977: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
danderson@3977: * or .
danderson@3977: *
danderson@3977: * Version: $Id$
danderson@3977: */
danderson@3977:
danderson@3977: #include
danderson@3977: #include
danderson@3977: #include
danderson@3977: #include "x86/jit_x86.h"
danderson@3977: #include "dll_exports.h"
danderson@3977: #include "sp_vm_engine.h"
danderson@3977: #include "engine2.h"
danderson@3977:
danderson@3977: using namespace SourcePawn;
danderson@3977:
danderson@3977: SourcePawnEngine2 g_engine2;
danderson@3977:
danderson@3977: #ifdef SPSHELL
danderson@3977: template class AutoT
danderson@3977: {
danderson@3977: public:
danderson@3977: AutoT(T *t)
danderson@3977: : t_(t)
danderson@3977: {
danderson@3977: }
danderson@3977: ~AutoT()
danderson@3977: {
danderson@3977: delete t_;
danderson@3977: }
danderson@3977:
danderson@3977: operator T *() const {
danderson@3977: return t_;
danderson@3977: }
danderson@3977: bool operator !() const {
danderson@3977: return !t_;
danderson@3977: }
danderson@3977: T * operator ->() const {
danderson@3977: return t_;
danderson@3977: }
danderson@3977: private:
danderson@3977: T *t_;
danderson@3977: };
danderson@3977:
danderson@3977: class ShellDebugListener : public IDebugListener
danderson@3977: {
danderson@3977: public:
danderson@3977: void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error) {
danderson@3977: int n_err = error->GetErrorCode();
danderson@3977:
danderson@3977: if (n_err != SP_ERROR_NATIVE)
danderson@3977: {
danderson@3977: fprintf(stderr, "plugin error: %s\n", error->GetErrorString());
danderson@3977: }
danderson@3977:
danderson@3977: if (const char *lastname = error->GetLastNative(NULL))
danderson@3977: {
danderson@3977: if (const char *custerr = error->GetCustomErrorString())
danderson@3977: {
danderson@3977: fprintf(stderr, "Native \"%s\" reported: %s", lastname, custerr);
danderson@3977: } else {
danderson@3977: fprintf(stderr, "Native \"%s\" encountered a generic error.", lastname);
danderson@3977: }
danderson@3977: }
danderson@3977:
danderson@3977: if (!error->DebugInfoAvailable())
danderson@3977: {
danderson@3977: fprintf(stderr, "Debug info not available!\n");
danderson@3977: return;
danderson@3977: }
danderson@3977:
danderson@3977: CallStackInfo stk_info;
danderson@3977: int i = 0;
danderson@3977: fprintf(stderr, "Displaying call stack trace:\n");
danderson@3977: while (error->GetTraceInfo(&stk_info))
danderson@3977: {
danderson@3977: fprintf(stderr,
danderson@3977: " [%d] Line %d, %s::%s()",
danderson@3977: i++,
danderson@3977: stk_info.line,
danderson@3977: stk_info.filename,
danderson@3977: stk_info.function);
danderson@3977: }
danderson@3977: }
danderson@3977:
danderson@3977: void OnDebugSpew(const char *msg, ...) {
danderson@3977: #if !defined(NDEBUG) && defined(DEBUG)
danderson@3977: va_list ap;
danderson@3977: va_start(ap, msg);
danderson@3977: vfprintf(stderr, msg, ap);
danderson@3977: va_end(ap);
danderson@3977: #endif
danderson@3977: }
danderson@3977: };
danderson@3977:
danderson@3977: static cell_t Print(IPluginContext *cx, const cell_t *params)
danderson@3977: {
danderson@3977: char *p;
danderson@3977: cx->LocalToString(params[1], &p);
danderson@3977:
danderson@3977: return printf("%s", p);
danderson@3977: }
danderson@3977:
danderson@3977: static cell_t PrintNum(IPluginContext *cx, const cell_t *params)
danderson@3977: {
danderson@3977: return printf("%d\n", params[1]);
danderson@3977: }
danderson@3977:
danderson@3977: static cell_t PrintNums(IPluginContext *cx, const cell_t *params)
danderson@3977: {
danderson@3977: for (size_t i = 1; i <= size_t(params[0]); i++) {
danderson@3977: int err;
danderson@3977: cell_t *addr;
danderson@3977: if ((err = cx->LocalToPhysAddr(params[i], &addr)) != SP_ERROR_NONE)
danderson@3977: return cx->ThrowNativeErrorEx(err, "Could not read argument");
danderson@3977: fprintf(stdout, "%d", *addr);
danderson@3977: if (i != size_t(params[0]))
danderson@3977: fprintf(stdout, ", ");
danderson@3977: }
danderson@3977: fprintf(stdout, "\n");
danderson@3977: return 1;
danderson@3977: }
danderson@3977:
dvander@3983: static cell_t DoNothing(IPluginContext *cx, const cell_t *params)
dvander@3983: {
dvander@3983: return 1;
dvander@3983: }
dvander@3983:
danderson@3977: static void BindNative(IPluginRuntime *rt, const char *name, SPVM_NATIVE_FUNC fn)
danderson@3977: {
danderson@3977: int err;
danderson@3977: uint32_t index;
danderson@3977: if ((err = rt->FindNativeByName(name, &index)) != SP_ERROR_NONE)
danderson@3977: return;
danderson@3977:
danderson@3977: sp_native_t *native;
danderson@3977: if (rt->GetNativeByIndex(index, &native) != SP_ERROR_NONE)
danderson@3977: return;
danderson@3977:
danderson@3977: native->pfn = fn;
danderson@3977: native->status = SP_NATIVE_BOUND;
danderson@3977: }
danderson@3977:
danderson@3977: static cell_t PrintFloat(IPluginContext *cx, const cell_t *params)
danderson@3977: {
danderson@3977: return printf("%f\n", sp_ctof(params[1]));
danderson@3977: }
danderson@3977:
danderson@3977: static int Execute(const char *file)
danderson@3977: {
danderson@3977: ICompilation *co = g_engine2.StartCompilation();
danderson@3977: if (!co) {
danderson@3977: fprintf(stderr, "Could not create a compilation context\n");
danderson@3977: return 1;
danderson@3977: }
danderson@3977:
danderson@3977: int err;
danderson@3977: AutoT rt(g_engine2.LoadPlugin(co, file, &err));
danderson@3977: if (!rt) {
danderson@3977: fprintf(stderr, "Could not load plugin: %s\n", g_engine1.GetErrorString(err));
danderson@3977: return 1;
danderson@3977: }
danderson@3977:
danderson@3977: BindNative(rt, "print", Print);
danderson@3977: BindNative(rt, "printnum", PrintNum);
danderson@3977: BindNative(rt, "printnums", PrintNums);
danderson@3977: BindNative(rt, "printfloat", PrintFloat);
dvander@3983: BindNative(rt, "donothing", DoNothing);
danderson@3977:
danderson@3977: IPluginFunction *fun = rt->GetFunctionByName("main");
danderson@3977: if (!fun)
danderson@3977: return 0;
danderson@3977:
danderson@3977: IPluginContext *cx = rt->GetDefaultContext();
danderson@3977:
danderson@3977: int result = fun->Execute2(cx, &err);
danderson@3977: if (err != SP_ERROR_NONE) {
danderson@3977: fprintf(stderr, "Error executing main(): %s\n", g_engine1.GetErrorString(err));
danderson@3977: return 1;
danderson@3977: }
danderson@3977:
danderson@3977: return result;
danderson@3977: }
danderson@3977:
danderson@3977: int main(int argc, char **argv)
danderson@3977: {
danderson@3977: if (argc != 2) {
danderson@3977: fprintf(stderr, "Usage: \n");
danderson@3977: return 1;
danderson@3977: }
danderson@3977:
danderson@3977: if (!g_engine2.Initialize()) {
danderson@3977: fprintf(stderr, "Could not initialize ISourcePawnEngine2\n");
danderson@3977: return 1;
danderson@3977: }
danderson@3977:
danderson@3977: ShellDebugListener debug;
danderson@3977: g_engine1.SetDebugListener(&debug);
danderson@3977:
danderson@3977: int errcode = Execute(argv[1]);
danderson@3977:
danderson@3977: g_engine1.SetDebugListener(NULL);
danderson@3977: g_engine2.Shutdown();
danderson@3977: return errcode;
danderson@3977: }
danderson@3977:
danderson@3977: #else
danderson@3977: EXPORTFUNC ISourcePawnEngine *GetSourcePawnEngine1()
danderson@3977: {
danderson@3977: return &g_engine1;
danderson@3977: }
danderson@3977:
danderson@3977: EXPORTFUNC ISourcePawnEngine2 *GetSourcePawnEngine2()
danderson@3977: {
danderson@3977: return &g_engine2;
danderson@3977: }
danderson@3977: #endif
danderson@3977:
danderson@3977: #if defined __linux__ || defined __APPLE__
danderson@3977: extern "C" void __cxa_pure_virtual(void)
danderson@3977: {
danderson@3977: }
danderson@3977:
danderson@3977: void *operator new(size_t size)
danderson@3977: {
danderson@3977: return malloc(size);
danderson@3977: }
danderson@3977:
danderson@3977: void *operator new[](size_t size)
danderson@3977: {
danderson@3977: return malloc(size);
danderson@3977: }
danderson@3977:
danderson@3977: void operator delete(void *ptr)
danderson@3977: {
danderson@3977: free(ptr);
danderson@3977: }
danderson@3977:
danderson@3977: void operator delete[](void * ptr)
danderson@3977: {
danderson@3977: free(ptr);
danderson@3977: }
danderson@3977: #endif
danderson@3977: