]> git.draconx.ca Git - cdecl99.git/blob - doc/libcdecl.3
4a882a0b1e474213c7526737b2d7bc1cee0f8772
[cdecl99.git] / doc / libcdecl.3
1 .Dd December 3, 2023
2 .Dt LIBCDECL \&3 "Cdecl99 Developer's Manual"
3 .Os cdecl99
4 .Sh NAME
5 .Nm libcdecl
6 .Nd C library for making sense of C declarations
7 .Sh SYNOPSIS
8 .Fd #include <cdecl.h>
9 .Pp
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);
13 .Pp
14 .Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
15 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
16 .Pp
17 .Fd const struct cdecl_error *cdecl_get_error(void);
18 .Pp
19 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
20 .Fd int cdecl_is_abstract(struct cdecl_declarator *declarator);
21 .Sh DESCRIPTION
22 .Nm
23 provides support for parsing C declarations and translating them to something
24 resembling English and vice-versa.
25 This manual describes the programmers' interface only; for details such as what
26 C language features are supported or the syntax of English declarations, please
27 see the
28 .Xr cdecl99 1
29 manual page.
30 .Pp
31 .Nm
32 is intended to be portable to any system with a working C implementation that
33 at least makes an effort to support C99.
34 The library is thread-safe when appropriate facilities exist and are enabled at
35 build time.
36 .Sh NAMESPACE
37 .Nm
38 reserves all identifiers beginning with either
39 .Li cdecl_
40 or
41 .Li CDECL_
42 in both the tag and ordinary identifier namespaces.
43 All external names beginning with
44 .Li cdecl_
45 are reserved, and the library headers may define object-like macros beginning
46 with
47 .Li CDECL_ .
48 The
49 .Nm
50 library headers may use other identifiers where they do not pollute the global
51 namespaces, such as struct members or function parameter names.
52 Such internal identifiers shall not contain any upper-case letters.
53 As these internal identifiers can only conflict with object-like macros, this
54 practice is safe as long as the convention of defining object-like macros using
55 upper-case letters is adhered to.
56 .Pp
57 External names beginning with
58 .Li cdecl
59 followed by two consecutive underscores are not considered part of the ABI and
60 are thus subject to change at any time.
61 .Sh ABSTRACT SYNTAX TREE
62 The functions in
63 .Nm
64 generally operate on an abstract syntax tree representing a C declaration.
65 A string is parsed into an AST which can be subsequently rendered into another
66 format.
67 Since some information about the original string is discarded when generating
68 the AST, parsing a declaration and then rendering to the same format is not the
69 identity function.
70 The AST is represented by the following structure:
71 .Bd -literal -offset indent
72 struct cdecl {
73         struct cdecl *next;
74         struct cdecl_declspec   *specifiers;
75         struct cdecl_declarator *declarators;
76 };
77 .Ed
78 .Pp
79 At the top level, every declaration consists of one or more declaration
80 specifiers followed by one or more full declarators; hence, the
81 .Va specifiers
82 and
83 .Va declarators
84 members are always non-null.
85 A declaration with more than one declarator is represented by using the
86 .Va next
87 member to form a singly-linked list of ASTs, one element for each declarator.
88 In the case of the toplevel declaration, the declaration specifiers will be
89 identical for all elements of the list.
90 But when the same kind of list is used to represent function parameters, the
91 specifiers may be different for each element.
92 .Pp
93 There are four kinds of declaration specifiers: storage-class, function and
94 type specifiers, as well as type qualifiers.
95 All are represented by the structure:
96 .Bd -literal -offset indent
97 struct cdecl_declspec {
98         struct cdecl_declspec *next;
99         unsigned type;
100         char *ident;
101 };
102 .Ed
103 .Pp
104 When multiple declaration specifiers are present, they are represented as
105 a singly-linked list, one element for each specifier.
106 Specifiers can appear in any order.
107 The function
108 .Pp
109 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
110 .Pp
111 can be used to determine what kind of specifier
112 .Fa spec
113 is.  The result is one of the following values:
114 .Bl -column ".Dv CDECL_SPEC_TYPE"
115 .It Em Kind            Ta Em Description
116 .It Dv CDECL_SPEC_TYPE Ta Type specifier .
117 .It Dv CDECL_SPEC_STOR Ta Storage-class specifier .
118 .It Dv CDECL_SPEC_QUAL Ta Type qualifier .
119 .It Dv CDECL_SPEC_FUNC Ta Function specifier .
120 .El
121 .Pp
122 The following table describes all the possible types of declaration specifiers:
123 .Bl -column ".Dv CDECL_TYPE_IMAGINARY"
124 .It Em Em Type              Ta Em Description
125 .It Dv CDECL_TYPE_VOID      Ta Fa void       No type specifier .
126 .It Dv CDECL_TYPE_CHAR      Ta Fa char       No type specifier .
127 .It Dv CDECL_TYPE_SHORT     Ta Fa short      No type specifier .
128 .It Dv CDECL_TYPE_INT       Ta Fa int        No type specifier .
129 .It Dv CDECL_TYPE_LONG      Ta Fa long       No type specifier .
130 .It Dv CDECL_TYPE_FLOAT     Ta Fa float      No type specifier .
131 .It Dv CDECL_TYPE_DOUBLE    Ta Fa double     No type specifier .
132 .It Dv CDECL_TYPE_SIGNED    Ta Fa signed     No type specifier .
133 .It Dv CDECL_TYPE_UNSIGNED  Ta Fa unsigned   No type specifier .
134 .It Dv CDECL_TYPE_BOOL      Ta Fa _Bool      No type specifier .
135 .It Dv CDECL_TYPE_COMPLEX   Ta Fa _Comples   No type specifier .
136 .It Dv CDECL_TYPE_IMAGINARY Ta Fa _Imaginary No type specifier .
137 .It Dv CDECL_TYPE_STRUCT    Ta Fa struct     No type specifier .
138 The
139 .Va ident
140 member points to a C string containing the struct tag.
141 .It Dv CDECL_TYPE_UNION     Ta Fa union      No type specifier .
142 The
143 .Va ident
144 member points to a C string containing the union tag.
145 .It Dv CDECL_TYPE_ENUM      Ta Fa enum       No type specifier .
146 The
147 .Va ident
148 member points to a C string containing the enum tag.
149 .It Dv CDECL_TYPE_IDENT     Ta Typedef name type specifier .
150 The
151 .Va ident
152 member points to a C string containing the identifier.
153 .It Dv CDECL_STOR_TYPEDEF   Ta Fa typedef    No storage-class specifier .
154 .It Dv CDECL_STOR_EXTERN    Ta Fa extern     No storage-class specifier .
155 .It Dv CDECL_STOR_STATIC    Ta Fa static     No storage-class specifier .
156 .It Dv CDECL_STOR_AUTO      Ta Fa auto       No storage-class specifier .
157 .It Dv CDECL_STOR_REGISTER  Ta Fa register   No storage-class specifier .
158 .It Dv CDECL_QUAL_RESTRICT  Ta Fa restrict   No type qualifier .
159 .It Dv CDECL_QUAL_VOLATILE  Ta Fa volatile   No type qualifier .
160 .It Dv CDECL_QUAL_CONST     Ta Fa const      No type qualifier .
161 .It Dv CDECL_FUNC_INLINE    Ta Fa inline     No function specifier .
162 .El
163 .Pp
164 Declarators are represented by the structure:
165 .Bd -literal -offset indent
166 struct cdecl_declarator {
167         struct cdecl_declarator *child;
168         unsigned type;
169         union {
170                 char *ident;
171                 struct cdecl_pointer  pointer;
172                 struct cdecl_array    array;
173                 struct cdecl_function function;
174         } u;
175 };
176 .Ed
177 .Pp
178 With the exception of function parameters (which are handled separately),
179 declarators form a chain from
180 .Do outermost Dc to Do innermost Dc
181 declarator.
182 This relationship is expressed by the
183 .Va child
184 struct member, which points to the next innermost declarator in the chain.
185 Unfortunately, C's declaration syntax is, in a sense, inside-out.
186 Thus, one needs to follow the chain backwards (from innermost to outermost) to
187 understand the semantic relationship between declarators in the chain.
188 In the next section, we will use the word
189 .Va parent
190 to describe this inverted child relationship: we consider the outermost
191 declarator's
192 .Va parent
193 as the declaration's base type (found amongst the declaration specifiers,
194 .No e.g. Li int , const unsigned long ,
195 etc.)
196 .Pp
197 The five types of declarators, described below, are distinguished by the
198 .Va type
199 struct member.
200 Each declarator (except null declarators) carries additional information
201 specific to its type, which corresponds to the members of the union
202 .Va u .
203 The possible values are described by the following table:
204 .Bl -column ".Dv CDECL_DECL_FUNCTION" ".Em Union Member"
205 .It Em Declarator Type     Ta Em Union Member Ta Em Description
206 .It Dv CDECL_DECL_NULL     Ta (none)          Ta Declares nothing.  This
207 declarator terminates the declarator chain, and has a NULL
208 .Va child .
209 .It Dv CDECL_DECL_IDENT    Ta Va ident        Ta Declares an identifier.  This
210 declarator has a NULL
211 .Va child .
212 .It Dv CDECL_DECL_POINTER  Ta Va pointer      Ta Declares a pointer, as in
213 .Do pointer to Va parent Dc
214 .It Dv CDECL_DECL_ARRAY    Ta Va array        Ta Declares an array, as in
215 .Do array of Va parent Dc
216 .It Dv CDECL_DECL_FUNCTION Ta Va function     Ta Declares a function, as in
217 .Do function returning Va parent Dc
218 .El
219 .Ss Terminal Declarators
220 Null and identifier declarators have no children and are thus leaf nodes.
221 A null declarator is not strictly a C language construct, but is used by
222 .Nm
223 to indicate an abstract declarator; that is, one which does not declare any
224 identifier.
225 Such declarators appear in type names and possibly function parameters.
226 An identifier declarator has the obvious meaning; the
227 .Va ident
228 union member points to the C string containing the identifier.
229 .Pp
230 Since a null declarator may be deeply nested in the declarator chain, the
231 function
232 .Pp
233 .Fd int cdecl_is_abstract(struct cdecl_declarator *declarator);
234 .Pp
235 can be used to determine whether or not a given declarator declares an
236 identifier.
237 The result is true if and only if the declarator is abstract.
238 .Ss Pointer Declarators
239 .Bd -literal -offset indent
240 struct cdecl_pointer {
241         struct cdecl_declspec *qualifiers;
242 };
243 .Ed
244 .Pp
245 If the
246 .Va qualifiers
247 member is non-null, then it points to the first element of a singly-linked list
248 of type qualifiers.
249 .Ss Array Declarators
250 .Bd -literal -offset indent
251 struct cdecl_array {
252         char *vla;
253         uintmax_t length;
254 };
255 .Ed
256 .Pp
257 If the
258 .Va vla
259 member is non-null, then this declarator is a variable-length array declarator.
260 The
261 .Va vla
262 member points to an identifier if it is known, else it points to the empty
263 string.
264 Otherwise, if
265 .Va length
266 is positive, then this is an array declarator with the specified length.
267 Otherwise, this is an incomplete array declarator.
268 .Ss Function Declarators
269 .Bd -literal -offset indent
270 typedef _Bool cdecl_bool; /* depends on configuration */
271 struct cdecl_function {
272         struct cdecl *parameters;
273         cdecl_bool variadic;
274 };
275 .Ed
276 .Pp
277 If
278 .Va parameters
279 is null, then this is a non-prototype function declarator with an empty
280 identifier list.
281 Otherwise,
282 .Va parameters
283 points to the first element of a singly-linked list of declarations
284 representing the function parameters.
285 Note that, unlike toplevel declarations, each function parameter has exactly
286 one full declarator (abstract or otherwise).
287 If
288 .Va variadic
289 is non-zero, then the function is variadic.
290 .Pp
291 Please note that if the compiler used to build the library does not support
292 .Vt _Bool ,
293 then
294 .Vt cdecl_bool
295 will be defined as
296 .Vt signed char
297 instead.
298 In most cases these will have a compatible binary representation, provided
299 that applications do not set
300 .Va variadic
301 to any values besides 0 or 1.
302 .Pp
303 Old-style function declarations with non-empty identifier lists cannot be
304 directly represented by this structure.
305 Such declarations are syntactically identical to a prototype with every
306 parameter consisting solely of a typedef name.
307 .Nm
308 cannot tell these apart when parsing and thus will return a parameter
309 list, which can be rendered as expected.
310 .Sh ERROR HANDLING
311 Some functions in
312 .Nm
313 can fail.
314 Such functions will be documented as indicating an error condition in a
315 particular way.
316 It is sometimes necessary to know more about a particular error in order to
317 print an informative error message or perform some other action.
318 To facilitate this,
319 .Nm
320 provides a structure which describes a particular error.
321 .Bd -literal -offset indent
322 struct cdecl_error {
323         unsigned code;
324         const char *str;
325 };
326 .Ed
327 .Pp
328 The
329 .Va code
330 member identifies the sort of error which has occurred, while the
331 .Va str
332 member points to a string containing a human-readable description of the error.
333 This error information can be retrieved by calling the function
334 .Pp
335 .Fd const struct cdecl_error *cdecl_get_error(void);
336 .Pp
337 which returns a pointer to the error structure most recently generated in the
338 current thread.
339 It is therefore thread-safe in the sense that errors occurring concurrently
340 in another thread will not interfere with a call to
341 .Fn cdecl_get_error .
342 The returned structure shall remain valid until the next call to any function
343 from
344 .Nm ,
345 by the same thread, other than another call to
346 .Fn cdecl_get_error .
347 .Pp
348 If no prior
349 .Nm
350 call has indicated that an error occurred in the current thread, the result
351 from calling
352 .Fn cdecl_get_error
353 is unspecified.
354 .Sh PARSING DECLARATIONS
355 The functions
356 .Pp
357 .Fd struct cdecl *cdecl_parse_decl(const char *decl);
358 .Fd struct cdecl *cdecl_parse_english(const char *english);
359 .Pp
360 parse a string into an abstract syntax tree representing the declaration.
361 The
362 .Fn cdecl_parse_decl
363 function interprets the string as C declaration syntax, while
364 .Fn cdecl_parse_english
365 uses the English declaration syntax.
366 If successful, a pointer to the abstract syntax tree representing the
367 declaration is returned.
368 If the parse fails for any reason, the function returns NULL, and
369 .Fn cdecl_get_error
370 may be used to retrieve the reason for failure.
371 .Pp
372 The manner in which memory is allocated by these functions for the returned
373 tree structure is unspecified.
374 In particular, multiple nodes may share memory or may be implemented as
375 read-only static allocations.
376 Thus, the caller should not directly modify any part of the returned structure,
377 as the results may be unexpected.
378 A copy should be made if modifications are required.
379 .Pp
380 When the structure returned by either parsing function is no longer needed, the
381 function
382 .Pp
383 .Fd void cdecl_free(struct cdecl *decl);
384 .Pp
385 may be used to release all memory allocations associated with that parse tree.
386 .Sh RENDERING DECLARATIONS
387 An abstract syntax tree (which may be the result of calling one of the parsing
388 functions or constructed explicitly by the program) can be rendered to a string
389 for output.
390 The functions
391 .Pp
392 .Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
393 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
394 .Pp
395 perform this rendering.
396 The
397 .Fa cdecl_declare
398 function produces output in C declaration syntax, while the
399 .Fa cdecl_explain
400 function produces output in the English declaration syntax.
401 .Pp
402 Only one top-level full declarator is rendered by each call; that is, these
403 functions do not traverse the
404 .Fa decl
405 linked list at the top level.
406 The caller can traverse this list to render multiple declarators.
407 In order to assist with generating C declaration syntax, as a special case,
408 when calling
409 .Fn cdecl_declare
410 the
411 .Va specifiers
412 member of the
413 .Fa decl
414 structure may be a null pointer.
415 In this case, only the declarator is rendered.
416 .Pp
417 The string is output in a manner similar to that of
418 .Xr snprintf 3 .
419 At most
420 .Fa n
421 bytes, including the '\\0' terminator, are written to
422 .Fa buf .
423 If
424 .Fa n
425 is zero, it is acceptable for
426 .Fa buf
427 to be a null pointer.
428 .Pp
429 The number of characters that would be written to
430 .Fa buf
431 if
432 .Fa n
433 were large enough is returned, not including the '\\0' terminator.
434 Hence the entire string was written if the returned value is less than
435 .Fa n .
436 If
437 .Fa n
438 is non-zero, the resulting string is '\\0' terminated even if it was truncated.
439 .Sh AUTHORS
440 Nick Bowler <nbowler@draconx.ca>
441 .Sh COPYRIGHT
442 Copyright \(co 2011\(en2012, 2021, 2023 Nick Bowler
443 .Pp
444 Permission is granted to copy, distribute and/or modify this manual under the
445 terms of the GNU General Public License as published by the Free Software
446 Foundation, either version 3 of the License, or (at your option) any later
447 version.
448 .Sh SEE ALSO
449 .Xr cdecl99 1