]> git.draconx.ca Git - cdecl99.git/commitdiff
Minor manual updates.
authorNick Bowler <nbowler@draconx.ca>
Sun, 7 Mar 2021 04:14:37 +0000 (23:14 -0500)
committerNick Bowler <nbowler@draconx.ca>
Sun, 7 Mar 2021 04:14:37 +0000 (23:14 -0500)
Fix some typographic errors and minor wording problems in the manuals.

Additionally, flatten the directory hierarchy so the manuals are just
under "doc".

Makefile.am
doc/cdecl99.1 [moved from doc/man/cdecl99.1 with 78% similarity]
doc/libcdecl.3 [moved from doc/man/libcdecl.3 with 60% similarity]

index 1d40ab3edbbc0bfb845dec63dd6ed4bfba914c9e..44b4601c6c99e648eb46f708a29251495b17a1b3 100644 (file)
@@ -31,7 +31,7 @@ EXTRA_DIST = bootstrap $(DX_BASEDIR)/scripts/fix-gnulib.pl m4/gnulib-cache.m4 \
              src/ordspecs.sed test/typegen.sh src/parse.y src/parse.stamp \
              src/scan.l src/scan.stamp COPYING.WTFPL2 README.md INSTALL
 
-dist_man_MANS = doc/man/cdecl99.1 doc/man/libcdecl.3
+dist_man_MANS = doc/cdecl99.1 doc/libcdecl.3
 
 include_HEADERS = src/cdecl.h
 noinst_HEADERS = conf_pre.h conf_post.h src/scan.h src/parse.h \
similarity index 78%
rename from doc/man/cdecl99.1
rename to doc/cdecl99.1
index eca715f0d4e85b0ce0f35f17af416becee70a183..d458380ed42a91ddf4a1d08e35a9009dff4937ff 100644 (file)
@@ -1,4 +1,4 @@
-.Dd July 18, 2011
+.Dd March 6, 2021
 .Os cdecl99
 .Dt CDECL99 \&1 "Cdecl99 User's Manual"
 .Sh NAME
@@ -8,19 +8,21 @@
 .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 ...
+.Op Fl f Ar 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
+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,
+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.
@@ -36,9 +38,10 @@ would accept.
 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.
+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.
 .Pp
 This option implies
 .Fl -quiet .
@@ -47,9 +50,9 @@ 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.
+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.
 .Pp
 This option implies
 .Fl -batch .
@@ -75,7 +78,8 @@ Print a help message and exit.
 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.
+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
@@ -94,12 +98,13 @@ 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
+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, nonterminals are represented
+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, nonterminals are represented
 .Va [ thusly ] ,
 \[*e] represents the empty string, and both
 .Li |
@@ -142,23 +147,25 @@ For example, the meaning of the declaration
 .Ic int f(int (foo))
 depends on whether or not a typedef named
 .Va foo
-is in scope.  If such a typedef is in scope, this declares
+is in scope.
+If such a typedef is in scope, this declares
 .Va f
 as a function that takes (after adjustment) a pointer to a function that takes
 a
 .Va foo
-and returns an int, returning an int.  If there is no such typedef, then this
-declares
+and returns an int, returning an int.
+If there is no such typedef, then this declares
 .Va f
 as a function that takes an int and returns an int.
 .Pp
 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
+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.
+will choose the alternative with the simplest explanation.
+Thus, f is interpreted as a function which takes an int and returns an int.
 .Sh EXAMPLES
 .Bl -tag -width Output:
 .It Input:
@@ -199,10 +206,12 @@ interpreted as a function which takes an int and returns an int.
 .Sh AUTHORS
 Nick Bowler <nbowler@draconx.ca>
 .Sh COPYRIGHT
