Rules¶
The rules of the C subset, by the name a diagnostic gives. A header
breaking one is still parsed; --strict makes any diagnostic an error.
anonymous-recordA struct, union or enum must have a tag. Anonymous ones have no name to refer to them by in other languages; a record is given a generated name, and the members of an anonymous enum are made constants.
nested-recordA struct or union must be defined at the top level, not inside another record; the record is hoisted to the top level.
bitfieldBit-fields have no equivalent in Rust or Zig; use a fixed-width integer and document the bits.
bit-maskA field of bits is an unsigned integer whose doc names the prefix of its masks, ‘see <PREFIX>_*’, and each mask a #define of contiguous bits that fit it, named by the prefix and the part, whose doc ends in ‘bits <hi>:<lo> of ‘<field>’’ or ‘bit <n> of ‘<field>’’; a mask that does not agree is not linked to the field.
flexible-arrayA flexible array member has no length to bind; use a pointer and a length. A record with one is allowed in no array and no struct, as ISO C requires; a flexible array of them is left out where that keeps the layout, and otherwise the record holding it is skipped.
attributeAttributes other than packed, such as aligned, change the layout in ways the targets cannot all express. A record whose layout an attribute or ‘#pragma pack’ changes, other than by packing it to one byte, is skipped; other attributes are ignored.
cxx-keywordA name must not be a keyword of C++, which includes the generated C API as it is; parameters are renamed, other names cannot be.
enum-valueAn enumerator must fit an int, as C99 requires; compilers that allow more disagree on the type of the enum. The enumerator is left out.
array-parameterAn array parameter is a pointer in C; declare it as one.
variadic-functionVariadic functions cannot be called idiomatically from other languages.
record-by-valuePass and return structs and unions by pointer, not by value.
enum-in-signatureDo not pass or return an enum; a C enum does not restrict the values, use an integer and document the enum it takes its values from.
typedefOnly function pointers may be typedef’d; refer to other types by their own name.
callback-nameA function pointer typedef must end in _cb, _callback, _fn, _fun, _func or _function.
callback-typedefA function pointer must be named by a typedef, as a callback; one written inline is bound only as a raw function pointer.
callback-lifetimeA callback parameter must say with @lifetime how long the library may invoke it, which nothing else can tell; without, it is bound only as a raw pointer.
callback-param-nameThe parameters of a function pointer must be named.
param-nameThe parameters of a function must be named, for its documentation and the bindings to name them.
function-like-macroFunction-like macros are code, not part of the FFI boundary; they are skipped.
macro-valueA #define must be a string literal or an integer constant expression; others are skipped.
unsupported-typeThe type has no equivalent across the targets; the declaration using it is skipped.
unsupported-declarationOnly types, functions and constants form the FFI boundary; variables and inline or static functions are skipped.
external-typeThe type is declared outside the headers and outside the C subset, so other languages cannot bind it.
string-returnA returned string is borrowed, never the caller’s to free, so it is returned as const char *.
callback-contextA callback takes exactly one void * context, and a function taking a callback takes its context as the next parameter, so other languages can pass a closure.
annotationThe documentation says what C cannot: @param[in], [out] or [in,out], @nullable, @len, @errno, @destroys, @lifetime and @nobind; each must name what exists and fits.
handle-lifecycleAn opaque record a function creates through an [out] pointer must have a function that @destroys it, so other languages can release it.
missing-docDeclarations on the FFI boundary must be documented.
doc-commentA declaration has one doc comment; adjacent ones are joined into one.
printer-nameThe pretty-printers that yace generates declare the enum ‘<prefix>_pr’ and the output formats ‘<PREFIX>_PR_DEF’, ‘<PREFIX>_PR_YAML’, ‘<PREFIX>_PR_TERSE’ and ‘<PREFIX>_PR_JSON’ in every target. In the C API they also declare ‘<record>_pr’ and ‘<record>_fpr’ for each record and ‘<enum>_str’ for each enum. yace skips a declaration of the headers that has one of these names, and every declaration that uses it. Such declarations come from the API’s own printers, as in xNVMe’s libxnvme_pp.h; tag such functions @nobind, or leave their header out, because the generated printers replace them.
parse-errorThe compiler could not parse the headers, together in the order given; the result is incomplete. Every error is reported, each once.
internal-erroryace failed on this declaration; it is skipped. This is a bug in yace.