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 int cdecl_spec_kind(struct cdecl_declspec *spec);
20 provides support for parsing C declarations and translating them to something
21 resembling English and vice-versa. This manual describes the programmers'
22 interface only; for details such as what C language features are supported or
23 the syntax of English declarations, please see the
28 is intended to be portable to any system with a working C implementation that
29 at least makes an effort to support C99. The library is thread-safe when
30 appropriate facilities exist and are enabled at build time.
33 reserves all identifiers beginning with either
37 in both the tag and ordinary identifier namespaces. All external names
40 are reserved, and the library headers may define object-like macros beginning
45 library headers may use other identifiers where they do not pollute the global
46 namespaces, such as struct members or function parameter names. Such internal
47 identifiers shall not contain any upper-case letters. As these internal
48 identifiers can only conflict with object-like macros, this practice is safe as
49 long as the convention of defining object-like macros using upper-case letters
52 External names beginning with
54 followed by two consecutive underscores are not considered part of the ABI and
55 are thus subject to change at any time.
56 .Sh ABSTRACT SYNTAX TREE
59 generally operate on an abstract syntax tree representing a C declaration.
60 A string is parsed into an AST which can be subsequently rendered into another
61 format. Since some information about the original string is discarded when
62 generating the AST, parsing a declaration and then rendering to the same format
63 is not the identity function. The AST is represented by the following
65 .Bd -literal -offset indent
68 struct cdecl_declspec *specifiers;
69 struct cdecl_declarator *declarators;
73 At the top level, every declaration consists of one or more declaration
74 specifiers followed by one or more full declarators; hence, the
78 members are always non-null. A declaration with more than one declarator is
79 represented by using the
81 member to form a singly-linked list of ASTs, one element for each declarator.
82 In the case of the toplevel declaration, the declaration specifiers will be
83 identical for all elements of the list. But when the same kind of list is used
84 to represent function parameters, the specifiers may be different for each
87 There are four kinds of declaration specifiers: storage-class, function and
88 type specifiers, as well as type qualifiers. All are represented by the
90 .Bd -literal -offset indent
91 struct cdecl_declspec {
92 struct cdecl_declspec *next;
98 When multiple declaration specifiers are present, they are represented as
99 a singly-linked list, one element for each specifier. Specifiers can appear
100 in any order. The function
102 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
104 can be used to determine what kind of specifier
106 is. The result is one of the following values:
107 .Bl -column ".Dv CDECL_SPEC_TYPE"
108 .It Em Kind Ta Em Description
109 .It Dv CDECL_SPEC_TYPE Ta Type specifier.
110 .It Dv CDECL_SPEC_STOR Ta Storage-class specifier.
111 .It Dv CDECL_SPEC_QUAL Ta Type qualifier.
112 .It Dv CDECL_SPEC_FUNC Ta Function specifier.
115 The following table describes all the possible types of declaration specifiers.
116 .Bl -column ".Dv CDECL_TYPE_IMAGINARY"
117 .It Em Em Type Ta Em Description
118 .It Dv CDECL_TYPE_VOID Ta Fa void No type specifier.
119 .It Dv CDECL_TYPE_CHAR Ta Fa char No type specifier.
120 .It Dv CDECL_TYPE_SHORT Ta Fa short No type specifier.
121 .It Dv CDECL_TYPE_INT Ta Fa int No type specifier.
122 .It Dv CDECL_TYPE_LONG Ta Fa long No type specifier.
123 .It Dv CDECL_TYPE_FLOAT Ta Fa float No type specifier.
124 .It Dv CDECL_TYPE_DOUBLE Ta Fa double No type specifier.
125 .It Dv CDECL_TYPE_SIGNED Ta Fa signed No type specifier.
126 .It Dv CDECL_TYPE_UNSIGNED Ta Fa unsigned No type specifier.
127 .It Dv CDECL_TYPE_BOOL Ta Fa _Bool No type specifier.
128 .It Dv CDECL_TYPE_COMPLEX Ta Fa _Comples No type specifier.
129 .It Dv CDECL_TYPE_IMAGINARY Ta Fa _Imaginary No type specifier.
130 .It Dv CDECL_TYPE_STRUCT Ta Fa struct No type specifier. The
132 member points to a C string containing the struct tag.
133 .It Dv CDECL_TYPE_UNION Ta Fa union No type specifier. The
135 member points to a C string containing the union tag.
136 .It Dv CDECL_TYPE_ENUM Ta Fa enum No type specifier. The
138 member points to a C string containing the enum tag.
139 .It Dv CDECL_TYPE_IDENT Ta Typedef name type specifier. The
141 member points to a C string containing the identifier.
142 .It Dv CDECL_STOR_TYPEDEF Ta Fa typedef No storage-class specifier.
143 .It Dv CDECL_STOR_EXTERN Ta Fa extern No storage-class specifier.
144 .It Dv CDECL_STOR_STATIC Ta Fa static No storage-class specifier.
145 .It Dv CDECL_STOR_AUTO Ta Fa auto No storage-class specifier.
146 .It Dv CDECL_STOR_REGISTER Ta Fa register No storage-class specifier.
147 .It Dv CDECL_QUAL_RESTRICT Ta Fa restrict No type qualifier.
148 .It Dv CDECL_QUAL_VOLATILE Ta Fa volatile No type qualifier.
149 .It Dv CDECL_QUAL_CONST Ta Fa const No type qualifier.
150 .It Dv CDECL_FUNC_INLINE Ta Fa inline No function specifier.
153 Declarators are represented by the structure:
154 .Bd -literal -offset indent
155 struct cdecl_declarator {
156 struct cdecl_declarator *child;
160 struct cdecl_pointer pointer;
161 struct cdecl_array array;
162 struct cdecl_function function;
167 There are five types of declarators, distinguished by the
169 struct member. The union
171 contains a member for each declarator type (except null) containing additional
172 information. The possible values are described by the following table. The
173 description of the child member is a lie.
174 .Bl -column ".Dv CDECL_DECL_FUNCTION" ".Em Union Member"
175 .It Em Declarator Type Ta Em Union Member Ta Em Description
176 .It Dv CDECL_DECL_NULL Ta (none) Ta Declares nothing. This
179 .It Dv CDECL_DECL_IDENT Ta Va ident Ta Declares an identifier. This
182 .It Dv CDECL_DECL_POINTER Ta Va pointer Ta Declares a pointer. The
184 member is interpreted as "pointer to child".
185 .It Dv CDECL_DECL_ARRAY Ta Va array Ta Declares an array. The
187 member is interpreted as "array of child".
188 .It Dv CDECL_DECL_FUNCTION Ta Va function Ta Declares a function. The
190 member is interpreted as "function returning child".
192 .Ss Terminal Declarators
193 Null and identifier declarators have no children and are thus leaf nodes. A
194 null declarator indicates an abstract declarator; that is, one which does not
195 declare any identifier. Such declarators appear in type names and possibly
196 function parameters. An identifier declarator has the obvious meaning; the
198 union member points to the C string containing the identifier.
199 .Ss Pointer Declarators
200 .Bd -literal -offset indent
201 struct cdecl_pointer {
202 struct cdecl_declspec *qualifiers;
208 member is non-null, then it points to the first element of a singly-linked list
210 .Ss Array Declarators
211 .Bd -literal -offset indent
220 member is non-null, then this declarator is a variable-length array declarator.
223 member points to an identifier if it is known, else it points to the empty
227 is positive, then this is an array declarator with the specified length.
228 Otherwise, this is an incomplete array declarator.
229 .Ss Function Declarators
230 .Bd -literal -offset indent
231 struct cdecl_function {
232 struct cdecl *parameters;
239 is null, then this is a non-prototype function declarator. Otherwise,
241 points to the first element of a singly-linked list of declarations
242 representing the function parameters. Note that, unlike toplevel declarations,
243 each function parameter has exactly one full declarator (abstract or
246 is true, then the function is variadic.
247 .Sh PARSING DECLARATIONS
248 To parse a declaration, the function
250 .Fd struct cdecl *cdecl_parse_decl(const char *declstr);
252 can be used. The provided string is parsed as a C declaration. If successful,
253 this function returns a pointer to an abstract syntax tree representing the
254 declaration. If the parse fails for any reason, the function returns NULL.
256 Similarly, English declarations can be parsed by using the function
258 .Fd struct cdecl *cdecl_parse_english(const char *english);
260 When the AST is no longer needed, it must be freed by passing it to the
263 .Fd void cdecl_free(struct cdecl *decl);
264 .Sh RENDERING DECLARATIONS
265 On the other hand, the abstract syntax tree can be rendered to a string for
266 output. One can use the function
268 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
270 to format the AST pointed to by
272 into something resembling English. At most one full declarator is rendered
273 in this way; for declarations with more than one full declarator, this function
274 should be called on each
276 in the singly-linked list.
278 In a manner similar to that of
282 bytes, including the '\\0' terminator, are written to
286 is zero, it is acceptable for
288 to be a null pointer. Regardless, the function returns the number of
289 characters that would be written to
293 were long enough, not including the '\\0' terminator. Thus, the entire string
294 was written if a value less than
298 Similarly, the function
300 .Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
302 will render the AST pointed to by
306 Nick Bowler <nbowler@draconx.ca>
308 Copyright \(co 2011 Nick Bowler
310 Permission is granted to copy, distribute and/or modify this manual under the
311 terms of the Do What The Fuck You Want To Public License, version 2.