From 3d4b904fb3de990c69d5b7f56808105e6702d8e4 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Mon, 18 Jul 2011 20:59:15 -0400 Subject: [PATCH] Add man pages. --- Makefile.am | 2 + doc/man/cdecl99.1 | 171 +++++++++++++++++++++++++++ doc/man/libcdecl.3 | 288 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 461 insertions(+) create mode 100644 doc/man/cdecl99.1 create mode 100644 doc/man/libcdecl.3 diff --git a/Makefile.am b/Makefile.am index ad56e4a..d05b6a5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,8 @@ CLEANFILES = src/typenames.h src/validtypes.h EXTRA_DIST = m4/gnulib-cache.m4 src/types.lst src/typenames.sed \ src/validtypes.sed src/parse.stamp src/scan.stamp +dist_man_MANS = doc/man/cdecl99.1 doc/man/libcdecl.3 + include_HEADERS = src/cdecl.h noinst_HEADERS = src/typemap.h src/output.h src/scan.h src/parse.h diff --git a/doc/man/cdecl99.1 b/doc/man/cdecl99.1 new file mode 100644 index 0000000..e5f1560 --- /dev/null +++ b/doc/man/cdecl99.1 @@ -0,0 +1,171 @@ +.Dd July 18, 2011 +.Os cdecl99 +.Dt CDECL99 \&1 "Cdecl99 User's Manual" +.Sh NAME +.Nm cdecl99 +.Nd Make sense of C declaratiosns +.Sh SYNOPSIS +.Nm +.Op Fl q +.Op Fl b Ns | Ns Fl i +.Op Fl f file Ns | Ns Fl e Ar command Op Fl e Ar command ... +.Sh DESCRIPTION +.Nm +is the command-line interface to libcdecl, enabling you to make heads and tails +of complicated C declarations. It supports parsing almost any syntactically +valid C99 declaration, producing output similar to that of +.Xr cdecl 1 . +Unlike +.Xr cdecl 1 , +.Nm +fully supports all relevant C99 keywords, has no undue restrictions on +identifiers, groks features such as complex types, variadic functions and named +parameters, and can also understand plain type names. On the other hand, +.Nm +does not support any older versions of C, nor does it support C++ other than +the common subset of those other languages and C99. +.Nm +is also much stricter than +.Xr cdecl 1 , +and will reject many invalid declarations that +.Xr cdecl 1 +would accept. +.Sh OPTIONS +.Bl -tag -width indent +.It Fl q , -quiet +Suppress the welcome message when starting +.Nm . +.It Fl b , -batch +Run in batch (non-interactive) mode. Execute the commands provided on standard +input as usual, but do not print any prompts. Exit with status 0 if and only +if all commands complete successfully. + +This option implies +.Fl -quiet . +.It Fl i , -interactive +Run in interactive mode. This is the default. +.It Fl e , -execute Ar command +Execute +.Ar command +as if it were entered at the prompt, then exit. This option can be specified +multiple times; all commands are run in the same order as specified on the +command line. + +This option implies +.Fl -batch . +.It Fl f , -file Ar file +Read commands from +.Ar file +instead of standard input. If both +.Fl -execute +and +.Fl -file +are specified, any +.Fl -file +option is ignored. + +This option implies +.Fl -batch . +.It Fl V , -version +Print a version message and exit. +.It Fl H , -help +Print a help message and exit. +.El +.Sh COMMANDS +All interactive +.Nm +commands consist of a single word followed by one or more spaces, followed by +the argument. Whitespace preceding the command name is ignored. +.Bl -tag -width indent +.It explain Ar declaration +Translates a given C declaration or type name into something resembling +English. +.It simplify Ar declaration +Simplifies a given C decalaration or type name by eliminating redundant +components. +.It declare Ar identifier No as Ar english-decl +Translates an English declaration into C code. +.It type Ar english-decl +Translates an English type name into C code. +.It help +Displays an overview of all available commands. +.It quit +Exits the program. +.El +.Sh ENGLISH DECLARATIONS +.Nm +uses a language similar to English to explain or construct C declarations. The +format is based on the one used in +.Xr cdecl 1 , +and is described by the following context-free grammar. This grammar is for +illustrative purposes only: it is ambiguous and doesn't capture all the nuances +of the C language. In this grammar, +.Fa underlined words +are nonterminals, \[*e] represents the empty string, and both +.Li | +and successive \[->] under the same nonterminal indicate alternation. All +other symbols are terminals. The nonterminals +.Fa identifier , type-specifier , type-qualifier , storage-class-specifier +and +.Fa function-specifier +are defined as in C. +.Bl -column -offset indent ".Fa english-decl" "" +.It Fa english Ta \[->] Ta Li declare Fa identifier Li as Fa english-decl +.It Ta \[->] Ta Li type Fa english-decl +.It Fa english-decl Ta \[->] Ta Fa sf-specs declarator +.It Fa declarator Ta \[->] Ta Fa qualifiers Li pointer to Fa declarator +.It Ta \[->] Ta Li array Fa size Li of Fa declarator +.It Ta \[->] Ta Li function Fa parameters Li returning Fa declarator +.It Ta \[->] Ta Fa tq-specs +.It Fa qualifiers Ta \[->] Ta Fa type-qualifier qualifiers | No \[*e] +.It Fa tq-specs Ta \[->] Ta Fa type-qualifier tq-specs +.It Ta \[->] Ta Fa type-specifier tq-specs +.It Ta \[->] Ta \[*e] +.It Fa sf-specs Ta \[->] Ta Fa storage-class-specifier sf-specs +.It Ta \[->] Ta Fa function-specifier sf-specs +.It Ta \[->] Ta \[*e] +.It Fa size Ta \[->] Ta Fa integer | Fa identifier | Li * | No \[*e] +.It Fa parameters Ta \[->] Ta Po Fa param-list Pc +.It Ta \[->] Ta Po Fa param-list Li , ... Pc +.It Ta \[->] Ta \[*e] +.It Fa param-list Ta \[->] Ta Fa parameter | Fa parameter Li , Fa param-list +.It Fa parameter Ta \[->] Ta Fa identifier Li as Fa english-decl +.It Ta \[->] Ta Fa english-decl +.El +.Sh RESOLVING AMBIGUITIES +The C context-free grammar has many ambiguities regarding declarations. +Ordinarily, these ambiguities are resolved by the context in which the +declaration appears, such as which typedef names are currently in scope. + +For example, the meaning of the declaration +.Ic int f(int (foo)) +depends on whether or not a typedef named +.Fa foo +is in scope. If such a typedef is in scope, this declares +.Fa f +as a function that takes (after adjustment) a pointer to a function that takes +a +.Fa foo +and returns an int, returning an int. If there is no such typedef, then this +declares +.Fa f +as a function that takes an int and returns an int. + +Since +.Nm +isn't a C compiler, on several occasions it has to arbitrarily pick one of two +possibilities. The rule that is generally applied is that +.Nm +will choose the alternative with the simplest explanation. Thus, f is +interpreted as a function which takes an int and returns an int. +.Sh AUTHORS +Nick Bowler +.Sh COPYRIGHT +Copyright \(co 2011 Nick Bowler + +Permission is granted to copy, distribute and/or modify this manual under the +terms of the Do What The Fuck You Want To Public License, version 2. +.Sh SEE ALSO +.Xr libcdecl 3 , +.Xr cdecl 1 , +.Xr c++decl 1 diff --git a/doc/man/libcdecl.3 b/doc/man/libcdecl.3 new file mode 100644 index 0000000..44cf25e --- /dev/null +++ b/doc/man/libcdecl.3 @@ -0,0 +1,288 @@ +.Dd July 18, 2011 +.Os cdecl99 +.Dt LIBCDECL \&3 "Cdecl99 Developer's Manual" +.Sh NAME +.Nm libcdecl +.Nd C library for making sense of C declarations +.Sh SYNOPSIS +.Fd #include + +.Fd struct cdecl *cdecl_parse_decl(const char *declstr); +.Fd struct cdecl *cdecl_parse_english(const char *english); +.Fd void cdecl_free(struct cdecl *decl); + +.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 int cdecl_spec_kind(struct cdecl_declspec *spec); +.Sh DESCRIPTION +.Nm +provides support for parsing C declarations and translating them to something +resembling English and vice-versa. This manual describes the programmers' +interface only; for details such as what C language features are supported or +the syntax of English declarations, please see the +.Xr cdecl99 1 +manual page. + +.Nm +is intended to be portable to any system with a working C implementation that +at least makes an effort to support C99. The library maintains no global state +and thus all functions should be safe for use in a multi-threaded environment. +.Sh ABSTRACT SYNTAX TREE +The functions in +.Nm +generally operate on an abstract syntax tree representing a C declaration. +A string is parsed into an AST which can be subsequently rendered into another +format. Since some information about the original string is discarded when +generating the AST, parsing a declaration and then rendering to the same format +is not the identity function. The AST is represented by the following +structure: +.Bd -literal -offset indent +struct cdecl { + struct cdecl *next; + struct cdecl_declspec *specifiers; + struct cdecl_declarator *declarators; +}; +.Ed + +At the top level, every declaration consists of one or more declaration +specifiers followed by one or more full declarators; hence, the +.Fa specifiers +and +.Fa declarators +members are always non-null. A declaration with more than one declarator is +represented by using the +.Fa next +member to form a singly-linked list of ASTs, one element for each declarator. +In the case of the toplevel declaration, the declaration specifiers will be +identical for all elements of the list. But when the same kind of list is used +to represent function parameters, the specifiers may be different for each +element. + +There are four kinds of declaration specifiers: storage-class, function and +type specifiers, as well as type qualifiers. All are represented by the +structure: +.Bd -literal -offset indent +struct cdecl_declspec { + struct cdecl_declspec *next; + unsigned type; + char *ident; +}; +.Ed + +When multiple declaration specifiers are present, they are represented as +a singly-linked list, one element for each specifier. Specifiers can appear +in any order. The function + +.Fd int cdecl_spec_kind(struct cdecl_declspec *spec); + +can be used to determine what kind of specifier +.Fa spec +is. The result is one of the following values: +.Bl -column ".Dv CDECL_SPEC_TYPE" +.It Em Kind Ta Em Description +.It Dv CDECL_SPEC_TYPE Ta Type specifier. +.It Dv CDECL_SPEC_STOR Ta Storage-class specifier. +.It Dv CDECL_SPEC_QUAL Ta Type qualifier. +.It Dv CDECL_SPEC_FUNC Ta Function specifier. +.El + +The following table describes all the possible types of declaration specifiers. +.Bl -column ".Dv CDECL_TYPE_IMAGINARY" +.It Em Em Type Ta Em Description +.It Dv CDECL_TYPE_VOID Ta Fa void No type specifier. +.It Dv CDECL_TYPE_CHAR Ta Fa char No type specifier. +.It Dv CDECL_TYPE_SHORT Ta Fa short No type specifier. +.It Dv CDECL_TYPE_INT Ta Fa int No type specifier. +.It Dv CDECL_TYPE_LONG Ta Fa long No type specifier. +.It Dv CDECL_TYPE_FLOAT Ta Fa float No type specifier. +.It Dv CDECL_TYPE_DOUBLE Ta Fa double No type specifier. +.It Dv CDECL_TYPE_SIGNED Ta Fa signed No type specifier. +.It Dv CDECL_TYPE_UNSIGNED Ta Fa unsigned No type specifier. +.It Dv CDECL_TYPE_BOOL Ta Fa _Bool No type specifier. +.It Dv CDECL_TYPE_COMPLEX Ta Fa _Comples No type specifier. +.It Dv CDECL_TYPE_IMAGINARY Ta Fa _Imaginary No type specifier. +.It Dv CDECL_TYPE_STRUCT Ta Fa struct No type specifier. The +.Fa ident +member points to a C string containing the struct tag. +.It Dv CDECL_TYPE_UNION Ta Fa union No type specifier. The +.Fa ident +member points to a C string containing the union tag. +.It Dv CDECL_TYPE_ENUM Ta Fa enum No type specifier. The +.Fa ident +member points to a C string containing the enum tag. +.It Dv CDECL_TYPE_IDENT Ta Typedef name type specifier. The +.Fa ident +member points to a C string containing the identifier. +.It Dv CDECL_STOR_TYPEDEF Ta Fa typedef No storage-class specifier. +.It Dv CDECL_STOR_EXTERN Ta Fa extern No storage-class specifier. +.It Dv CDECL_STOR_STATIC Ta Fa static No storage-class specifier. +.It Dv CDECL_STOR_AUTO Ta Fa auto No storage-class specifier. +.It Dv CDECL_STOR_REGISTER Ta Fa register No storage-class specifier. +.It Dv CDECL_QUAL_RESTRICT Ta Fa restrict No type qualifier. +.It Dv CDECL_QUAL_VOLATILE Ta Fa volatile No type qualifier. +.It Dv CDECL_QUAL_CONST Ta Fa const No type qualifier. +.It Dv CDECL_FUNC_INLINE Ta Fa inline No function specifier. +.El + +Declarators are represented by the structure: +.Bd -literal -offset indent +struct cdecl_declarator { + struct cdecl_declarator *child; + unsigned type; + union { + char *ident; + struct cdecl_pointer pointer; + struct cdecl_array array; + struct cdecl_function function; + } u; +}; +.Ed + +There are five types of declarators, distinguished by the +.Fa type +struct member. The union +.u +contains a member for each declarator type (except null) containing additional +information. The possible values are described by the following table. The +description of the child member is a lie. +.Bl -column ".Dv CDECL_DECL_FUNCTION" ".Em Union Member" +.It Em Declarator Type Ta Em Union Member Ta Em Description +.It Dv CDECL_DECL_NULL Ta (none) Ta Declares nothing. This +declarator has no +.Fa child . +.It Dv CDECL_DECL_IDENT Ta Fa ident Ta Declares an identifier. This +declarator has no +.Fa child . +.It Dv CDECL_DECL_POINTER Ta Fa pointer Ta Declares a pointer. The +.Fa child +member is interpreted as "pointer to child". +.It Dv CDECL_DECL_ARRAY Ta Fa array Ta Declares an array. The +.Fa child +member is interpreted as "array of child". +.It Dv CDECL_DECL_FUNCTION Ta Fa function Ta Declares a function. The +.Fa child +member is interpreted as "function returning child". +.El +.Ss Terminal Declarators +Null and identifier declarators have no children and are thus leaf nodes. A +null declarator indicates an abstract declarator; that is, one which does not +declare any identifier. Such declarators appear in type names and possibly +function parameters. An identifier declarator has the obvious meaning; the +.Fa ident +union member points to the C string containing the identifier. +.Ss Pointer Declarators +.Bd -literal -offset indent +struct cdecl_pointer { + struct cdecl_declspec *qualifiers; +}; +.Ed + +If the +.Fa qualifiers +member is non-null, then it points to the first element of a singly-linked list +of type qualifiers. +.Ss Array Declarators +.Bd -literal -offset indent +struct cdecl_array { + char *vla; + uintmax_t length; +}; +.Ed + +If the +.Fa vla +member is non-null, then this declarator is a variable-length array declarator. +The +.Fa vla +member points to an identifier if it is known, else it points to the empty +string. +Otherwise, if +.Fa length +is positive, then this is an array declarator with the specified length. +Otherwise, this is an incomplete array declarator. +.Ss Function Declarators +.Bd -literal -offset indent +struct cdecl_function { + struct cdecl *parameters; + _Bool variadic; +}; +.Ed + +If +.Fa parameters +is null, then this is a non-prototype function declarator. Otherwise, +.Fa parameters +points to the first element of a singly-linked list of declarations +representing the function parameters. Note that, unlike toplevel declarations, +each function parameter has exactly one full declarator (abstract or +otherwise). If +.Fa variadic +is true, then the function is variadic. +.Sh PARSING DECLARATIONS +To parse a declaration, the function + +.Fd struct cdecl *cdecl_parse_decl(const char *declstr); + +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. + +Similarly, English declarations can be parsed by using the function + +.Fd struct cdecl *cdecl_parse_english(const char *english); + +When the AST is no longer needed, it must be freed by passing it to the +function + +.Fd void cdecl_free(struct cdecl *decl); +.Sh RENDERING DECLARATIONS +On the other hand, the abstract syntax tree can be rendered to a string for +output. One can use the function + +.Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl); + +to format the AST pointed to by +.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. + +In a manner similar to that of +.Xr snprintf 3 , +at most +.Fa n +bytes, including the '\\0' terminator, are written to +.Fa buf . +If +.Fa n +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 +.Fa buf +if +.Fa n +were long enough, not including the '\\0' terminator. Thus, the entire string +was written if a value less than +.Fa n +is returned. + +Similarly, the function + +.Fd size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl); + +will render the AST pointed to by +.Fa decl +into C code. +.Sh AUTHORS +Nick Bowler +.Sh COPYRIGHT +Copyright \(co 2011 Nick Bowler + +Permission is granted to copy, distribute and/or modify this manual under the +terms of the Do What The Fuck You Want To Public License, version 2. +.Sh SEE ALSO +.Xr cdecl99 1 -- 2.43.2