doc

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