[Xcb] parametrized structs

Christian Linhart chris at DemoRecorder.com
Fri Aug 22 03:01:27 PDT 2014


On 08/22/14 09:53, Ran Benita wrote:
> On Mon, Aug 18, 2014 at 04:41:23PM +0200, Christian Linhart wrote:
>> Add TODO list of things which cannot be done yet
>> with the current feature-set of xml and the generator.
>> ---
>>  src/xinput.xml | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 67 insertions(+)
>>
> 
> ...
> 
>> +Parametrized structs
> 
> What does this mean?
> 
This is something similar to C++ templates ( but a bit simpler... )
( I'll provide an alternative further below )

Here's why we need that:

The struct DeviceTimeCoord contains a list whose length is determined
from outside: It is determined by the member "num_axes" in the
GetDeviceMotionEvents-reply.

So we need a mechanism to get that length into the struct.

One way is to parametrize the struct similar to a C++ - template, but run-time evaluated.

The xml could look like follows ( explanations further below )

===============================================================================
01    <struct name="DeviceTimeCoord">
02        <param name="num_axes" type="CARD8" />
03        <field type="TIMESTAMP" name="time" />
04        <list type="INT32" name="valuators">
05            <paramref>num_axes</paramref>
06        </list>
07    </struct>
08
09    <request name="GetDeviceMotionEvents" opcode="10">
10        <field type="TIMESTAMP" name="start" />
11        <field type="TIMESTAMP" name="stop" altenum="Time" />
12        <field type="CARD8"     name="device_id" />
13        <pad bytes="3"/>
14        <reply>
15            <field type="CARD8"  name="xi_reply_type" />
16            <field type="CARD32" name="num_events" />
17            <field type="CARD8"  name="num_axes" />
18            <field type="CARD8"  name="device_mode" enum="ValuatorMode" />
19            <pad bytes="18" />
20            <list name="events" >
21                <type>
22                     <structref>DeviceTimeCoord</structref>
23                     <arg name="num_axes"><fieldref>num_axes</fieldref></arg>
24                </type>
25                <fieldref>num_events</fieldref>
26            </list>
27        </reply>
28    </request>
===============================================================================


Explanations:

In line 2, the <param>-tag declares a parameter for this struct ( name of parameter "num_axes", type CARD8 ).

In line 5, the <paramref>-tag is an expression which delivers the value of the parameter, 
which in this case is used for the length of the list

in lines 20 - 24, the type of a list element cannot be specified as xml-attribute "type"
because it is more complex ( has an argument list ).
Therefore the type is specified as a tag named "type" in the body of the list-tag.
It contains the reference to struct DeviceTimeCoord, and the argument-list,
where the "name"-attribute is the name of the parameter.

In pseudo-C++-code this would look like.

==================================================================
template< CARD8 num_axes >   /* derived from line 2 of the xml */
     struct DeviceTimeCoord
{
	TIMESTAMP time;
	INT32 valuators[num_axes];  /* drived from lines 4-6 of the xml */
};

struct GetDeviceMotionEvents_Reply
{
	CARD8 xi_reply_type;
	CARD32 num_events;
	CARD8 num_axes;
	CARD7 device_mode;
	BYTE pad[18];
	DeviceTimeCoord<num_axes> events[num_events]; 
			/* derived from lines 20-26 of the xml */
			/* num_axes and num_events are run-time values, 
			which would be illegal in C++, but I hope the 
			C++ pseudo-code still helps with understanding */
};
==================================================================

***

Alternative: Inline structs:

Another possibility would be inline structs (where the generator
would have to extract the implicit parametrization to add these
params to the param-list of Sizeof, Unpack, ... functions.

This could look like:
==================================================================
01    <request name="GetDeviceMotionEvents" opcode="10">
02        <field type="TIMESTAMP" name="start" />
03        <field type="TIMESTAMP" name="stop" altenum="Time" />
04        <field type="CARD8"     name="device_id" />
05        <pad bytes="3"/>
06        <reply>
07            <field type="CARD8"  name="xi_reply_type" />
08            <field type="CARD32" name="num_events" />
09            <field type="CARD8"  name="num_axes" />
10            <field type="CARD8"  name="device_mode" enum="ValuatorMode" />
11            <pad bytes="18" />
12            <list name="events" >
13                <struct name="DeviceTimeCoord">
14                    <field type="TIMESTAMP" name="time" />
15                    <list type="INT32" name="valuators">
16                        <fieldref>num_axes</fieldref>
17                    </list>
18                </struct>
19                <fieldref>num_events</fieldref>
20            </list>
21        </reply>
22    </request>
==================================================================

In lines 13 to 17, the struct is defined inline and therefore it is clear
what "num_axes" refers to.

In this example, the inline struct has a name, but the name could be
omitted. This would then be an anonymous inline struct.

***

For me it is not clear what will be better:
* explicit parametrization like in the first example?
* implicit parametrization by inlining as in the second example?

My guess is that explicit parametrization will be easier to implement in the generator.

Implicit parametrization by inlining will make writing the xml easier
when such a struct is only needed at one place.

When it is needed in multiple places, then inlining will cause
code-duplication whereas explicit parametrization will
allow code-reuse.

***

What do you think?

Chris

P.S.: I can implement either of the two schemes in the generator
though I have a slight preference for 
explicit parametrization because it allows
code-reuse on the xml-side.

Here's why I feel confident that I can implement that:
I have a lot of experience will parsing and code-generation,
especially from former projects and a job where I wrote
parsers for CASE-tools and IDEs. The most complex one was a parser
parsing C++-code, where I implemented to whole ISO C++-98 standard
including template instantiation...




More information about the Xcb mailing list