home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Languages / python / PyObjC-0.47-MIHS / pyobjc-0.47-src / Modules / ObjCMethod.m < prev    next >
Encoding:
Text File  |  1996-11-13  |  9.5 KB  |  373 lines

  1. /* Copyright (c) 1996 by Lele Gaifax.  All Rights Reserved
  2.  *
  3.  * This software may be used and distributed freely for any purpose
  4.  * provided that this notice is included unchanged on any and all
  5.  * copies. The author does not warrant or guarantee this software in
  6.  * any way.
  7.  *
  8.  * This file is part of the PyObjC package.
  9.  *
  10.  * $RCSfile: ObjCMethod.m,v $
  11.  * $Revision: 1.1.1.1 $
  12.  * $Date: 1996/11/14 01:50:23 $
  13.  *
  14.  * Created Mon Oct 28 12:33:43 1996.
  15.  */
  16.  
  17. #include "ObjC.h"
  18. #include "objc_support.h"
  19.  
  20. ObjCMethod *
  21. ObjCMethod_new_with_selector (ObjCObject *obj, SEL sel)
  22. {
  23.   ObjCMethod *self = PyObject_NEW (ObjCMethod, &ObjCMethod_Type);
  24.  
  25.   if (!self)
  26.     return NULL;
  27.   
  28.   self->obj = obj;
  29.   Py_INCREF (self->obj);
  30.   self->sel = sel;
  31.  
  32.   return self;
  33. }
  34.  
  35. ObjCMethod *
  36. ObjCMethod_new_with_name (ObjCObject *obj, const char *meth_name)
  37. {
  38.   SEL sel = SELUID(meth_name);
  39.  
  40.   if (!sel)
  41.     {
  42.       char error_msg[100];
  43.  
  44.       sprintf (error_msg, "Unknown method name: `%s'", meth_name);
  45.       PyErr_SetString (ObjC_Error, error_msg);
  46.       return NULL;
  47.     }
  48.   else
  49.     return ObjCMethod_new_with_selector (obj, sel);
  50. }
  51.  
  52. static void
  53. ObjCMethod_dealloc (ObjCMethod *self)
  54. {
  55.   Py_DECREF (self->obj);
  56.   PyMem_DEL (self);
  57. }
  58.  
  59. static PyObject *
  60. ObjCMethod_repr (ObjCMethod *self)
  61. {
  62.   char buffer[512];
  63.  
  64.   sprintf (buffer, "<Objective-C %s method `%s' on %s at %lx>",
  65.        ISCLASS(self->obj->oc_object) ? "factory" : "instance",
  66.        SELNAME(self->sel),
  67.        NAMEOF(self->obj->oc_object), (long) self);
  68.   return PyString_FromString (buffer);
  69. }
  70.  
  71. static char ObjCMethod_pack_argument_doc[] =
  72. FUNDOC("Pack one of the method's arguments into an object suitable to be used in a\n\
  73. succeding call of the method, possibly initialized with a value. This is valid\n\
  74. only for pointer-argument, aka pass-by-reference.",
  75.        ".pack_argument (N, VALUE)",
  76.        "N\t: apply to the Nth argument of this method\n\
  77. \t\tVALUE\t: optional initializer value",
  78.        "An ObjCPointer instance");
  79. static PyObject *
  80. ObjCMethod_pack_argument (ObjCMethod *meth, PyObject *args)
  81. {
  82.   unsigned int argn;
  83.   PyObject *value = NULL;
  84.   
  85.   if (PyArg_ParseTuple (args, "i|O;argument number and a facultative initializator object", &argn, &value))
  86.     {
  87.       METHOD methinfo;
  88.       unsigned int argcount;
  89.       
  90.       if (ISCLASS(meth->obj->oc_object))
  91.     methinfo = CLASSMETH(meth->obj->oc_object, meth->sel);
  92.       else
  93.     methinfo = INSTMETH(meth->obj->oc_object, meth->sel);
  94.  
  95.       if (!methinfo)
  96.     {
  97. #define ERRORMSG " does not recognize `"
  98.       const char *whoiam = NAMEOF(meth->obj->oc_object);
  99.       const char *selname = SELNAME(meth->sel);
  100.       char buffer[strlen (whoiam) + sizeof ERRORMSG + 1 + strlen (selname) + 1 + 1];
  101.       
  102.       strcpy (buffer, whoiam);
  103.       strcat (buffer, ERRORMSG);
  104.       strcat (buffer, (ISCLASS(meth->obj->oc_object) ? "+" : "-"));
  105.       strcat (buffer, selname);
  106.       strcat (buffer, "'");
  107.       PyErr_SetString (ObjC_Error, buffer);
  108. #undef ERRORMSG
  109.       return NULL;
  110.     }
  111.  
  112.       argcount = METHNARGS(methinfo);
  113.  
  114.       if (argn < argcount-2)
  115.     {
  116.       const char *type;
  117.       unsigned int size;
  118.       char *buffer;
  119.  
  120. #ifdef GNU_RUNTIME
  121.       type = objc_skip_argspec (methinfo->method_types);
  122.       type = objc_skip_argspec (type); // skip SELF
  123.       type = objc_skip_argspec (type); // skip SEL
  124.       while (argn--)
  125.         type = objc_skip_argspec (type);
  126. #else
  127.       unsigned int offset;
  128.       
  129.       method_getArgumentInfo (methinfo, argn+2, &type, &offset);
  130. #endif
  131.       
  132.       if (*type != _C_PTR)
  133.         {
  134.           PyErr_SetString (ObjC_Error, ".pack_argument() can be used on pointer-argument only");
  135.           return NULL;
  136.         }
  137.  
  138.       size = objc_sizeof_type (type+1);
  139.       
  140.       buffer = alloca (size);
  141.       if (value)
  142.         {
  143.           const char *error = depythonify_c_value (type+1, value, &buffer);
  144.  
  145.           if (error)
  146.         {
  147.           const char *typeend = objc_skip_typespec (type+1);
  148. #define ERRMSG "expected %s for argument %d: its type is `%.*s'"
  149.           char errmsg[sizeof ERRMSG + strlen (error) + typeend-type];
  150.  
  151.           sprintf (errmsg, ERRMSG, error, argn, (int) (typeend-type-1), type+1);
  152.           PyErr_SetString (ObjC_Error, errmsg);
  153. #undef ERRMSG
  154.           return NULL;
  155.         }
  156.         }
  157.       else
  158.         memset (buffer, 0, size);
  159.       
  160.       return (PyObject *) ObjCPointer_new (buffer, type+1);
  161.     }
  162.       else
  163.     {
  164.       PyErr_SetString (ObjC_Error, "argument index out of range");
  165.       return NULL;
  166.     }
  167.     }
  168.   return NULL;
  169. }
  170.  
  171. static char ObjCMethod_unpack_argument_doc[] =
  172. FUNDOC("Translate a pass-by-reference argument' content into the Python representation.",
  173.        ".unpack_argument (N, VALUE)",
  174.        "N\t: apply to the Nth argument of this method\n\
  175. \t\tVALUE\t: its packed value",
  176.        "A Python object");
  177. static PyObject *
  178. ObjCMethod_unpack_argument (ObjCMethod *meth, PyObject *args)
  179. {
  180.   unsigned int argn;
  181.   PyObject *value;
  182.   
  183.   if (PyArg_ParseTuple (args, "iO;argument number and the value to unpack (a string or ObjCPointer instance)",
  184.             &argn, &value))
  185.     {
  186.       METHOD methinfo;
  187.       unsigned int argcount;
  188.       
  189.       if (ISCLASS(meth->obj->oc_object))
  190.     methinfo = CLASSMETH(meth->obj->oc_object, meth->sel);
  191.       else
  192.     methinfo = INSTMETH(meth->obj->oc_object, meth->sel);
  193.  
  194.       if (!methinfo)
  195.     {
  196. #define ERRORMSG " does not recognize `"
  197.       const char *whoiam = NAMEOF(meth->obj->oc_object);
  198.       const char *selname = SELNAME(meth->sel);
  199.       char buffer[strlen (whoiam) + sizeof ERRORMSG + 1 + strlen (selname) + 1 + 1];
  200.       
  201.       strcpy (buffer, whoiam);
  202.       strcat (buffer, ERRORMSG);
  203.       strcat (buffer, (ISCLASS(meth->obj->oc_object) ? "+" : "-"));
  204.       strcat (buffer, selname);
  205.       strcat (buffer, "'");
  206.       PyErr_SetString (ObjC_Error, buffer);
  207. #undef ERRORMSG
  208.       return NULL;
  209.     }
  210.  
  211.       argcount = METHNARGS(methinfo);
  212.  
  213.       if (argn < argcount-2)
  214.     {
  215.       const char *type;
  216.       char *buffer;
  217.  
  218. #ifdef GNU_RUNTIME
  219.       type = objc_skip_argspec (methinfo->method_types);
  220.       type = objc_skip_argspec (type); // skip SELF
  221.       type = objc_skip_argspec (type); // skil SEL
  222.       while (argn--)
  223.         type = objc_skip_argspec (type);
  224. #else
  225.       unsigned int offset;
  226.       
  227.       method_getArgumentInfo (methinfo, argn+2, &type, &offset);
  228. #endif
  229.  
  230.       if (*type != _C_PTR)
  231.         {
  232.           PyErr_SetString (ObjC_Error, ".unpack_argument() can be used on pointer-argument only");
  233.           return NULL;
  234.         }
  235.  
  236.       type++;
  237.       if (PyString_Check (value))
  238.         {
  239.           unsigned int expected_size = objc_sizeof_type (type);
  240.  
  241.           if (expected_size != PyString_Size (value))
  242.         {
  243. #define ERRMSG "a string of size %d instead of %d"
  244.           char errmsg[sizeof (ERRMSG)+6+6];
  245.           
  246.           sprintf (errmsg, ERRMSG, expected_size, PyString_Size (value));
  247.           PyErr_SetString (ObjC_Error, errmsg);
  248.           return NULL;
  249. #undef ERRMSG
  250.         }
  251.  
  252.           buffer = PyString_AS_STRING ((PyStringObject *) value);
  253.         }
  254.       else if (ObjCPointer_Check (value))
  255.         {
  256.           const char *typeend = objc_skip_typespec (type);
  257.           const char *vtype = PyString_AS_STRING (((ObjCPointer *) value)->type);
  258.           
  259.           if (strncmp (vtype, type, typeend - type))
  260.         {
  261. #define ERRMSG "a pointer to `%.*s' instead of `%s'"
  262.           char errmsg[sizeof (ERRMSG)+
  263.                  (typeend-type)+
  264.                  PyString_Size ((PyObject *) ((ObjCPointer *) value)->type)];
  265.           
  266.           sprintf (errmsg, ERRMSG, (int) (typeend-type), type, vtype);
  267.  
  268.           PyErr_SetString (ObjC_Error, errmsg);
  269.           return NULL;
  270. #undef ERRMSG
  271.         }
  272.  
  273.           buffer = ((ObjCPointer *) value)->ptr;
  274.         }
  275.       else
  276.         {
  277.           PyErr_BadArgument();
  278.           return NULL;
  279.         }
  280.       return pythonify_c_value (type, buffer, meth);
  281.     }
  282.       else
  283.     {
  284.       PyErr_SetString (ObjC_Error, "argument index out of range");
  285.       return NULL;
  286.     }
  287.     }
  288.   return NULL;
  289. }
  290.  
  291. static PyMethodDef ObjCMethod_methods[] =
  292. {
  293.   { "pack_argument",    (PyCFunction) ObjCMethod_pack_argument,    METH_VARARGS, ObjCMethod_pack_argument_doc },
  294.   { "unpack_argument",    (PyCFunction) ObjCMethod_unpack_argument,    METH_VARARGS, ObjCMethod_unpack_argument_doc },
  295.   { 0, 0, 0, 0 }
  296. };
  297.       
  298. static PyObject *
  299. ObjCMethod_getattr (ObjCMethod *self, char *name)
  300. {
  301.   PyObject *method;
  302.   
  303.   method = Py_FindMethod (ObjCMethod_methods, (PyObject *) self, name);
  304.   if (method)
  305.     return method;
  306.   else
  307.     {
  308.       PyErr_Clear();
  309.       
  310.       if (!strcmp (name, "name"))
  311.     return PyString_FromString ((char *) SELNAME(self->sel));
  312.       else if (!strcmp (name, "__members__"))
  313.     {
  314.       const char *members[] = { "name" };
  315.       PyObject *list;
  316.       unsigned int idx;
  317.  
  318.       idx = sizeof (members) / sizeof (members[0]);
  319.       list = PyList_New (idx);
  320.       while (idx--)
  321.         PyList_SetItem (list, idx, PyString_FromString ((char *) members[idx]));
  322.       return list;
  323.     }
  324.     }
  325.  
  326.   PyErr_SetString (PyExc_AttributeError, name);
  327.   return NULL;
  328. }
  329.  
  330. static PyObject *
  331. ObjCMethod_call (ObjCMethod *self, PyObject *args, PyObject *kw)
  332. {
  333.   PyObject *retobject = execute_and_pythonify_objc_method (self, args);
  334.  
  335.   return retobject;
  336. }
  337.  
  338. PyTypeObject ObjCMethod_Type =
  339. {
  340.   PyObject_HEAD_INIT(&PyType_Type)
  341.   0,                          /*ob_size*/
  342.   "ObjCMethod",                      /*tp_name*/
  343.   sizeof(ObjCMethod),                  /*tp_basicsize*/
  344.   0,                          /*tp_itemsize*/
  345.   
  346.   /* methods */
  347.   (destructor) ObjCMethod_dealloc,          /*tp_dealloc*/
  348.   (printfunc) 0,                  /*tp_print*/
  349.   (getattrfunc) ObjCMethod_getattr,          /*tp_getattr*/
  350.   (setattrfunc) 0,                  /*tp_setattr*/
  351.   (cmpfunc) 0,                      /*tp_compare*/
  352.   (reprfunc) ObjCMethod_repr,              /*tp_repr*/
  353.   0,                          /*tp_as_number*/
  354.   0,                          /*tp_as_sequence*/
  355.   0,                          /*tp_as_mapping*/
  356.   (hashfunc) 0,                      /*tp_hash*/
  357.   (ternaryfunc) ObjCMethod_call,          /*tp_call*/
  358.   (reprfunc) 0,                      /*tp_str*/
  359.   (getattrofunc) 0,                  /*tp_getattro*/
  360.   (setattrofunc) 0,                  /*tp_setattro*/
  361.  
  362.   /* Space for future expansion */
  363.   0L,0L,
  364.   
  365.   "Wrapper around Objective-C selector"          /* Documentation string */
  366. };
  367.  
  368. /*
  369. ** Local Variables:
  370. ** change-log-default-name:"../ChangeLog.PyObjC"
  371. ** End:
  372. */
  373.