1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/* bzflag
* Copyright (c) 1993 - 2008 Tim Riker
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <Python.h>
#include <compile.h>
#include <eval.h>
#include "bzfsAPI.h"
#include "PyBZFlag.h"
BZ_GET_PLUGIN_VERSION
static char *ReadFile (const char *filename);
static Python::BZFlag *module_bzflag;
static PyObject *global_dict;
static char *code_buffer;
class PluginHandler : public bz_APIPluginHandler
{
public:
virtual bool handle (bzApiString plugin, bzApiString param);
};
static void
AppendSysPath (char *directory)
{
PyObject *mod_sys, *dict, *path, *dir;
PyErr_Clear ();
dir = Py_BuildValue ("s", directory);
mod_sys = PyImport_ImportModule ("sys");
dict = PyModule_GetDict (mod_sys);
path = PyDict_GetItemString (dict, "path");
if (!PyList_Check (path))
return;
PyList_Append (path, dir);
if (PyErr_Occurred ())
Py_FatalError ("could not build sys.path");
Py_DECREF (mod_sys);
};
bool
PluginHandler::handle (bzApiString plugin, bzApiString param)
{
const char *filename = plugin.c_str ();
char *buffer = ReadFile (filename);
code_buffer = buffer;
PyErr_Clear();
PyCodeObject *code = (PyCodeObject *) Py_CompileString (buffer, plugin.c_str(), Py_file_input);
if (PyErr_Occurred ()) {
PyErr_Print ();
return false;
}
// eek! totally unportable - append the script's directory to sys.path,
// in case there are any local modules
if (strrchr (filename, '/')) {
int len = strrchr (filename, '/') - filename;
char *dir = new char[len + 1];
strncpy (dir, filename, len);
dir[len] = '\0';
AppendSysPath (dir);
free (dir);
} else {
AppendSysPath (".");
}
PyErr_Clear ();
PyEval_EvalCode (code, global_dict, global_dict);
if (PyErr_Occurred ()) {
PyErr_Print ();
return false;
}
return true;
};
static PluginHandler *py_handler;
BZF_PLUGIN_CALL
int
bz_Load (const char *commandLine)
{
// I would use assert here, but "Assertion `3 == 2' failed" is really not a useful error at all
if (BZ_API_VERSION != 5) {
fprintf (stderr, "Python plugin currently wraps the version 5 API, but BZFS is exporting version %d. Please complain loudly\n", BZ_API_VERSION);
abort ();
}
Py_SetProgramName ("BZFlag");
Py_Initialize ();
PyEval_InitThreads ();
module_bzflag = new Python::BZFlag ();
py_handler = new PluginHandler ();
if (!bz_registerCustomPluginHandler ("py", py_handler))
fprintf (stderr, "couldn't register custom plugin handler\n");
// set up the global dict
// FIXME - should this be per-script?
global_dict = PyDict_New ();
PyDict_SetItemString (global_dict, "__builtins__", PyEval_GetBuiltins ());
PyDict_SetItemString (global_dict, "__name__", PyString_FromString ("__main__"));
return 0;
}
BZF_PLUGIN_CALL
int
bz_Unload (void)
{
PyDict_Clear (global_dict);
Py_DECREF (global_dict);
Py_Finalize ();
delete [] code_buffer;
return 0;
}
static char *
ReadFile (const char *filename)
{
FILE *f = fopen (filename, "r");
unsigned int pos = ftell (f);
fseek (f, 0, SEEK_END);
unsigned int len = ftell (f);
fseek (f, pos, SEEK_SET);
char *buffer = new char[len + 1];
fread (buffer, 1, len, f);
buffer[len] = '\0';
fclose (f);
return buffer;
}
// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
|