XCB Protocol Implementation Macro Language
by Jamey Sharp
In this document, terms shall be used as follows.
A "field" is a unit of information in a real protocol request. Fields are never visible to programmers using XCB.
A "reply field" is a unit of information in a real protocol reply. Reply fields are directly visible to programmers using XCB.
A "param" ("parameter") is a unit of information passed to a protocol request wrapper function. It may or may not correspond to a field.
These macros desribe all data that comes from the X server.
Extension Support: BEGINEXTENSION and ENDEXTENSION
BEGINEXTENSION(X name, C name)
An extension's X name is the string used to identify it to the server (e.g. 'DPMS', 'SHAPE', 'XVideo'). The X protocol specification says that the X name of the extension "should use the ISO Latin-1 encoding, and uppercase and lowercase matter."
An extension's C name should be a valid C identifier which can be guessed easily from the X name: it will appear in some names visible to programmers using XCB.
VOIDREQUEST(name, 0 or more[PARAMs]])
Creates a function named [[XcbApi#XCBName][XCB<name>|XcbApi]] returning [[XcbApi#XCBNameCookie][XCBVoidCookie|XcbApi]] and accepting whatever parameters are necessary to deliver the given[PARAMs]] to the X server. Requests created with this macro do not expect a reply.
REQUEST(name, 0 or more[PARAMs]], 1 or more [FIELDs]])
Creates a function named [[XcbApi#XCBName][XCB<name>|XcbApi]] whose return result is an [[XcbApi#XCBNameCookie][XCB<name>Cookie|XcbApi]] and whose parameters are whatever is necessary to deliver the given[PARAMs]] to the X server. Declares the struct [[XcbApi#XCBNameCookie][XCB<name>Cookie|XcbApi]]. Creates a function named [[XcbApi#XCBNameReply][XCB<name>Reply|XcbApi]] returning a pointer to [[XcbApi#XCBNameRep][XCB<name>Rep|XcbApi]] which forces a cookie returned from [[XcbApi#XCBName][XCB<name>|XcbApi]], waiting for the response from the server if necessary. The [FIELDs]] must be quoted.
EVENT(name, number, 1 or more FIELDs)
Declares the struct [[XcbApi#XCBEventNameEvent][XCB<name>Event|XcbApi]] containing the given FIELDs. Also defines [[XcbApi#XCBEventName][XCB<name>|XcbApi]] equal to number.
EVENTCOPY(new name, new number, old name)
ERROR(name, number, 1 or more FIELDs)
Declares the struct [[XcbApi#XCBErrorNameError][XCB<name>Error|XcbApi]] containing the given FIELDs. Also defines [[XcbApi#XCBErrorName][XCB<name>|XcbApi]] equal to number.
ERRORCOPY(new name, new number, old name)
Request Parameters and Fields
These PARAM and FIELD macros may only appear within the second parameter to the[REQUEST]] or [VOIDREQUEST]] macros, and must always be quoted.
All of these macro calls must appear in the order specified by Appendix B (Protocol Encoding) of the X Window System Protocol specification, or the equivalent documentation for any extension. However,[LISTs]] (including !LISTofVALUEs) are always grouped after any fixed-length section.
Information about padding bytes must be known, so you may need to specify it using the[PAD]] macro. However, in several cases this information can be inferred by the macros and thus can be omitted:
* After the last fixed-length field in a fixed-length request or reply. * After the last fixed-length field in a variable-length request. * Between each variable-length field and the next 4-byte aligned boundary in a request.
For extensions, this macro generates code to look up the major number and sets the minor number to the given value.
For the core protocol, this macro sets the major number to the given value.
Inserts the given number of padding bytes.
Defines a parameter with a field of the same type.
VALUEPARAM(bitmask type, bitmask name, value array name)
Defines a BITMASK/LISTofVALUE parameter pair. The bitmask type should probably be either CARD16 or CARD32, depending on the specified width of the bitmask. The value array must be given to the generated function in the order the X server expects.
Caution! No type-, value-, or bounds-checking is done on this array by XCB. The X server and your operating system may not catch errors either, leading to odd results if you're not careful.
LISTPARAM(element type, list name, optional length expression)
Defines a !LISTofFOO parameter. The length of the list may be given as any C expression and may reference any of the other fields of this request.
If the length is not given, then it is obtained in a language-dependent manner. In C, a
name_len immediately before the list parameter.
Note that requests like QueryTextExtents require a[LOCALPARAM]] for the length field, while others like InternAtom require a [PARAM]].
The recommended idiom for strings is to pass the length of the string into XCB, because it is much easier for callers to convert null-terminated strings to this style of counted strings than to go the other way around, and because requiring null-terminated strings as input could cause some valid protocol requests to be impossible to produce using XCB.
[[!format txt """ PARAM(CARD16, `name_len') LISTPARAM(char, `name', `name_len') """]] _Example macro usage for strings with on-wire lengths._ [[!format txt """ LISTPARAM(char, `path') """]] _Example macro usage for strings without on-wire lengths._
Defines a parameter with no associated field. The name can be used in expressions.
This macro can be useful in conjunction with LISTs where you need to pass the number of items to the[LISTPARAM]] macro, but in the protocol the list length is implicit in the request length.
EXPRFIELD(field name, expression)
Defines a field which should be filled in with the given expression. The field has no associated parameter. The name can be used in expressions.
This macro can be useful when the protocol requires an explicit field containing a value which is easily calculated from the information available.
In the core protocol, the only request that this is used for is QueryTextExtents, where the length of the string is implicit in the length of the request, with the exception that whether the string is odd or even length must be specified separately. This declaration expresses that:
[[!format txt """
odd''length',string''len & 1')
Historically, EXPRFIELD was also used to allow C-style null-terminated strings to be passed to XCB and converted to counted strings automatically. This usage is deprecated. See [LISTPARAM]].
[[!format txt """ EXPRFIELD(CARD16, `name_len', `strlen(name)') LISTPARAM(char, `name', `name_len') """]] _Deprecated example of converting a null-terminated string to a counted string._
ARRAYREPLY(field type, field name, length name)
Header File Generation
HEADERONLY and SOURCEONLY
These two macros are deprecated. They're too language-specific to appear in generics.xcb, and XCB should be able to figure out where to put all declarations on its own anyway.
Code which should appear only in a header (.h) file or only in an implementation (.c) file may be enclosed in the HEADERONLY and SOURCEONLY macros.
XCBGEN and ENDXCBGEN
The first line (aside from comments) of any XCB protocol implementation should contain a call to the XCBGEN macro, and the last line should contain a call to the ENDXCBGEN macro. The header name should generally be the base name of the source file, with all lowercase letters capitalized, and all other characters converted to underscores ("_"): for example, xcb_conn.m4 uses XCB_CONN here.
XCBGEN automatically causes the header file to be #included by the implementation file.
Transliterates lowercase characters to uppercase.
Transliterates the first character of the string to uppercase.
Split a string into a list of strings, at each point that the given substring appears.
JOIN(sep, string, ...)
Join a list of strings with a given string as separator.
MAP(macro, string, ...)
Applies the macro to each following string and returns the transformed list.
PUSHDIV and divert should never be called with any number except -1. Instead, save the return value of ALLOCDIV into a macro that is named for the contents of the diversion, and use that macro.
[[!format txt """ define(`FUNCDIV', ALLOCDIV) """]] _Example of creating a new diversion._
Any use of
divert(0) should be replaced with POPDIV(), and the first call to divert before that should be replaced with a call to PUSHDIV. This ensures that the protocol description file can be used in a wide variety of ways, including those that want only the values of the macros and diversions created inside the file.
Returns a diversion number not currently in use.
Pushes the given diversion onto the diversion stack, switching to it in the process.
Pops the current diversion off the diversion stack, returning to the diversion which was in effect before the last[PUSHDIV]].
Move line indentation to the right 4 spaces.
Move line indentation to the left 4 spaces.
Indent current line according to the current indentation level set by[INDENT]] and [UNINDENT]].
FUNCTION(return type and function name, params, body)
Declares a C function, placing the appropriate prototype in the header file and the complete function in the implementation file.
STATICFUNCTION(return type and function name, params, body)
Declares a static-scope C function. No prototype is placed in the header file, and the keyword static is applied to the function in the implementation file.
INLINEFUNCTION(return type and function name, params, body)
Declare a C function which should be compiled inline if possible. The function is placed in the header file and declared "static inline".
A future implementation of these macros should fall back to generating a regular function if inlines aren't supported by the compiler, but this isn't implemented yet.
TYPEDEF(old name, new name)
ENUM(type name, name list)
Declares a struct holding an XID, and a function to allocate new instances of this struct.
STRUCT(name, 1 or more FIELDs)
Typedefs a structure defined to contain the given fields so that it has the given name.
UNION(name, 1 or more FIELDs)
Typedefs a union defined to contain the given fields so that it has the given name.
These declarations may be used in[STRUCT]], [UNION]], or [REQUEST]] reply definitions.
Declares a field of the given type with the given name.
LISTFIELD(type, name, quantity)
Declares a list with the given name and containing the given quantity of elements of the given type.
If the given type is fixed-length, declares the [[XcbApi#XCBNameField][XCB<request><field>|XcbApi]] function.
If the given type has an iterator, declares the [[XcbApi#XCBNameFieldIter][XCB<request><field>Iter|XcbApi]] function.
Declares the [[XcbApi#XCBNameFieldLength][XCB<request><field>Length|XcbApi]] function.
ARRAYFIELD(type, name, quantity)
These macros need to be documented.