-.Dd March 13, 2021
-.Os cdecl99
+.Dd December 3, 2023
.Dt LIBCDECL \&3 "Cdecl99 Developer's Manual"
+.Os cdecl99
.Sh NAME
.Nm libcdecl
.Nd C library for making sense of C declarations
.Fd struct cdecl *cdecl_parse_english(const char *english);
.Fd void cdecl_free(struct cdecl *decl);
.Pp
-.Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
.Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
+.Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
.Pp
.Fd const struct cdecl_error *cdecl_get_error(void);
.Pp
.Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
-.Fd bool cdecl_is_abstract(struct cdecl_declarator *declarator);
+.Fd int cdecl_is_abstract(struct cdecl_declarator *declarator);
.Sh DESCRIPTION
.Nm
provides support for parsing C declarations and translating them to something
to describe this inverted child relationship: we consider the outermost
declarator's
.Va parent
-as the declaration's base type (found amongst the declaration specifiers, e.g.
-.Li int , const unsigned long ,
+as the declaration's base type (found amongst the declaration specifiers,
+.No e.g. Li int , const unsigned long ,
etc.)
.Pp
The five types of declarators, described below, are distinguished by the
Since a null declarator may be deeply nested in the declarator chain, the
function
.Pp
-.Fd bool cdecl_is_abstract(struct cdecl_declarator *declarator);
+.Fd int cdecl_is_abstract(struct cdecl_declarator *declarator);
.Pp
can be used to determine whether or not a given declarator declares an
identifier.
Otherwise, this is an incomplete array declarator.
.Ss Function Declarators
.Bd -literal -offset indent
+typedef _Bool cdecl_bool; /* depends on configuration */
struct cdecl_function {
struct cdecl *parameters;
- _Bool variadic;
+ cdecl_bool variadic;
};
.Ed
.Pp
If
.Va parameters
-is null, then this is a non-prototype function declarator.
+is null, then this is a non-prototype function declarator with an empty
+identifier list.
Otherwise,
.Va parameters
points to the first element of a singly-linked list of declarations
one full declarator (abstract or otherwise).
If
.Va variadic
-is true, then the function is variadic.
+is non-zero, then the function is variadic.
+.Pp
+Please note that if the compiler used to build the library does not support
+.Vt _Bool ,
+then
+.Vt cdecl_bool
+will be defined as
+.Vt signed char
+instead.
+In most cases these will have a compatible binary representation, provided
+that applications do not set
+.Va variadic
+to any values besides 0 or 1.
.Pp
-Note that old-style function declarations with non-empty identifier lists are
-not directly represented here: this is because they are syntactically identical
-to a prototype where every parameter is a typedef name.
-Since
+Old-style function declarations with non-empty identifier lists cannot be
+directly represented by this structure.
+Such declarations are syntactically identical to a prototype with every
+parameter consisting solely of a typedef name.
.Nm
-isn't a C compiler, there is no way for its parser to tell these two kinds of
-declarations apart.
+cannot tell these apart when parsing and thus will return a parameter
+list, which can be rendered as expected.
.Sh ERROR HANDLING
Some functions in
.Nm
.Fn cdecl_get_error
is unspecified.
.Sh PARSING DECLARATIONS
-To parse a declaration, the function
-.Pp
-.Fd struct cdecl *cdecl_parse_decl(const char *declstr);
+The functions
.Pp
-can be used.
-The provided string is parsed as a C declaration.
-If successful, this function returns a pointer to an abstract syntax tree
-representing the declaration.
-If the parse fails for any reason, the function returns NULL.
+.Fd struct cdecl *cdecl_parse_decl(const char *decl);
+.Fd struct cdecl *cdecl_parse_english(const char *english);
.Pp
-Similarly, English declarations can be parsed by using the function
+parse a string into an abstract syntax tree representing the declaration.
+The
+.Fn cdecl_parse_decl
+function interprets the string as C declaration syntax, while
+.Fn cdecl_parse_english
+uses the English declaration syntax.
+If successful, a pointer to the abstract syntax tree representing the
+declaration is returned.
+If the parse fails for any reason, the function returns NULL, and
+.Fn cdecl_get_error
+may be used to retrieve the reason for failure.
.Pp
-.Fd struct cdecl *cdecl_parse_english(const char *english);
+The manner in which memory is allocated by these functions for the returned
+tree structure is unspecified.
+In particular, multiple nodes may share memory or may be implemented as
+read-only static allocations.
+Thus, the caller should not directly modify any part of the returned structure,
+as the results may be unexpected.
+A copy should be made if modifications are required.
.Pp
-When the AST is no longer needed, it must be freed by passing it to the
+When the structure returned by either parsing function is no longer needed, the
function
.Pp
.Fd void cdecl_free(struct cdecl *decl);
+.Pp
+may be used to release all memory allocations associated with that parse tree.
.Sh RENDERING DECLARATIONS
-After parsing, the abstract syntax tree can be rendered to a string for output.
-Use the function
+An abstract syntax tree (which may be the result of calling one of the parsing
+functions or constructed explicitly by the program) can be rendered to a string
+for output.
+The functions
.Pp
+.Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
.Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
.Pp
-to format the AST pointed to by
+perform this rendering.
+The
+.Fa cdecl_declare
+function produces output in C declaration syntax, while the
+.Fa cdecl_explain
+function produces output in the English declaration syntax.
+.Pp
+Only one top-level full declarator is rendered by each call; that is, these
+functions do not traverse the
+.Fa decl
+linked list at the top level.
+The caller can traverse this list to render multiple declarators.
+In order to assist with generating C declaration syntax, as a special case,
+when calling
+.Fn cdecl_declare
+the
+.Va specifiers
+member of the
.Fa decl
-into something resembling English.
-At most one full declarator is rendered in this way; for declarations with more
-than one full declarator, this function should be called on each
-.Dv struct cdecl
-in the singly-linked list.
-.Pp
-In a manner similar to that of
-.Xr snprintf 3 ,
-at most
+structure may be a null pointer.
+In this case, only the declarator is rendered.
+.Pp
+The string is output in a manner similar to that of
+.Xr snprintf 3 .
+At most
.Fa n
bytes, including the '\\0' terminator, are written to
.Fa buf .
is zero, it is acceptable for
.Fa buf
to be a null pointer.
-Regardless, the function returns the number of characters that would be written
-to
+.Pp
+The number of characters that would be written to
.Fa buf
if
.Fa n
-were long enough, not including the '\\0' terminator.
-Thus, the entire string was written if a value less than
+were large enough is returned, not including the '\\0' terminator.
+Hence the entire string was written if the returned value is less than
+.Fa n .
+If
.Fa n
-is returned.
-.Pp
-Similarly, the function
-.Pp
-.Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl);
-.Pp
-will render the AST pointed to by
-.Fa decl
-into C code.
+is non-zero, the resulting string is '\\0' terminated even if it was truncated.
.Sh AUTHORS
Nick Bowler <nbowler@draconx.ca>
.Sh COPYRIGHT
-Copyright \(co 2011\(en2012, 2021 Nick Bowler
+Copyright \(co 2011\(en2012, 2021, 2023 Nick Bowler
.Pp
Permission is granted to copy, distribute and/or modify this manual under the
terms of the GNU General Public License as published by the Free Software