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 maintains no global state
30 and thus all functions should be safe for use in a multi-threaded environment.
31 .Sh ABSTRACT SYNTAX TREE
34 generally operate on an abstract syntax tree representing a C declaration.
35 A string is parsed into an AST which can be subsequently rendered into another
36 format. Since some information about the original string is discarded when
37 generating the AST, parsing a declaration and then rendering to the same format
38 is not the identity function. The AST is represented by the following
40 .Bd -literal -offset indent
43 struct cdecl_declspec *specifiers;
44 struct cdecl_declarator *declarators;
48 At the top level, every declaration consists of one or more declaration
49 specifiers followed by one or more full declarators; hence, the
53 members are always non-null. A declaration with more than one declarator is
54 represented by using the
56 member to form a singly-linked list of ASTs, one element for each declarator.
57 In the case of the toplevel declaration, the declaration specifiers will be
58 identical for all elements of the list. But when the same kind of list is used
59 to represent function parameters, the specifiers may be different for each
62 There are four kinds of declaration specifiers: storage-class, function and
63 type specifiers, as well as type qualifiers. All are represented by the
65 .Bd -literal -offset indent
66 struct cdecl_declspec {
67 struct cdecl_declspec *next;
73 When multiple declaration specifiers are present, they are represented as
74 a singly-linked list, one element for each specifier. Specifiers can appear
75 in any order. The function
77 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
79 can be used to determine what kind of specifier
81 is. The result is one of the following values:
82 .Bl -column ".Dv CDECL_SPEC_TYPE"
83 .It Em Kind Ta Em Description
84 .It Dv CDECL_SPEC_TYPE Ta Type specifier.
85 .It Dv CDECL_SPEC_STOR Ta Storage-class specifier.
86 .It Dv CDECL_SPEC_QUAL Ta Type qualifier.
87 .It Dv CDECL_SPEC_FUNC Ta Function specifier.
90 The following table describes all the possible types of declaration specifiers.
91 .Bl -column ".Dv CDECL_TYPE_IMAGINARY"
92 .It Em Em Type Ta Em Description
93 .It Dv CDECL_TYPE_VOID Ta Fa void No type specifier.
94 .It Dv CDECL_TYPE_CHAR Ta Fa char No type specifier.
95 .It Dv CDECL_TYPE_SHORT Ta Fa short No type specifier.
96 .It Dv CDECL_TYPE_INT Ta Fa int No type specifier.
97 .It Dv CDECL_TYPE_LONG Ta Fa long No type specifier.
98 .It Dv CDECL_TYPE_FLOAT Ta Fa float No type specifier.
99 .It Dv CDECL_TYPE_DOUBLE Ta Fa double No type specifier.
100 .It Dv CDECL_TYPE_SIGNED Ta Fa signed No type specifier.
101 .It Dv CDECL_TYPE_UNSIGNED Ta Fa unsigned No type specifier.
102 .It Dv CDECL_TYPE_BOOL Ta Fa _Bool No type specifier.
103 .It Dv CDECL_TYPE_COMPLEX Ta Fa _Comples No type specifier.
104 .It Dv CDECL_TYPE_IMAGINARY Ta Fa _Imaginary No type specifier.
105 .It Dv CDECL_TYPE_STRUCT Ta Fa struct No type specifier. The
107 member points to a C string containing the struct tag.
108 .It Dv CDECL_TYPE_UNION Ta Fa union No type specifier. The
110 member points to a C string containing the union tag.
111 .It Dv CDECL_TYPE_ENUM Ta Fa enum No type specifier. The
113 member points to a C string containing the enum tag.
114 .It Dv CDECL_TYPE_IDENT Ta Typedef name type specifier. The
116 member points to a C string containing the identifier.
117 .It Dv CDECL_STOR_TYPEDEF Ta Fa typedef No storage-class specifier.
118 .It Dv CDECL_STOR_EXTERN Ta Fa extern No storage-class specifier.
119 .It Dv CDECL_STOR_STATIC Ta Fa static No storage-class specifier.
120 .It Dv CDECL_STOR_AUTO Ta Fa auto No storage-class specifier.
121 .It Dv CDECL_STOR_REGISTER Ta Fa register No storage-class specifier.
122 .It Dv CDECL_QUAL_RESTRICT Ta Fa restrict No type qualifier.
123 .It Dv CDECL_QUAL_VOLATILE Ta Fa volatile No type qualifier.
124 .It Dv CDECL_QUAL_CONST Ta Fa const No type qualifier.
125 .It Dv CDECL_FUNC_INLINE Ta Fa inline No function specifier.
128 Declarators are represented by the structure:
129 .Bd -literal -offset indent
130 struct cdecl_declarator {
131 struct cdecl_declarator *child;
135 struct cdecl_pointer pointer;
136 struct cdecl_array array;
137 struct cdecl_function function;
142 There are five types of declarators, distinguished by the
144 struct member. The union
146 contains a member for each declarator type (except null) containing additional
147 information. The possible values are described by the following table. The
148 description of the child member is a lie.
149 .Bl -column ".Dv CDECL_DECL_FUNCTION" ".Em Union Member"
150 .It Em Declarator Type Ta Em Union Member Ta Em Description
151 .It Dv CDECL_DECL_NULL Ta (none) Ta Declares nothing. This
154 .It Dv CDECL_DECL_IDENT Ta Va ident Ta Declares an identifier. This
157 .It Dv CDECL_DECL_POINTER Ta Va pointer Ta Declares a pointer. The
159 member is interpreted as "pointer to child".
160 .It Dv CDECL_DECL_ARRAY Ta Va array Ta Declares an array. The
162 member is interpreted as "array of child".
163 .It Dv CDECL_DECL_FUNCTION Ta Va function Ta Declares a function. The
165 member is interpreted as "function returning child".
167 .Ss Terminal Declarators
168 Null and identifier declarators have no children and are thus leaf nodes. A
169 null declarator indicates an abstract declarator; that is, one which does not
170 declare any identifier. Such declarators appear in type names and possibly
171 function parameters. An identifier declarator has the obvious meaning; the
173 union member points to the C string containing the identifier.
174 .Ss Pointer Declarators
175 .Bd -literal -offset indent
176 struct cdecl_pointer {
177 struct cdecl_declspec *qualifiers;
183 member is non-null, then it points to the first element of a singly-linked list
185 .Ss Array Declarators
186 .Bd -literal -offset indent
195 member is non-null, then this declarator is a variable-length array declarator.
198 member points to an identifier if it is known, else it points to the empty
202 is positive, then this is an array declarator with the specified length.
203 Otherwise, this is an incomplete array declarator.
204 .Ss Function Declarators
205 .Bd -literal -offset indent
206 struct cdecl_function {
207 struct cdecl *parameters;
214 is null, then this is a non-prototype function declarator. Otherwise,
216 points to the first element of a singly-linked list of declarations
217 representing the function parameters. Note that, unlike toplevel declarations,
218 each function parameter has exactly one full declarator (abstract or
221 is true, then the function is variadic.
222 .Sh PARSING DECLARATIONS
223 To parse a declaration, the function
225 .Fd struct cdecl *cdecl_parse_decl(const char *declstr);
227 can be used. The provided string is parsed as a C declaration. If successful,
228 this function returns a pointer to an abstract syntax tree representing the
229 declaration. If the parse fails for any reason, the function returns NULL.
231 Similarly, English declarations can be parsed by using the function
233 .Fd struct cdecl *cdecl_parse_english(const char *english);
235 When the AST is no longer needed, it must be freed by passing it to the
238 .Fd void cdecl_free(struct cdecl *decl);
239 .Sh RENDERING DECLARATIONS
240 On the other hand, the abstract syntax tree can be rendered to a string for
241 output. One can use the function
243 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
245 to format the AST pointed to by
247 into something resembling English. At most one full declarator is rendered
248 in this way; for declarations with more than one full declarator, this function
249 should be called on each
251 in the singly-linked list.
253 In a manner similar to that of
257 bytes, including the '\\0' terminator, are written to
261 is zero, it is acceptable for
263 to be a null pointer. Regardless, the function returns the number of
264 characters that would be written to
268 were long enough, not including the '\\0' terminator. Thus, the entire string
269 was written if a value less than
273 Similarly, the function
275 .Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
277 will render the AST pointed to by
281 Nick Bowler <nbowler@draconx.ca>
283 Copyright \(co 2011 Nick Bowler
285 Permission is granted to copy, distribute and/or modify this manual under the
286 terms of the Do What The Fuck You Want To Public License, version 2.