symbian-qemu-0.9.1-12/python-2.6.1/Python/structmember.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 
       
     2 /* Map C struct members to Python object attributes */
       
     3 
       
     4 #include "Python.h"
       
     5 
       
     6 #include "structmember.h"
       
     7 
       
     8 static PyObject *
       
     9 listmembers(struct memberlist *mlist)
       
    10 {
       
    11 	int i, n;
       
    12 	PyObject *v;
       
    13 	for (n = 0; mlist[n].name != NULL; n++)
       
    14 		;
       
    15 	v = PyList_New(n);
       
    16 	if (v != NULL) {
       
    17 		for (i = 0; i < n; i++)
       
    18 			PyList_SetItem(v, i,
       
    19 				       PyString_FromString(mlist[i].name));
       
    20 		if (PyErr_Occurred()) {
       
    21 			Py_DECREF(v);
       
    22 			v = NULL;
       
    23 		}
       
    24 		else {
       
    25 			PyList_Sort(v);
       
    26 		}
       
    27 	}
       
    28 	return v;
       
    29 }
       
    30 
       
    31 PyObject *
       
    32 PyMember_Get(const char *addr, struct memberlist *mlist, const char *name)
       
    33 {
       
    34 	struct memberlist *l;
       
    35 
       
    36 	if (strcmp(name, "__members__") == 0)
       
    37 		return listmembers(mlist);
       
    38 	for (l = mlist; l->name != NULL; l++) {
       
    39 		if (strcmp(l->name, name) == 0) {
       
    40 			PyMemberDef copy;
       
    41 			copy.name = l->name;
       
    42 			copy.type = l->type;
       
    43 			copy.offset = l->offset;
       
    44 			copy.flags = l->flags;
       
    45 			copy.doc = NULL;
       
    46 			return PyMember_GetOne(addr, &copy);
       
    47 		}
       
    48 	}
       
    49 	PyErr_SetString(PyExc_AttributeError, name);
       
    50 	return NULL;
       
    51 }
       
    52 
       
    53 PyObject *
       
    54 PyMember_GetOne(const char *addr, PyMemberDef *l)
       
    55 {
       
    56 	PyObject *v;
       
    57 	if ((l->flags & READ_RESTRICTED) &&
       
    58 	    PyEval_GetRestricted()) {
       
    59 		PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
       
    60 		return NULL;
       
    61 	}
       
    62 	addr += l->offset;
       
    63 	switch (l->type) {
       
    64 	case T_BOOL:
       
    65 		v = PyBool_FromLong(*(char*)addr);
       
    66 		break;
       
    67 	case T_BYTE:
       
    68 		v = PyInt_FromLong(*(char*)addr);
       
    69 		break;
       
    70 	case T_UBYTE:
       
    71 		v = PyLong_FromUnsignedLong(*(unsigned char*)addr);
       
    72 		break;
       
    73 	case T_SHORT:
       
    74 		v = PyInt_FromLong(*(short*)addr);
       
    75 		break;
       
    76 	case T_USHORT:
       
    77 		v = PyLong_FromUnsignedLong(*(unsigned short*)addr);
       
    78 		break;
       
    79 	case T_INT:
       
    80 		v = PyInt_FromLong(*(int*)addr);
       
    81 		break;
       
    82 	case T_UINT:
       
    83 		v = PyLong_FromUnsignedLong(*(unsigned int*)addr);
       
    84 		break;
       
    85 	case T_LONG:
       
    86 		v = PyInt_FromLong(*(long*)addr);
       
    87 		break;
       
    88 	case T_ULONG:
       
    89 		v = PyLong_FromUnsignedLong(*(unsigned long*)addr);
       
    90 		break;
       
    91 	case T_PYSSIZET:
       
    92 		v = PyInt_FromSsize_t(*(Py_ssize_t*)addr);
       
    93 		break;
       
    94 	case T_FLOAT:
       
    95 		v = PyFloat_FromDouble((double)*(float*)addr);
       
    96 		break;
       
    97 	case T_DOUBLE:
       
    98 		v = PyFloat_FromDouble(*(double*)addr);
       
    99 		break;
       
   100 	case T_STRING:
       
   101 		if (*(char**)addr == NULL) {
       
   102 			Py_INCREF(Py_None);
       
   103 			v = Py_None;
       
   104 		}
       
   105 		else
       
   106 			v = PyString_FromString(*(char**)addr);
       
   107 		break;
       
   108 	case T_STRING_INPLACE:
       
   109 		v = PyString_FromString((char*)addr);
       
   110 		break;
       
   111 	case T_CHAR:
       
   112 		v = PyString_FromStringAndSize((char*)addr, 1);
       
   113 		break;
       
   114 	case T_OBJECT:
       
   115 		v = *(PyObject **)addr;
       
   116 		if (v == NULL)
       
   117 			v = Py_None;
       
   118 		Py_INCREF(v);
       
   119 		break;
       
   120 	case T_OBJECT_EX:
       
   121 		v = *(PyObject **)addr;
       
   122 		if (v == NULL)
       
   123 			PyErr_SetString(PyExc_AttributeError, l->name);
       
   124 		Py_XINCREF(v);
       
   125 		break;
       
   126 #ifdef HAVE_LONG_LONG
       
   127 	case T_LONGLONG:
       
   128 		v = PyLong_FromLongLong(*(PY_LONG_LONG *)addr);
       
   129 		break;
       
   130 	case T_ULONGLONG:
       
   131 		v = PyLong_FromUnsignedLongLong(*(unsigned PY_LONG_LONG *)addr);
       
   132 		break;
       
   133 #endif /* HAVE_LONG_LONG */
       
   134 	default:
       
   135 		PyErr_SetString(PyExc_SystemError, "bad memberdescr type");
       
   136 		v = NULL;
       
   137 	}
       
   138 	return v;
       
   139 }
       
   140 
       
   141 int
       
   142 PyMember_Set(char *addr, struct memberlist *mlist, const char *name, PyObject *v)
       
   143 {
       
   144 	struct memberlist *l;
       
   145 
       
   146 	for (l = mlist; l->name != NULL; l++) {
       
   147 		if (strcmp(l->name, name) == 0) {
       
   148 			PyMemberDef copy;
       
   149 			copy.name = l->name;
       
   150 			copy.type = l->type;
       
   151 			copy.offset = l->offset;
       
   152 			copy.flags = l->flags;
       
   153 			copy.doc = NULL;
       
   154 			return PyMember_SetOne(addr, &copy, v);
       
   155 		}
       
   156 	}
       
   157 
       
   158 	PyErr_SetString(PyExc_AttributeError, name);
       
   159 	return -1;
       
   160 }
       
   161 
       
   162 #define WARN(msg)					\
       
   163     do {						\
       
   164 	if (PyErr_Warn(PyExc_RuntimeWarning, msg) < 0)	\
       
   165 		return -1;				\
       
   166     } while (0)
       
   167 
       
   168 int
       
   169 PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
       
   170 {
       
   171 	PyObject *oldv;
       
   172 
       
   173 	if ((l->flags & READONLY) || l->type == T_STRING)
       
   174 	{
       
   175 		PyErr_SetString(PyExc_TypeError, "readonly attribute");
       
   176 		return -1;
       
   177 	}
       
   178 	if ((l->flags & PY_WRITE_RESTRICTED) && PyEval_GetRestricted()) {
       
   179 		PyErr_SetString(PyExc_RuntimeError, "restricted attribute");
       
   180 		return -1;
       
   181 	}
       
   182 	if (v == NULL && l->type != T_OBJECT_EX && l->type != T_OBJECT) {
       
   183 		PyErr_SetString(PyExc_TypeError,
       
   184 				"can't delete numeric/char attribute");
       
   185 		return -1;
       
   186 	}
       
   187 	addr += l->offset;
       
   188 	switch (l->type) {
       
   189 	case T_BOOL:{
       
   190 		if (!PyBool_Check(v)) {
       
   191 			PyErr_SetString(PyExc_TypeError,
       
   192 					"attribute value type must be bool");
       
   193 			return -1;
       
   194 		}
       
   195 		if (v == Py_True)
       
   196 			*(char*)addr = (char) 1;
       
   197 		else
       
   198 			*(char*)addr = (char) 0;
       
   199 		break;
       
   200 		}
       
   201 	case T_BYTE:{
       
   202 		long long_val = PyInt_AsLong(v);
       
   203 		if ((long_val == -1) && PyErr_Occurred())
       
   204 			return -1;
       
   205 		*(char*)addr = (char)long_val;
       
   206 		/* XXX: For compatibility, only warn about truncations
       
   207 		   for now. */
       
   208 		if ((long_val > CHAR_MAX) || (long_val < CHAR_MIN))
       
   209 			WARN("Truncation of value to char");
       
   210 		break;
       
   211 		}
       
   212 	case T_UBYTE:{
       
   213 		long long_val = PyInt_AsLong(v);
       
   214 		if ((long_val == -1) && PyErr_Occurred())
       
   215 			return -1;
       
   216 		*(unsigned char*)addr = (unsigned char)long_val;
       
   217 		if ((long_val > UCHAR_MAX) || (long_val < 0))
       
   218 			WARN("Truncation of value to unsigned char");
       
   219 		break;
       
   220 		}
       
   221 	case T_SHORT:{
       
   222 		long long_val = PyInt_AsLong(v);
       
   223 		if ((long_val == -1) && PyErr_Occurred())
       
   224 			return -1;
       
   225 		*(short*)addr = (short)long_val;
       
   226 		if ((long_val > SHRT_MAX) || (long_val < SHRT_MIN))
       
   227 			WARN("Truncation of value to short");
       
   228 		break;
       
   229 		}
       
   230 	case T_USHORT:{
       
   231 		long long_val = PyInt_AsLong(v);
       
   232 		if ((long_val == -1) && PyErr_Occurred())
       
   233 			return -1;
       
   234 		*(unsigned short*)addr = (unsigned short)long_val;
       
   235 		if ((long_val > USHRT_MAX) || (long_val < 0))
       
   236 			WARN("Truncation of value to unsigned short");
       
   237 		break;
       
   238 		}
       
   239   	case T_INT:{
       
   240 		long long_val = PyInt_AsLong(v);
       
   241 		if ((long_val == -1) && PyErr_Occurred())
       
   242 			return -1;
       
   243 		*(int *)addr = (int)long_val;
       
   244 		if ((long_val > INT_MAX) || (long_val < INT_MIN))
       
   245 			WARN("Truncation of value to int");
       
   246 		break;
       
   247 		}
       
   248 	case T_UINT:{
       
   249 		unsigned long ulong_val = PyLong_AsUnsignedLong(v);
       
   250 		if ((ulong_val == (unsigned int)-1) && PyErr_Occurred()) {
       
   251 			/* XXX: For compatibility, accept negative int values
       
   252 			   as well. */
       
   253 			PyErr_Clear();
       
   254 			ulong_val = PyLong_AsLong(v);
       
   255 			if ((ulong_val == (unsigned int)-1) && PyErr_Occurred())
       
   256 				return -1;
       
   257 			*(unsigned int *)addr = (unsigned int)ulong_val;
       
   258 			WARN("Writing negative value into unsigned field");
       
   259 		} else
       
   260 			*(unsigned int *)addr = (unsigned int)ulong_val;
       
   261 		if (ulong_val > UINT_MAX)
       
   262 			WARN("Truncation of value to unsigned int");
       
   263 		break;
       
   264 		}
       
   265 	case T_LONG:{
       
   266 		*(long*)addr = PyLong_AsLong(v);
       
   267 		if ((*(long*)addr == -1) && PyErr_Occurred())
       
   268 			return -1;
       
   269 		break;
       
   270 		}
       
   271 	case T_ULONG:{
       
   272 		*(unsigned long*)addr = PyLong_AsUnsignedLong(v);
       
   273 		if ((*(unsigned long*)addr == (unsigned long)-1)
       
   274 		    && PyErr_Occurred()) {
       
   275 			/* XXX: For compatibility, accept negative int values
       
   276 			   as well. */
       
   277 			PyErr_Clear();
       
   278 			*(unsigned long*)addr = PyLong_AsLong(v);
       
   279 			if ((*(unsigned long*)addr == (unsigned int)-1)
       
   280 			    && PyErr_Occurred())
       
   281 				return -1;
       
   282 			WARN("Writing negative value into unsigned field");
       
   283 		}
       
   284 		break;
       
   285 		}
       
   286 	case T_PYSSIZET:{
       
   287 		*(Py_ssize_t*)addr = PyInt_AsSsize_t(v);
       
   288 		if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)
       
   289 		    && PyErr_Occurred())
       
   290 				return -1;
       
   291 		break;
       
   292 		}
       
   293 	case T_FLOAT:{
       
   294 		double double_val = PyFloat_AsDouble(v);
       
   295 		if ((double_val == -1) && PyErr_Occurred())
       
   296 			return -1;
       
   297 		*(float*)addr = (float)double_val;
       
   298 		break;
       
   299 		}
       
   300 	case T_DOUBLE:
       
   301 		*(double*)addr = PyFloat_AsDouble(v);
       
   302 		if ((*(double*)addr == -1) && PyErr_Occurred())
       
   303 			return -1;
       
   304 		break;
       
   305 	case T_OBJECT:
       
   306 	case T_OBJECT_EX:
       
   307 		Py_XINCREF(v);
       
   308 		oldv = *(PyObject **)addr;
       
   309 		*(PyObject **)addr = v;
       
   310 		Py_XDECREF(oldv);
       
   311 		break;
       
   312 	case T_CHAR:
       
   313 		if (PyString_Check(v) && PyString_Size(v) == 1) {
       
   314 			*(char*)addr = PyString_AsString(v)[0];
       
   315 		}
       
   316 		else {
       
   317 			PyErr_BadArgument();
       
   318 			return -1;
       
   319 		}
       
   320 		break;
       
   321 #ifdef HAVE_LONG_LONG
       
   322 	case T_LONGLONG:{
       
   323 		PY_LONG_LONG value;
       
   324 		*(PY_LONG_LONG*)addr = value = PyLong_AsLongLong(v);
       
   325 		if ((value == -1) && PyErr_Occurred())
       
   326 			return -1;
       
   327 		break;
       
   328 		}
       
   329 	case T_ULONGLONG:{
       
   330 		unsigned PY_LONG_LONG value;
       
   331 		/* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
       
   332 			doesn't ??? */
       
   333 		if (PyLong_Check(v))
       
   334 			*(unsigned PY_LONG_LONG*)addr = value = PyLong_AsUnsignedLongLong(v);
       
   335 		else
       
   336 			*(unsigned PY_LONG_LONG*)addr = value = PyInt_AsLong(v);
       
   337 		if ((value == (unsigned PY_LONG_LONG)-1) && PyErr_Occurred())
       
   338 			return -1;
       
   339 		break;
       
   340 		}
       
   341 #endif /* HAVE_LONG_LONG */
       
   342 	default:
       
   343 		PyErr_Format(PyExc_SystemError,
       
   344 			     "bad memberdescr type for %s", l->name);
       
   345 		return -1;
       
   346 	}
       
   347 	return 0;
       
   348 }