@@ -3936,82 +3936,97 @@ IBUG(char *msg)
39363936 return -1 ;
39373937}
39383938
3939+ /*
3940+ This function is called to initialize a Structure or Union with positional
3941+ arguments. It calls itself recursively for all Structure or Union base
3942+ classes, then retrieves the _fields_ member to associate the argument
3943+ position with the correct field name.
3944+
3945+ Returns -1 on error, or the index of next argument on success.
3946+ */
39393947static int
3940- Struct_init (PyObject * self , PyObject * args , PyObject * kwds )
3948+ _init_pos_args (PyObject * self , PyTypeObject * type ,
3949+ PyObject * args , PyObject * kwds ,
3950+ int index )
39413951{
3942- int i ;
3952+ StgDictObject * dict ;
39433953 PyObject * fields ;
3954+ int i ;
3955+
3956+ if (PyType_stgdict ((PyObject * )type -> tp_base )) {
3957+ index = _init_pos_args (self , type -> tp_base ,
3958+ args , kwds ,
3959+ index );
3960+ if (index == -1 )
3961+ return -1 ;
3962+ }
3963+
3964+ dict = PyType_stgdict ((PyObject * )type );
3965+ fields = PyDict_GetItemString ((PyObject * )dict , "_fields_" );
3966+ if (fields == NULL )
3967+ return index ;
3968+
3969+ for (i = 0 ;
3970+ i < dict -> length && (i + index ) < PyTuple_GET_SIZE (args );
3971+ ++ i ) {
3972+ PyObject * pair = PySequence_GetItem (fields , i );
3973+ PyObject * name , * val ;
3974+ int res ;
3975+ if (!pair )
3976+ return -1 ;
3977+ name = PySequence_GetItem (pair , 0 );
3978+ if (!name ) {
3979+ Py_DECREF (pair );
3980+ return -1 ;
3981+ }
3982+ val = PyTuple_GET_ITEM (args , i + index );
3983+ if (kwds && PyDict_GetItem (kwds , name )) {
3984+ char * field = PyBytes_AsString (name );
3985+ if (field == NULL ) {
3986+ PyErr_Clear ();
3987+ field = "???" ;
3988+ }
3989+ PyErr_Format (PyExc_TypeError ,
3990+ "duplicate values for field '%s'" ,
3991+ field );
3992+ Py_DECREF (pair );
3993+ Py_DECREF (name );
3994+ return -1 ;
3995+ }
3996+
3997+ res = PyObject_SetAttr (self , name , val );
3998+ Py_DECREF (pair );
3999+ Py_DECREF (name );
4000+ if (res == -1 )
4001+ return -1 ;
4002+ }
4003+ return index + dict -> length ;
4004+ }
4005+
4006+ static int
4007+ Struct_init (PyObject * self , PyObject * args , PyObject * kwds )
4008+ {
4009+ StgDictObject * stgdict = PyObject_stgdict (self );
39444010
39454011/* Optimization possible: Store the attribute names _fields_[x][0]
39464012 * in C accessible fields somewhere ?
39474013 */
39484014
3949- /* Check this code again for correctness! */
3950-
39514015 if (!PyTuple_Check (args )) {
39524016 PyErr_SetString (PyExc_TypeError ,
39534017 "args not a tuple?" );
39544018 return -1 ;
39554019 }
39564020 if (PyTuple_GET_SIZE (args )) {
3957- fields = PyObject_GetAttrString (self , "_fields_" );
3958- if (!fields ) {
3959- PyErr_Clear ();
3960- fields = PyTuple_New (0 );
3961- if (!fields )
3962- return -1 ;
3963- }
3964-
3965- if (PyTuple_GET_SIZE (args ) > PySequence_Length (fields )) {
3966- Py_DECREF (fields );
4021+ int res = _init_pos_args (self , Py_TYPE (self ),
4022+ args , kwds , 0 );
4023+ if (res == -1 )
4024+ return -1 ;
4025+ if (res < PyTuple_GET_SIZE (args )) {
39674026 PyErr_SetString (PyExc_TypeError ,
39684027 "too many initializers" );
39694028 return -1 ;
39704029 }
3971-
3972- for (i = 0 ; i < PyTuple_GET_SIZE (args ); ++ i ) {
3973- PyObject * pair = PySequence_GetItem (fields , i );
3974- PyObject * name ;
3975- PyObject * val ;
3976- if (!pair ) {
3977- Py_DECREF (fields );
3978- return IBUG ("_fields_[i] failed" );
3979- }
3980-
3981- name = PySequence_GetItem (pair , 0 );
3982- if (!name ) {
3983- Py_DECREF (pair );
3984- Py_DECREF (fields );
3985- return IBUG ("_fields_[i][0] failed" );
3986- }
3987-
3988- if (kwds && PyDict_GetItem (kwds , name )) {
3989- char * field = PyBytes_AsString (name );
3990- if (field == NULL ) {
3991- PyErr_Clear ();
3992- field = "???" ;
3993- }
3994- PyErr_Format (PyExc_TypeError ,
3995- "duplicate values for field %s" ,
3996- field );
3997- Py_DECREF (pair );
3998- Py_DECREF (name );
3999- Py_DECREF (fields );
4000- return -1 ;
4001- }
4002-
4003- val = PyTuple_GET_ITEM (args , i );
4004- if (-1 == PyObject_SetAttr (self , name , val )) {
4005- Py_DECREF (pair );
4006- Py_DECREF (name );
4007- Py_DECREF (fields );
4008- return -1 ;
4009- }
4010-
4011- Py_DECREF (name );
4012- Py_DECREF (pair );
4013- }
4014- Py_DECREF (fields );
40154030 }
40164031
40174032 if (kwds ) {
0 commit comments