@@ -4017,82 +4017,97 @@ IBUG(char *msg)
40174017 return -1 ;
40184018}
40194019
4020+ /*
4021+ This function is called to initialize a Structure or Union with positional
4022+ arguments. It calls itself recursively for all Structure or Union base
4023+ classes, then retrieves the _fields_ member to associate the argument
4024+ position with the correct field name.
4025+
4026+ Returns -1 on error, or the index of next argument on success.
4027+ */
40204028static int
4021- Struct_init (PyObject * self , PyObject * args , PyObject * kwds )
4029+ _init_pos_args (PyObject * self , PyTypeObject * type ,
4030+ PyObject * args , PyObject * kwds ,
4031+ int index )
40224032{
4023- int i ;
4033+ StgDictObject * dict ;
40244034 PyObject * fields ;
4035+ int i ;
4036+
4037+ if (PyType_stgdict ((PyObject * )type -> tp_base )) {
4038+ index = _init_pos_args (self , type -> tp_base ,
4039+ args , kwds ,
4040+ index );
4041+ if (index == -1 )
4042+ return -1 ;
4043+ }
4044+
4045+ dict = PyType_stgdict ((PyObject * )type );
4046+ fields = PyDict_GetItemString ((PyObject * )dict , "_fields_" );
4047+ if (fields == NULL )
4048+ return index ;
4049+
4050+ for (i = 0 ;
4051+ i < dict -> length && (i + index ) < PyTuple_GET_SIZE (args );
4052+ ++ i ) {
4053+ PyObject * pair = PySequence_GetItem (fields , i );
4054+ PyObject * name , * val ;
4055+ int res ;
4056+ if (!pair )
4057+ return -1 ;
4058+ name = PySequence_GetItem (pair , 0 );
4059+ if (!name ) {
4060+ Py_DECREF (pair );
4061+ return -1 ;
4062+ }
4063+ val = PyTuple_GET_ITEM (args , i + index );
4064+ if (kwds && PyDict_GetItem (kwds , name )) {
4065+ char * field = PyString_AsString (name );
4066+ if (field == NULL ) {
4067+ PyErr_Clear ();
4068+ field = "???" ;
4069+ }
4070+ PyErr_Format (PyExc_TypeError ,
4071+ "duplicate values for field '%s'" ,
4072+ field );
4073+ Py_DECREF (pair );
4074+ Py_DECREF (name );
4075+ return -1 ;
4076+ }
4077+
4078+ res = PyObject_SetAttr (self , name , val );
4079+ Py_DECREF (pair );
4080+ Py_DECREF (name );
4081+ if (res == -1 )
4082+ return -1 ;
4083+ }
4084+ return index + dict -> length ;
4085+ }
4086+
4087+ static int
4088+ Struct_init (PyObject * self , PyObject * args , PyObject * kwds )
4089+ {
4090+ StgDictObject * stgdict = PyObject_stgdict (self );
40254091
40264092/* Optimization possible: Store the attribute names _fields_[x][0]
40274093 * in C accessible fields somewhere ?
40284094 */
40294095
4030- /* Check this code again for correctness! */
4031-
40324096 if (!PyTuple_Check (args )) {
40334097 PyErr_SetString (PyExc_TypeError ,
40344098 "args not a tuple?" );
40354099 return -1 ;
40364100 }
40374101 if (PyTuple_GET_SIZE (args )) {
4038- fields = PyObject_GetAttrString (self , "_fields_" );
4039- if (!fields ) {
4040- PyErr_Clear ();
4041- fields = PyTuple_New (0 );
4042- if (!fields )
4043- return -1 ;
4044- }
4045-
4046- if (PyTuple_GET_SIZE (args ) > PySequence_Length (fields )) {
4047- Py_DECREF (fields );
4102+ int res = _init_pos_args (self , Py_TYPE (self ),
4103+ args , kwds , 0 );
4104+ if (res == -1 )
4105+ return -1 ;
4106+ if (res < PyTuple_GET_SIZE (args )) {
40484107 PyErr_SetString (PyExc_TypeError ,
40494108 "too many initializers" );
40504109 return -1 ;
40514110 }
4052-
4053- for (i = 0 ; i < PyTuple_GET_SIZE (args ); ++ i ) {
4054- PyObject * pair = PySequence_GetItem (fields , i );
4055- PyObject * name ;
4056- PyObject * val ;
4057- if (!pair ) {
4058- Py_DECREF (fields );
4059- return IBUG ("_fields_[i] failed" );
4060- }
4061-
4062- name = PySequence_GetItem (pair , 0 );
4063- if (!name ) {
4064- Py_DECREF (pair );
4065- Py_DECREF (fields );
4066- return IBUG ("_fields_[i][0] failed" );
4067- }
4068-
4069- if (kwds && PyDict_GetItem (kwds , name )) {
4070- char * field = PyString_AsString (name );
4071- if (field == NULL ) {
4072- PyErr_Clear ();
4073- field = "???" ;
4074- }
4075- PyErr_Format (PyExc_TypeError ,
4076- "duplicate values for field %s" ,
4077- field );
4078- Py_DECREF (pair );
4079- Py_DECREF (name );
4080- Py_DECREF (fields );
4081- return -1 ;
4082- }
4083-
4084- val = PyTuple_GET_ITEM (args , i );
4085- if (-1 == PyObject_SetAttr (self , name , val )) {
4086- Py_DECREF (pair );
4087- Py_DECREF (name );
4088- Py_DECREF (fields );
4089- return -1 ;
4090- }
4091-
4092- Py_DECREF (name );
4093- Py_DECREF (pair );
4094- }
4095- Py_DECREF (fields );
40964111 }
40974112
40984113 if (kwds ) {
0 commit comments