3 .Dt LIBCDECL \&3 "Cdecl99 Developer's Manual"
6 .Nd C library for making sense of C declarations
10 .Fd struct cdecl *cdecl_parse_decl(const char *declstr);
11 .Fd struct cdecl *cdecl_parse_english(const char *english);
12 .Fd void cdecl_free(struct cdecl *decl);
14 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
15 .Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
17 .Fd const struct cdecl_error *cdecl_get_error(void);
19 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
20 .Fd bool cdecl_is_abstract(struct cdecl_declarator *declarator);
23 provides support for parsing C declarations and translating them to something
24 resembling English and vice-versa. This manual describes the programmers'
25 interface only; for details such as what C language features are supported or
26 the syntax of English declarations, please see the
31 is intended to be portable to any system with a working C implementation that
32 at least makes an effort to support C99. The library is thread-safe when
33 appropriate facilities exist and are enabled at build time.
36 reserves all identifiers beginning with either
40 in both the tag and ordinary identifier namespaces. All external names
43 are reserved, and the library headers may define object-like macros beginning
48 library headers may use other identifiers where they do not pollute the global
49 namespaces, such as struct members or function parameter names. Such internal
50 identifiers shall not contain any upper-case letters. As these internal
51 identifiers can only conflict with object-like macros, this practice is safe as
52 long as the convention of defining object-like macros using upper-case letters
55 External names beginning with
57 followed by two consecutive underscores are not considered part of the ABI and
58 are thus subject to change at any time.
59 .Sh ABSTRACT SYNTAX TREE
62 generally operate on an abstract syntax tree representing a C declaration.
63 A string is parsed into an AST which can be subsequently rendered into another
64 format. Since some information about the original string is discarded when
65 generating the AST, parsing a declaration and then rendering to the same format
66 is not the identity function. The AST is represented by the following
68 .Bd -literal -offset indent
71 struct cdecl_declspec *specifiers;
72 struct cdecl_declarator *declarators;
76 At the top level, every declaration consists of one or more declaration
77 specifiers followed by one or more full declarators; hence, the
81 members are always non-null. A declaration with more than one declarator is
82 represented by using the
84 member to form a singly-linked list of ASTs, one element for each declarator.
85 In the case of the toplevel declaration, the declaration specifiers will be
86 identical for all elements of the list. But when the same kind of list is used
87 to represent function parameters, the specifiers may be different for each
90 There are four kinds of declaration specifiers: storage-class, function and
91 type specifiers, as well as type qualifiers. All are represented by the
93 .Bd -literal -offset indent
94 struct cdecl_declspec {
95 struct cdecl_declspec *next;
101 When multiple declaration specifiers are present, they are represented as
102 a singly-linked list, one element for each specifier. Specifiers can appear
103 in any order. The function
105 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
107 can be used to determine what kind of specifier
109 is. The result is one of the following values:
110 .Bl -column ".Dv CDECL_SPEC_TYPE"
111 .It Em Kind Ta Em Description
112 .It Dv CDECL_SPEC_TYPE Ta Type specifier.
113 .It Dv CDECL_SPEC_STOR Ta Storage-class specifier.
114 .It Dv CDECL_SPEC_QUAL Ta Type qualifier.
115 .It Dv CDECL_SPEC_FUNC Ta Function specifier.
118 The following table describes all the possible types of declaration specifiers.
119 .Bl -column ".Dv CDECL_TYPE_IMAGINARY"
120 .It Em Em Type Ta Em Description
121 .It Dv CDECL_TYPE_VOID Ta Fa void No type specifier.
122 .It Dv CDECL_TYPE_CHAR Ta Fa char No type specifier.
123 .It Dv CDECL_TYPE_SHORT Ta Fa short No type specifier.
124 .It Dv CDECL_TYPE_INT Ta Fa int No type specifier.
125 .It Dv CDECL_TYPE_LONG Ta Fa long No type specifier.
126 .It Dv CDECL_TYPE_FLOAT Ta Fa float No type specifier.
127 .It Dv CDECL_TYPE_DOUBLE Ta Fa double No type specifier.
128 .It Dv CDECL_TYPE_SIGNED Ta Fa signed No type specifier.
129 .It Dv CDECL_TYPE_UNSIGNED Ta Fa unsigned No type specifier.
130 .It Dv CDECL_TYPE_BOOL Ta Fa _Bool No type specifier.
131 .It Dv CDECL_TYPE_COMPLEX Ta Fa _Comples No type specifier.
132 .It Dv CDECL_TYPE_IMAGINARY Ta Fa _Imaginary No type specifier.
133 .It Dv CDECL_TYPE_STRUCT Ta Fa struct No type specifier. The
135 member points to a C string containing the struct tag.
136 .It Dv CDECL_TYPE_UNION Ta Fa union No type specifier. The
138 member points to a C string containing the union tag.
139 .It Dv CDECL_TYPE_ENUM Ta Fa enum No type specifier. The
141 member points to a C string containing the enum tag.
142 .It Dv CDECL_TYPE_IDENT Ta Typedef name type specifier. The
144 member points to a C string containing the identifier.
145 .It Dv CDECL_STOR_TYPEDEF Ta Fa typedef No storage-class specifier.
146 .It Dv CDECL_STOR_EXTERN Ta Fa extern No storage-class specifier.
147 .It Dv CDECL_STOR_STATIC Ta Fa static No storage-class specifier.
148 .It Dv CDECL_STOR_AUTO Ta Fa auto No storage-class specifier.
149 .It Dv CDECL_STOR_REGISTER Ta Fa register No storage-class specifier.
150 .It Dv CDECL_QUAL_RESTRICT Ta Fa restrict No type qualifier.
151 .It Dv CDECL_QUAL_VOLATILE Ta Fa volatile No type qualifier.
152 .It Dv CDECL_QUAL_CONST Ta Fa const No type qualifier.
153 .It Dv CDECL_FUNC_INLINE Ta Fa inline No function specifier.
156 Declarators are represented by the structure:
157 .Bd -literal -offset indent
158 struct cdecl_declarator {
159 struct cdecl_declarator *child;
163 struct cdecl_pointer pointer;
164 struct cdecl_array array;
165 struct cdecl_function function;
170 There are five types of declarators, distinguished by the
172 struct member. The union
174 contains a member for each declarator type (except null) containing additional
175 information. The possible values are described by the following table. The
176 description of the child member is a lie.
177 .Bl -column ".Dv CDECL_DECL_FUNCTION" ".Em Union Member"
178 .It Em Declarator Type Ta Em Union Member Ta Em Description
179 .It Dv CDECL_DECL_NULL Ta (none) Ta Declares nothing. This
182 .It Dv CDECL_DECL_IDENT Ta Va ident Ta Declares an identifier. This
185 .It Dv CDECL_DECL_POINTER Ta Va pointer Ta Declares a pointer. The
187 member is interpreted as "pointer to child".
188 .It Dv CDECL_DECL_ARRAY Ta Va array Ta Declares an array. The
190 member is interpreted as "array of child".
191 .It Dv CDECL_DECL_FUNCTION Ta Va function Ta Declares a function. The
193 member is interpreted as "function returning child".
195 .Ss Terminal Declarators
196 Null and identifier declarators have no children and are thus leaf nodes. A
197 null declarator is not strictly a C language construct, but is used by
199 to indicate an abstract declarator; that is, one which does not declare any
200 identifier. Such declarators appear in type names and possibly function
201 parameters. An identifier declarator has the obvious meaning; the
203 union member points to the C string containing the identifier.
205 Since a null declarator may be deeply nested in the declarator chain, the
208 .Fd bool cdecl_is_abstract(struct cdecl_declarator *declarator);
210 can be used to determine whether or not a given declarator declares an
211 identifier. The result is true if and only if the declarator is abstract.
212 .Ss Pointer Declarators
213 .Bd -literal -offset indent
214 struct cdecl_pointer {
215 struct cdecl_declspec *qualifiers;
221 member is non-null, then it points to the first element of a singly-linked list
223 .Ss Array Declarators
224 .Bd -literal -offset indent
233 member is non-null, then this declarator is a variable-length array declarator.
236 member points to an identifier if it is known, else it points to the empty
240 is positive, then this is an array declarator with the specified length.
241 Otherwise, this is an incomplete array declarator.
242 .Ss Function Declarators
243 .Bd -literal -offset indent
244 struct cdecl_function {
245 struct cdecl *parameters;
252 is null, then this is a non-prototype function declarator. Otherwise,
254 points to the first element of a singly-linked list of declarations
255 representing the function parameters. Note that, unlike toplevel declarations,
256 each function parameter has exactly one full declarator (abstract or
259 is true, then the function is variadic.
263 can fail. Such functions will be documented as indicating an error condition
264 in a particular way. It is sometimes necessary to know more about a particular
265 error in order to print an informative error message or perform some other
266 action. To facilitate this,
268 provides a structure which describes a particular error.
269 .Bd -literal -offset indent
278 member identifies the sort of error which has occurred, while the
280 member points to a string containing a human-readable description of the error.
281 This error information can be retrieved by calling the function
283 .Fd const struct cdecl_error *cdecl_get_error(void);
285 which returns a pointer to the error structure most recently generated in the
286 current thread. It is therefore thread-safe in that errors occurring in
287 another thread will not interfere with the current one. The returned pointer
288 shall remain valid until the next call to any function from
290 by the same thread, except that multiple consecutive calls to
292 shall all return the same value. The same applies to the
294 pointer inside the error structure itself.
296 If this function is called before an error has been indicated by an earlier
297 call in the same thread, the behaviour is undefined.
298 .Sh PARSING DECLARATIONS
299 To parse a declaration, the function
301 .Fd struct cdecl *cdecl_parse_decl(const char *declstr);
303 can be used. The provided string is parsed as a C declaration. If successful,
304 this function returns a pointer to an abstract syntax tree representing the
305 declaration. If the parse fails for any reason, the function returns NULL.
307 Similarly, English declarations can be parsed by using the function
309 .Fd struct cdecl *cdecl_parse_english(const char *english);
311 When the AST is no longer needed, it must be freed by passing it to the
314 .Fd void cdecl_free(struct cdecl *decl);
315 .Sh RENDERING DECLARATIONS
316 On the other hand, the abstract syntax tree can be rendered to a string for
317 output. One can use the function
319 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
321 to format the AST pointed to by
323 into something resembling English. At most one full declarator is rendered
324 in this way; for declarations with more than one full declarator, this function
325 should be called on each
327 in the singly-linked list.
329 In a manner similar to that of
333 bytes, including the '\\0' terminator, are written to
337 is zero, it is acceptable for
339 to be a null pointer. Regardless, the function returns the number of
340 characters that would be written to
344 were long enough, not including the '\\0' terminator. Thus, the entire string
345 was written if a value less than
349 Similarly, the function
351 .Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
353 will render the AST pointed to by
357 Nick Bowler <nbowler@draconx.ca>
359 Copyright \(co 2011 Nick Bowler
361 Permission is granted to copy, distribute and/or modify this manual under the
362 terms of the Do What The Fuck You Want To Public License, version 2.