-Copyright \(co 2011 Nick Bowler
+Copyright \(co 2011, 2021 Nick Bowler
 .Pp
 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.
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
 .Sh SEE ALSO
 .Xr libcdecl 3 ,
 .Xr cdecl 1 ,
similarity index 60%
rename from doc/man/libcdecl.3
rename to doc/libcdecl.3
index 00280f5aae44d23528f46a6943b990c7f2b32f33..495a353f68b8810ee27b59f6876cc64abc86eb40 100644 (file)
@@ -1,4 +1,4 @@
-.Dd July 18, 2011
+.Dd March 6, 2021
 .Os cdecl99
 .Dt LIBCDECL \&3 "Cdecl99 Developer's Manual"
 .Sh NAME
 .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
+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.
 .Pp
 .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 is thread-safe when
-appropriate facilities exist and are enabled at build time.
+at least makes an effort to support C99.
+The library is thread-safe when appropriate facilities exist and are enabled at
+build time.
 .Sh NAMESPACE
 .Nm
 reserves all identifiers beginning with either
 .Li cdecl_
 or
 .Li CDECL_
-in both the tag and ordinary identifier namespaces.  All external names
-beginning with
+in both the tag and ordinary identifier namespaces.
+All external names beginning with
 .Li cdecl_
 are reserved, and the library headers may define object-like macros beginning
 with
@@ -46,11 +48,11 @@ with
 The
 .Nm
 library headers may use other identifiers where they do not pollute the global
-namespaces, such as struct members or function parameter names.  Such internal
-identifiers shall not contain any upper-case letters.  As these internal
-identifiers can only conflict with object-like macros, this practice is safe as
-long as the convention of defining object-like macros using upper-case letters
-is adhered to.
+namespaces, such as struct members or function parameter names.
+Such internal identifiers shall not contain any upper-case letters.
+As these internal identifiers can only conflict with object-like macros, this
+practice is safe as long as the convention of defining object-like macros using
+upper-case letters is adhered to.
 .Pp
 External names beginning with
 .Li cdecl
@@ -61,10 +63,11 @@ 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:
+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;
@@ -78,18 +81,18 @@ specifiers followed by one or more full declarators; hence, the
 .Va specifiers
 and
 .Va declarators
-members are always non-null.  A declaration with more than one declarator is
-represented by using the
+members are always non-null.
+A declaration with more than one declarator is represented by using the
 .Va 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.
+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.
 .Pp
 There are four kinds of declaration specifiers: storage-class, function and
-type specifiers, as well as type qualifiers.  All are represented by the
-structure:
+type specifiers, as well as type qualifiers.
+All are represented by the structure:
 .Bd -literal -offset indent
 struct cdecl_declspec {
        struct cdecl_declspec *next;
@@ -99,8 +102,9 @@ struct cdecl_declspec {
 .Ed
 .Pp
 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
+a singly-linked list, one element for each specifier.
+Specifiers can appear in any order.
+The function
 .Pp
 .Fd int cdecl_spec_kind(struct cdecl_declspec *spec);
 .Pp
@@ -109,48 +113,52 @@ can be used to determine what kind of specifier
 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.
+.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
 .Pp
-The following table describes all the possible types of declaration specifiers.
+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
+.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
 .Va ident
 member points to a C string containing the struct tag.
-.It Dv CDECL_TYPE_UNION     Ta Fa union      No type specifier.  The
+.It Dv CDECL_TYPE_UNION     Ta Fa union      No type specifier .
+The
 .Va ident
 member points to a C string containing the union tag.
-.It Dv CDECL_TYPE_ENUM      Ta Fa enum       No type specifier.  The
+.It Dv CDECL_TYPE_ENUM      Ta Fa enum       No type specifier .
+The
 .Va ident
 member points to a C string containing the enum tag.
-.It Dv CDECL_TYPE_IDENT     Ta Typedef name type specifier.  The
+.It Dv CDECL_TYPE_IDENT     Ta Typedef name type specifier .
+The
 .Va 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.
+.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
 .Pp
 Declarators are represented by the structure:
@@ -170,13 +178,14 @@ struct cdecl_declarator {
 With the exception of function parameters (which are handled separately),
 declarators form a chain from
 .Do outermost Dc to Do innermost Dc
-declarator.  This relationship is expressed by the
+declarator.
+This relationship is expressed by the
 .Va child
 struct member, which points to the next innermost declarator in the chain.
-Unfortunately, C's declaration syntax is, in a sense, inside-out.  Thus, one
-needs to follow the chain backwards (from innermost to outermost) to understand
-the semantic relationship between declarators in the chain.  In the next
-section, we will use the word
+Unfortunately, C's declaration syntax is, in a sense, inside-out.
+Thus, one needs to follow the chain backwards (from innermost to outermost) to
+understand the semantic relationship between declarators in the chain.
+In the next section, we will use the word
 .Va parent
 to describe this inverted child relationship: we consider the outermost
 declarator's
@@ -184,15 +193,14 @@ declarator's
 as the declaration's base type (found amongst the declaration specifiers, e.g.
 .Li int , const unsigned long ,
 etc.)
-
+.Pp
 The five types of declarators, described below, are distinguished by the
 .Va type
-struct member.  Each declarator (except null declarators) carries additional
-information specific to its type, which corresponds to the members of the union
+struct member.
+Each declarator (except null declarators) carries additional information
+specific to its type, which corresponds to the members of the union
 .Va u .
-
-contains a member for each declarator type (except null) containing additional
-information.  The possible values are described by the following table.
+The possible values are described by the following table:
 .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
@@ -209,12 +217,13 @@ declarator has a NULL
 .Do function returning Va parent Dc
 .El
 .Ss Terminal Declarators
-Null and identifier declarators have no children and are thus leaf nodes.  A
-null declarator is not strictly a C language construct, but is used by
+Null and identifier declarators have no children and are thus leaf nodes.
+null declarator is not strictly a C language construct, but is used by
 .Nm
 to indicate 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
+identifier.
+Such declarators appear in type names and possibly function parameters.
+An identifier declarator has the obvious meaning; the
 .Va ident
 union member points to the C string containing the identifier.
 .Pp
@@ -224,7 +233,8 @@ function
 .Fd bool cdecl_is_abstract(struct cdecl_declarator *declarator);
 .Pp
 can be used to determine whether or not a given declarator declares an
-identifier.  The result is true if and only if the declarator is abstract.
+identifier.
+The result is true if and only if the declarator is abstract.
 .Ss Pointer Declarators
 .Bd -literal -offset indent
 struct cdecl_pointer {
@@ -265,28 +275,33 @@ struct cdecl_function {
 .Pp
 If
 .Va parameters
-is null, then this is a non-prototype function declarator.  Otherwise,
+is null, then this is a non-prototype function declarator.
+Otherwise,
 .Va 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
+representing the function parameters.
+Note that, unlike toplevel declarations, each function parameter has exactly
+one full declarator (abstract or otherwise).
+If
 .Va variadic
 is true, then the function is variadic.
 .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
+to a prototype where every parameter is a typedef name.
+Since
 .Nm
-isn't a C compiler, there is no way for the parser to tell these two kinds of
+isn't a C compiler, there is no way for its parser to tell these two kinds of
 declarations apart.
 .Sh ERROR HANDLING
 Some functions in
 .Nm
-can fail.  Such functions will be documented as indicating an error condition
-in a particular way.  It is sometimes necessary to know more about a particular
-error in order to print an informative error message or perform some other
-action.  To facilitate this,
+can fail.
+Such functions will be documented as indicating an error condition in a
+particular way.
+It is sometimes necessary to know more about a particular error in order to
+print an informative error message or perform some other action.
+To facilitate this,
 .Nm
 provides a structure which describes a particular error.
 .Bd -literal -offset indent
@@ -306,13 +321,16 @@ This error information can be retrieved by calling the function
 .Fd const struct cdecl_error *cdecl_get_error(void);
 .Pp
 which returns a pointer to the error structure most recently generated in the
-current thread.  It is therefore thread-safe in that errors occurring in
-another thread will not interfere with the current one.  The returned pointer
-shall remain valid until the next call to any function from
+current thread.
+It is therefore thread-safe in that errors occurring in another thread will not
+interfere with the current one.
+The returned pointer shall remain valid until the next call to any function
+from
 .Nm
 by the same thread, except that multiple consecutive calls to
 .Va cdecl_get_error
-shall all return the same value.  The same applies to the
+shall all return the same value.
+The same applies to the
 .Va str
 pointer inside the error structure itself.
 .Pp
@@ -323,9 +341,11 @@ To parse a declaration, the function
 .Pp
 .Fd struct cdecl *cdecl_parse_decl(const char *declstr);
 .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.
+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.
 .Pp
 Similarly, English declarations can be parsed by using the function
 .Pp
@@ -336,16 +356,16 @@ function
 .Pp
 .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
+After parsing, the abstract syntax tree can be rendered to a string for output.
+Use the function
 .Pp
 .Fd size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl);
 .Pp
 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
+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
@@ -359,13 +379,14 @@ 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
+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
+were long enough, not including the '\\0' terminator.
+Thus, the entire string was written if a value less than
 .Fa n
 is returned.
 .Pp
@@ -379,9 +400,11 @@ into C code.
 .Sh AUTHORS
 Nick Bowler <nbowler@draconx.ca>
 .Sh COPYRIGHT
-Copyright \(co 2011 Nick Bowler
+Copyright \(co 2011\(en2012, 2021 Nick Bowler
 .Pp
 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.
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
 .Sh SEE ALSO
 .Xr cdecl99 1