tools: Add xdrgen
Add a Python-based tool for translating XDR specifications into XDR encoder and decoder functions written in the Linux kernel's C coding style. The generator attempts to match the usual C coding style of the Linux kernel's SunRPC consumers. This approach is similar to the netlink code generator in tools/net/ynl . The maintainability benefits of machine-generated XDR code include: - Stronger type checking - Reduces the number of bugs introduced by human error - Makes the XDR code easier to audit and analyze - Enables rapid prototyping of new RPC-based protocols - Hardens the layering between protocol logic and marshaling - Makes it easier to add observability on demand - Unit tests might be built for both the tool and (automatically) for the generated code In addition, converting the XDR layer to use memory-safe languages such as Rust will be easier if much of the code can be converted automatically. Tested-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
45bb63ed20
commit
4b132aacb0
153 changed files with 4196 additions and 0 deletions
243
include/linux/sunrpc/xdrgen/_builtins.h
Normal file
243
include/linux/sunrpc/xdrgen/_builtins.h
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* This header defines XDR data type primitives specified in
|
||||||
|
* Section 4 of RFC 4506, used by RPC programs implemented
|
||||||
|
* in the Linux kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SUNRPC_XDRGEN__BUILTINS_H_
|
||||||
|
#define _SUNRPC_XDRGEN__BUILTINS_H_
|
||||||
|
|
||||||
|
#include <linux/sunrpc/xdr.h>
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_void(struct xdr_stream *xdr)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_void(struct xdr_stream *xdr)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_bool(struct xdr_stream *xdr, bool *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = (*p != xdr_zero);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_bool(struct xdr_stream *xdr, bool val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*p = val ? xdr_one : xdr_zero;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_int(struct xdr_stream *xdr, s32 *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = be32_to_cpup(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_int(struct xdr_stream *xdr, s32 val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*p = cpu_to_be32(val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_unsigned_int(struct xdr_stream *xdr, u32 *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = be32_to_cpup(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_unsigned_int(struct xdr_stream *xdr, u32 val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*p = cpu_to_be32(val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_long(struct xdr_stream *xdr, s32 *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = be32_to_cpup(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_long(struct xdr_stream *xdr, s32 val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*p = cpu_to_be32(val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_unsigned_long(struct xdr_stream *xdr, u32 *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = be32_to_cpup(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_unsigned_long(struct xdr_stream *xdr, u32 val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*p = cpu_to_be32(val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_hyper(struct xdr_stream *xdr, s64 *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT * 2);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = get_unaligned_be64(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_hyper(struct xdr_stream *xdr, s64 val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
put_unaligned_be64(val, p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_unsigned_hyper(struct xdr_stream *xdr, u64 *ptr)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_inline_decode(xdr, XDR_UNIT * 2);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
*ptr = get_unaligned_be64(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_unsigned_hyper(struct xdr_stream *xdr, u64 val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2);
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
put_unaligned_be64(val, p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_string(struct xdr_stream *xdr, string *ptr, u32 maxlen)
|
||||||
|
{
|
||||||
|
__be32 *p;
|
||||||
|
u32 len;
|
||||||
|
|
||||||
|
if (unlikely(xdr_stream_decode_u32(xdr, &len) != XDR_UNIT))
|
||||||
|
return false;
|
||||||
|
if (unlikely(maxlen && len > maxlen))
|
||||||
|
return false;
|
||||||
|
if (len != 0) {
|
||||||
|
p = xdr_inline_decode(xdr, len);
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
ptr->data = (unsigned char *)p;
|
||||||
|
}
|
||||||
|
ptr->len = len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_string(struct xdr_stream *xdr, string val, u32 maxlen)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(val.len));
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
xdr_encode_opaque(p, val.data, val.len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_decode_opaque(struct xdr_stream *xdr, opaque *ptr, u32 maxlen)
|
||||||
|
{
|
||||||
|
__be32 *p;
|
||||||
|
u32 len;
|
||||||
|
|
||||||
|
if (unlikely(xdr_stream_decode_u32(xdr, &len) != XDR_UNIT))
|
||||||
|
return false;
|
||||||
|
if (unlikely(maxlen && len > maxlen))
|
||||||
|
return false;
|
||||||
|
if (len != 0) {
|
||||||
|
p = xdr_inline_decode(xdr, len);
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
ptr->data = (u8 *)p;
|
||||||
|
}
|
||||||
|
ptr->len = len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
xdrgen_encode_opaque(struct xdr_stream *xdr, opaque val)
|
||||||
|
{
|
||||||
|
__be32 *p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(val.len));
|
||||||
|
|
||||||
|
if (unlikely(!p))
|
||||||
|
return false;
|
||||||
|
xdr_encode_opaque(p, val.data, val.len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _SUNRPC_XDRGEN__BUILTINS_H_ */
|
26
include/linux/sunrpc/xdrgen/_defs.h
Normal file
26
include/linux/sunrpc/xdrgen/_defs.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Oracle and/or its affiliates.
|
||||||
|
*
|
||||||
|
* This header defines XDR data type primitives specified in
|
||||||
|
* Section 4 of RFC 4506, used by RPC programs implemented
|
||||||
|
* in the Linux kernel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SUNRPC_XDRGEN__DEFS_H_
|
||||||
|
#define _SUNRPC_XDRGEN__DEFS_H_
|
||||||
|
|
||||||
|
#define TRUE (true)
|
||||||
|
#define FALSE (false)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 len;
|
||||||
|
unsigned char *data;
|
||||||
|
} string;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 len;
|
||||||
|
u8 *data;
|
||||||
|
} opaque;
|
||||||
|
|
||||||
|
#endif /* _SUNRPC_XDRGEN__DEFS_H_ */
|
2
tools/net/sunrpc/xdrgen/.gitignore
vendored
Normal file
2
tools/net/sunrpc/xdrgen/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
__pycache__
|
||||||
|
generators/__pycache__
|
244
tools/net/sunrpc/xdrgen/README
Normal file
244
tools/net/sunrpc/xdrgen/README
Normal file
|
@ -0,0 +1,244 @@
|
||||||
|
xdrgen - Linux Kernel XDR code generator
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
SunRPC programs are typically specified using a language defined by
|
||||||
|
RFC 4506. In fact, all IETF-published NFS specifications provide a
|
||||||
|
description of the specified protocol using this language.
|
||||||
|
|
||||||
|
Since the 1990's, user space consumers of SunRPC have had access to
|
||||||
|
a tool that could read such XDR specifications and then generate C
|
||||||
|
code that implements the RPC portions of that protocol. This tool is
|
||||||
|
called rpcgen.
|
||||||
|
|
||||||
|
This RPC-level code is code that handles input directly from the
|
||||||
|
network, and thus a high degree of memory safety and sanity checking
|
||||||
|
is needed to help ensure proper levels of security. Bugs in this
|
||||||
|
code can have significant impact on security and performance.
|
||||||
|
|
||||||
|
However, it is code that is repetitive and tedious to write by hand.
|
||||||
|
|
||||||
|
The C code generated by rpcgen makes extensive use of the facilities
|
||||||
|
of the user space TI-RPC library and libc. Furthermore, the dialect
|
||||||
|
of the generated code is very traditional K&R C.
|
||||||
|
|
||||||
|
The Linux kernel's implementation of SunRPC-based protocols hand-roll
|
||||||
|
their XDR implementation. There are two main reasons for this:
|
||||||
|
|
||||||
|
1. libtirpc (and its predecessors) operate only in user space. The
|
||||||
|
kernel's RPC implementation and its API are significantly
|
||||||
|
different than libtirpc.
|
||||||
|
|
||||||
|
2. rpcgen-generated code is believed to be less efficient than code
|
||||||
|
that is hand-written.
|
||||||
|
|
||||||
|
These days, gcc and its kin are capable of optimizing code better
|
||||||
|
than human authors. There are only a few instances where writing
|
||||||
|
XDR code by hand will make a measurable performance different.
|
||||||
|
|
||||||
|
In addition, the current hand-written code in the Linux kernel is
|
||||||
|
difficult to audit and prove that it implements exactly what is in
|
||||||
|
the protocol specification.
|
||||||
|
|
||||||
|
In order to accrue the benefits of machine-generated XDR code in the
|
||||||
|
kernel, a tool is needed that will output C code that works against
|
||||||
|
the kernel's SunRPC implementation rather than libtirpc.
|
||||||
|
|
||||||
|
Enter xdrgen.
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
These dependencies are typically packaged by Linux distributions:
|
||||||
|
|
||||||
|
- python3
|
||||||
|
- python3-lark
|
||||||
|
- python3-jinja2
|
||||||
|
|
||||||
|
These dependencies are available via PyPi:
|
||||||
|
|
||||||
|
- pip install 'lark[interegular]'
|
||||||
|
|
||||||
|
|
||||||
|
XDR Specifications
|
||||||
|
------------------
|
||||||
|
|
||||||
|
When adding a new protocol implementation to the kernel, the XDR
|
||||||
|
specification can be derived by feeding a .txt copy of the RFC to
|
||||||
|
the script located in tools/net/sunrpc/extract.sh.
|
||||||
|
|
||||||
|
$ extract.sh < rfc0001.txt > new2.x
|
||||||
|
|
||||||
|
|
||||||
|
Operation
|
||||||
|
---------
|
||||||
|
|
||||||
|
Once a .x file is available, use xdrgen to generate source and
|
||||||
|
header files containing an implementation of XDR encoding and
|
||||||
|
decoding functions for the specified protocol.
|
||||||
|
|
||||||
|
$ ./xdrgen definitions new2.x > include/linux/sunrpc/xdrgen/new2.h
|
||||||
|
$ ./xdrgen declarations new2.x > new2xdr_gen.h
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
$ ./xdrgen source new2.x > new2xdr_gen.c
|
||||||
|
|
||||||
|
The files are ready to use for a server-side protocol implementation,
|
||||||
|
or may be used as a guide for implementing these routines by hand.
|
||||||
|
|
||||||
|
By default, the only comments added to this code are kdoc comments
|
||||||
|
that appear directly in front of the public per-procedure APIs. For
|
||||||
|
deeper introspection, specifying the "--annotate" flag will insert
|
||||||
|
additional comments in the generated code to help readers match the
|
||||||
|
generated code to specific parts of the XDR specification.
|
||||||
|
|
||||||
|
Because the generated code is targeted for the Linux kernel, it
|
||||||
|
is tagged with a GPLv2-only license.
|
||||||
|
|
||||||
|
The xdrgen tool can also provide lexical and syntax checking of
|
||||||
|
an XDR specification:
|
||||||
|
|
||||||
|
$ ./xdrgen lint xdr/new.x
|
||||||
|
|
||||||
|
|
||||||
|
How It Works
|
||||||
|
------------
|
||||||
|
|
||||||
|
xdrgen does not use machine learning to generate source code. The
|
||||||
|
translation is entirely deterministic.
|
||||||
|
|
||||||
|
RFC 4506 Section 6 contains a BNF grammar of the XDR specification
|
||||||
|
language. The grammar has been adapted for use by the Python Lark
|
||||||
|
module.
|
||||||
|
|
||||||
|
The xdr.ebnf file in this directory contains the grammar used to
|
||||||
|
parse XDR specifications. xdrgen configures Lark using the grammar
|
||||||
|
in xdr.ebnf. Lark parses the target XDR specification using this
|
||||||
|
grammar, creating a parse tree.
|
||||||
|
|
||||||
|
xdrgen then transforms the parse tree into an abstract syntax tree.
|
||||||
|
This tree is passed to a series of code generators.
|
||||||
|
|
||||||
|
The generators are implemented as Python classes residing in the
|
||||||
|
generators/ directory. Each generator emits code created from Jinja2
|
||||||
|
templates stored in the templates/ directory.
|
||||||
|
|
||||||
|
The source code is generated in the same order in which they appear
|
||||||
|
in the specification to ensure the generated code compiles. This
|
||||||
|
conforms with the behavior of rpcgen.
|
||||||
|
|
||||||
|
xdrgen assumes that the generated source code is further compiled by
|
||||||
|
a compiler that can optimize in a number of ways, including:
|
||||||
|
|
||||||
|
- Unused functions are discarded (ie, not added to the executable)
|
||||||
|
|
||||||
|
- Aggressive function inlining removes unnecessary stack frames
|
||||||
|
|
||||||
|
- Single-arm switch statements are replaced by a single conditional
|
||||||
|
branch
|
||||||
|
|
||||||
|
And so on.
|
||||||
|
|
||||||
|
|
||||||
|
Pragmas
|
||||||
|
-------
|
||||||
|
|
||||||
|
Pragma directives specify exceptions to the normal generation of
|
||||||
|
encoding and decoding functions. Currently one directive is
|
||||||
|
implemented: "public".
|
||||||
|
|
||||||
|
Pragma exclude
|
||||||
|
------ -------
|
||||||
|
|
||||||
|
pragma exclude <RPC procedure> ;
|
||||||
|
|
||||||
|
In some cases, a procedure encoder or decoder function might need
|
||||||
|
special processing that cannot be automatically generated. The
|
||||||
|
automatically-generated functions might conflict or interfere with
|
||||||
|
the hand-rolled function. To avoid editing the generated source code
|
||||||
|
by hand, a pragma can specify that the procedure's encoder and
|
||||||
|
decoder functions are not included in the generated header and
|
||||||
|
source.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
pragma exclude NFSPROC3_READDIRPLUS;
|
||||||
|
|
||||||
|
Excludes the decoder function for the READDIRPLUS argument and the
|
||||||
|
encoder function for the READDIRPLUS result.
|
||||||
|
|
||||||
|
Note that because data item encoder and decoder functions are
|
||||||
|
defined "static __maybe_unused", subsequent compilation
|
||||||
|
automatically excludes data item encoder and decoder functions that
|
||||||
|
are used only by excluded procedure.
|
||||||
|
|
||||||
|
Pragma header
|
||||||
|
------ ------
|
||||||
|
|
||||||
|
pragma header <string> ;
|
||||||
|
|
||||||
|
Provide a name to use for the header file. For example:
|
||||||
|
|
||||||
|
pragma header nlm4;
|
||||||
|
|
||||||
|
Adds
|
||||||
|
|
||||||
|
#include "nlm4xdr_gen.h"
|
||||||
|
|
||||||
|
to the generated source file.
|
||||||
|
|
||||||
|
Pragma public
|
||||||
|
------ ------
|
||||||
|
|
||||||
|
pragma public <XDR data item> ;
|
||||||
|
|
||||||
|
Normally XDR encoder and decoder functions are "static". In case an
|
||||||
|
implementer wants to call these functions from other source code,
|
||||||
|
s/he can add a public pragma in the input .x file to indicate a set
|
||||||
|
of functions that should get a prototype in the generated header,
|
||||||
|
and the function definitions will not be declared static.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
pragma public nfsstat3;
|
||||||
|
|
||||||
|
Adds these prototypes in the generated header:
|
||||||
|
|
||||||
|
bool xdrgen_decode_nfsstat3(struct xdr_stream *xdr, enum nfsstat3 *ptr);
|
||||||
|
bool xdrgen_encode_nfsstat3(struct xdr_stream *xdr, enum nfsstat3 value);
|
||||||
|
|
||||||
|
And, in the generated source code, both of these functions appear
|
||||||
|
without the "static __maybe_unused" modifiers.
|
||||||
|
|
||||||
|
|
||||||
|
Future Work
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Finish implementing XDR pointer and list types.
|
||||||
|
|
||||||
|
Generate client-side procedure functions
|
||||||
|
|
||||||
|
Expand the README into a user guide similar to rpcgen(1)
|
||||||
|
|
||||||
|
Add more pragma directives:
|
||||||
|
|
||||||
|
* @pages -- use xdr_read/write_pages() for the specified opaque
|
||||||
|
field
|
||||||
|
* @skip -- do not decode, but rather skip, the specified argument
|
||||||
|
field
|
||||||
|
|
||||||
|
Enable something like a #include to dynamically insert the content
|
||||||
|
of other specification files
|
||||||
|
|
||||||
|
Properly support line-by-line pass-through via the "%" decorator
|
||||||
|
|
||||||
|
Build a unit test suite for verifying translation of XDR language
|
||||||
|
into compilable code
|
||||||
|
|
||||||
|
Add a command-line option to insert trace_printk call sites in the
|
||||||
|
generated source code, for improved (temporary) observability
|
||||||
|
|
||||||
|
Generate kernel Rust code as well as C code
|
2
tools/net/sunrpc/xdrgen/__init__.py
Normal file
2
tools/net/sunrpc/xdrgen/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Just to make sphinx-apidoc document this directory
|
113
tools/net/sunrpc/xdrgen/generators/__init__.py
Normal file
113
tools/net/sunrpc/xdrgen/generators/__init__.py
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
"""Define a base code generator class"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from jinja2 import Environment, FileSystemLoader, Template
|
||||||
|
|
||||||
|
from xdr_ast import _XdrAst, Specification, _RpcProgram, _XdrTypeSpecifier
|
||||||
|
from xdr_ast import public_apis, pass_by_reference, get_header_name
|
||||||
|
from xdr_parse import get_xdr_annotate
|
||||||
|
|
||||||
|
|
||||||
|
def create_jinja2_environment(language: str, xdr_type: str) -> Environment:
|
||||||
|
"""Open a set of templates based on output language"""
|
||||||
|
match language:
|
||||||
|
case "C":
|
||||||
|
environment = Environment(
|
||||||
|
loader=FileSystemLoader(sys.path[0] + "/templates/C/" + xdr_type + "/"),
|
||||||
|
trim_blocks=True,
|
||||||
|
lstrip_blocks=True,
|
||||||
|
)
|
||||||
|
environment.globals["annotate"] = get_xdr_annotate()
|
||||||
|
environment.globals["public_apis"] = public_apis
|
||||||
|
environment.globals["pass_by_reference"] = pass_by_reference
|
||||||
|
return environment
|
||||||
|
case _:
|
||||||
|
raise NotImplementedError("Language not supported")
|
||||||
|
|
||||||
|
|
||||||
|
def get_jinja2_template(
|
||||||
|
environment: Environment, template_type: str, template_name: str
|
||||||
|
) -> Template:
|
||||||
|
"""Retrieve a Jinja2 template for emitting source code"""
|
||||||
|
return environment.get_template(template_type + "/" + template_name + ".j2")
|
||||||
|
|
||||||
|
|
||||||
|
def find_xdr_program_name(root: Specification) -> str:
|
||||||
|
"""Retrieve the RPC program name from an abstract syntax tree"""
|
||||||
|
raw_name = get_header_name()
|
||||||
|
if raw_name != "none":
|
||||||
|
return raw_name.lower()
|
||||||
|
for definition in root.definitions:
|
||||||
|
if isinstance(definition.value, _RpcProgram):
|
||||||
|
raw_name = definition.value.name
|
||||||
|
return raw_name.lower().removesuffix("_program").removesuffix("_prog")
|
||||||
|
return "noprog"
|
||||||
|
|
||||||
|
|
||||||
|
def header_guard_infix(filename: str) -> str:
|
||||||
|
"""Extract the header guard infix from the specification filename"""
|
||||||
|
basename = filename.split("/")[-1]
|
||||||
|
program = basename.replace(".x", "")
|
||||||
|
return program.upper()
|
||||||
|
|
||||||
|
|
||||||
|
def kernel_c_type(spec: _XdrTypeSpecifier) -> str:
|
||||||
|
"""Return name of C type"""
|
||||||
|
builtin_native_c_type = {
|
||||||
|
"bool": "bool",
|
||||||
|
"int": "s32",
|
||||||
|
"unsigned_int": "u32",
|
||||||
|
"long": "s32",
|
||||||
|
"unsigned_long": "u32",
|
||||||
|
"hyper": "s64",
|
||||||
|
"unsigned_hyper": "u64",
|
||||||
|
}
|
||||||
|
if spec.type_name in builtin_native_c_type:
|
||||||
|
return builtin_native_c_type[spec.type_name]
|
||||||
|
return spec.type_name
|
||||||
|
|
||||||
|
|
||||||
|
class Boilerplate:
|
||||||
|
"""Base class to generate boilerplate for source files"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
raise NotImplementedError("No language support defined")
|
||||||
|
|
||||||
|
def emit_declaration(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit declaration header boilerplate"""
|
||||||
|
raise NotImplementedError("Header boilerplate generation not supported")
|
||||||
|
|
||||||
|
def emit_definition(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit definition header boilerplate"""
|
||||||
|
raise NotImplementedError("Header boilerplate generation not supported")
|
||||||
|
|
||||||
|
def emit_source(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit generic source code for this XDR type"""
|
||||||
|
raise NotImplementedError("Source boilerplate generation not supported")
|
||||||
|
|
||||||
|
|
||||||
|
class SourceGenerator:
|
||||||
|
"""Base class to generate header and source code for XDR types"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
raise NotImplementedError("No language support defined")
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _XdrAst) -> None:
|
||||||
|
"""Emit one function declaration for this XDR type"""
|
||||||
|
raise NotImplementedError("Declaration generation not supported")
|
||||||
|
|
||||||
|
def emit_decoder(self, node: _XdrAst) -> None:
|
||||||
|
"""Emit one decoder function for this XDR type"""
|
||||||
|
raise NotImplementedError("Decoder generation not supported")
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrAst) -> None:
|
||||||
|
"""Emit one definition for this XDR type"""
|
||||||
|
raise NotImplementedError("Definition generation not supported")
|
||||||
|
|
||||||
|
def emit_encoder(self, node: _XdrAst) -> None:
|
||||||
|
"""Emit one encoder function for this XDR type"""
|
||||||
|
raise NotImplementedError("Encoder generation not supported")
|
20
tools/net/sunrpc/xdrgen/generators/constant.py
Normal file
20
tools/net/sunrpc/xdrgen/generators/constant.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code to handle XDR constants"""
|
||||||
|
|
||||||
|
from generators import SourceGenerator, create_jinja2_environment
|
||||||
|
from xdr_ast import _XdrConstant
|
||||||
|
|
||||||
|
class XdrConstantGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for XDR constants"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "constants")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrConstant) -> None:
|
||||||
|
"""Emit one definition for a constant"""
|
||||||
|
template = self.environment.get_template("definition.j2")
|
||||||
|
print(template.render(name=node.name, value=node.value))
|
44
tools/net/sunrpc/xdrgen/generators/enum.py
Normal file
44
tools/net/sunrpc/xdrgen/generators/enum.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code to handle XDR enum types"""
|
||||||
|
|
||||||
|
from generators import SourceGenerator, create_jinja2_environment
|
||||||
|
from xdr_ast import _XdrEnum, public_apis
|
||||||
|
|
||||||
|
|
||||||
|
class XdrEnumGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for XDR enum types"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "enum")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _XdrEnum) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR enum type"""
|
||||||
|
if node.name in public_apis:
|
||||||
|
template = self.environment.get_template("declaration/close.j2")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrEnum) -> None:
|
||||||
|
"""Emit one definition for an XDR enum type"""
|
||||||
|
template = self.environment.get_template("definition/open.j2")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
template = self.environment.get_template("definition/enumerator.j2")
|
||||||
|
for enumerator in node.enumerators:
|
||||||
|
print(template.render(name=enumerator.name, value=enumerator.value))
|
||||||
|
|
||||||
|
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")
|
||||||
|
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")
|
||||||
|
print(template.render(name=node.name))
|
33
tools/net/sunrpc/xdrgen/generators/header_bottom.py
Normal file
33
tools/net/sunrpc/xdrgen/generators/header_bottom.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate header bottom boilerplate"""
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
|
||||||
|
from generators import Boilerplate, header_guard_infix
|
||||||
|
from generators import create_jinja2_environment, get_jinja2_template
|
||||||
|
from xdr_ast import Specification
|
||||||
|
|
||||||
|
|
||||||
|
class XdrHeaderBottomGenerator(Boilerplate):
|
||||||
|
"""Generate header boilerplate"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "header_bottom")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit the bottom header guard"""
|
||||||
|
template = get_jinja2_template(self.environment, "declaration", "header")
|
||||||
|
print(template.render(infix=header_guard_infix(filename)))
|
||||||
|
|
||||||
|
def emit_definition(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit the bottom header guard"""
|
||||||
|
template = get_jinja2_template(self.environment, "definition", "header")
|
||||||
|
print(template.render(infix=header_guard_infix(filename)))
|
||||||
|
|
||||||
|
def emit_source(self, filename: str, root: Specification) -> None:
|
||||||
|
pass
|
45
tools/net/sunrpc/xdrgen/generators/header_top.py
Normal file
45
tools/net/sunrpc/xdrgen/generators/header_top.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate header top boilerplate"""
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
|
||||||
|
from generators import Boilerplate, header_guard_infix
|
||||||
|
from generators import create_jinja2_environment, get_jinja2_template
|
||||||
|
from xdr_ast import Specification
|
||||||
|
|
||||||
|
|
||||||
|
class XdrHeaderTopGenerator(Boilerplate):
|
||||||
|
"""Generate header boilerplate"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "header_top")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit the top header guard"""
|
||||||
|
template = get_jinja2_template(self.environment, "declaration", "header")
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
infix=header_guard_infix(filename),
|
||||||
|
filename=filename,
|
||||||
|
mtime=time.ctime(os.path.getmtime(filename)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def emit_definition(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit the top header guard"""
|
||||||
|
template = get_jinja2_template(self.environment, "definition", "header")
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
infix=header_guard_infix(filename),
|
||||||
|
filename=filename,
|
||||||
|
mtime=time.ctime(os.path.getmtime(filename)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def emit_source(self, filename: str, root: Specification) -> None:
|
||||||
|
pass
|
272
tools/net/sunrpc/xdrgen/generators/pointer.py
Normal file
272
tools/net/sunrpc/xdrgen/generators/pointer.py
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code to handle XDR pointer types"""
|
||||||
|
|
||||||
|
from jinja2 import Environment
|
||||||
|
|
||||||
|
from generators import SourceGenerator, kernel_c_type
|
||||||
|
from generators import create_jinja2_environment, get_jinja2_template
|
||||||
|
|
||||||
|
from xdr_ast import _XdrBasic, _XdrVariableLengthString
|
||||||
|
from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
|
||||||
|
from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
|
||||||
|
from xdr_ast import _XdrOptionalData, _XdrPointer, _XdrDeclaration
|
||||||
|
from xdr_ast import public_apis
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_declaration(environment: Environment, node: _XdrPointer) -> None:
|
||||||
|
"""Emit a declaration pair for an XDR pointer type"""
|
||||||
|
if node.name in public_apis:
|
||||||
|
template = get_jinja2_template(environment, "declaration", "close")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_member_definition(
|
||||||
|
environment: Environment, field: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a definition for one field in an XDR struct"""
|
||||||
|
if isinstance(field, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(template.render(name=field.name))
|
||||||
|
elif isinstance(field, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(template.render(name=field.name))
|
||||||
|
elif isinstance(field, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrOptionalData):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_definition(environment: Environment, node: _XdrPointer) -> None:
|
||||||
|
"""Emit a definition for an XDR pointer type"""
|
||||||
|
template = get_jinja2_template(environment, "definition", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
for field in node.fields[0:-1]:
|
||||||
|
emit_pointer_member_definition(environment, field)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "definition", "close")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_member_decoder(
|
||||||
|
environment: Environment, field: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a decoder for one field in an XDR pointer"""
|
||||||
|
if isinstance(field, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
size=field.size,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrOptionalData):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_decoder(environment: Environment, node: _XdrPointer) -> None:
|
||||||
|
"""Emit one decoder function for an XDR pointer type"""
|
||||||
|
template = get_jinja2_template(environment, "decoder", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
for field in node.fields[0:-1]:
|
||||||
|
emit_pointer_member_decoder(environment, field)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "decoder", "close")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_member_encoder(
|
||||||
|
environment: Environment, field: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit an encoder for one field in a XDR pointer"""
|
||||||
|
if isinstance(field, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrOptionalData):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_pointer_encoder(environment: Environment, node: _XdrPointer) -> None:
|
||||||
|
"""Emit one encoder function for an XDR pointer type"""
|
||||||
|
template = get_jinja2_template(environment, "encoder", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
for field in node.fields[0:-1]:
|
||||||
|
emit_pointer_member_encoder(environment, field)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "encoder", "close")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
class XdrPointerGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for XDR pointer"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "pointer")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _XdrPointer) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR pointer type"""
|
||||||
|
emit_pointer_declaration(self.environment, node)
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrPointer) -> None:
|
||||||
|
"""Emit one declaration for an XDR pointer type"""
|
||||||
|
emit_pointer_definition(self.environment, node)
|
||||||
|
|
||||||
|
def emit_decoder(self, node: _XdrPointer) -> None:
|
||||||
|
"""Emit one decoder function for an XDR pointer type"""
|
||||||
|
emit_pointer_decoder(self.environment, node)
|
||||||
|
|
||||||
|
def emit_encoder(self, node: _XdrPointer) -> None:
|
||||||
|
"""Emit one encoder function for an XDR pointer type"""
|
||||||
|
emit_pointer_encoder(self.environment, node)
|
168
tools/net/sunrpc/xdrgen/generators/program.py
Normal file
168
tools/net/sunrpc/xdrgen/generators/program.py
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code for an RPC program's procedures"""
|
||||||
|
|
||||||
|
from jinja2 import Environment
|
||||||
|
|
||||||
|
from generators import SourceGenerator, create_jinja2_environment
|
||||||
|
from xdr_ast import _RpcProgram, _RpcVersion, excluded_apis
|
||||||
|
|
||||||
|
|
||||||
|
def emit_version_definitions(
|
||||||
|
environment: Environment, program: str, version: _RpcVersion
|
||||||
|
) -> None:
|
||||||
|
"""Emit procedure numbers for each RPC version's procedures"""
|
||||||
|
template = environment.get_template("definition/open.j2")
|
||||||
|
print(template.render(program=program.upper()))
|
||||||
|
|
||||||
|
template = environment.get_template("definition/procedure.j2")
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=procedure.name,
|
||||||
|
value=procedure.number,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
template = environment.get_template("definition/close.j2")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
def emit_version_declarations(
|
||||||
|
environment: Environment, program: str, version: _RpcVersion
|
||||||
|
) -> None:
|
||||||
|
"""Emit declarations for each RPC version's procedures"""
|
||||||
|
arguments = set()
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
arguments.add(procedure.argument.type_name)
|
||||||
|
if len(arguments) > 0:
|
||||||
|
print("")
|
||||||
|
template = environment.get_template("declaration/argument.j2")
|
||||||
|
for argument in arguments:
|
||||||
|
print(template.render(program=program, argument=argument))
|
||||||
|
|
||||||
|
results = set()
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
results.add(procedure.result.type_name)
|
||||||
|
if len(results) > 0:
|
||||||
|
print("")
|
||||||
|
template = environment.get_template("declaration/result.j2")
|
||||||
|
for result in results:
|
||||||
|
print(template.render(program=program, result=result))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_version_argument_decoders(
|
||||||
|
environment: Environment, program: str, version: _RpcVersion
|
||||||
|
) -> None:
|
||||||
|
"""Emit server argument decoders for each RPC version's procedures"""
|
||||||
|
arguments = set()
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
arguments.add(procedure.argument.type_name)
|
||||||
|
|
||||||
|
template = environment.get_template("decoder/argument.j2")
|
||||||
|
for argument in arguments:
|
||||||
|
print(template.render(program=program, argument=argument))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_version_result_decoders(
|
||||||
|
environment: Environment, program: str, version: _RpcVersion
|
||||||
|
) -> None:
|
||||||
|
"""Emit client result decoders for each RPC version's procedures"""
|
||||||
|
results = set()
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
results.add(procedure.result.type_name)
|
||||||
|
|
||||||
|
template = environment.get_template("decoder/result.j2")
|
||||||
|
for result in results:
|
||||||
|
print(template.render(program=program, result=result))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_version_argument_encoders(
|
||||||
|
environment: Environment, program: str, version: _RpcVersion
|
||||||
|
) -> None:
|
||||||
|
"""Emit client argument encoders for each RPC version's procedures"""
|
||||||
|
arguments = set()
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
arguments.add(procedure.argument.type_name)
|
||||||
|
|
||||||
|
template = environment.get_template("encoder/argument.j2")
|
||||||
|
for argument in arguments:
|
||||||
|
print(template.render(program=program, argument=argument))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_version_result_encoders(
|
||||||
|
environment: Environment, program: str, version: _RpcVersion
|
||||||
|
) -> None:
|
||||||
|
"""Emit server result encoders for each RPC version's procedures"""
|
||||||
|
results = set()
|
||||||
|
for procedure in version.procedures:
|
||||||
|
if procedure.name not in excluded_apis:
|
||||||
|
results.add(procedure.result.type_name)
|
||||||
|
|
||||||
|
template = environment.get_template("encoder/result.j2")
|
||||||
|
for result in results:
|
||||||
|
print(template.render(program=program, result=result))
|
||||||
|
|
||||||
|
|
||||||
|
class XdrProgramGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for an RPC program's procedures"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "program")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_definition(self, node: _RpcProgram) -> None:
|
||||||
|
"""Emit procedure numbers for each of an RPC programs's procedures"""
|
||||||
|
raw_name = node.name
|
||||||
|
program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
|
||||||
|
|
||||||
|
for version in node.versions:
|
||||||
|
emit_version_definitions(self.environment, program, version)
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _RpcProgram) -> None:
|
||||||
|
"""Emit a declaration pair for each of an RPC programs's procedures"""
|
||||||
|
raw_name = node.name
|
||||||
|
program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
|
||||||
|
|
||||||
|
for version in node.versions:
|
||||||
|
emit_version_declarations(self.environment, program, version)
|
||||||
|
|
||||||
|
def emit_decoder(self, node: _RpcProgram) -> None:
|
||||||
|
"""Emit all decoder functions for an RPC program's procedures"""
|
||||||
|
raw_name = node.name
|
||||||
|
program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
|
||||||
|
match self.peer:
|
||||||
|
case "server":
|
||||||
|
for version in node.versions:
|
||||||
|
emit_version_argument_decoders(
|
||||||
|
self.environment, program, version,
|
||||||
|
)
|
||||||
|
case "client":
|
||||||
|
for version in node.versions:
|
||||||
|
emit_version_result_decoders(
|
||||||
|
self.environment, program, version,
|
||||||
|
)
|
||||||
|
|
||||||
|
def emit_encoder(self, node: _RpcProgram) -> None:
|
||||||
|
"""Emit all encoder functions for an RPC program's procedures"""
|
||||||
|
raw_name = node.name
|
||||||
|
program = raw_name.lower().removesuffix("_program").removesuffix("_prog")
|
||||||
|
match self.peer:
|
||||||
|
case "server":
|
||||||
|
for version in node.versions:
|
||||||
|
emit_version_result_encoders(
|
||||||
|
self.environment, program, version,
|
||||||
|
)
|
||||||
|
case "client":
|
||||||
|
for version in node.versions:
|
||||||
|
emit_version_argument_encoders(
|
||||||
|
self.environment, program, version,
|
||||||
|
)
|
32
tools/net/sunrpc/xdrgen/generators/source_top.py
Normal file
32
tools/net/sunrpc/xdrgen/generators/source_top.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate source code boilerplate"""
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
import time
|
||||||
|
|
||||||
|
from generators import Boilerplate
|
||||||
|
from generators import find_xdr_program_name, create_jinja2_environment
|
||||||
|
from xdr_ast import _RpcProgram, Specification, get_header_name
|
||||||
|
|
||||||
|
|
||||||
|
class XdrSourceTopGenerator(Boilerplate):
|
||||||
|
"""Generate source code boilerplate"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "source_top")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_source(self, filename: str, root: Specification) -> None:
|
||||||
|
"""Emit the top source boilerplate"""
|
||||||
|
name = find_xdr_program_name(root)
|
||||||
|
template = self.environment.get_template(self.peer + ".j2")
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
program=name,
|
||||||
|
filename=filename,
|
||||||
|
mtime=time.ctime(os.path.getmtime(filename)),
|
||||||
|
)
|
||||||
|
)
|
272
tools/net/sunrpc/xdrgen/generators/struct.py
Normal file
272
tools/net/sunrpc/xdrgen/generators/struct.py
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code to handle XDR struct types"""
|
||||||
|
|
||||||
|
from jinja2 import Environment
|
||||||
|
|
||||||
|
from generators import SourceGenerator, kernel_c_type
|
||||||
|
from generators import create_jinja2_environment, get_jinja2_template
|
||||||
|
|
||||||
|
from xdr_ast import _XdrBasic, _XdrVariableLengthString
|
||||||
|
from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
|
||||||
|
from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
|
||||||
|
from xdr_ast import _XdrOptionalData, _XdrStruct, _XdrDeclaration
|
||||||
|
from xdr_ast import public_apis
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_declaration(environment: Environment, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR struct type"""
|
||||||
|
if node.name in public_apis:
|
||||||
|
template = get_jinja2_template(environment, "declaration", "close")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_member_definition(
|
||||||
|
environment: Environment, field: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a definition for one field in an XDR struct"""
|
||||||
|
if isinstance(field, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(template.render(name=field.name))
|
||||||
|
elif isinstance(field, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(template.render(name=field.name))
|
||||||
|
elif isinstance(field, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrOptionalData):
|
||||||
|
template = get_jinja2_template(environment, "definition", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=kernel_c_type(field.spec),
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_definition(environment: Environment, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one definition for an XDR struct type"""
|
||||||
|
template = get_jinja2_template(environment, "definition", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
for field in node.fields:
|
||||||
|
emit_struct_member_definition(environment, field)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "definition", "close")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_member_decoder(
|
||||||
|
environment: Environment, field: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a decoder for one field in an XDR struct"""
|
||||||
|
if isinstance(field, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
size=field.size,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrOptionalData):
|
||||||
|
template = get_jinja2_template(environment, "decoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_decoder(environment: Environment, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one decoder function for an XDR struct type"""
|
||||||
|
template = get_jinja2_template(environment, "decoder", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
for field in node.fields:
|
||||||
|
emit_struct_member_decoder(environment, field)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "decoder", "close")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_member_encoder(
|
||||||
|
environment: Environment, field: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit an encoder for one field in an XDR struct"""
|
||||||
|
if isinstance(field, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
size=field.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
maxsize=field.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(field, _XdrOptionalData):
|
||||||
|
template = get_jinja2_template(environment, "encoder", field.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=field.name,
|
||||||
|
type=field.spec.type_name,
|
||||||
|
classifier=field.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_struct_encoder(environment: Environment, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one encoder function for an XDR struct type"""
|
||||||
|
template = get_jinja2_template(environment, "encoder", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
for field in node.fields:
|
||||||
|
emit_struct_member_encoder(environment, field)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "encoder", "close")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
class XdrStructGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for XDR structs"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "struct")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR struct type"""
|
||||||
|
emit_struct_declaration(self.environment, node)
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one definition for an XDR struct type"""
|
||||||
|
emit_struct_definition(self.environment, node)
|
||||||
|
|
||||||
|
def emit_decoder(self, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one decoder function for an XDR struct type"""
|
||||||
|
emit_struct_decoder(self.environment, node)
|
||||||
|
|
||||||
|
def emit_encoder(self, node: _XdrStruct) -> None:
|
||||||
|
"""Emit one encoder function for an XDR struct type"""
|
||||||
|
emit_struct_encoder(self.environment, node)
|
255
tools/net/sunrpc/xdrgen/generators/typedef.py
Normal file
255
tools/net/sunrpc/xdrgen/generators/typedef.py
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code to handle XDR typedefs"""
|
||||||
|
|
||||||
|
from jinja2 import Environment
|
||||||
|
|
||||||
|
from generators import SourceGenerator, kernel_c_type
|
||||||
|
from generators import create_jinja2_environment, get_jinja2_template
|
||||||
|
|
||||||
|
from xdr_ast import _XdrBasic, _XdrTypedef, _XdrVariableLengthString
|
||||||
|
from xdr_ast import _XdrFixedLengthOpaque, _XdrVariableLengthOpaque
|
||||||
|
from xdr_ast import _XdrFixedLengthArray, _XdrVariableLengthArray
|
||||||
|
from xdr_ast import _XdrOptionalData, _XdrVoid, _XdrDeclaration
|
||||||
|
from xdr_ast import public_apis
|
||||||
|
|
||||||
|
|
||||||
|
def emit_typedef_declaration(environment: Environment, node: _XdrDeclaration) -> None:
|
||||||
|
"""Emit a declaration pair for one XDR typedef"""
|
||||||
|
if node.name not in public_apis:
|
||||||
|
return
|
||||||
|
if isinstance(node, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "declaration", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=kernel_c_type(node.spec),
|
||||||
|
classifier=node.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "declaration", node.template)
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
elif isinstance(node, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "declaration", node.template)
|
||||||
|
print(template.render(name=node.name, size=node.size))
|
||||||
|
elif isinstance(node, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "declaration", node.template)
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
elif isinstance(node, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "declaration", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
size=node.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "declaration", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
classifier=node.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrOptionalData):
|
||||||
|
raise NotImplementedError("<optional_data> typedef not yet implemented")
|
||||||
|
elif isinstance(node, _XdrVoid):
|
||||||
|
raise NotImplementedError("<void> typedef not yet implemented")
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("typedef: type not recognized")
|
||||||
|
|
||||||
|
|
||||||
|
def emit_type_definition(environment: Environment, node: _XdrDeclaration) -> None:
|
||||||
|
"""Emit a definition for one XDR typedef"""
|
||||||
|
if isinstance(node, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "definition", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=kernel_c_type(node.spec),
|
||||||
|
classifier=node.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "definition", node.template)
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
elif isinstance(node, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "definition", node.template)
|
||||||
|
print(template.render(name=node.name, size=node.size))
|
||||||
|
elif isinstance(node, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "definition", node.template)
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
elif isinstance(node, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "definition", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
size=node.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "definition", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
classifier=node.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrOptionalData):
|
||||||
|
raise NotImplementedError("<optional_data> typedef not yet implemented")
|
||||||
|
elif isinstance(node, _XdrVoid):
|
||||||
|
raise NotImplementedError("<void> typedef not yet implemented")
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("typedef: type not recognized")
|
||||||
|
|
||||||
|
|
||||||
|
def emit_typedef_decoder(environment: Environment, node: _XdrDeclaration) -> None:
|
||||||
|
"""Emit a decoder function for one XDR typedef"""
|
||||||
|
if isinstance(node, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
maxsize=node.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
size=node.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
maxsize=node.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
size=node.size,
|
||||||
|
classifier=node.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
maxsize=node.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrOptionalData):
|
||||||
|
raise NotImplementedError("<optional_data> typedef not yet implemented")
|
||||||
|
elif isinstance(node, _XdrVoid):
|
||||||
|
raise NotImplementedError("<void> typedef not yet implemented")
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("typedef: type not recognized")
|
||||||
|
|
||||||
|
|
||||||
|
def emit_typedef_encoder(environment: Environment, node: _XdrDeclaration) -> None:
|
||||||
|
"""Emit an encoder function for one XDR typedef"""
|
||||||
|
if isinstance(node, _XdrBasic):
|
||||||
|
template = get_jinja2_template(environment, "encoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthString):
|
||||||
|
template = get_jinja2_template(environment, "encoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
maxsize=node.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrFixedLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "encoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
size=node.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthOpaque):
|
||||||
|
template = get_jinja2_template(environment, "encoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
maxsize=node.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrFixedLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "encoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
size=node.size,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrVariableLengthArray):
|
||||||
|
template = get_jinja2_template(environment, "encoder", node.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
maxsize=node.maxsize,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
elif isinstance(node, _XdrOptionalData):
|
||||||
|
raise NotImplementedError("<optional_data> typedef not yet implemented")
|
||||||
|
elif isinstance(node, _XdrVoid):
|
||||||
|
raise NotImplementedError("<void> typedef not yet implemented")
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("typedef: type not recognized")
|
||||||
|
|
||||||
|
|
||||||
|
class XdrTypedefGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for XDR typedefs"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "typedef")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _XdrTypedef) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR enum type"""
|
||||||
|
emit_typedef_declaration(self.environment, node.declaration)
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrTypedef) -> None:
|
||||||
|
"""Emit one definition for an XDR typedef"""
|
||||||
|
emit_type_definition(self.environment, node.declaration)
|
||||||
|
|
||||||
|
def emit_decoder(self, node: _XdrTypedef) -> None:
|
||||||
|
"""Emit one decoder function for an XDR typedef"""
|
||||||
|
emit_typedef_decoder(self.environment, node.declaration)
|
||||||
|
|
||||||
|
def emit_encoder(self, node: _XdrTypedef) -> None:
|
||||||
|
"""Emit one encoder function for an XDR typedef"""
|
||||||
|
emit_typedef_encoder(self.environment, node.declaration)
|
243
tools/net/sunrpc/xdrgen/generators/union.py
Normal file
243
tools/net/sunrpc/xdrgen/generators/union.py
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Generate code to handle XDR unions"""
|
||||||
|
|
||||||
|
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 _XdrDeclaration, _XdrCaseSpec, public_apis
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_declaration(environment: Environment, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR union type"""
|
||||||
|
if node.name in public_apis:
|
||||||
|
template = get_jinja2_template(environment, "declaration", "close")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_switch_spec_definition(
|
||||||
|
environment: Environment, node: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a definition for an XDR union's discriminant"""
|
||||||
|
assert isinstance(node, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "definition", "switch_spec")
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.name,
|
||||||
|
type=node.spec.type_name,
|
||||||
|
classifier=node.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_case_spec_definition(
|
||||||
|
environment: Environment, node: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a definition for an XDR union's case arm"""
|
||||||
|
if isinstance(node.arm, _XdrVoid):
|
||||||
|
return
|
||||||
|
assert isinstance(node.arm, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "definition", "case_spec")
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.arm.name,
|
||||||
|
type=node.arm.spec.type_name,
|
||||||
|
classifier=node.arm.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_definition(environment: Environment, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one XDR union definition"""
|
||||||
|
template = get_jinja2_template(environment, "definition", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
emit_union_switch_spec_definition(environment, node.discriminant)
|
||||||
|
|
||||||
|
for case in node.cases:
|
||||||
|
emit_union_case_spec_definition(environment, case)
|
||||||
|
|
||||||
|
if node.default is not None:
|
||||||
|
emit_union_case_spec_definition(environment, node.default)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "definition", "close")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_switch_spec_decoder(
|
||||||
|
environment: Environment, node: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit a decoder for an XDR union's discriminant"""
|
||||||
|
assert isinstance(node, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "decoder", "switch_spec")
|
||||||
|
print(template.render(name=node.name, type=node.spec.type_name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_case_spec_decoder(environment: Environment, node: _XdrCaseSpec) -> 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")
|
||||||
|
for case in node.values:
|
||||||
|
print(template.render(case=case))
|
||||||
|
|
||||||
|
assert isinstance(node.arm, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "decoder", node.arm.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=node.arm.name,
|
||||||
|
type=node.arm.spec.type_name,
|
||||||
|
classifier=node.arm.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "decoder", "break")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_default_spec_decoder(environment: Environment, node: _XdrUnion) -> None:
|
||||||
|
"""Emit a decoder function for an XDR union's default arm"""
|
||||||
|
default_case = node.default
|
||||||
|
|
||||||
|
# Avoid a gcc warning about a default case with boolean discriminant
|
||||||
|
if default_case is None and node.discriminant.spec.type_name == "bool":
|
||||||
|
return
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "decoder", "default_spec")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
if default_case is None or isinstance(default_case.arm, _XdrVoid):
|
||||||
|
template = get_jinja2_template(environment, "decoder", "break")
|
||||||
|
print(template.render())
|
||||||
|
return
|
||||||
|
|
||||||
|
assert isinstance(default_case.arm, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "decoder", default_case.arm.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=default_case.arm.name,
|
||||||
|
type=default_case.arm.spec.type_name,
|
||||||
|
classifier=default_case.arm.spec.c_classifier,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_decoder(environment: Environment, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one XDR union decoder"""
|
||||||
|
template = get_jinja2_template(environment, "decoder", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
emit_union_switch_spec_decoder(environment, node.discriminant)
|
||||||
|
|
||||||
|
for case in node.cases:
|
||||||
|
emit_union_case_spec_decoder(environment, case)
|
||||||
|
|
||||||
|
emit_union_default_spec_decoder(environment, node)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "decoder", "close")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_switch_spec_encoder(
|
||||||
|
environment: Environment, node: _XdrDeclaration
|
||||||
|
) -> None:
|
||||||
|
"""Emit an encoder for an XDR union's discriminant"""
|
||||||
|
assert isinstance(node, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "encoder", "switch_spec")
|
||||||
|
print(template.render(name=node.name, type=node.spec.type_name))
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_case_spec_encoder(environment: Environment, node: _XdrCaseSpec) -> 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")
|
||||||
|
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(
|
||||||
|
name=node.arm.name,
|
||||||
|
type=node.arm.spec.type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "encoder", "break")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_default_spec_encoder(environment: Environment, node: _XdrUnion) -> None:
|
||||||
|
"""Emit an encoder function for an XDR union's default arm"""
|
||||||
|
default_case = node.default
|
||||||
|
|
||||||
|
# Avoid a gcc warning about a default case with boolean discriminant
|
||||||
|
if default_case is None and node.discriminant.spec.type_name == "bool":
|
||||||
|
return
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "encoder", "default_spec")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
if default_case is None or isinstance(default_case.arm, _XdrVoid):
|
||||||
|
template = get_jinja2_template(environment, "encoder", "break")
|
||||||
|
print(template.render())
|
||||||
|
return
|
||||||
|
|
||||||
|
assert isinstance(default_case.arm, _XdrBasic)
|
||||||
|
template = get_jinja2_template(environment, "encoder", default_case.arm.template)
|
||||||
|
print(
|
||||||
|
template.render(
|
||||||
|
name=default_case.arm.name,
|
||||||
|
type=default_case.arm.spec.type_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_union_encoder(environment, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one XDR union encoder"""
|
||||||
|
template = get_jinja2_template(environment, "encoder", "open")
|
||||||
|
print(template.render(name=node.name))
|
||||||
|
|
||||||
|
emit_union_switch_spec_encoder(environment, node.discriminant)
|
||||||
|
|
||||||
|
for case in node.cases:
|
||||||
|
emit_union_case_spec_encoder(environment, case)
|
||||||
|
|
||||||
|
emit_union_default_spec_encoder(environment, node)
|
||||||
|
|
||||||
|
template = get_jinja2_template(environment, "encoder", "close")
|
||||||
|
print(template.render())
|
||||||
|
|
||||||
|
|
||||||
|
class XdrUnionGenerator(SourceGenerator):
|
||||||
|
"""Generate source code for XDR unions"""
|
||||||
|
|
||||||
|
def __init__(self, language: str, peer: str):
|
||||||
|
"""Initialize an instance of this class"""
|
||||||
|
self.environment = create_jinja2_environment(language, "union")
|
||||||
|
self.peer = peer
|
||||||
|
|
||||||
|
def emit_declaration(self, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one declaration pair for an XDR union"""
|
||||||
|
emit_union_declaration(self.environment, node)
|
||||||
|
|
||||||
|
def emit_definition(self, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one definition for an XDR union"""
|
||||||
|
emit_union_definition(self.environment, node)
|
||||||
|
|
||||||
|
def emit_decoder(self, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one decoder function for an XDR union"""
|
||||||
|
emit_union_decoder(self.environment, node)
|
||||||
|
|
||||||
|
def emit_encoder(self, node: _XdrUnion) -> None:
|
||||||
|
"""Emit one encoder function for an XDR union"""
|
||||||
|
emit_union_encoder(self.environment, node)
|
119
tools/net/sunrpc/xdrgen/grammars/xdr.lark
Normal file
119
tools/net/sunrpc/xdrgen/grammars/xdr.lark
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// A Lark grammar for the XDR specification language based on
|
||||||
|
// https://tools.ietf.org/html/rfc4506 Section 6.3
|
||||||
|
|
||||||
|
declaration : "opaque" identifier "[" value "]" -> fixed_length_opaque
|
||||||
|
| "opaque" identifier "<" [ value ] ">" -> variable_length_opaque
|
||||||
|
| "string" identifier "<" [ value ] ">" -> variable_length_string
|
||||||
|
| type_specifier identifier "[" value "]" -> fixed_length_array
|
||||||
|
| type_specifier identifier "<" [ value ] ">" -> variable_length_array
|
||||||
|
| type_specifier "*" identifier -> optional_data
|
||||||
|
| type_specifier identifier -> basic
|
||||||
|
| "void" -> void
|
||||||
|
|
||||||
|
value : decimal_constant
|
||||||
|
| hexadecimal_constant
|
||||||
|
| octal_constant
|
||||||
|
| identifier
|
||||||
|
|
||||||
|
constant : decimal_constant | hexadecimal_constant | octal_constant
|
||||||
|
|
||||||
|
type_specifier : unsigned_hyper
|
||||||
|
| unsigned_long
|
||||||
|
| unsigned_int
|
||||||
|
| hyper
|
||||||
|
| long
|
||||||
|
| int
|
||||||
|
| float
|
||||||
|
| double
|
||||||
|
| quadruple
|
||||||
|
| bool
|
||||||
|
| enum_type_spec
|
||||||
|
| struct_type_spec
|
||||||
|
| union_type_spec
|
||||||
|
| identifier
|
||||||
|
|
||||||
|
unsigned_hyper : "unsigned" "hyper"
|
||||||
|
unsigned_long : "unsigned" "long"
|
||||||
|
unsigned_int : "unsigned" "int"
|
||||||
|
hyper : "hyper"
|
||||||
|
long : "long"
|
||||||
|
int : "int"
|
||||||
|
float : "float"
|
||||||
|
double : "double"
|
||||||
|
quadruple : "quadruple"
|
||||||
|
bool : "bool"
|
||||||
|
|
||||||
|
enum_type_spec : "enum" enum_body
|
||||||
|
|
||||||
|
enum_body : "{" ( identifier "=" value ) ( "," identifier "=" value )* "}"
|
||||||
|
|
||||||
|
struct_type_spec : "struct" struct_body
|
||||||
|
|
||||||
|
struct_body : "{" ( declaration ";" )+ "}"
|
||||||
|
|
||||||
|
union_type_spec : "union" union_body
|
||||||
|
|
||||||
|
union_body : switch_spec "{" case_spec+ [ default_spec ] "}"
|
||||||
|
|
||||||
|
switch_spec : "switch" "(" declaration ")"
|
||||||
|
|
||||||
|
case_spec : ( "case" value ":" )+ declaration ";"
|
||||||
|
|
||||||
|
default_spec : "default" ":" declaration ";"
|
||||||
|
|
||||||
|
constant_def : "const" identifier "=" value ";"
|
||||||
|
|
||||||
|
type_def : "typedef" declaration ";" -> typedef
|
||||||
|
| "enum" identifier enum_body ";" -> enum
|
||||||
|
| "struct" identifier struct_body ";" -> struct
|
||||||
|
| "union" identifier union_body ";" -> union
|
||||||
|
|
||||||
|
specification : definition*
|
||||||
|
|
||||||
|
definition : constant_def
|
||||||
|
| type_def
|
||||||
|
| program_def
|
||||||
|
| pragma_def
|
||||||
|
|
||||||
|
//
|
||||||
|
// RPC program definitions not specified in RFC 4506
|
||||||
|
//
|
||||||
|
|
||||||
|
program_def : "program" identifier "{" version_def+ "}" "=" constant ";"
|
||||||
|
|
||||||
|
version_def : "version" identifier "{" procedure_def+ "}" "=" constant ";"
|
||||||
|
|
||||||
|
procedure_def : type_specifier identifier "(" type_specifier ")" "=" constant ";"
|
||||||
|
|
||||||
|
pragma_def : "pragma" directive identifier [ identifier ] ";"
|
||||||
|
|
||||||
|
directive : exclude_directive
|
||||||
|
| header_directive
|
||||||
|
| pages_directive
|
||||||
|
| public_directive
|
||||||
|
| skip_directive
|
||||||
|
|
||||||
|
exclude_directive : "exclude"
|
||||||
|
header_directive : "header"
|
||||||
|
pages_directive : "pages"
|
||||||
|
public_directive : "public"
|
||||||
|
skip_directive : "skip"
|
||||||
|
|
||||||
|
//
|
||||||
|
// XDR language primitives
|
||||||
|
//
|
||||||
|
|
||||||
|
identifier : /([a-z]|[A-Z])(_|[a-z]|[A-Z]|[0-9])*/
|
||||||
|
|
||||||
|
decimal_constant : /[\+-]?(0|[1-9][0-9]*)/
|
||||||
|
hexadecimal_constant : /0x([a-f]|[A-F]|[0-9])+/
|
||||||
|
octal_constant : /0[0-7]+/
|
||||||
|
|
||||||
|
PASSTHRU : "%" | "%" /.+/
|
||||||
|
%ignore PASSTHRU
|
||||||
|
|
||||||
|
%import common.C_COMMENT
|
||||||
|
%ignore C_COMMENT
|
||||||
|
|
||||||
|
%import common.WS
|
||||||
|
%ignore WS
|
2
tools/net/sunrpc/xdrgen/subcmds/__init__.py
Normal file
2
tools/net/sunrpc/xdrgen/subcmds/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
# Just to make sphinx-apidoc document this directory
|
76
tools/net/sunrpc/xdrgen/subcmds/declarations.py
Normal file
76
tools/net/sunrpc/xdrgen/subcmds/declarations.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Translate an XDR specification into executable code that
|
||||||
|
can be compiled for the Linux kernel."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from argparse import Namespace
|
||||||
|
from lark import logger
|
||||||
|
from lark.exceptions import UnexpectedInput
|
||||||
|
|
||||||
|
from generators.constant import XdrConstantGenerator
|
||||||
|
from generators.enum import XdrEnumGenerator
|
||||||
|
from generators.header_bottom import XdrHeaderBottomGenerator
|
||||||
|
from generators.header_top import XdrHeaderTopGenerator
|
||||||
|
from generators.pointer import XdrPointerGenerator
|
||||||
|
from generators.program import XdrProgramGenerator
|
||||||
|
from generators.typedef import XdrTypedefGenerator
|
||||||
|
from generators.struct import XdrStructGenerator
|
||||||
|
from generators.union import XdrUnionGenerator
|
||||||
|
|
||||||
|
from xdr_ast import transform_parse_tree, _RpcProgram, Specification
|
||||||
|
from xdr_ast import _XdrConstant, _XdrEnum, _XdrPointer
|
||||||
|
from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion
|
||||||
|
from xdr_parse import xdr_parser, set_xdr_annotate
|
||||||
|
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_header_declarations(
|
||||||
|
root: Specification, language: str, peer: str
|
||||||
|
) -> None:
|
||||||
|
"""Emit header declarations"""
|
||||||
|
for definition in root.definitions:
|
||||||
|
if isinstance(definition.value, _XdrEnum):
|
||||||
|
gen = XdrEnumGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrPointer):
|
||||||
|
gen = XdrPointerGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrTypedef):
|
||||||
|
gen = XdrTypedefGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrStruct):
|
||||||
|
gen = XdrStructGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrUnion):
|
||||||
|
gen = XdrUnionGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _RpcProgram):
|
||||||
|
gen = XdrProgramGenerator(language, peer)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
gen.emit_declaration(definition.value)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_parse_error(e: UnexpectedInput) -> bool:
|
||||||
|
"""Simple parse error reporting, no recovery attempted"""
|
||||||
|
print(e)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def subcmd(args: Namespace) -> int:
|
||||||
|
"""Generate definitions and declarations"""
|
||||||
|
|
||||||
|
set_xdr_annotate(args.annotate)
|
||||||
|
parser = xdr_parser()
|
||||||
|
with open(args.filename, encoding="utf-8") as f:
|
||||||
|
parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
|
||||||
|
ast = transform_parse_tree(parse_tree)
|
||||||
|
|
||||||
|
gen = XdrHeaderTopGenerator(args.language, args.peer)
|
||||||
|
gen.emit_declaration(args.filename, ast)
|
||||||
|
|
||||||
|
emit_header_declarations(ast, args.language, args.peer)
|
||||||
|
|
||||||
|
gen = XdrHeaderBottomGenerator(args.language, args.peer)
|
||||||
|
gen.emit_declaration(args.filename, ast)
|
||||||
|
|
||||||
|
return 0
|
78
tools/net/sunrpc/xdrgen/subcmds/definitions.py
Normal file
78
tools/net/sunrpc/xdrgen/subcmds/definitions.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Translate an XDR specification into executable code that
|
||||||
|
can be compiled for the Linux kernel."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from argparse import Namespace
|
||||||
|
from lark import logger
|
||||||
|
from lark.exceptions import UnexpectedInput
|
||||||
|
|
||||||
|
from generators.constant import XdrConstantGenerator
|
||||||
|
from generators.enum import XdrEnumGenerator
|
||||||
|
from generators.header_bottom import XdrHeaderBottomGenerator
|
||||||
|
from generators.header_top import XdrHeaderTopGenerator
|
||||||
|
from generators.pointer import XdrPointerGenerator
|
||||||
|
from generators.program import XdrProgramGenerator
|
||||||
|
from generators.typedef import XdrTypedefGenerator
|
||||||
|
from generators.struct import XdrStructGenerator
|
||||||
|
from generators.union import XdrUnionGenerator
|
||||||
|
|
||||||
|
from xdr_ast import transform_parse_tree, Specification
|
||||||
|
from xdr_ast import _RpcProgram, _XdrConstant, _XdrEnum, _XdrPointer
|
||||||
|
from xdr_ast import _XdrTypedef, _XdrStruct, _XdrUnion
|
||||||
|
from xdr_parse import xdr_parser, set_xdr_annotate
|
||||||
|
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_header_definitions(
|
||||||
|
root: Specification, language: str, peer: str
|
||||||
|
) -> None:
|
||||||
|
"""Emit header definitions"""
|
||||||
|
for definition in root.definitions:
|
||||||
|
if isinstance(definition.value, _XdrConstant):
|
||||||
|
gen = XdrConstantGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrEnum):
|
||||||
|
gen = XdrEnumGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrPointer):
|
||||||
|
gen = XdrPointerGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _RpcProgram):
|
||||||
|
gen = XdrProgramGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrTypedef):
|
||||||
|
gen = XdrTypedefGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrStruct):
|
||||||
|
gen = XdrStructGenerator(language, peer)
|
||||||
|
elif isinstance(definition.value, _XdrUnion):
|
||||||
|
gen = XdrUnionGenerator(language, peer)
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
gen.emit_definition(definition.value)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_parse_error(e: UnexpectedInput) -> bool:
|
||||||
|
"""Simple parse error reporting, no recovery attempted"""
|
||||||
|
print(e)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def subcmd(args: Namespace) -> int:
|
||||||
|
"""Generate definitions"""
|
||||||
|
|
||||||
|
set_xdr_annotate(args.annotate)
|
||||||
|
parser = xdr_parser()
|
||||||
|
with open(args.filename, encoding="utf-8") as f:
|
||||||
|
parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
|
||||||
|
ast = transform_parse_tree(parse_tree)
|
||||||
|
|
||||||
|
gen = XdrHeaderTopGenerator(args.language, args.peer)
|
||||||
|
gen.emit_definition(args.filename, ast)
|
||||||
|
|
||||||
|
emit_header_definitions(ast, args.language, args.peer)
|
||||||
|
|
||||||
|
gen = XdrHeaderBottomGenerator(args.language, args.peer)
|
||||||
|
gen.emit_definition(args.filename, ast)
|
||||||
|
|
||||||
|
return 0
|
33
tools/net/sunrpc/xdrgen/subcmds/lint.py
Normal file
33
tools/net/sunrpc/xdrgen/subcmds/lint.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Translate an XDR specification into executable code that
|
||||||
|
can be compiled for the Linux kernel."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from argparse import Namespace
|
||||||
|
from lark import logger
|
||||||
|
from lark.exceptions import UnexpectedInput
|
||||||
|
|
||||||
|
from xdr_parse import xdr_parser
|
||||||
|
from xdr_ast import transform_parse_tree
|
||||||
|
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_parse_error(e: UnexpectedInput) -> bool:
|
||||||
|
"""Simple parse error reporting, no recovery attempted"""
|
||||||
|
print(e)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def subcmd(args: Namespace) -> int:
|
||||||
|
"""Lexical and syntax check of an XDR specification"""
|
||||||
|
|
||||||
|
parser = xdr_parser()
|
||||||
|
with open(args.filename, encoding="utf-8") as f:
|
||||||
|
parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
|
||||||
|
transform_parse_tree(parse_tree)
|
||||||
|
|
||||||
|
return 0
|
118
tools/net/sunrpc/xdrgen/subcmds/source.py
Normal file
118
tools/net/sunrpc/xdrgen/subcmds/source.py
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# ex: set filetype=python:
|
||||||
|
|
||||||
|
"""Translate an XDR specification into executable code that
|
||||||
|
can be compiled for the Linux kernel."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from argparse import Namespace
|
||||||
|
from lark import logger
|
||||||
|
from lark.exceptions import UnexpectedInput
|
||||||
|
|
||||||
|
from generators.source_top import XdrSourceTopGenerator
|
||||||
|
from generators.enum import XdrEnumGenerator
|
||||||
|
from generators.pointer import XdrPointerGenerator
|
||||||
|
from generators.program import XdrProgramGenerator
|
||||||
|
from generators.typedef import XdrTypedefGenerator
|
||||||
|
from generators.struct import XdrStructGenerator
|
||||||
|
from generators.union import XdrUnionGenerator
|
||||||
|
|
||||||
|
from xdr_ast import transform_parse_tree, _RpcProgram, Specification
|
||||||
|
from xdr_ast import _XdrAst, _XdrEnum, _XdrPointer
|
||||||
|
from xdr_ast import _XdrStruct, _XdrTypedef, _XdrUnion
|
||||||
|
|
||||||
|
from xdr_parse import xdr_parser, set_xdr_annotate
|
||||||
|
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_source_decoder(node: _XdrAst, language: str, peer: str) -> None:
|
||||||
|
"""Emit one XDR decoder function for a source file"""
|
||||||
|
if isinstance(node, _XdrEnum):
|
||||||
|
gen = XdrEnumGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrPointer):
|
||||||
|
gen = XdrPointerGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrTypedef):
|
||||||
|
gen = XdrTypedefGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrStruct):
|
||||||
|
gen = XdrStructGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrUnion):
|
||||||
|
gen = XdrUnionGenerator(language, peer)
|
||||||
|
elif isinstance(node, _RpcProgram):
|
||||||
|
gen = XdrProgramGenerator(language, peer)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
gen.emit_decoder(node)
|
||||||
|
|
||||||
|
|
||||||
|
def emit_source_encoder(node: _XdrAst, language: str, peer: str) -> None:
|
||||||
|
"""Emit one XDR encoder function for a source file"""
|
||||||
|
if isinstance(node, _XdrEnum):
|
||||||
|
gen = XdrEnumGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrPointer):
|
||||||
|
gen = XdrPointerGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrTypedef):
|
||||||
|
gen = XdrTypedefGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrStruct):
|
||||||
|
gen = XdrStructGenerator(language, peer)
|
||||||
|
elif isinstance(node, _XdrUnion):
|
||||||
|
gen = XdrUnionGenerator(language, peer)
|
||||||
|
elif isinstance(node, _RpcProgram):
|
||||||
|
gen = XdrProgramGenerator(language, peer)
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
gen.emit_encoder(node)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_server_source(filename: str, root: Specification, language: str) -> None:
|
||||||
|
"""Generate server-side source code"""
|
||||||
|
|
||||||
|
gen = XdrSourceTopGenerator(language, "server")
|
||||||
|
gen.emit_source(filename, root)
|
||||||
|
|
||||||
|
for definition in root.definitions:
|
||||||
|
emit_source_decoder(definition.value, language, "server")
|
||||||
|
for definition in root.definitions:
|
||||||
|
emit_source_encoder(definition.value, language, "server")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_client_source(filename: str, root: Specification, language: str) -> None:
|
||||||
|
"""Generate server-side source code"""
|
||||||
|
|
||||||
|
gen = XdrSourceTopGenerator(language, "client")
|
||||||
|
gen.emit_source(filename, root)
|
||||||
|
|
||||||
|
# cel: todo: client needs XDR size macros
|
||||||
|
|
||||||
|
for definition in root.definitions:
|
||||||
|
emit_source_encoder(definition.value, language, "client")
|
||||||
|
for definition in root.definitions:
|
||||||
|
emit_source_decoder(definition.value, language, "client")
|
||||||
|
|
||||||
|
# cel: todo: client needs PROC macros
|
||||||
|
|
||||||
|
|
||||||
|
def handle_parse_error(e: UnexpectedInput) -> bool:
|
||||||
|
"""Simple parse error reporting, no recovery attempted"""
|
||||||
|
print(e)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def subcmd(args: Namespace) -> int:
|
||||||
|
"""Generate encoder and decoder functions"""
|
||||||
|
|
||||||
|
set_xdr_annotate(args.annotate)
|
||||||
|
parser = xdr_parser()
|
||||||
|
with open(args.filename, encoding="utf-8") as f:
|
||||||
|
parse_tree = parser.parse(f.read(), on_error=handle_parse_error)
|
||||||
|
ast = transform_parse_tree(parse_tree)
|
||||||
|
match args.peer:
|
||||||
|
case "server":
|
||||||
|
generate_server_source(args.filename, ast, args.language)
|
||||||
|
case "client":
|
||||||
|
generate_client_source(args.filename, ast, args.language)
|
||||||
|
case _:
|
||||||
|
print("Code generation for", args.peer, "is not yet supported")
|
||||||
|
|
||||||
|
return 0
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
enum { {{ name }} = {{ value }} };
|
|
@ -0,0 +1,4 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, enum {{ name }} *ptr);
|
||||||
|
bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, enum {{ name }} value);
|
19
tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2
Normal file
19
tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* enum {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
{% if name in public_apis %}
|
||||||
|
bool
|
||||||
|
{% else %}
|
||||||
|
static bool __maybe_unused
|
||||||
|
{% endif %}
|
||||||
|
xdrgen_decode_{{ name }}(struct xdr_stream *xdr, enum {{ name }} *ptr)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
if (xdr_stream_decode_u32(xdr, &val) < 0)
|
||||||
|
return false;
|
||||||
|
*ptr = val;
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
};
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{{ name }} = {{ value }},
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
enum {{ name }} {
|
14
tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2
Normal file
14
tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* enum {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
{% if name in public_apis %}
|
||||||
|
bool
|
||||||
|
{% else %}
|
||||||
|
static bool __maybe_unused
|
||||||
|
{% endif %}
|
||||||
|
xdrgen_encode_{{ name }}(struct xdr_stream *xdr, enum {{ name }} value)
|
||||||
|
{
|
||||||
|
return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
#endif /* _LINUX_XDRGEN_{{ infix }}_DECL_H */
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
#endif /* _LINUX_XDRGEN_{{ infix }}_DEF_H */
|
|
@ -0,0 +1,14 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Generated by xdrgen. Manual edits will be lost. */
|
||||||
|
/* XDR specification file: {{ filename }} */
|
||||||
|
/* XDR specification modification time: {{ mtime }} */
|
||||||
|
|
||||||
|
#ifndef _LINUX_XDRGEN_{{ infix }}_DECL_H
|
||||||
|
#define _LINUX_XDRGEN_{{ infix }}_DECL_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include <linux/sunrpc/xdr.h>
|
||||||
|
#include <linux/sunrpc/xdrgen/_defs.h>
|
||||||
|
#include <linux/sunrpc/xdrgen/_builtins.h>
|
||||||
|
#include <linux/sunrpc/xdrgen/{{ infix.lower() }}.h>
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Generated by xdrgen. Manual edits will be lost. */
|
||||||
|
/* XDR specification file: {{ filename }} */
|
||||||
|
/* XDR specification modification time: {{ mtime }} */
|
||||||
|
|
||||||
|
#ifndef _LINUX_XDRGEN_{{ infix }}_DEF_H
|
||||||
|
#define _LINUX_XDRGEN_{{ infix }}_DEF_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/sunrpc/xdrgen/_defs.h>
|
|
@ -0,0 +1,4 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
|
||||||
|
bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value);
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (basic) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
return true;
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length array) */
|
||||||
|
{% endif %}
|
||||||
|
for (u32 i = 0; i < {{ size }}; i++) {
|
||||||
|
if (xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.items[i]) < 0)
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (xdr_stream_decode_opaque_fixed(xdr, ptr->{{ name }}, {{ size }}) < 0)
|
||||||
|
return false;
|
22
tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/open.j2
Normal file
22
tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/open.j2
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* pointer {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
{% if name in public_apis %}
|
||||||
|
bool
|
||||||
|
{% else %}
|
||||||
|
static bool __maybe_unused
|
||||||
|
{% endif %}
|
||||||
|
xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr)
|
||||||
|
{
|
||||||
|
bool opted;
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* opted */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_bool(xdr, &opted))
|
||||||
|
return false;
|
||||||
|
if (!opted)
|
||||||
|
return true;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (optional data) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_{{ type }}(xdr, ptr->{{ name }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,13 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length array) */
|
||||||
|
{% endif %}
|
||||||
|
if (xdr_stream_decode_u32(xdr, &ptr->{{ name }}.count) != XDR_UNIT)
|
||||||
|
return false;
|
||||||
|
{% if maxsize != "0" %}
|
||||||
|
if (ptr->{{ name }}.count > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
{% endif %}
|
||||||
|
for (u32 i = 0; i < ptr->{{ name }}.count; i++)
|
||||||
|
if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.element[i]))
|
||||||
|
return false;
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_opaque(xdr, (opaque *)ptr, {{ maxsize }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length string) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_string(xdr, (string *)ptr, {{ maxsize }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (basic) */
|
||||||
|
{% endif %}
|
||||||
|
{{ classifier }}{{ type }} {{ name }};
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (fixed-length array) */
|
||||||
|
{% endif %}
|
||||||
|
{{ type }} {{ name }}[{{ size }}];
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (fixed-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
u8 {{ name }}[{{ size }}];
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* pointer {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
struct {{ name }} {
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (optional data) */
|
||||||
|
{% endif %}
|
||||||
|
{{ classifier }}{{ type }} *{{ name }};
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (variable-length array) */
|
||||||
|
{% endif %}
|
||||||
|
struct {
|
||||||
|
u32 count;
|
||||||
|
{{ classifier }}{{ type }} *element;
|
||||||
|
} {{ name }};
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (variable-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
opaque {{ name }};
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (variable-length string) */
|
||||||
|
{% endif %}
|
||||||
|
string {{ name }};
|
10
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/basic.j2
Normal file
10
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/basic.j2
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (basic) */
|
||||||
|
{% endif %}
|
||||||
|
{% if type in pass_by_reference %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}))
|
||||||
|
{% else %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
return true;
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length array) */
|
||||||
|
{% endif %}
|
||||||
|
for (u32 i = 0; i < {{ size }}; i++) {
|
||||||
|
{% if type in pass_by_reference %}
|
||||||
|
if (xdrgen_encode_{{ type }}(xdr, &value->items[i]) < 0)
|
||||||
|
{% else %}
|
||||||
|
if (xdrgen_encode_{{ type }}(xdr, value->items[i]) < 0)
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (xdr_stream_encode_opaque_fixed(xdr, value->{{ name }}, {{ size }}) < 0)
|
||||||
|
return false;
|
20
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/open.j2
Normal file
20
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/open.j2
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* pointer {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
{% if name in public_apis %}
|
||||||
|
bool
|
||||||
|
{% else %}
|
||||||
|
static bool __maybe_unused
|
||||||
|
{% endif %}
|
||||||
|
xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value)
|
||||||
|
{
|
||||||
|
{% if annotate %}
|
||||||
|
/* opted */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_encode_bool(xdr, value != NULL))
|
||||||
|
return false;
|
||||||
|
if (!value)
|
||||||
|
return true;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (optional data) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,15 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length array) */
|
||||||
|
{% endif %}
|
||||||
|
if (value->{{ name }}.count > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
if (xdr_stream_encode_u32(xdr, value->{{ name }}.count) != XDR_UNIT)
|
||||||
|
return false;
|
||||||
|
for (u32 i = 0; i < value->{{ name }}.count; i++)
|
||||||
|
{% if type in pass_by_reference %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}.element[i]))
|
||||||
|
{% else %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}.element[i]))
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (value->{{ name }}.len > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
|
||||||
|
return false;
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length string) */
|
||||||
|
{% endif %}
|
||||||
|
if (value->{{ name }}.len > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
|
||||||
|
return false;
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
bool {{ program }}_svc_decode_{{ argument }}(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
bool {{ program }}_svc_encode_{{ result }}(struct svc_rqst *rqstp, struct xdr_stream *xdr);
|
|
@ -0,0 +1,21 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {{ program }}_svc_decode_{{ argument }} - Decode a {{ argument }} argument
|
||||||
|
* @rqstp: RPC transaction context
|
||||||
|
* @xdr: source XDR data stream
|
||||||
|
*
|
||||||
|
* Return values:
|
||||||
|
* %true: procedure arguments decoded successfully
|
||||||
|
* %false: decode failed
|
||||||
|
*/
|
||||||
|
bool {{ program }}_svc_decode_{{ argument }}(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||||
|
{
|
||||||
|
{% if argument == 'void' %}
|
||||||
|
return xdrgen_decode_void(xdr);
|
||||||
|
{% else %}
|
||||||
|
struct {{ argument }} *argp = rqstp->rq_argp;
|
||||||
|
|
||||||
|
return xdrgen_decode_{{ argument }}(xdr, argp);
|
||||||
|
{% endif %}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* Decode {{ result }} results */
|
||||||
|
{% endif %}
|
||||||
|
static int {{ program }}_xdr_dec_{{ result }}(struct rpc_rqst *req,
|
||||||
|
struct xdr_stream *xdr, void *data)
|
||||||
|
{
|
||||||
|
{% if result == 'void' %}
|
||||||
|
xdrgen_decode_void(xdr);
|
||||||
|
{% else %}
|
||||||
|
struct {{ result }} *result = data;
|
||||||
|
|
||||||
|
if (!xdrgen_decode_{{ result }}(xdr, result))
|
||||||
|
return -EIO;
|
||||||
|
if (result->stat != nfs_ok) {
|
||||||
|
trace_nfs_xdr_status(xdr, (int)result->stat);
|
||||||
|
return {{ program }}_stat_to_errno(result->stat);
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
};
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* procedure numbers for {{ program }} */
|
||||||
|
{% endif %}
|
||||||
|
enum {
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{{ name }} = {{ value }},
|
|
@ -0,0 +1,16 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{%if annotate %}
|
||||||
|
/* Encode {{ argument }} arguments */
|
||||||
|
{% endif %}
|
||||||
|
static void {{ program }}_xdr_enc_{{ argument }}(struct rpc_rqst *req,
|
||||||
|
struct xdr_stream *xdr, const void *data)
|
||||||
|
{
|
||||||
|
{% if argument == 'void' %}
|
||||||
|
xdrgen_encode_void(xdr);
|
||||||
|
{% else %}
|
||||||
|
const struct {{ argument }} *args = data;
|
||||||
|
|
||||||
|
xdrgen_encode_{{ argument }}(xdr, args);
|
||||||
|
{% endif %}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {{ program }}_svc_encode_{{ result }} - Encode a {{ result }} result
|
||||||
|
* @rqstp: RPC transaction context
|
||||||
|
* @xdr: target XDR data stream
|
||||||
|
*
|
||||||
|
* Return values:
|
||||||
|
* %true: procedure results encoded successfully
|
||||||
|
* %false: encode failed
|
||||||
|
*/
|
||||||
|
bool {{ program }}_svc_encode_{{ result }}(struct svc_rqst *rqstp, struct xdr_stream *xdr)
|
||||||
|
{
|
||||||
|
{% if result == 'void' %}
|
||||||
|
return xdrgen_encode_void(xdr);
|
||||||
|
{% else %}
|
||||||
|
struct {{ result }} *resp = rqstp->rq_resp;
|
||||||
|
|
||||||
|
return xdrgen_encode_{{ result }}(xdr, resp);
|
||||||
|
{% endif %}
|
||||||
|
}
|
8
tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2
Normal file
8
tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Generated by xdrgen. Manual edits will be lost.
|
||||||
|
// XDR specification file: {{ filename }}
|
||||||
|
// XDR specification modification time: {{ mtime }}
|
||||||
|
|
||||||
|
#include <linux/sunrpc/xprt.h>
|
||||||
|
|
||||||
|
#include "{{ program }}xdr_gen.h"
|
8
tools/net/sunrpc/xdrgen/templates/C/source_top/server.j2
Normal file
8
tools/net/sunrpc/xdrgen/templates/C/source_top/server.j2
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
// Generated by xdrgen. Manual edits will be lost.
|
||||||
|
// XDR specification file: {{ filename }}
|
||||||
|
// XDR specification modification time: {{ mtime }}
|
||||||
|
|
||||||
|
#include <linux/sunrpc/svc.h>
|
||||||
|
|
||||||
|
#include "{{ program }}xdr_gen.h"
|
|
@ -0,0 +1,4 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
bool xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr);
|
||||||
|
bool xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value);
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (basic) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
return true;
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length array) */
|
||||||
|
{% endif %}
|
||||||
|
for (u32 i = 0; i < {{ size }}; i++) {
|
||||||
|
if (xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.items[i]) < 0)
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (xdr_stream_decode_opaque_fixed(xdr, ptr->{{ name }}, {{ size }}) < 0)
|
||||||
|
return false;
|
12
tools/net/sunrpc/xdrgen/templates/C/struct/decoder/open.j2
Normal file
12
tools/net/sunrpc/xdrgen/templates/C/struct/decoder/open.j2
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* struct {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
{% if name in public_apis %}
|
||||||
|
bool
|
||||||
|
{% else %}
|
||||||
|
static bool __maybe_unused
|
||||||
|
{% endif %}
|
||||||
|
xdrgen_decode_{{ name }}(struct xdr_stream *xdr, struct {{ name }} *ptr)
|
||||||
|
{
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (optional data) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_{{ type }}(xdr, ptr->{{ name }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,13 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length array) */
|
||||||
|
{% endif %}
|
||||||
|
if (xdr_stream_decode_u32(xdr, &ptr->{{ name }}.count) != XDR_UNIT)
|
||||||
|
return false;
|
||||||
|
{% if maxsize != "0" %}
|
||||||
|
if (ptr->{{ name }}.count > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
{% endif %}
|
||||||
|
for (u32 i = 0; i < ptr->{{ name }}.count; i++)
|
||||||
|
if (!xdrgen_decode_{{ type }}(xdr, &ptr->{{ name }}.element[i]))
|
||||||
|
return false;
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_opaque(xdr, (opaque *)ptr, {{ maxsize }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length string) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_decode_string(xdr, (string *)ptr, {{ maxsize }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (basic) */
|
||||||
|
{% endif %}
|
||||||
|
{{ classifier }}{{ type }} {{ name }};
|
|
@ -0,0 +1,2 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
};
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (fixed-length array) */
|
||||||
|
{% endif %}
|
||||||
|
{{ type }} {{ name }}[{{ size }}];
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (fixed-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
u8 {{ name }}[{{ size }}];
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* struct {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
struct {{ name }} {
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (optional data) */
|
||||||
|
{% endif %}
|
||||||
|
{{ classifier }}{{ type }} *{{ name }};
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (variable-length array) */
|
||||||
|
{% endif %}
|
||||||
|
struct {
|
||||||
|
u32 count;
|
||||||
|
{{ classifier }}{{ type }} *element;
|
||||||
|
} {{ name }};
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (variable-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
opaque {{ name }};
|
|
@ -0,0 +1,5 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* (variable-length string) */
|
||||||
|
{% endif %}
|
||||||
|
string {{ name }};
|
10
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/basic.j2
Normal file
10
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/basic.j2
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (basic) */
|
||||||
|
{% endif %}
|
||||||
|
{% if type in pass_by_reference %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}))
|
||||||
|
{% else %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
|
@ -0,0 +1,3 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
return true;
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length array) */
|
||||||
|
{% endif %}
|
||||||
|
for (u32 i = 0; i < {{ size }}; i++) {
|
||||||
|
{% if type in pass_by_reference %}
|
||||||
|
if (xdrgen_encode_{{ type }}(xdr, &value->items[i]) < 0)
|
||||||
|
{% else %}
|
||||||
|
if (xdrgen_encode_{{ type }}(xdr, value->items[i]) < 0)
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (fixed-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (xdr_stream_encode_opaque_fixed(xdr, value->{{ name }}, {{ size }}) < 0)
|
||||||
|
return false;
|
12
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/open.j2
Normal file
12
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/open.j2
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
|
||||||
|
{% if annotate %}
|
||||||
|
/* struct {{ name }} */
|
||||||
|
{% endif %}
|
||||||
|
{% if name in public_apis %}
|
||||||
|
bool
|
||||||
|
{% else %}
|
||||||
|
static bool __maybe_unused
|
||||||
|
{% endif %}
|
||||||
|
xdrgen_encode_{{ name }}(struct xdr_stream *xdr, const struct {{ name }} *value)
|
||||||
|
{
|
|
@ -0,0 +1,6 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (optional data) */
|
||||||
|
{% endif %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}))
|
||||||
|
return false;
|
|
@ -0,0 +1,15 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length array) */
|
||||||
|
{% endif %}
|
||||||
|
if (value->{{ name }}.count > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
if (xdr_stream_encode_u32(xdr, value->{{ name }}.count) != XDR_UNIT)
|
||||||
|
return false;
|
||||||
|
for (u32 i = 0; i < value->{{ name }}.count; i++)
|
||||||
|
{% if type in pass_by_reference %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, &value->{{ name }}.element[i]))
|
||||||
|
{% else %}
|
||||||
|
if (!xdrgen_encode_{{ type }}(xdr, value->{{ name }}.element[i]))
|
||||||
|
{% endif %}
|
||||||
|
return false;
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length opaque) */
|
||||||
|
{% endif %}
|
||||||
|
if (value->{{ name }}.len > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
|
||||||
|
return false;
|
|
@ -0,0 +1,8 @@
|
||||||
|
{# SPDX-License-Identifier: GPL-2.0 #}
|
||||||
|
{% if annotate %}
|
||||||
|
/* member {{ name }} (variable-length string) */
|
||||||
|
{% endif %}
|
||||||
|
if (value->{{ name }}.len > {{ maxsize }})
|
||||||
|
return false;
|
||||||
|
if (xdr_stream_encode_opaque(xdr, value->{{ name }}.data, value->{{ name }}.len) < 0)
|
||||||
|
return false;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue