Internals of XCB python generator code
======================================
Part 1: XML parser & type system
a) basics
X protocol types are defined in the xcbgen code are derived from
the base class Type (xptypes.py).
Any Type object exports fields common to all derived types:
name: tuple of strings for the typename
size: size of Type in Bytes, or None if variable sized
nmemb: (fixed) number (>1) of (list) elements, or
None if number of elements is variable,
1 if non-list type
resolved: boolean indicating if Type is resolved
(i.e. all referenced Types are defined previously)
is_simple, is_list, ...: boolean fields in order to replace
python's isinstance()
The following member functions must be overridden in any
derived Type:
resolve(self, module)
the module parameter is always handed from the "parent"
object in the actual type hierarchy
out(self, name)
overridden by language-specific module for code
generation (e.g. c_client.py)]
fixed_size(self)
wether Type is of fixed or variable size
make_member_of(self, module, complex_type, field_type,
field_name, visible, wire, auto)
this method registers a Type with its "parent" object
in the type hierarchy (it gets called from the "parent"
object)
module: global module object, handed from the "parent"
object
complex_type: "parent" object
field_type: tuple of strings for the typename
field_name: name of this field within complex_type
visible: boolean indicating if the field is visible in
the request API
wire: boolean indicating if the field appears in the
request structure
auto: true if the field is in the request structure,
but not in the request API (e.g. opcode)
In order to parse the protocol XML files, a code generator (for C: c_client.py) instantiates a Module object (xcbgen/state.py) and registers callback functions for the toplevel Types with it. The Module object encapsulates all details of the XML parser. Next the code generator calls the Module.register() function, which in turn parses the XML file (by calling the function matcher.execute()). In this step only the toplevel elements are recognized and their Types registered with the Module object. The last step is the type resolution (function Module.resolve()), during which Type.resolve() gets called recursively for all registered Types and their respective child nodes.
b) derived Types
SimpleType(Type)
represents cardinal types like 'CARD32' or a typedef'ed
cardinal
Type fields: is_simple(True), size(fixed value),
nmemb(1==none-list Type)
Enum(SimpleType)
Enum is a SimpleType of fixed size 4
Type fields: is_simple(True), size(4), nmemb(1)
new fields: values, bits
values: python list of tuples [(name,value)]
bits: [(name,bitnum)]
ListType(Type)
List with a fixed or variable number of elements
Type fields: is_list(True), size(size of element Type),
nmemb(number of elements or None)
new fields: member, parent, expr
member: Type object of list elements
parent: python list of Type objects higher in
the type hierarchy ("parent object",
"grandparent" object, ...)
expr: Expression object (see below) to
determine the length of the list if the
number of elements is variable
ExprType(Type)
Expression that evaluates to a fixed sized type
Type fields: is_expr(True), nmemb(1),
size(type size expression evaluates to)
new fields: member, parent, expr
member: Type object representing the type the
expression evaluates to
parent: python list of Type objects higher in
the type hierarchy
expr: Expression object (see below)
PadType(Type)
Padding field (padding bytes can formally be regarded
as list(CARD8))
Type fields: is_pad(True), size(1),
nmemb(1 or fixed value)
ComplexType(Type)
Base class for all structure Types
(i.e. Types that contain named fields)
Type fields: is_container(True), size(0), nmemb(1)
new fields: elt, fields, lenfield_parent
elt: elements of (XML) subtree for this
Element (children of this node)
fields: python list of Fields (see below)
lenfield_parent:
python list containing only the current
Type object [self]
this list gets extended if container/
container-like Types are nested
it contains all Type objects that child
Type objects like ListType may need to
search for length fields (see below)
(note: changed to support Bitmask)
Struct(ComplexType)
Struct data type, no further fields
Union(ComplexType)
Union data type
Type fields: is_union(True)
Reply(ComplexType)
reply only appears as field in a request
Type fields: is_reply(True)
preset Fields: response_type, pad0, sequence, length
response_type: CARD8
pad0: PadType(None)
sequence: CARD16 (sequence number of the
corresponding request)
length: CARD32 (length field)
Request(ComplexType)
Request data type
new fields: reply, opcode
reply: None or Reply Type object
opcode: 8-bit major opcode of the request
preset Fields: major_opcode, minor_opcode or pad0, length
major_opcode: CARD8
minor_opcode: CARD8 (used in protocol
extensions)
pad0: PadType(None)
length: CARD16
Event(ComplexType)
Event data type
new fields: opcodes, has_seq
opcodes: python dict
has_seq: if the event contains the sequence
number of the last request issued
preset Fields: response_type, pad0, sequence
response: CARD8 type code
pad0: PadType(None) (if has_seq==True)
sequence: CARD16 (sequence number of the
corresponding request if
has_seq==True)
Error(ComplexType)
Error data type
new fields: opcodes
opcode: python dict
preset Fields: response_type, error_code, sequence
response_type: CARD8
error_code: CARD8
sequence: CARD16 (sequence number of the
corresponding request)
the following new types will be added in the near future:
SwitchType(Type)
List-like data type for variable number of elements of
variable type and size
used for conditional inclusion of fields
BitcaseType(ComplexType)
item in a SwitchType
c) auxiliary types (expr.py)
Field(object)
represents a field in a structure
fields: type, field_type, field_name, visible, wire, auto
type: Type object of the field
field_type: tuple of strings for the typename
field_name: name of this field within complex_type
visible: boolean indicating if the field is
visible in the request API
wire: boolean indicating if the field appears
in the request structure
auto: true if the field is in the request
structure, but not in the request API
(e.g. opcode)
Expression(object)
represents a mathematical expression for a list length,
exprfield or switch/bitcase mask
Expression understands the following XML elements:
- list: new length field is prepared for lists that have
no explicit length field
- fieldref: sets lenfield_name accordingly
- valueparam: sets lenfield_name and _type accordingly
(sets lenwire=True and bitfield=True)
- op: operator (+, -, *, /, &, or <<) is
evaluated recursively (sets op, lhs, rhs
accordingly)
fields: parent, nmemb, lenfield_name, lenfield_type,
lenwire, bitfield, op, rhs, lhs
parent: higher-level Type object the Expression
belongs to
nmemb: fixed value in a constant expression or
None
lenfield_name: name of the length field for
datatypes with a variable number
of elements or None
lenfield_type: type of the length field or None
lenwire: boolean indicating if the length field
appears in the request structure
bitfield: true if the length field is a bitmask
op: operator symbol or None
lhs: left hand side operator Expression or None
rhs: right hand side operator Expression or None