home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Objects / methodobject.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  5.0 KB  |  251 lines

  1.  
  2. /* Method object implementation */
  3.  
  4. #include "Python.h"
  5.  
  6. #include "token.h"
  7.  
  8. static PyCFunctionObject *free_list = NULL;
  9.  
  10. PyObject *
  11. PyCFunction_New(PyMethodDef *ml, PyObject *self)
  12. {
  13.     PyCFunctionObject *op;
  14.     op = free_list;
  15.     if (op != NULL) {
  16.         free_list = (PyCFunctionObject *)(op->m_self);
  17.         PyObject_INIT(op, &PyCFunction_Type);
  18.     }
  19.     else {
  20.         op = PyObject_NEW(PyCFunctionObject, &PyCFunction_Type);
  21.         if (op == NULL)
  22.             return NULL;
  23.     }
  24.     op->m_ml = ml;
  25.     Py_XINCREF(self);
  26.     op->m_self = self;
  27.     return (PyObject *)op;
  28. }
  29.  
  30. PyCFunction
  31. PyCFunction_GetFunction(PyObject *op)
  32. {
  33.     if (!PyCFunction_Check(op)) {
  34.         PyErr_BadInternalCall();
  35.         return NULL;
  36.     }
  37.     return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
  38. }
  39.  
  40. PyObject *
  41. PyCFunction_GetSelf(PyObject *op)
  42. {
  43.     if (!PyCFunction_Check(op)) {
  44.         PyErr_BadInternalCall();
  45.         return NULL;
  46.     }
  47.     return ((PyCFunctionObject *)op) -> m_self;
  48. }
  49.  
  50. int
  51. PyCFunction_GetFlags(PyObject *op)
  52. {
  53.     if (!PyCFunction_Check(op)) {
  54.         PyErr_BadInternalCall();
  55.         return -1;
  56.     }
  57.     return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
  58. }
  59.  
  60. /* Methods (the standard built-in methods, that is) */
  61.  
  62. static void
  63. meth_dealloc(PyCFunctionObject *m)
  64. {
  65.     Py_XDECREF(m->m_self);
  66.     m->m_self = (PyObject *)free_list;
  67.     free_list = m;
  68. }
  69.  
  70. static PyObject *
  71. meth_getattr(PyCFunctionObject *m, char *name)
  72. {
  73.     if (strcmp(name, "__name__") == 0) {
  74.         return PyString_FromString(m->m_ml->ml_name);
  75.     }
  76.     if (strcmp(name, "__doc__") == 0) {
  77.         char *doc = m->m_ml->ml_doc;
  78.         if (doc != NULL)
  79.             return PyString_FromString(doc);
  80.         Py_INCREF(Py_None);
  81.         return Py_None;
  82.     }
  83.     if (strcmp(name, "__self__") == 0) {
  84.         PyObject *self;
  85.         if (PyEval_GetRestricted()) {
  86.             PyErr_SetString(PyExc_RuntimeError,
  87.              "method.__self__ not accessible in restricted mode");
  88.             return NULL;
  89.         }
  90.         self = m->m_self;
  91.         if (self == NULL)
  92.             self = Py_None;
  93.         Py_INCREF(self);
  94.         return self;
  95.     }
  96.     if (strcmp(name, "__members__") == 0) {
  97.         return Py_BuildValue("[sss]",
  98.                      "__doc__", "__name__", "__self__");
  99.     }
  100.     PyErr_SetString(PyExc_AttributeError, name);
  101.     return NULL;
  102. }
  103.  
  104. static PyObject *
  105. meth_repr(PyCFunctionObject *m)
  106. {
  107.     char buf[200];
  108.     if (m->m_self == NULL)
  109.         sprintf(buf, "<built-in function %.80s>", m->m_ml->ml_name);
  110.     else
  111.         sprintf(buf,
  112.             "<built-in method %.80s of %.80s object at %p>",
  113.             m->m_ml->ml_name, m->m_self->ob_type->tp_name,
  114.             m->m_self);
  115.     return PyString_FromString(buf);
  116. }
  117.  
  118. static int
  119. meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
  120. {
  121.     if (a->m_self != b->m_self)
  122.         return (a->m_self < b->m_self) ? -1 : 1;
  123.     if (a->m_ml->ml_meth == b->m_ml->ml_meth)
  124.         return 0;
  125.     if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
  126.         return -1;
  127.     else
  128.         return 1;
  129. }
  130.  
  131. static long
  132. meth_hash(PyCFunctionObject *a)
  133. {
  134.     long x,y;
  135.     if (a->m_self == NULL)
  136.         x = 0;
  137.     else {
  138.         x = PyObject_Hash(a->m_self);
  139.         if (x == -1)
  140.             return -1;
  141.     }
  142.     y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
  143.     if (y == -1)
  144.         return -1;
  145.     x ^= y;
  146.     if (x == -1)
  147.         x = -2;
  148.     return x;
  149. }
  150.  
  151. PyTypeObject PyCFunction_Type = {
  152.     PyObject_HEAD_INIT(&PyType_Type)
  153.     0,
  154.     "builtin_function_or_method",
  155.     sizeof(PyCFunctionObject),
  156.     0,
  157.     (destructor)meth_dealloc, /*tp_dealloc*/
  158.     0,        /*tp_print*/
  159.     (getattrfunc)meth_getattr, /*tp_getattr*/
  160.     0,        /*tp_setattr*/
  161.     (cmpfunc)meth_compare, /*tp_compare*/
  162.     (reprfunc)meth_repr, /*tp_repr*/
  163.     0,        /*tp_as_number*/
  164.     0,        /*tp_as_sequence*/
  165.     0,        /*tp_as_mapping*/
  166.     (hashfunc)meth_hash, /*tp_hash*/
  167. };
  168.  
  169. /* List all methods in a chain -- helper for findmethodinchain */
  170.  
  171. static PyObject *
  172. listmethodchain(PyMethodChain *chain)
  173. {
  174.     PyMethodChain *c;
  175.     PyMethodDef *ml;
  176.     int i, n;
  177.     PyObject *v;
  178.     
  179.     n = 0;
  180.     for (c = chain; c != NULL; c = c->link) {
  181.         for (ml = c->methods; ml->ml_name != NULL; ml++)
  182.             n++;
  183.     }
  184.     v = PyList_New(n);
  185.     if (v == NULL)
  186.         return NULL;
  187.     i = 0;
  188.     for (c = chain; c != NULL; c = c->link) {
  189.         for (ml = c->methods; ml->ml_name != NULL; ml++) {
  190.             PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
  191.             i++;
  192.         }
  193.     }
  194.     if (PyErr_Occurred()) {
  195.         Py_DECREF(v);
  196.         return NULL;
  197.     }
  198.     PyList_Sort(v);
  199.     return v;
  200. }
  201.  
  202. /* Find a method in a method chain */
  203.  
  204. PyObject *
  205. Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, char *name)
  206. {
  207.     if (name[0] == '_' && name[1] == '_') {
  208.         if (strcmp(name, "__methods__") == 0)
  209.             return listmethodchain(chain);
  210.         if (strcmp(name, "__doc__") == 0) {
  211.             char *doc = self->ob_type->tp_doc;
  212.             if (doc != NULL)
  213.                 return PyString_FromString(doc);
  214.         }
  215.     }
  216.     while (chain != NULL) {
  217.         PyMethodDef *ml = chain->methods;
  218.         for (; ml->ml_name != NULL; ml++) {
  219.             if (name[0] == ml->ml_name[0] &&
  220.                 strcmp(name+1, ml->ml_name+1) == 0)
  221.                 return PyCFunction_New(ml, self);
  222.         }
  223.         chain = chain->link;
  224.     }
  225.     PyErr_SetString(PyExc_AttributeError, name);
  226.     return NULL;
  227. }
  228.  
  229. /* Find a method in a single method list */
  230.  
  231. PyObject *
  232. Py_FindMethod(PyMethodDef *methods, PyObject *self, char *name)
  233. {
  234.     PyMethodChain chain;
  235.     chain.methods = methods;
  236.     chain.link = NULL;
  237.     return Py_FindMethodInChain(&chain, self, name);
  238. }
  239.  
  240. /* Clear out the free list */
  241.  
  242. void
  243. PyCFunction_Fini(void)
  244. {
  245.     while (free_list) {
  246.         PyCFunctionObject *v = free_list;
  247.         free_list = (PyCFunctionObject *)(v->m_self);
  248.         PyObject_DEL(v);
  249.     }
  250. }
  251.