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