XCB Protocol Implementation Macro Language
by Jamey Sharp
Terminology
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.
Responses
These macros desribe all data that comes from the X server.
Extension Support: BEGINEXTENSION and ENDEXTENSION
BEGINEXTENSION(X name, C name)
ENDEXTENSION
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
VOIDREQUEST(name, 0 or more ?[#Request''Parameters''and Fields[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 ?[#Request''Parameters''and Fields[PARAMs]] to the X server. Requests created with this macro do not expect a reply.
REQUEST
REQUEST(name, 0 or more ?[#Request''Parameters''and''Fields[PARAMs]], 1 or more ?[#Field''Declarations[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 ?[#Request''Parameters''and Fields[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 ?[#Field Declarations[FIELDs]] must be quoted.
EVENT
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
EVENTCOPY(new name, new number, old name)
(undocumented)
ERROR
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
ERRORCOPY(new name, new number, old name)
(undocumented)
Request Parameters and Fields
These PARAM and FIELD macros may only appear within the second parameter to the ?[#REQUESTREQUEST] or ?[#VOIDREQUESTVOIDREQUEST] 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, ?[#LISTPARAM[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 ?[#PADPAD] 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.
OPCODE
OPCODE(number)
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.
PAD
PAD(bytes)
Inserts the given number of padding bytes.
PARAM
PARAM(type, name)
Defines a parameter with a field of the same type.
VALUEPARAM
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
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 ?[#LOCALPARAMLOCALPARAM] is automatically generated for name_len
immediately before the list parameter.
Note that requests like QueryTextExtents require a ?[#LOCALPARAMLOCALPARAM] for the length field, while others like InternAtom require a ?[#PARAMPARAM].
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.
PARAM(CARD16, `name_len') LISTPARAM(char, `name', `name_len')_Example macro usage for strings with on-wire lengths._LISTPARAM(char, `path')_Example macro usage for strings without on-wire lengths._
LOCALPARAM
LOCALPARAM(type, name)
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 ?[#LISTPARAMLISTPARAM] macro, but in the protocol the list length is implicit in the request length.
EXPRFIELD
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:
EXPRFIELD(BOOL, `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 ?[#LISTPARAMLISTPARAM].
EXPRFIELD(CARD16, `name_len', `strlen(name)') LISTPARAM(char, `name', `name_len')_Deprecated example of converting a null-terminated string to a counted string._
ARRAYREPLY
ARRAYREPLY(field type, field name, length name)
Deprecated: use ?[#LISTFIELDLISTFIELD].
REPLY
REPLY(type, name)
Deprecated: use ?[#FIELDFIELD]
Utility Macros
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
XCBGEN(header name)
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, xcbconn.m4 uses XCB_CONN here.
XCBGEN automatically causes the header file to be #included by the implementation file.
Internal Macros
TOUPPER
TOUPPER(string)
Transliterates lowercase characters to uppercase.
UCFIRST
UCFIRST(string)
Transliterates the first character of the string to uppercase.
SPLIT
SPLIT(substring, string)
Split a string into a list of strings, at each point that the given substring appears.
JOIN
JOIN(sep, string, ...)
Join a list of strings with a given string as separator.
MAP
MAP(macro, string, ...)
Applies the macro to each following string and returns the transformed list.
UNIMPLEMENTED
(undocumented)
Diversions
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.
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.
ALLOCDIV
ALLOCDIV()
Returns a diversion number not currently in use.
PUSHDIV
PUSHDIV(diversion)
Pushes the given diversion onto the diversion stack, switching to it in the process.
POPDIV
POPDIV()
Pops the current diversion off the diversion stack, returning to the diversion which was in effect before the last ?[#PUSHDIVPUSHDIV].
Indentation
INDENT
INDENT()
Move line indentation to the right 4 spaces.
UNINDENT
UNINDENT()
Move line indentation to the left 4 spaces.
TAB
TAB()
Indent current line according to the current indentation level set by ?[#INDENTINDENT] and ?[#UNINDENTUNINDENT].
Functions
FUNCTION
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
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
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.
Types
TYPEDEF
TYPEDEF(old name, new name)
(undocumented)
ENUM
ENUM(type name, name list)
(undocumented)
XIDTYPE
XIDTYPE(name)
Declares a struct holding an XID, and a function to allocate new instances of this struct.
STRUCT
STRUCT(name, 1 or more FIELDs)
Typedefs a structure defined to contain the given fields so that it has the given name.
UNION
UNION(name, 1 or more FIELDs)
Typedefs a union defined to contain the given fields so that it has the given name.
Field Declarations
These declarations may be used in ?[#STRUCTSTRUCT], ?[#UNIONUNION], or ?[#REQUESTREQUEST] reply definitions.
FIELD
FIELD(type, name)
Declares a field of the given type with the given name.
LISTFIELD
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
ARRAYFIELD(type, name, quantity)
Deprecated: use ?[#LISTFIELDLISTFIELD].
Undocumented
These macros need to be documented.
COMMENT
(undocumented)