00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: mycallable.c,v 1.4 2006-01-05 20:42:42 sven Exp $";
00022 #endif
00023
00024 #include <Python.h>
00025 #include <eggdrop/eggdrop.h>
00026
00027 #include "pythonscript.h"
00028
00029 static char *ParameterType(int Type) {
00030 if (Type == SCRIPT_STRING) return "a string";
00031 if (Type == SCRIPT_STRING_LIST) return "a list of strings";
00032 if (Type == SCRIPT_INTEGER) return "an integer";
00033 if (Type == SCRIPT_UNSIGNED) return "an integer (or a small long)";
00034 if (Type == SCRIPT_POINTER) return "a C pointer (what's that good for?)";
00035 if (Type == SCRIPT_CALLBACK) return "a python function";
00036 if (Type == SCRIPT_USER) return "an eggdrop user";
00037 if (Type == SCRIPT_PARTIER) return "a partyline user (ATM this is just an int)";
00038 if (Type == SCRIPT_BYTES) return "a string containing binary data";
00039 if (Type == SCRIPT_VAR) return "no idea";
00040 return "some kind of object I've never heard about";
00041 }
00042
00043 static PyObject *my_command_handler(PyObject *self, PyObject *pythonargs, PyObject *kwd) {
00044 script_var_t retval;
00045 script_args_t args;
00046 CallableObject *Instance = (CallableObject *) self;
00047 script_raw_command_t *cmd = Instance->client_data;
00048
00049 if (Instance->type != PYTHON_FUNC) {
00050 PyErr_SetString(PyExc_TypeError, "Object is not callable");
00051 return 0;
00052 }
00053
00054 if (!cmd) {
00055 PyErr_SetString(PyExc_TypeError, "'callable' object is not callable. The C function has been removed. "
00056 "DON'T KEEP REFERENCES TO EGGDROP FUNCTIONS!");
00057 return 0;
00058 }
00059
00060 retval.type = 0;
00061 retval.value = 0;
00062 retval.len = -1;
00063
00064 args.module = &my_script_interface;
00065 args.client_data = pythonargs;
00066 args.len = PyObject_Length(pythonargs);
00067
00068 cmd->callback(cmd->client_data, &args, &retval);
00069 if (retval.type & SCRIPT_ERROR) {
00070 if (PyErr_Occurred()) return 0;
00071 if (retval.type & SCRIPT_STRING) PyErr_SetString(PyExc_RuntimeError, retval.value);
00072 else PyErr_SetString(PyExc_TypeError, "error message unavailable");
00073 return 0;
00074 }
00075 return c_to_python_var(&retval);
00076 }
00077
00078 static PyObject *Repr(PyObject *self) {
00079 PyObject *Ret, *Repr;
00080 CallableObject *Obj = (CallableObject *) self;
00081 script_linked_var_t *var = Obj->client_data;
00082 script_raw_command_t *func = Obj->client_data;
00083
00084 if (!Obj->client_data) return PyString_FromString("<Expired eggdrop object. DROP THIS REFERENCE!>");
00085 if (Obj->type == PYTHON_FUNC) {
00086 return PyString_FromFormat("<Eggdrop function '%s'>", func->name);
00087 }
00088 Ret = GetVar(var);
00089 if (!Ret) {
00090 PyObject *ExcType, *ExcText, *Trace;
00091 PyErr_Fetch(&ExcType, &ExcText, &Trace);
00092 Repr = PyString_FromFormat("<%s>", PyString_AsString(ExcText));
00093 Py_XDECREF(ExcType);
00094 Py_XDECREF(ExcText);
00095 Py_XDECREF(Trace);
00096 return Repr;
00097 }
00098 Repr = PyObject_Repr(Ret);
00099 Py_DECREF(Ret);
00100 return Repr;
00101 }
00102
00103 static PyObject *GetDoc(PyObject *self, void *ignored) {
00104 CallableObject *Obj = (CallableObject *) self;
00105 script_raw_command_t *func = Obj->client_data;
00106
00107 if (!Obj->client_data) return PyString_FromString("Expired eggdrop object. DROP THIS REFERENCE!");
00108 if (Obj->type == PYTHON_FUNC) {
00109 int minpara, maxpara, i;
00110 char *Parnames, *Pos, *NextPos, *opt = 0;
00111 script_command_t *com = func->client_data;
00112 PyObject *Ret;
00113
00114 minpara = com->nargs;
00115 maxpara = strlen(com->syntax);
00116 if (minpara == maxpara) {
00117 Ret = PyString_FromFormat("This is the internal eggdrop function '%s'.\nIt takes exactly %d parameter%s and returns %s.\nThe parameters are:\n \n", func->name, minpara, minpara == 1 ? "" : "s", (com->flags & SCRIPT_PASS_RETVAL) ? "a variable data type" : ParameterType(com->retval_type));
00118 } else {
00119 Ret = PyString_FromFormat("This is the internal eggdrop function '%s'.\nIt takes at least %d and up to %d parameter%s and returns %s.\nThe parameters are:\n \n", func->name, minpara, maxpara, maxpara == 1 ? "" : "s", ParameterType(com->retval_type));
00120 }
00121 Parnames = malloc(strlen(com->syntax_error) + 1);
00122 strcpy(Parnames, com->syntax_error);
00123 Pos = Parnames;
00124 for (i = 0; i < maxpara; ++i) {
00125 if (Pos) {
00126 NextPos = strchr(Pos, ' ');
00127 if (NextPos) *NextPos = 0;
00128 ++NextPos;
00129 } else {
00130 NextPos = 0;
00131 }
00132 if (Pos && *Pos == '?') opt = " This parameter is optional.";
00133 else opt = "";
00134 PyString_ConcatAndDel(&Ret, PyString_FromFormat("\nParameter %d, %s: %s.%s", i + 1, Pos ? Pos : "?",ParameterType(com->syntax[i]), opt));
00135 Pos = NextPos;
00136 }
00137 free(Parnames);
00138 return Ret;
00139 } else {
00140 return PyString_FromFormat("You shouldn't get this reference. Don't do that! Ever!");
00141 }
00142 }
00143
00144 static PyGetSetDef GetSeter[] = {
00145 {"__doc__", GetDoc, 0, 0, 0},
00146 {0}
00147 };
00148
00149 PyTypeObject Callable_Type = {
00150 PyObject_HEAD_INIT(0)
00151 0,
00152 "eggdrop.callable",
00153 sizeof(CallableObject),
00154 0,
00155 0,
00156 0,
00157 0,
00158 0,
00159 0,
00160 Repr,
00161 0,
00162 0,
00163 0,
00164 0,
00165 my_command_handler,
00166 0,
00167 0,
00168 0,
00169 0,
00170 Py_TPFLAGS_DEFAULT,
00171 "callable eggdrop function",
00172 0,
00173 0,
00174 0,
00175 0,
00176 0,
00177 0,
00178 0,
00179 0,
00180 GetSeter,
00181 0,
00182 0,
00183 0,
00184 0,
00185 0,
00186 0,
00187 0,
00188 0
00189 };