mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
xdrgen: Implement big-endian enums
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
6e853dcd2d
commit
b376d519bd
|
@ -680,6 +680,27 @@ xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xdr_stream_decode_be32 - Decode a big-endian 32-bit integer
|
||||
* @xdr: pointer to xdr_stream
|
||||
* @ptr: location to store integer
|
||||
*
|
||||
* Return values:
|
||||
* %0 on success
|
||||
* %-EBADMSG on XDR buffer overflow
|
||||
*/
|
||||
static inline ssize_t
|
||||
xdr_stream_decode_be32(struct xdr_stream *xdr, __be32 *ptr)
|
||||
{
|
||||
const size_t count = sizeof(*ptr);
|
||||
__be32 *p = xdr_inline_decode(xdr, count);
|
||||
|
||||
if (unlikely(!p))
|
||||
return -EBADMSG;
|
||||
*ptr = *p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xdr_stream_decode_u64 - Decode a 64-bit integer
|
||||
* @xdr: pointer to xdr_stream
|
||||
|
|
|
@ -150,6 +150,23 @@ Pragma directives specify exceptions to the normal generation of
|
|||
encoding and decoding functions. Currently one directive is
|
||||
implemented: "public".
|
||||
|
||||
Pragma big_endian
|
||||
------ ----------
|
||||
|
||||
pragma big_endian <enum> ;
|
||||
|
||||
For variables that might contain only a small number values, it
|
||||
is more efficient to avoid the byte-swap when encoding or decoding
|
||||
on little-endian machines. Such is often the case with error status
|
||||
codes. For example:
|
||||
|
||||
pragma big_endian nfsstat3;
|
||||
|
||||
In this case, when generating an XDR struct or union containing a
|
||||
field of type "nfsstat3", xdrgen will make the type of that field
|
||||
"__be32" instead of "enum nfsstat3". XDR unions then switch on the
|
||||
non-byte-swapped value of that field.
|
||||
|
||||
Pragma exclude
|
||||
------ -------
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"""Generate code to handle XDR enum types"""
|
||||
|
||||
from generators import SourceGenerator, create_jinja2_environment
|
||||
from xdr_ast import _XdrEnum, public_apis
|
||||
from xdr_ast import _XdrEnum, public_apis, big_endian
|
||||
|
||||
|
||||
class XdrEnumGenerator(SourceGenerator):
|
||||
|
@ -30,15 +30,24 @@ class XdrEnumGenerator(SourceGenerator):
|
|||
for enumerator in node.enumerators:
|
||||
print(template.render(name=enumerator.name, value=enumerator.value))
|
||||
|
||||
template = self.environment.get_template("definition/close.j2")
|
||||
if node.name in big_endian:
|
||||
template = self.environment.get_template("definition/close_be.j2")
|
||||
else:
|
||||
template = self.environment.get_template("definition/close.j2")
|
||||
print(template.render(name=node.name))
|
||||
|
||||
def emit_decoder(self, node: _XdrEnum) -> None:
|
||||
"""Emit one decoder function for an XDR enum type"""
|
||||
template = self.environment.get_template("decoder/enum.j2")
|
||||
if node.name in big_endian:
|
||||
template = self.environment.get_template("decoder/enum_be.j2")
|
||||
else:
|
||||
template = self.environment.get_template("decoder/enum.j2")
|
||||
print(template.render(name=node.name))
|
||||
|
||||
def emit_encoder(self, node: _XdrEnum) -> None:
|
||||
"""Emit one encoder function for an XDR enum type"""
|
||||
template = self.environment.get_template("encoder/enum.j2")
|
||||
if node.name in big_endian:
|
||||
template = self.environment.get_template("encoder/enum_be.j2")
|
||||
else:
|
||||
template = self.environment.get_template("encoder/enum.j2")
|
||||
print(template.render(name=node.name))
|
||||
|
|
|
@ -8,7 +8,7 @@ from jinja2 import Environment
|
|||
from generators import SourceGenerator
|
||||
from generators import create_jinja2_environment, get_jinja2_template
|
||||
|
||||
from xdr_ast import _XdrBasic, _XdrUnion, _XdrVoid
|
||||
from xdr_ast import _XdrBasic, _XdrUnion, _XdrVoid, big_endian
|
||||
from xdr_ast import _XdrDeclaration, _XdrCaseSpec, public_apis
|
||||
|
||||
|
||||
|
@ -77,13 +77,18 @@ def emit_union_switch_spec_decoder(
|
|||
print(template.render(name=node.name, type=node.spec.type_name))
|
||||
|
||||
|
||||
def emit_union_case_spec_decoder(environment: Environment, node: _XdrCaseSpec) -> None:
|
||||
def emit_union_case_spec_decoder(
|
||||
environment: Environment, node: _XdrCaseSpec, big_endian_discriminant: bool
|
||||
) -> None:
|
||||
"""Emit decoder functions for an XDR union's case arm"""
|
||||
|
||||
if isinstance(node.arm, _XdrVoid):
|
||||
return
|
||||
|
||||
template = get_jinja2_template(environment, "decoder", "case_spec")
|
||||
if big_endian_discriminant:
|
||||
template = get_jinja2_template(environment, "decoder", "case_spec_be")
|
||||
else:
|
||||
template = get_jinja2_template(environment, "decoder", "case_spec")
|
||||
for case in node.values:
|
||||
print(template.render(case=case))
|
||||
|
||||
|
@ -136,7 +141,11 @@ def emit_union_decoder(environment: Environment, node: _XdrUnion) -> None:
|
|||
emit_union_switch_spec_decoder(environment, node.discriminant)
|
||||
|
||||
for case in node.cases:
|
||||
emit_union_case_spec_decoder(environment, case)
|
||||
emit_union_case_spec_decoder(
|
||||
environment,
|
||||
case,
|
||||
node.discriminant.spec.type_name in big_endian,
|
||||
)
|
||||
|
||||
emit_union_default_spec_decoder(environment, node)
|
||||
|
||||
|
@ -153,17 +162,21 @@ def emit_union_switch_spec_encoder(
|
|||
print(template.render(name=node.name, type=node.spec.type_name))
|
||||
|
||||
|
||||
def emit_union_case_spec_encoder(environment: Environment, node: _XdrCaseSpec) -> None:
|
||||
def emit_union_case_spec_encoder(
|
||||
environment: Environment, node: _XdrCaseSpec, big_endian_discriminant: bool
|
||||
) -> None:
|
||||
"""Emit encoder functions for an XDR union's case arm"""
|
||||
|
||||
if isinstance(node.arm, _XdrVoid):
|
||||
return
|
||||
|
||||
template = get_jinja2_template(environment, "encoder", "case_spec")
|
||||
if big_endian_discriminant:
|
||||
template = get_jinja2_template(environment, "encoder", "case_spec_be")
|
||||
else:
|
||||
template = get_jinja2_template(environment, "encoder", "case_spec")
|
||||
for case in node.values:
|
||||
print(template.render(case=case))
|
||||
|
||||
assert isinstance(node.arm, _XdrBasic)
|
||||
template = get_jinja2_template(environment, "encoder", node.arm.template)
|
||||
print(
|
||||
template.render(
|
||||
|
@ -192,7 +205,6 @@ def emit_union_default_spec_encoder(environment: Environment, node: _XdrUnion) -
|
|||
print(template.render())
|
||||
return
|
||||
|
||||
assert isinstance(default_case.arm, _XdrBasic)
|
||||
template = get_jinja2_template(environment, "encoder", default_case.arm.template)
|
||||
print(
|
||||
template.render(
|
||||
|
@ -210,7 +222,11 @@ def emit_union_encoder(environment, node: _XdrUnion) -> None:
|
|||
emit_union_switch_spec_encoder(environment, node.discriminant)
|
||||
|
||||
for case in node.cases:
|
||||
emit_union_case_spec_encoder(environment, case)
|
||||
emit_union_case_spec_encoder(
|
||||
environment,
|
||||
case,
|
||||
node.discriminant.spec.type_name in big_endian,
|
||||
)
|
||||
|
||||
emit_union_default_spec_encoder(environment, node)
|
||||
|
||||
|
|
|
@ -87,12 +87,14 @@ procedure_def : type_specifier identifier "(" type_specifier ")" "=" c
|
|||
|
||||
pragma_def : "pragma" directive identifier [ identifier ] ";"
|
||||
|
||||
directive : exclude_directive
|
||||
directive : big_endian_directive
|
||||
| exclude_directive
|
||||
| header_directive
|
||||
| pages_directive
|
||||
| public_directive
|
||||
| skip_directive
|
||||
|
||||
big_endian_directive : "big_endian"
|
||||
exclude_directive : "exclude"
|
||||
header_directive : "header"
|
||||
pages_directive : "pages"
|
||||
|
|
14
tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2
Normal file
14
tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2
Normal file
|
@ -0,0 +1,14 @@
|
|||
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||
|
||||
{% if annotate %}
|
||||
/* enum {{ name }} (big-endian) */
|
||||
{% endif %}
|
||||
{% if name in public_apis %}
|
||||
bool
|
||||
{% else %}
|
||||
static bool __maybe_unused
|
||||
{% endif %}
|
||||
xdrgen_decode_{{ name }}(struct xdr_stream *xdr, {{ name }} *ptr)
|
||||
{
|
||||
return xdr_stream_decode_be32(xdr, ptr) == 0;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||
};
|
||||
typedef __be32 {{ name }};
|
14
tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2
Normal file
14
tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2
Normal file
|
@ -0,0 +1,14 @@
|
|||
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||
|
||||
{% if annotate %}
|
||||
/* enum {{ name }} (big-endian) */
|
||||
{% endif %}
|
||||
{% if name in public_apis %}
|
||||
bool
|
||||
{% else %}
|
||||
static bool __maybe_unused
|
||||
{% endif %}
|
||||
xdrgen_encode_{{ name }}(struct xdr_stream *xdr, {{ name }} value)
|
||||
{
|
||||
return xdr_stream_encode_be32(xdr, value) == XDR_UNIT;
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||
case __constant_cpu_to_be32({{ case }}):
|
|
@ -0,0 +1,2 @@
|
|||
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||
case __constant_cpu_to_be32({{ case }}):
|
|
@ -12,6 +12,7 @@ from lark.tree import Meta
|
|||
|
||||
this_module = sys.modules[__name__]
|
||||
|
||||
big_endian = []
|
||||
excluded_apis = []
|
||||
header_name = "none"
|
||||
public_apis = []
|
||||
|
@ -480,6 +481,8 @@ class ParseToAst(Transformer):
|
|||
"""Instantiate one _Pragma object"""
|
||||
directive = children[0].children[0].data
|
||||
match directive:
|
||||
case "big_endian_directive":
|
||||
big_endian.append(children[1].symbol)
|
||||
case "exclude_directive":
|
||||
excluded_apis.append(children[1].symbol)
|
||||
case "header_directive":
|
||||
|
|
Loading…
Reference in New Issue
Block a user