[Xcb] [PATCH libxcb 2/3] generator: support lists of structs which contain a switch
Christian Linhart
chris at DemoRecorder.com
Mon Oct 13 01:57:35 PDT 2014
On 10/12/14 18:33, Ran Benita wrote:
> Mentioning a request which needs this in the commit message would be
> nice!
The whole patchset is for getting the reply of request QueryDeviceState to work.
So it is at least needed there. (and probably needed for more requests which I completed in the xml later. )
I guess I should mention such an example-request for each individual patch
and not just in the start-message of a patch-thread,
so that all of the info is in one place for reviewers.
>
> On Thu, Aug 21, 2014 at 10:35:55PM +0200, Christian Linhart wrote:
>> This essentially requires to have a correct sizeof-function
>> for the struct.
>> This in turn requires a sizeof-function for the switch, too.
>>
>> Making a sizeof-function for the switch is triggered by
>> replacing "elif" by "if" in the first change of this patch.
>> This way, c_need_sizeof is also set to True for switches if appropriate.
>>
>> The _c_serialize_helper_switch_field function has to support
>> the context "sizeof":
>> This is done in the second change of this patch
>>
>> The third change of this patch fixes an alignment error:
>> It does not make sense to base the padding on the struct-type
>> which is generated for switch because this struct does not
>> represent the protocol. Rather it is the output of deserialization.
>> ( The implicit padding for var-sized fields has other issues, IMHO,
>> but I am not touching these now...)
>>
>> The effect on the generated code for the current xml-files
>> is as follows:
>> * several additional sizeof-functions are generated
>> * the fix of the alignment error only changes one place
>> in the XKB-extension for the GetKbdByName-reply.
>> This is no problem because that reply in its current form
>> is broken/unfinished anyways.
>>
>> Note:
>> This patch also fixes a problem in the generator when
>> a fixed-size list is the last field of a case or bitcase.
>>
>> ---
>> src/c_client.py | 14 ++++++++++++--
>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/c_client.py b/src/c_client.py
>> index fa59fff..1ed486c 100644
>> --- a/src/c_client.py
>> +++ b/src/c_client.py
>> @@ -354,15 +354,16 @@ def _c_type_setup(self, name, postfix):
>> if field.type.is_list and not field.type.member.fixed_size():
>> field.c_pointer = '*'
>>
>> if field.type.is_switch:
>> field.c_pointer = '*'
>> field.c_field_const_type = 'const ' + field.c_field_type
>> self.c_need_aux = True
>> - elif not field.type.fixed_size() and not field.type.is_case_or_bitcase:
>> +
>> + if not field.type.fixed_size() and not field.type.is_case_or_bitcase:
>> self.c_need_sizeof = True
>
> The switches are internal, they can not be used directly e.g. by another
> extension module, right?
No necessarily.
The sizeof function is not generated for the switch itself,
but it is generated for a struct which contains the switch.
Such a struct may be used in another extension module.
Then that other extension module may need to access the sizeof function.
( So, optimizing that would require some global cross-module optimization logic in the generator.
We probably want to avoid that complexity. :-) )
> I wish we could generate them only when needed,
> or make them static so the compiler can prune them.
> Right now most
> sizeof()'s are just dead .text. But this one doesn't add too many, so OK.
Good that the impact is within reason.
> Second, how hard would it be to make the above condition positive? (i.e.
> this or that or that).
I did not change the condition from the original code in order not to break anything.
Of course, one "not" can be removed by applying boolean algebra:
"if not field.type.fixed_size() and not field.type.is_case_or_bitcase:"
is equivalent to
"if not (field.type.fixed_size() or field.type.is_case_or_bitcase):"
Would that be preferable?
Another option would be to define
* a function named "variable_size" to the Type class in xcb/proto/xcbgen/xtypes.py:
def variable_size(self):
return not self.fixed_size()
* a function which somehow is a positive test for something which is not a case or bitcase
(and possibly excludes something more)
but I am not sure whether that improves code readability because the reader needs to know
how these new functions relate to their complementary counterparts...
Anyways I digress now, I guess. :-)
>
>>
>> field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
>> field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
>> field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
>> field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
>> field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
>> @@ -766,14 +767,18 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
>> # call _serialize()/_unpack() to determine the actual size
>> if 'serialize' == context:
>> length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
>> c_field_names, prefix_str, field.c_field_name)
>> elif context in ('unserialize', 'unpack'):
>> length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
>> c_field_names, prefix_str, field.c_field_name)
>> + elif 'sizeof' == context:
>> + #remove trailing ", " from c_field_names because it will be used at end of arglist
>> + my_c_field_names = c_field_names[:-2]
>> + length = "%s( xcb_tmp, %s )" % ( field.type.c_sizeof_name, my_c_field_names )
>>
>> return length
>> # _c_serialize_helper_switch_field()
>>
>> def _c_serialize_helper_list_field(context, self, field,
>> code_lines, temp_vars,
>> space, prefix):
>> @@ -1042,15 +1047,20 @@ def _c_serialize_helper_fields(context, self,
>>
>> if 'serialize' == context:
>> if '' != length:
>> code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
>> code_lines.append('%s xcb_parts_idx++;' % space)
>> count += 1
>>
>> - code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
>> + code_lines.append(
>> + '%s xcb_align_to = ALIGNOF(%s);'
>> + % (space,
>> + 'char'
>> + if field.c_field_type == 'void' or field.type.is_switch
>> + else field.c_field_type))
>
> Right, using the type doesn't make sense. Would be better as a separate
> commit though!
Thank you for that feedback. I'll try to separate my future changes in even smaller pieces.
> (Also, maybe extract the if-else to a variable?)
I'll put that on a TODO.list for a cleanup task.
>
> Anyway, looks good to me:
>
> Reviewed-by: Ran Benita <ran234 at gmail.com>
Thank you for reviewing it!
Chris
>
>>
>> need_padding = True
>> if self.c_var_followed_by_fixed_fields:
>> need_padding = False
>>
>> return count
>> # _c_serialize_helper_fields()
>> --
>> 2.0.1
>>
>> _______________________________________________
>> Xcb mailing list
>> Xcb at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/xcb
>
More information about the Xcb
mailing list