codegen: Expose variant comments.

This commit is contained in:
Emilio Cobos Álvarez 2018-02-12 19:29:07 +01:00
parent 079d8383cc
commit 5d04c36441
No known key found for this signature in database
GPG Key ID: 056B727BB9C1027C
17 changed files with 282 additions and 15 deletions

View File

@ -2129,36 +2129,54 @@ impl EnumVariation {
/// A helper type to construct different enum variations.
enum EnumBuilder<'a> {
Rust {
codegen_depth: usize,
attrs: Vec<quote::Tokens>,
ident: proc_macro2::Term,
tokens: quote::Tokens,
emitted_any_variants: bool,
},
Bitfield {
codegen_depth: usize,
canonical_name: &'a str,
tokens: quote::Tokens,
},
Consts(Vec<quote::Tokens>),
Consts {
variants: Vec<quote::Tokens>,
codegen_depth: usize,
},
ModuleConsts {
codegen_depth: usize,
module_name: &'a str,
module_items: Vec<quote::Tokens>,
},
}
impl<'a> EnumBuilder<'a> {
/// Returns the depth of the code generation for a variant of this enum.
fn codegen_depth(&self) -> usize {
match *self {
EnumBuilder::Rust { codegen_depth, .. } |
EnumBuilder::Bitfield { codegen_depth, .. } |
EnumBuilder::ModuleConsts { codegen_depth, .. } |
EnumBuilder::Consts { codegen_depth, .. } => codegen_depth,
}
}
/// Create a new enum given an item builder, a canonical name, a name for
/// the representation, and which variation it should be generated as.
fn new(
name: &'a str,
attrs: Vec<quote::Tokens>,
repr: quote::Tokens,
enum_variation: EnumVariation
enum_variation: EnumVariation,
enum_codegen_depth: usize,
) -> Self {
let ident = proc_macro2::Term::intern(name);
match enum_variation {
EnumVariation::Bitfield => {
EnumBuilder::Bitfield {
codegen_depth: enum_codegen_depth,
canonical_name: name,
tokens: quote! {
#( #attrs )*
@ -2170,6 +2188,7 @@ impl<'a> EnumBuilder<'a> {
EnumVariation::Rust => {
let tokens = quote!();
EnumBuilder::Rust {
codegen_depth: enum_codegen_depth + 1,
attrs,
ident,
tokens,
@ -2178,20 +2197,26 @@ impl<'a> EnumBuilder<'a> {
}
EnumVariation::Consts => {
EnumBuilder::Consts(vec![
quote! {
pub type #ident = #repr;
}
])
EnumBuilder::Consts {
variants: vec![
quote! {
#( #attrs )*
pub type #ident = #repr;
}
],
codegen_depth: enum_codegen_depth,
}
}
EnumVariation::ModuleConsts => {
let ident = proc_macro2::Term::intern(CONSTIFIED_ENUM_MODULE_REPR_NAME);
let type_definition = quote! {
#( #attrs )*
pub type #ident = #repr;
};
EnumBuilder::ModuleConsts {
codegen_depth: enum_codegen_depth + 1,
module_name: name,
module_items: vec![type_definition],
}
@ -2214,14 +2239,24 @@ impl<'a> EnumBuilder<'a> {
EnumVariantValue::Unsigned(v) => helpers::ast_ty::uint_expr(v),
};
let mut doc = quote! {};
if ctx.options().generate_comments {
if let Some(raw_comment) = variant.comment() {
let comment = comment::preprocess(raw_comment, self.codegen_depth());
doc = attributes::doc(comment);
}
}
match self {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants: _ } => {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants: _, codegen_depth } => {
let name = ctx.rust_ident(variant_name);
EnumBuilder::Rust {
attrs,
ident,
codegen_depth,
tokens: quote! {
#tokens
#doc
#name = #expr,
},
emitted_any_variants: true,
@ -2238,6 +2273,7 @@ impl<'a> EnumBuilder<'a> {
let ident = ctx.rust_ident(constant_name);
result.push(quote! {
#doc
pub const #ident : #rust_ty = #rust_ty ( #expr );
});
@ -2256,24 +2292,28 @@ impl<'a> EnumBuilder<'a> {
let ident = ctx.rust_ident(constant_name);
result.push(quote! {
#doc
pub const #ident : #rust_ty = #expr ;
});
self
}
EnumBuilder::ModuleConsts {
codegen_depth,
module_name,
mut module_items,
} => {
let name = ctx.rust_ident(variant_name);
let ty = ctx.rust_ident(CONSTIFIED_ENUM_MODULE_REPR_NAME);
module_items.push(quote! {
#doc
pub const #name : #ty = #expr ;
});
EnumBuilder::ModuleConsts {
module_name,
module_items,
codegen_depth,
}
}
}
@ -2286,23 +2326,24 @@ impl<'a> EnumBuilder<'a> {
result: &mut CodegenResult<'b>,
) -> quote::Tokens {
match self {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants } => {
EnumBuilder::Rust { attrs, ident, tokens, emitted_any_variants, .. } => {
let variants = if !emitted_any_variants {
quote!(__bindgen_cannot_repr_c_on_empty_enum = 0)
} else {
tokens
};
quote! (
quote! {
#( #attrs )*
pub enum #ident {
#variants
}
)
}
}
EnumBuilder::Bitfield {
canonical_name,
tokens,
..
} => {
let rust_ty_name = ctx.rust_ident_raw(canonical_name);
let prefix = ctx.trait_prefix();
@ -2349,10 +2390,11 @@ impl<'a> EnumBuilder<'a> {
tokens
}
EnumBuilder::Consts(tokens) => quote! { #( #tokens )* },
EnumBuilder::Consts { variants, .. } => quote! { #( #variants )* },
EnumBuilder::ModuleConsts {
module_items,
module_name,
..
} => {
let ident = ctx.rust_ident(module_name);
quote! {
@ -2489,7 +2531,8 @@ impl CodeGenerator for Enum {
&name,
attrs,
repr,
variation
variation,
item.codegen_depth(ctx),
);
// A map where we keep a value -> variant relation.
@ -2522,8 +2565,7 @@ impl CodeGenerator for Enum {
let mut iter = self.variants().iter().peekable();
while let Some(variant) = iter.next().or_else(|| {
constified_variants.pop_front()
})
{
}) {
if variant.hidden() {
continue;
}

View File

@ -221,6 +221,11 @@ impl EnumVariant {
self.val
}
/// Get this variant's documentation.
pub fn comment(&self) -> Option<&str> {
self.comment.as_ref().map(|s| &**s)
}
/// Returns whether this variant should be enforced to be a constant by code
/// generation.
pub fn force_constification(&self) -> bool {

View File

@ -13,5 +13,6 @@ pub enum nsCSSPropertyID {
eCSSProperty_b = 1,
eCSSPropertyAlias_aa = 2,
eCSSPropertyAlias_bb = 3,
/// < <div rustbindgen constant></div>
eCSSProperty_COUNT_unexistingVariantValue = 4,
}

View File

@ -0,0 +1,44 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
/// Document field with three slashes
pub const B_VAR_A: B = B(0);
/// Document field with preceeding star
pub const B_VAR_B: B = B(1);
/// Document field with preceeding exclamation
pub const B_VAR_C: B = B(2);
/// < Document field with following star
pub const B_VAR_D: B = B(3);
/// < Document field with following exclamation
pub const B_VAR_E: B = B(4);
impl ::std::ops::BitOr<B> for B {
type Output = Self;
#[inline]
fn bitor(self, other: Self) -> Self {
B(self.0 | other.0)
}
}
impl ::std::ops::BitOrAssign for B {
#[inline]
fn bitor_assign(&mut self, rhs: B) {
self.0 |= rhs.0;
}
}
impl ::std::ops::BitAnd<B> for B {
type Output = Self;
#[inline]
fn bitand(self, other: Self) -> Self {
B(self.0 & other.0)
}
}
impl ::std::ops::BitAndAssign for B {
#[inline]
fn bitand_assign(&mut self, rhs: B) {
self.0 &= rhs.0;
}
}
#[repr(C)]
/// Document enum
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct B(pub u32);

View File

@ -0,0 +1,18 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod B {
/// Document enum
pub type Type = u32;
/// Document field with three slashes
pub const VAR_A: Type = 0;
/// Document field with preceeding star
pub const VAR_B: Type = 1;
/// Document field with preceeding exclamation
pub const VAR_C: Type = 2;
/// < Document field with following star
pub const VAR_D: Type = 3;
/// < Document field with following exclamation
pub const VAR_E: Type = 4;
}

View File

@ -0,0 +1,19 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
#[repr(u32)]
/// Document enum
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum B {
/// Document field with three slashes
VAR_A = 0,
/// Document field with preceeding star
VAR_B = 1,
/// Document field with preceeding exclamation
VAR_C = 2,
/// < Document field with following star
VAR_D = 3,
/// < Document field with following exclamation
VAR_E = 4,
}

View File

@ -0,0 +1,16 @@
/* automatically generated by rust-bindgen */
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
/// Document field with three slashes
pub const B_VAR_A: B = 0;
/// Document field with preceeding star
pub const B_VAR_B: B = 1;
/// Document field with preceeding exclamation
pub const B_VAR_C: B = 2;
/// < Document field with following star
pub const B_VAR_D: B = 3;
/// < Document field with following exclamation
pub const B_VAR_E: B = 4;
/// Document enum
pub type B = u32;

View File

@ -128,24 +128,43 @@ pub enum JSValueShiftedTag {
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSWhyMagic {
/// a hole in a native object's elements
JS_ELEMENTS_HOLE = 0,
/// there is not a pending iterator value
JS_NO_ITER_VALUE = 1,
/// exception value thrown when closing a generator
JS_GENERATOR_CLOSING = 2,
/// compiler sentinel value
JS_NO_CONSTANT = 3,
/// used in debug builds to catch tracing errors
JS_THIS_POISON = 4,
/// used in debug builds to catch tracing errors
JS_ARG_POISON = 5,
/// an empty subnode in the AST serializer
JS_SERIALIZE_NO_NODE = 6,
/// lazy arguments value on the stack
JS_LAZY_ARGUMENTS = 7,
/// optimized-away 'arguments' value
JS_OPTIMIZED_ARGUMENTS = 8,
/// magic value passed to natives to indicate construction
JS_IS_CONSTRUCTING = 9,
/// arguments.callee has been overwritten
JS_OVERWRITTEN_CALLEE = 10,
/// value of static block object slot
JS_BLOCK_NEEDS_CLONE = 11,
/// see class js::HashableValue
JS_HASH_KEY_EMPTY = 12,
/// error while running Ion code
JS_ION_ERROR = 13,
/// missing recover instruction result
JS_ION_BAILOUT = 14,
/// optimized out slot
JS_OPTIMIZED_OUT = 15,
/// uninitialized lexical bindings that produce ReferenceError on touch.
JS_UNINITIALIZED_LEXICAL = 16,
/// for local use
JS_GENERIC_MAGIC = 17,
/// for local use
JS_WHY_MAGIC_COUNT = 18,
}
#[repr(C)]

View File

@ -171,24 +171,43 @@ pub enum JSValueShiftedTag {
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSWhyMagic {
/// a hole in a native object's elements
JS_ELEMENTS_HOLE = 0,
/// there is not a pending iterator value
JS_NO_ITER_VALUE = 1,
/// exception value thrown when closing a generator
JS_GENERATOR_CLOSING = 2,
/// compiler sentinel value
JS_NO_CONSTANT = 3,
/// used in debug builds to catch tracing errors
JS_THIS_POISON = 4,
/// used in debug builds to catch tracing errors
JS_ARG_POISON = 5,
/// an empty subnode in the AST serializer
JS_SERIALIZE_NO_NODE = 6,
/// lazy arguments value on the stack
JS_LAZY_ARGUMENTS = 7,
/// optimized-away 'arguments' value
JS_OPTIMIZED_ARGUMENTS = 8,
/// magic value passed to natives to indicate construction
JS_IS_CONSTRUCTING = 9,
/// arguments.callee has been overwritten
JS_OVERWRITTEN_CALLEE = 10,
/// value of static block object slot
JS_BLOCK_NEEDS_CLONE = 11,
/// see class js::HashableValue
JS_HASH_KEY_EMPTY = 12,
/// error while running Ion code
JS_ION_ERROR = 13,
/// missing recover instruction result
JS_ION_BAILOUT = 14,
/// optimized out slot
JS_OPTIMIZED_OUT = 15,
/// uninitialized lexical bindings that produce ReferenceError on touch.
JS_UNINITIALIZED_LEXICAL = 16,
/// for local use
JS_GENERIC_MAGIC = 17,
/// for local use
JS_WHY_MAGIC_COUNT = 18,
}
#[repr(C)]

View File

@ -11,8 +11,11 @@ pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
/// < index of last fragment
IP_LAST_FRAG_IDX = 0,
/// < index of first fragment
IP_FIRST_FRAG_IDX = 1,
/// < minimum number of fragments
IP_MIN_FRAG_NUM = 2,
IP_MAX_FRAG_NUM = 4,
}

View File

@ -118,13 +118,21 @@ pub const RTE_ETH_FLOW_MAX: u32 = 22;
/// packets to multiple queues.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_rx_mq_mode {
/// None of DCB,RSS or VMDQ mode
ETH_MQ_RX_NONE = 0,
/// For RX side, only RSS is on
ETH_MQ_RX_RSS = 1,
/// For RX side,only DCB is on.
ETH_MQ_RX_DCB = 2,
/// Both DCB and RSS enable
ETH_MQ_RX_DCB_RSS = 3,
/// Only VMDQ, no RSS nor DCB
ETH_MQ_RX_VMDQ_ONLY = 4,
/// RSS mode with VMDQ
ETH_MQ_RX_VMDQ_RSS = 5,
/// Use VMDQ+DCB to route traffic to queues
ETH_MQ_RX_VMDQ_DCB = 6,
/// Enable both VMDQ and DCB in VMDq
ETH_MQ_RX_VMDQ_DCB_RSS = 7,
}
/// A structure used to configure the RX features of an Ethernet port.
@ -345,9 +353,13 @@ impl rte_eth_rxmode {
/// packets using multi-TCs.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_tx_mq_mode {
/// < It is in neither DCB nor VT mode.
ETH_MQ_TX_NONE = 0,
/// < For TX side,only DCB is on.
ETH_MQ_TX_DCB = 1,
/// < For TX side,both DCB and VT is on.
ETH_MQ_TX_VMDQ_DCB = 2,
/// < Only VT on, no DCB
ETH_MQ_TX_VMDQ_ONLY = 3,
}
/// A structure used to configure the TX features of an Ethernet port.
@ -534,7 +546,9 @@ impl Default for rte_eth_rss_conf {
/// in DCB configratioins
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_nb_tcs {
/// < 4 TCs with DCB.
ETH_4_TCS = 4,
/// < 8 TCs with DCB.
ETH_8_TCS = 8,
}
#[repr(u32)]
@ -542,9 +556,13 @@ pub enum rte_eth_nb_tcs {
/// in VMDQ configurations.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_nb_pools {
/// < 8 VMDq pools.
ETH_8_POOLS = 8,
/// < 16 VMDq pools.
ETH_16_POOLS = 16,
/// < 32 VMDq pools.
ETH_32_POOLS = 32,
/// < 64 VMDq pools.
ETH_64_POOLS = 64,
}
/// A structure used to configure the VMDQ+DCB feature
@ -1055,10 +1073,15 @@ impl Default for rte_eth_vmdq_rx_conf {
/// Flow Director setting modes: none, signature or perfect.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_mode {
/// < Disable FDIR support.
RTE_FDIR_MODE_NONE = 0,
/// < Enable FDIR signature filter mode.
RTE_FDIR_MODE_SIGNATURE = 1,
/// < Enable FDIR perfect filter mode.
RTE_FDIR_MODE_PERFECT = 2,
/// < Enable FDIR filter mode - MAC VLAN.
RTE_FDIR_MODE_PERFECT_MAC_VLAN = 3,
/// < Enable FDIR filter mode - tunnel.
RTE_FDIR_MODE_PERFECT_TUNNEL = 4,
}
#[repr(u32)]
@ -1066,16 +1089,22 @@ pub enum rte_fdir_mode {
/// in the board memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_pballoc_type {
/// < 64k.
RTE_FDIR_PBALLOC_64K = 0,
/// < 128k.
RTE_FDIR_PBALLOC_128K = 1,
/// < 256k.
RTE_FDIR_PBALLOC_256K = 2,
}
#[repr(u32)]
/// Select report mode of FDIR hash information in RX descriptors.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_status_mode {
/// < Never report FDIR hash.
RTE_FDIR_NO_REPORT_STATUS = 0,
/// < Only report FDIR hash for matching pkts.
RTE_FDIR_REPORT_STATUS = 1,
/// < Always report FDIR hash.
RTE_FDIR_REPORT_STATUS_ALWAYS = 2,
}
/// A structure used to define the input for IPV4 flow

View File

@ -161,13 +161,21 @@ pub const RTE_ETH_FLOW_MAX: u32 = 22;
/// packets to multiple queues.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_rx_mq_mode {
/// None of DCB,RSS or VMDQ mode
ETH_MQ_RX_NONE = 0,
/// For RX side, only RSS is on
ETH_MQ_RX_RSS = 1,
/// For RX side,only DCB is on.
ETH_MQ_RX_DCB = 2,
/// Both DCB and RSS enable
ETH_MQ_RX_DCB_RSS = 3,
/// Only VMDQ, no RSS nor DCB
ETH_MQ_RX_VMDQ_ONLY = 4,
/// RSS mode with VMDQ
ETH_MQ_RX_VMDQ_RSS = 5,
/// Use VMDQ+DCB to route traffic to queues
ETH_MQ_RX_VMDQ_DCB = 6,
/// Enable both VMDQ and DCB in VMDq
ETH_MQ_RX_VMDQ_DCB_RSS = 7,
}
/// A structure used to configure the RX features of an Ethernet port.
@ -393,9 +401,13 @@ impl rte_eth_rxmode {
/// packets using multi-TCs.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_tx_mq_mode {
/// < It is in neither DCB nor VT mode.
ETH_MQ_TX_NONE = 0,
/// < For TX side,only DCB is on.
ETH_MQ_TX_DCB = 1,
/// < For TX side,both DCB and VT is on.
ETH_MQ_TX_VMDQ_DCB = 2,
/// < Only VT on, no DCB
ETH_MQ_TX_VMDQ_ONLY = 3,
}
/// A structure used to configure the TX features of an Ethernet port.
@ -592,7 +604,9 @@ impl Default for rte_eth_rss_conf {
/// in DCB configratioins
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_nb_tcs {
/// < 4 TCs with DCB.
ETH_4_TCS = 4,
/// < 8 TCs with DCB.
ETH_8_TCS = 8,
}
#[repr(u32)]
@ -600,9 +614,13 @@ pub enum rte_eth_nb_tcs {
/// in VMDQ configurations.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_nb_pools {
/// < 8 VMDq pools.
ETH_8_POOLS = 8,
/// < 16 VMDq pools.
ETH_16_POOLS = 16,
/// < 32 VMDq pools.
ETH_32_POOLS = 32,
/// < 64 VMDq pools.
ETH_64_POOLS = 64,
}
/// A structure used to configure the VMDQ+DCB feature
@ -1153,10 +1171,15 @@ impl Default for rte_eth_vmdq_rx_conf {
/// Flow Director setting modes: none, signature or perfect.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_mode {
/// < Disable FDIR support.
RTE_FDIR_MODE_NONE = 0,
/// < Enable FDIR signature filter mode.
RTE_FDIR_MODE_SIGNATURE = 1,
/// < Enable FDIR perfect filter mode.
RTE_FDIR_MODE_PERFECT = 2,
/// < Enable FDIR filter mode - MAC VLAN.
RTE_FDIR_MODE_PERFECT_MAC_VLAN = 3,
/// < Enable FDIR filter mode - tunnel.
RTE_FDIR_MODE_PERFECT_TUNNEL = 4,
}
#[repr(u32)]
@ -1164,16 +1187,22 @@ pub enum rte_fdir_mode {
/// in the board memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_pballoc_type {
/// < 64k.
RTE_FDIR_PBALLOC_64K = 0,
/// < 128k.
RTE_FDIR_PBALLOC_128K = 1,
/// < 256k.
RTE_FDIR_PBALLOC_256K = 2,
}
#[repr(u32)]
/// Select report mode of FDIR hash information in RX descriptors.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_status_mode {
/// < Never report FDIR hash.
RTE_FDIR_NO_REPORT_STATUS = 0,
/// < Only report FDIR hash for matching pkts.
RTE_FDIR_REPORT_STATUS = 1,
/// < Always report FDIR hash.
RTE_FDIR_REPORT_STATUS_ALWAYS = 2,
}
/// A structure used to define the input for IPV4 flow

View File

@ -48,8 +48,11 @@ pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
/// < index of last fragment
IP_LAST_FRAG_IDX = 0,
/// < index of first fragment
IP_FIRST_FRAG_IDX = 1,
/// < minimum number of fragments
IP_MIN_FRAG_NUM = 2,
IP_MAX_FRAG_NUM = 4,
}

View File

@ -0,0 +1,3 @@
// bindgen-flags: --bitfield-enum B
#include "enum-doc.h"

View File

@ -0,0 +1,3 @@
// bindgen-flags: --constified-enum-module B
#include "enum-doc.h"

View File

@ -0,0 +1,3 @@
// bindgen-flags: --rustified-enum B
#include "enum-doc.h"

11
tests/headers/enum-doc.h Normal file
View File

@ -0,0 +1,11 @@
/** Document enum */
enum B {
/// Document field with three slashes
VAR_A = 0,
/** Document field with preceeding star */
VAR_B = 1,
/*! Document field with preceeding exclamation */
VAR_C = 2,
VAR_D = 3, /**< Document field with following star */
VAR_E = 4, /*!< Document field with following exclamation */
};