".Va" means "variable name", which is more appropriate than "function
argument" for variables. Nevertheless, they're probably typeset the
same way, anyway.
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
\[*e] represents the empty string, and both
.Li |
and successive \[->] under the same nonterminal indicate alternation. All
other symbols are terminals. The 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
+.Va identifier , type-specifier , type-qualifier , storage-class-specifier
-.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
+.Bl -column -offset indent ".Va english-decl" ""
+.It Va english Ta \[->] Ta Li declare Va identifier Li as Va english-decl
+.It Ta \[->] Ta Li type Va english-decl
+.It Va english-decl Ta \[->] Ta Va sf-specs declarator
+.It Va declarator Ta \[->] Ta Va qualifiers Li pointer to Va declarator
+.It Ta \[->] Ta Li array Va size Li of Va declarator
+.It Ta \[->] Ta Li function Va parameters Li returning Va declarator
+.It Ta \[->] Ta Va tq-specs
+.It Va qualifiers Ta \[->] Ta Va type-qualifier qualifiers | No \[*e]
+.It Va tq-specs Ta \[->] Ta Va type-qualifier tq-specs
+.It Ta \[->] Ta Va type-specifier tq-specs
-.It Fa sf-specs Ta \[->] Ta Fa storage-class-specifier sf-specs
-.It Ta \[->] Ta Fa function-specifier sf-specs
+.It Va sf-specs Ta \[->] Ta Va storage-class-specifier sf-specs
+.It Ta \[->] Ta Va function-specifier sf-specs
-.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 Va size Ta \[->] Ta Va integer | Va identifier | Li * | No \[*e]
+.It Va parameters Ta \[->] Ta Po Va param-list Pc
+.It Ta \[->] Ta Po Va param-list Li , ... Pc
-.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
+.It Va param-list Ta \[->] Ta Va parameter | Va parameter Li , Va param-list
+.It Va parameter Ta \[->] Ta Va identifier Li as Va english-decl
+.It Ta \[->] Ta Va english-decl
.El
.Sh RESOLVING AMBIGUITIES
The C context-free grammar has many ambiguities regarding declarations.
.El
.Sh RESOLVING AMBIGUITIES
The C context-free grammar has many ambiguities regarding declarations.
For example, the meaning of the declaration
.Ic int f(int (foo))
depends on whether or not a typedef named
For example, the meaning of the declaration
.Ic int f(int (foo))
depends on whether or not a typedef named
is in scope. If such a typedef is in scope, this declares
is in scope. If such a typedef is in scope, this declares
as a function that takes (after adjustment) a pointer to a function that takes
a
as a function that takes (after adjustment) a pointer to a function that takes
a
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
as a function that takes an int and returns an int.
Since
as a function that takes an int and returns an int.
Since
At the top level, every declaration consists of one or more declaration
specifiers followed by one or more full declarators; hence, the
At the top level, every declaration consists of one or more declaration
specifiers followed by one or more full declarators; hence, the
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
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
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
.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_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
member points to a C string containing the struct tag.
.It Dv CDECL_TYPE_UNION Ta Fa union No type specifier. The
member points to a C string containing the struct tag.
.It Dv CDECL_TYPE_UNION Ta Fa union No type specifier. The
member points to a C string containing the union tag.
.It Dv CDECL_TYPE_ENUM Ta Fa enum No type specifier. The
member points to a C string containing the union tag.
.It Dv CDECL_TYPE_ENUM Ta Fa enum No type specifier. The
member points to a C string containing the enum tag.
.It Dv CDECL_TYPE_IDENT Ta Typedef name type specifier. The
member points to a C string containing the enum tag.
.It Dv CDECL_TYPE_IDENT Ta Typedef name type specifier. The
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.
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.
.Ed
There are five types of declarators, distinguished by the
.Ed
There are five types of declarators, distinguished by the
struct member. The union
.u
contains a member for each declarator type (except null) containing additional
struct member. The union
.u
contains a member for each declarator type (except null) containing additional
.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
.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
+.Va child .
+.It Dv CDECL_DECL_IDENT Ta Va ident Ta Declares an identifier. This
-.Fa child .
-.It Dv CDECL_DECL_POINTER Ta Fa pointer Ta Declares a pointer. The
-.Fa child
+.Va child .
+.It Dv CDECL_DECL_POINTER Ta Va pointer Ta Declares a pointer. The
+.Va child
member is interpreted as "pointer to child".
member is interpreted as "pointer to child".
-.It Dv CDECL_DECL_ARRAY Ta Fa array Ta Declares an array. The
-.Fa child
+.It Dv CDECL_DECL_ARRAY Ta Va array Ta Declares an array. The
+.Va child
member is interpreted as "array of child".
member is interpreted as "array of child".
-.It Dv CDECL_DECL_FUNCTION Ta Fa function Ta Declares a function. The
-.Fa child
+.It Dv CDECL_DECL_FUNCTION Ta Va function Ta Declares a function. The
+.Va child
member is interpreted as "function returning child".
.El
.Ss Terminal Declarators
member is interpreted as "function returning child".
.El
.Ss Terminal Declarators
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
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
union member points to the C string containing the identifier.
.Ss Pointer Declarators
.Bd -literal -offset indent
union member points to the C string containing the identifier.
.Ss Pointer Declarators
.Bd -literal -offset indent
member is non-null, then it points to the first element of a singly-linked list
of type qualifiers.
.Ss Array Declarators
member is non-null, then it points to the first element of a singly-linked list
of type qualifiers.
.Ss Array Declarators
member is non-null, then this declarator is a variable-length array declarator.
The
member is non-null, then this declarator is a variable-length array declarator.
The
member points to an identifier if it is known, else it points to the empty
string.
Otherwise, if
member points to an identifier if it is known, else it points to the empty
string.
Otherwise, if
is positive, then this is an array declarator with the specified length.
Otherwise, this is an incomplete array declarator.
.Ss Function Declarators
is positive, then this is an array declarator with the specified length.
Otherwise, this is an incomplete array declarator.
.Ss Function Declarators
is null, then this is a non-prototype function declarator. Otherwise,
is null, then this is a non-prototype function declarator. Otherwise,
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
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
is true, then the function is variadic.
.Sh PARSING DECLARATIONS
To parse a declaration, the function
is true, then the function is variadic.
.Sh PARSING DECLARATIONS
To parse a declaration, the function