.*.o.d
*.so
lib/libkafs_utils.*
+lib/afs_xg.*
+rxgen/__pycache__/
+rxgen/parsetab.py
CFLAGS := -g -Wall -Wformat -fpic -O2 -Wno-pointer-arith
-LIB_SRCS := rxrpc_xdr.C af_rxrpc.C rxrpc_core.C
+RXGEN := ../rxgen/rxgen.py
+RPC_HEADERS := $(wildcard ../rpc-api/*.h)
+RPC_DEFS := $(filter-out %test.xg, $(sort $(wildcard ../rpc-api/*.xg)))
+#RPC_HEADERS := ../rpc-api/test.h
+#RPC_DEFS := ../rpc-api/test.xg
+
+LIB_SRCS := afs_xg.C rxrpc_xdr.C af_rxrpc.C rxrpc_core.C
LIB_OBJS := $(patsubst %.C,%.o,$(LIB_SRCS))
%.o: %.C
libkafs_utils.a: $(LIB_OBJS)
$(AR) rcs -o $@ $(LIB_OBJS)
+afs_xg.o: afs_xg.C afs_xg.H rxrpc.H
+
+afs_xg.C afs_xg.H: $(RPC_HEADERS) $(RPC_DEFS) $(wildcard ../rxgen/*.py) Makefile
+ $(RXGEN) $(RPC_HEADERS) $(RPC_DEFS)
+
DEPS := $(wildcard .*.o.d)
ifneq ($(DEPS),)
include $(DEPS)
endif
clean:
- $(RM) *~ *.o *.so *.a $(DEPS)
+ $(RM) *~ afs_xg.[CH] *.o *.so *.a $(DEPS)
--- /dev/null
+
+clean:
+ $(RM) -r *~ parsetab.py __pycache__/
--- /dev/null
+#!/usr/bin/python3
+#
+# Emit C structure
+# -*- coding: utf-8 -*-
+
+__copyright__ = """
+Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+Written by David Howells (dhowells@redhat.com)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+from rxgen_bits import *
+
+###############################################################################
+#
+# Emit a structure member definition list
+#
+###############################################################################
+def emit_struct_member_list(o, struct, members):
+ for m in members:
+ o.where(struct.name + "::" + m.name)
+ if m.is_single():
+ if m.is_string():
+ o.rxhdr("\t", m.ty.c_name, "\t", m.name, ";\n")
+ elif m.is_opaque():
+ o.rxhdr("\t", m.ty.c_name, "\t", m.name, ";\n")
+ else:
+ o.rxhdr("\t", m.ty.c_name, "\t", m.name, ";\n")
+ elif m.is_int_array() or m.is_struct_array():
+ o.rxhdr("\t", m.ty.c_name, "\t", m.name, "[", m.ty.dim.name, "];\n")
+ elif m.is_bulk():
+ o.rxhdr("\tstd::vector<", m.ty.c_name, "> ", m.name, ";\n")
+ else:
+ raise RuntimeError("Unsupported type '" + str(m.ty) + "'\n")
+
+###############################################################################
+#
+# Emit a C union definition for this type
+#
+###############################################################################
+def emit_union_decl(o, struct):
+ selector = struct.selector_name
+ want_i = False
+
+ #
+ # Write out a C structure definition for this type
+ #
+ o.rxhdr("struct ", struct.name, " {\n")
+ o.rxhdr("\t", struct.selector_type, " ", selector, ";\n")
+
+ for case in struct.members:
+ for m in case.members:
+ if m.is_array():
+ want_i = True
+ break
+ o.rxhdr("\t\t/* case ", case.tag, " */\n")
+ emit_struct_member_list(o, struct, case.members)
+
+ o.rxhdr("};\n")
+
+###############################################################################
+#
+# Emit a C structure definition for this type
+#
+###############################################################################
+def emit_struct_decl(o, struct):
+ o.rxhdr("\n")
+ if struct.is_union():
+ emit_union_decl(o, struct)
+ else:
+ o.rxhdr("struct ", struct.name, " {\n")
+ emit_struct_member_list(o, struct, struct.members)
+ o.rxhdr("};\n")
+
+###############################################################################
+#
+# Emit code to calculate the size of a member list
+#
+###############################################################################
+def emit_struct_calc_members(o, members):
+ for m in members:
+ if m.is_single_int32():
+ o.rxsrc("\trxrpc::reserve(resv);\t// ", m.name, "\n")
+ elif m.is_single_int64():
+ o.rxsrc("\trxrpc::reserve_u64(resv);\t// ", m.name, "\n")
+ elif m.is_single_struct():
+ o.rxsrc("\treserve_", m.ty.name, "(resv, p.", m.name, ");\n")
+ elif m.is_single_string():
+ o.rxsrc("\trxrpc::reserve_string(resv, p.",
+ m.name, ", ", m.what_max_obj(), ");\n");
+ elif m.is_single_opaque():
+ o.rxsrc("\trxrpc::reserve_opaque(resv, p.",
+ m.name, ", ", m.what_max_obj(), ");\n");
+ elif m.is_array():
+ if m.is_int32_array():
+ o.rxsrc("\trxrpc::reserve_a32(resv, ", m.dim.name, ");\t// ", m.name, "[]\n")
+ elif m.is_int64_array():
+ o.rxsrc("\trxrpc::reserve_a64(resv, ", m.dim.name, ");\t// ", m.name, "[]\n")
+ elif m.is_struct_array():
+ o.rxsrc("\tfor (size_t i = 0; i < ", m.dim.name, "; i++)\n")
+ o.rxsrc("\t\treserve_", m.ty.name, "(resv, p.", m.name, "[i]);\n")
+ else:
+ raise RuntimeError("No enc-calc for array type '" + str(m.ty) + "'")
+ elif m.is_bulk():
+ o.rxsrc("\trxrpc::reserve(resv);\t// ", m.name, "__nr\n")
+ if m.is_int32():
+ o.rxsrc("\trxrpc::reserve_a32(resv, p.", m.name, ".size());\n")
+ else:
+ o.rxsrc("\tfor (size_t i = 0; i < p.", m.name, ".size(); i++)\n")
+ if m.is_string():
+ o.rxsrc("\t\trxrpc::reserve_string(resv, p.",
+ m.name, "[i], ", m.what_max_obj(), ");\n");
+ elif m.is_opaque():
+ o.rxsrc("\t\trxrpc::reserve_opaque(resv, p.",
+ m.name, "[i], ", m.what_max_obj(), ");\n");
+ else:
+ o.rxsrc("\t\treserve_", m.ty.name, "(resv, p.", m.name, "[i]);\n")
+ elif str(m.ty) == "opr_uuid":
+ o.rxsrc("\t\trxrpc::reserve_", m.ty.name, "(resv, p.", m.name, ");\n")
+ else:
+ raise RuntimeError("No enc-calc for type '" + str(m.ty) + "'")
+
+###############################################################################
+#
+# Emit a structure member list encoder
+#
+###############################################################################
+def emit_struct_encode_members(o, struct, members):
+ for m in members:
+ o.where(struct.name + "::" + m.name)
+ if m.is_single_int32():
+ o.rxsrc("\trxrpc::enc (z_buf, p.", m.name, ");\n")
+ elif m.is_single_int64():
+ o.rxsrc("\trxrpc::enc_u64 (z_buf, p.", m.name, ");\n")
+ elif m.is_single_struct():
+ o.rxsrc("\tencode_", m.ty.name, "(z_buf, p.", m.name, ");\n")
+ elif m.is_array():
+ o.rxsrc("\tfor (size_t i = 0; i < ", m.dim.name, "; i++)\n")
+ if m.is_int32_array():
+ o.rxsrc("\t\trxrpc::enc (z_buf, p.", m.name, "[i]);\n")
+ elif m.is_int64_array():
+ o.rxsrc("\t\trxrpc::enc_u64 (z_buf, p.", m.name, "[i]);\n")
+ elif m.is_struct_array():
+ o.rxsrc("\t\tencode_", m.ty.name, "(z_buf, p.", m.name, "[i]);\n")
+ else:
+ raise RuntimeError("No encoding for array type '" + str(m.ty) + "'")
+ elif m.is_single_string():
+ o.rxsrc("\trxrpc::enc_string(z_buf, p.", m.name, ", ",
+ m.what_max_obj(), ");\n")
+ elif m.is_single_opaque():
+ o.rxsrc("\trxrpc::enc_opaque(z_buf, p.", m.name, ", ", m.what_max_obj(), ");\n")
+ elif m.is_single_uuid():
+ o.rxsrc("\trxrpc::enc_uuid(z_buf, p.", m.name, ");\n")
+ elif m.is_bulk():
+ o.rxsrc("\trxrpc::enc (z_buf, p.", m.name, ".size());\n")
+ o.rxsrc("\tfor (size_t i = 0; i < p.", m.name, ".size(); i++)\n")
+ if m.is_int32():
+ o.rxsrc("\t\trxrpc::enc(z_buf, p.", m.name, "[i]);\n")
+ elif m.is_string():
+ o.rxsrc("\t\trxrpc::enc_string(z_buf, p.", m.name, "[i], ",
+ m.what_max_obj(), ");\n")
+ elif m.is_opaque():
+ o.rxsrc("\t\trxrpc::enc_opaque(z_buf, p.", m.name, "[i], ",
+ m.what_max_obj(), ");\n")
+ else:
+ o.rxsrc("\t\tencode_", m.ty.name, "(z_buf, p.", m.name, "[i]);\n")
+ else:
+ raise RuntimeError("No encoding for type '" + str(m.ty) + "'")
+
+###############################################################################
+#
+# Emit a structure member list decoder
+#
+###############################################################################
+def emit_struct_decode_members(o, struct, members):
+ for m in members:
+ o.where(struct.name + "::" + m.name)
+ if m.is_single_int32():
+ o.rxsrc("\tp.", m.name, "\t= rxrpc::dec(z_rxq);\n")
+ elif m.is_single_int64():
+ o.rxsrc("\tp.", m.name, "\t= rxrpc::dec_u64(z_rxq);\n")
+ elif m.is_single_struct():
+ o.rxsrc("\tdecode_", m.ty.name, "(z_rxq, p.", m.name, ");\n")
+ elif m.is_array():
+ o.rxsrc("\tfor (size_t i = 0; i < ", m.dim.name, "; i++)\n")
+ if m.is_int32_array():
+ o.rxsrc("\t\tp.", m.name, "[i] = rxrpc::dec(z_rxq);\n")
+ elif m.is_int64_array():
+ o.rxsrc("\t\tp.", m.name, "[i] = rxrpc::dec_u64(z_rxq);\n")
+ elif m.is_struct_array():
+ o.rxsrc("\t\tdecode_", m.ty.name, "(z_rxq, p.", m.name, "[i]);\n")
+ else:
+ raise RuntimeError("No decoding for array type '" + str(m.ty) + "'")
+ elif m.is_single_string():
+ o.rxsrc("\trxrpc::dec_string(z_rxq, p.", m.name)
+ if m.max_obj != None:
+ o.rxsrc(", ", m.max_obj);
+ o.rxsrc(");\n")
+ elif m.is_single_opaque():
+ o.rxsrc("\trxrpc::dec_opaque(z_rxq, p.", m.name)
+ if m.max_obj != None:
+ o.rxsrc(", ", m.max_obj);
+ o.rxsrc(");\n")
+ elif m.is_bulk():
+ o.rxsrc("\tsize_t ", m.name, "__nr = rxrpc::dec(z_rxq);\n")
+ o.rxsrc("\tif (", m.name, "__nr > 0) {\n")
+ o.rxsrc("\t\tp.", m.name, ".resize(", m.name, "__nr);\n")
+ o.rxsrc("\t\tfor (size_t i = 0; i < ", m.name, "__nr; i++)\n")
+ if m.is_int32():
+ o.rxsrc("\t\t\tp.", m.name, "[i]\t= rxrpc::dec(z_rxq);\n")
+ elif m.is_string():
+ o.rxsrc("\t\t\trxrpc::dec_string(z_rxq, p.", m.name)
+ if m.max_obj != None:
+ o.rxsrc("[i], ", m.max_obj);
+ o.rxsrc(");\n")
+ elif m.is_opaque():
+ o.rxsrc("\t\t\trxrpc::dec_opaque(z_rxq, p.", m.name)
+ if m.max_obj != None:
+ o.rxsrc("[i], ", m.max_obj);
+ o.rxsrc(");\n")
+ else:
+ o.rxsrc("\t\t\tdecode_", m.ty.name, "(z_rxq, p.", m.name, "[i]);\n")
+ o.rxsrc("\t}\n")
+ elif str(m.ty) == "opr_uuid":
+ o.rxsrc("\tz_rxq.read(&p.", m.name, ", 16);\n")
+ else:
+ raise RuntimeError("No decoding for type '" + str(m.ty) + "'")
+
+###############################################################################
+#
+# Emit union encoders and decoders
+#
+###############################################################################
+def emit_union_encdec(o, struct):
+ selector = struct.selector_name
+ want_i = False
+
+ #
+ # Write a size calculation function
+ #
+ o.rxsrc("\n")
+ o.rxsrc("void reserve_", struct.name,
+ "(rxrpc::Resv &resv, const ", struct.c_name, " &p)\n")
+ o.rxsrc("{\n")
+ o.rxsrc("\trxrpc::reserve(resv); // selector - p.", selector, "\n")
+ o.rxsrc("\tswitch (p.", selector, ") {\n")
+ for case in struct.members:
+ for m in case.members:
+ if m.is_array() and m.is_struct_array():
+ o.rxsrc("\tint i;\n\n")
+ break
+ for case in struct.members:
+ o.rxsrc("\tcase ", case.tag, ":\n")
+ emit_struct_calc_members(o, case.members)
+ o.rxsrc("\tbreak;\n")
+ o.rxsrc("}\n")
+ o.rxsrc("}\n")
+
+ #
+ # Write an encoding function
+ #
+ o.rxsrc("\n")
+ o.rxsrc("void encode_", struct.name,
+ "(rxrpc::Enc_buffer *z_buf, const ", struct.c_name, " &p)\n")
+ o.rxsrc("{\n")
+
+ if want_i:
+ o.rxsrc("\tint i;\n\n")
+
+ o.rxsrc("\trxrpc::enc(z_buf, p.", selector, ");\n")
+ o.rxsrc("\tswitch (p.", selector, ") {\n")
+ for case in struct.members:
+ o.rxsrc("\tcase ", case.tag, ":\n")
+ emit_struct_encode_members(o, struct, case.members)
+ o.rxsrc("\tbreak;\n")
+ o.rxsrc("\t}\n")
+ o.rxsrc("}\n")
+
+ #
+ # Write a decoding function
+ #
+ o.rxsrc("\n")
+ #o.rxsrc("static __attribute__((unused))\n")
+ o.rxsrc("void decode_", struct.name,
+ "(rxrpc::Rx_queue &z_rxq, ", struct.c_name, " &p)\n")
+ o.rxsrc("{\n")
+
+ if want_i:
+ o.rxsrc("\tint i;\n\n")
+
+ o.rxsrc("\tp.", selector, " = rxrpc::dec(z_rxq);\n")
+ o.rxsrc("\tswitch (p.", selector, ") {\n")
+ for case in struct.members:
+ o.rxsrc("\tcase ", case.tag, ":\n")
+ emit_struct_decode_members(o, struct, case.members)
+ o.rxsrc("\tbreak;\n")
+ o.rxsrc("}\n")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit structure encoders and decoders
+#
+###############################################################################
+def emit_struct_encdec(o, struct):
+ if struct.is_union():
+ emit_union_encdec(o, struct)
+ return
+
+ #
+ # Write a size calculation function
+ #
+ o.rxsrc("\n")
+ o.rxsrc("void reserve_", struct.name,
+ "(rxrpc::Resv &resv, const struct ", struct.name, " &p)\n")
+ o.rxsrc("{\n")
+ emit_struct_calc_members(o, struct.members)
+ o.rxsrc("}\n")
+ o.rxsrc("\n")
+
+ #
+ # Write an encoding function
+ #
+ o.rxsrc("\n")
+ o.rxsrc("void encode_", struct.name,
+ "(rxrpc::Enc_buffer *z_buf, const struct ", struct.name, " &p)\n")
+ o.rxsrc("{\n")
+
+ emit_struct_encode_members(o, struct, struct.members)
+ o.rxsrc("}\n")
+
+ #
+ # Write a decoding function
+ #
+ o.rxsrc("\n")
+ o.rxsrc("void decode_", struct.name,
+ "(rxrpc::Rx_queue &z_rxq, struct ", struct.name, " &p)\n")
+ o.rxsrc("{\n")
+
+ emit_struct_decode_members(o, struct, struct.members)
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit C func definitions for enc/dec routines
+#
+###############################################################################
+def emit_struct_encdec_decl(o, struct):
+ o.rxhdr("extern void reserve_", struct.name,
+ "(rxrpc::Resv &resv, const struct ", struct.name, " &p);\n")
+ o.rxhdr("extern void encode_", struct.name,
+ "(rxrpc::Enc_buffer *z_buf, const struct ", struct.name, " &p);\n")
+ o.rxhdr("extern void decode_", struct.name,
+ "(rxrpc::Rx_queue &z_rxq, struct ", struct.name, " &p);\n")
--- /dev/null
+#!/usr/bin/python3
+#
+# Emit C synchronous functions
+# -*- coding: utf-8 -*-
+
+__copyright__ = """
+Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+Written by David Howells (dhowells@redhat.com)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+from rxgen_bits import *
+
+###############################################################################
+#
+# Calculate the C function prototypes
+#
+###############################################################################
+def emit_func_prototype(o, func):
+ # Function prototype lists (we add commas and the closing bracket later)
+ send_request_protos = list()
+ send_response_protos = list()
+
+ for p in func.params:
+ o.where(func.name + ":" + p.name)
+ s_req = list()
+ r_req = list()
+ s_rsp = list()
+ r_rsp = list()
+
+ t = p.ty.c_name
+ if p.is_array():
+ raise RuntimeError("Array arg not supported")
+ elif p.is_bulk():
+ s_req.append("const std::vector<" + p.ty.c_name + "> &" + p.name)
+ r_req.append("const std::vector<" + p.ty.c_name + "> &" + p.name)
+ s_rsp.append("const std::vector<" + p.ty.c_name + "> &" + p.name)
+ r_rsp.append("std::vector<" + p.ty.c_name + "> &_" + p.name)
+ elif p.is_single_string() or p.is_single_opaque() or p.is_single_struct() or \
+ p.is_single_uuid():
+ s_req.append("const " + t + " &" + p.name)
+ r_req.append("const " + t + " &" + p.name)
+ s_rsp.append("const " + t + " &" + p.name)
+ r_rsp.append(t + " &_" + p.name)
+ else:
+ enc_const = ""
+ if not p.is_single_int():
+ enc_const = "const "
+ proto = p.ty.c_name + " "
+ if not p.is_single_int():
+ proto += "&"
+ s_req.append(enc_const + proto + p.name)
+ r_rsp.append(proto + "*" + p.name)
+ r_req.append(enc_const + proto + p.name)
+ s_rsp.append(enc_const + proto + p.name)
+
+ if p.direction == xdr_direction.IN or p.direction == xdr_direction.INOUT:
+ send_request_protos += s_req
+ if p.direction == xdr_direction.OUT or p.direction == xdr_direction.INOUT:
+ send_response_protos += s_rsp
+
+ o.rxhdr("\n")
+ o.rxhdr("/*\n")
+ o.rxhdr(" * ", func.name, "\n")
+ o.rxhdr(" */\n")
+
+ o.rxhdr("extern rxrpc::ref<rxrpc::Enc_buffer> encode_", func.name, "(\n")
+ need_sep = False
+ for proto in send_request_protos:
+ if need_sep:
+ o.rxhdr(",\n")
+ o.rxhdr("\t", proto)
+ need_sep = True
+ o.rxhdr(");\n")
+ o.rxhdr("\n")
+
+ o.rxhdr("extern rxrpc::ref<rxrpc::Enc_buffer> encode_S_", func.name, "(\n")
+ need_sep = False
+ for proto in send_response_protos:
+ if need_sep:
+ o.rxhdr(",\n")
+ o.rxhdr("\t", proto)
+ need_sep = True
+ o.rxhdr(");\n")
+ o.rxhdr("\n")
+
+ o.rxhdr("extern rxrpc::ref<rxrpc::Call> begin_", func.name + "(\n")
+ o.rxhdr("\trxrpc::Call_params *z_params,\n")
+ o.rxhdr("\trxrpc::Enc_buffer *z_buf);\n")
+
+ o.rxhdr("\n")
+ o.rxhdr("extern void decode_", func.name, "(\n")
+ o.rxhdr("\trxrpc::Call *z_call")
+ for p in func.response:
+ o.rxhdr(",\n\t")
+ if p.is_bulk():
+ o.rxhdr("std::vector<", p.ty.c_name, "> &_", p.name)
+ need_i = True
+ else:
+ o.rxhdr(p.ty.c_name, " &_", p.name)
+ o.rxhdr(");\n")
+
+ o.rxhdr("\n")
+ o.rxhdr("extern int S_", func.name, "(\n")
+ o.rxhdr("\trxrpc::Call *z_call")
+ for p in func.request:
+ o.rxhdr(",\n\t")
+ if p.is_single_int():
+ o.rxhdr(p.ty.c_name, " ", p.name)
+ elif p.is_bulk():
+ o.rxhdr("std::vector<", p.ty.c_name, "> &a_", p.name)
+ else:
+ o.rxhdr(p.ty.c_name, " &a_", p.name)
+ o.rxhdr(");\n")
+
+ # Synchronous client call
+ o.rxhdr("\n")
+ o.rxhdr("extern void ", func.name, "(\n")
+ o.rxhdr("\trxrpc::Call_params *z_params")
+
+ # Request parameters
+ for proto in send_request_protos:
+ o.rxhdr(",\n\t", proto)
+
+ # Reply parameters
+ for p in func.response:
+ o.rxhdr(",\n\t")
+ if p.is_bulk():
+ o.rxhdr("std::vector<", p.ty.c_name, "> &_", p.name)
+ elif p.is_single_string():
+ o.rxhdr(p.ty.c_name, " &_", p.name)
+ elif p.is_single_opaque():
+ o.rxhdr(p.ty.c_name, " &_", p.name)
+ elif p.is_single_int():
+ o.rxhdr(p.ty.c_name, " &_", p.name)
+ elif p.is_single_struct():
+ o.rxhdr(p.ty.c_name, " &_", p.name)
+ elif str(p.ty) == "opr_uuid":
+ o.rxhdr(p.ty.c_name, " &_", p.name)
+ else:
+ print(p.name)
+ raise RuntimeError("No prototype for type '" + str(p.ty) + "'")
+ o.rxhdr(");\n")
+
+ func.send_request_protos = send_request_protos
+ func.send_response_protos = send_response_protos
+
+###############################################################################
+#
+# Emit a function to encode a request or a response into a buffer, not
+# including any split insertion.
+#
+###############################################################################
+def emit_func_encode(o, func, what):
+ # Function definition and arguments
+ if what == "request":
+ protos = func.send_request_protos
+ params = func.request
+ else:
+ protos = func.send_response_protos
+ params = func.response
+
+ o.rxsrc("\n")
+ if what == "request":
+ o.rxsrc("rxrpc::ref<rxrpc::Enc_buffer> encode_", func.name, "(")
+ else:
+ o.rxsrc("rxrpc::ref<rxrpc::Enc_buffer> encode_S_", func.name, "(")
+
+ need_sep = False
+ for proto in protos:
+ if need_sep:
+ o.rxsrc(",")
+ else:
+ need_sep = True
+ o.rxsrc("\n\t\t", proto)
+
+ o.rxsrc(")\n")
+ o.rxsrc("{\n")
+
+ blob_params = list()
+ bulk_params = list()
+ for p in params:
+ if p.is_single_string() or p.is_single_opaque():
+ blob_params.append(p)
+ if p.is_bulk():
+ bulk_params.append(p)
+
+ # Local variables
+ o.rxsrc("\trxrpc::ref<rxrpc::Enc_buffer> z_buf;\n")
+ o.rxsrc("\trxrpc::Resv z_resv = { .max_ioc = 1, };\n")
+ o.rxsrc("\n")
+
+ # Parameter checks
+ if blob_params or bulk_params:
+ for p in blob_params:
+ o.where(func.name + ":" + p.name)
+ if p.max_obj:
+ o.rxsrc("\tif (", p.name, ".size() > ", p.max_obj.name,
+ ") throw std::invalid_argument(\"Size of ", p.name, " too large\");\n")
+
+ for p in bulk_params:
+ o.where(func.name + ":" + p.name)
+ if p.max_count:
+ o.rxsrc("\tif (", p.name, ".size() > ", p.max_count.name,
+ ") throw std::invalid_argument(\"Size of ", p.name, " too large\");\n")
+ o.rxsrc("\n")
+
+ # Calculate the size of the parameter.
+ o.rxsrc("\t/* Determine size */\n")
+ o.rxsrc("\trxrpc::reserve(z_resv); // ", func.opcode.name, "\n");
+ for p in params:
+ if p.is_single_string():
+ o.rxsrc("\trxrpc::reserve_string(z_resv, ",
+ p.name, ", ", p.what_max_obj(), ");\n")
+ elif p.is_single_opaque():
+ o.rxsrc("\trxrpc::reserve_opaque(z_resv, ",
+ p.name, ", ", p.what_max_obj(), ");\n")
+ elif p.is_bulk():
+ o.rxsrc("\trxrpc::reserve(z_resv); // #", p.name, "\n")
+ if p.is_bulk_int32():
+ o.rxsrc("\trxrpc::reserve_a32(z_resv, ", p.name, ".size());\n")
+ elif p.is_bulk_int64():
+ o.rxsrc("\trxrpc::reserve_a64(z_resv, ", p.name, ".size());\n")
+ elif p.is_bulk():
+ o.rxsrc("\tfor (size_t i = 0; i < ", p.name, ".size(); i++)\n")
+ o.rxsrc("\t\txdr::reserve_", str(p.ty.name), "(z_resv, ", p.name, "[i]);\n")
+ elif p.is_int32():
+ o.rxsrc("\trxrpc::reserve(z_resv); // ", p.name, "\n")
+ elif p.is_int64():
+ o.rxsrc("\trxrpc::reserve_u64(z_resv); // ", p.name, "\n")
+ elif p.is_single_uuid():
+ o.rxsrc("\trxrpc::reserve_opr_uuid(z_resv, ", p.name, ");\n")
+ else:
+ o.rxsrc("\txdr::reserve_", p.ty.name, "(z_resv, ", p.name, ");\n")
+
+ # Allocate the buffer
+ o.rxsrc("\n")
+ o.rxsrc("\t/* Marshal */\n")
+ o.rxsrc("\tz_buf = rxrpc::alloc_enc_buffer(z_resv);\n")
+
+ # Marshal the data
+ if what == "request":
+ o.rxsrc("\trxrpc::enc(z_buf, ", func.opcode.name, ");\n")
+
+ for p in params:
+ o.where(func.name + ":" + p.name)
+ if p.is_single_int32():
+ o.rxsrc("\trxrpc::enc(z_buf, ", p.name, ");\n")
+ elif p.is_single_int64():
+ o.rxsrc("\trxrpc::enc_u64(z_buf, ", p.name, ");\n")
+ elif p.is_single_compound():
+ o.rxsrc("\txdr::encode_", p.ty.name, "(z_buf, ", p.name, ");\n")
+ elif p.is_single_string():
+ o.rxsrc("\trxrpc::enc_string(z_buf, ", p.name, ", ", p.what_max_obj(), ");\n")
+ elif p.is_single_opaque():
+ o.rxsrc("\trxrpc::enc_opaque(z_buf, ", p.name, ", ", p.what_max_obj(), ");\n")
+ elif p.is_bulk():
+ o.rxsrc("\trxrpc::enc(z_buf, ", p.name, ".size());\n")
+ o.rxsrc("\tfor (size_t i = 0; i < ", p.name, ".size(); i++)\n")
+ if p.is_bulk_int32():
+ if not p.ty.name.startswith("u"):
+ o.rxsrc("\t\trxrpc::enc(z_buf, (u", p.ty.name, ")", p.name, "[i]);\n")
+ else:
+ o.rxsrc("\t\trxrpc::enc(z_buf, ", p.name, "[i]);\n")
+ elif p.is_bulk_int64():
+ o.rxsrc("\t\trxrpc::enc_u64(z_buf, (uint32_t)", p.name, "[i]);\n")
+ elif p.is_bulk_struct():
+ o.rxsrc("\t\txdr::encode_", p.ty.name, "(z_buf, ", p.name, "[i]);\n")
+ else:
+ raise RuntimeError("No decoding for array type '" + str(p.ty) + "'")
+ elif p.is_single_uuid():
+ o.rxsrc("\trxrpc::enc_uuid(z_buf, ", p.name, ");\n")
+ else:
+ raise RuntimeError("Unsupported param encoding '" + str(p.ty) + "'")
+
+ o.rxsrc("\trxrpc::seal_buffer(z_buf);\n")
+
+ # Send the data
+ o.rxsrc("\treturn z_buf;\n")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit a function to encode and dispatch a request or a response
+#
+###############################################################################
+def emit_func_send(o, func, what):
+ # Function definition and arguments
+ if what == "request":
+ protos = func.send_request_protos
+ params = func.request
+ else:
+ protos = func.send_response_protos
+ params = func.response
+
+ o.rxsrc("\n")
+ if what == "request":
+ o.rxsrc("rxrpc::ref<rxrpc::Call> begin_", func.name, "(\n")
+ o.rxsrc("\trxrpc::Call_params *z_params,\n")
+ o.rxsrc("\trxrpc::Enc_buffer *z_buf)\n")
+ else:
+ o.rxsrc("void reply_to_", func.name, "(\n")
+ o.rxsrc("\trxrpc::Call *z_call,\n")
+ o.rxsrc("\trxrpc::Enc_buffer *z_buf)\n")
+
+ o.rxsrc("{\n")
+
+ # Local variables
+ if what == "request":
+ o.rxsrc("\trxrpc::ref<rxrpc::Call> z_call =\n")
+ o.rxsrc("\t\trxrpc::make_call(z_params, \"",
+ func.package.name, "::", func.name, "\", z_buf);\n")
+ o.rxsrc("\tz_call->throw_abort_func = afs_throw_abort;\n")
+ if func.split:
+ o.rxsrc("\tz_call->split = true;\n")
+
+ # Send the data
+ if what == "request":
+ o.rxsrc("\treturn z_call;\n")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit a weak stub function to implement a server call.
+#
+###############################################################################
+def emit_func_server_stub(o, func):
+ # Function definition and arguments
+ params = func.request
+
+ o.rxsrc("\n")
+ o.rxsrc("__attribute__((weak))\n")
+ o.rxsrc("int S_", func.name, "(\n")
+ o.rxsrc("\trxrpc::Call *z_call")
+ for p in params:
+ o.rxsrc(",\n\t")
+ if p.is_bulk():
+ o.rxsrc("std::vector<", p.ty.c_name, "> &_", p.name)
+ elif p.is_single_int():
+ o.rxsrc(p.ty.c_name, " ", p.name)
+ elif p.is_single_string():
+ o.rxsrc(p.ty.c_name, " &", p.name)
+ elif p.is_single_opaque():
+ o.rxsrc(p.ty.c_name, " &", p.name)
+ elif p.is_single_compound():
+ o.rxsrc(p.ty.c_name, " &", p.name)
+ elif str(p.ty) == "opr_uuid":
+ o.rxsrc(p.ty.c_name, " &", p.name)
+ else:
+ print(p.name)
+ raise RuntimeError("No prototype for type '" + str(p.ty) + "'")
+
+ o.rxsrc(")\n")
+ o.rxsrc("{\n")
+ o.rxsrc("\tthrow rxrpc::AbortRXGEN_OPCODE(z_call->op_name);\n")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit a function to decode a request and invoke the appropriate server
+# function. The opcode is expected to have been removed from the incoming call
+# on the server side.
+#
+###############################################################################
+def emit_func_receive_request(o, func):
+ # Function definition and arguments
+ params = func.request
+ nomem = False
+ need_i = False
+
+ o.rxsrc("\n")
+ o.rxsrc("void decode_S_", func.name, "(rxrpc::Call *z_call)\n")
+ o.rxsrc("{\n")
+
+ # Local variables
+ for p in params:
+ if p.is_bulk():
+ o.rxsrc("\tstd::vector<", p.ty.c_name, "> a_", p.name, ";\n")
+ need_i = True
+ elif p.is_single_string():
+ o.rxsrc("\t", p.ty.c_name, " a_", p.name, ";\n")
+ elif p.is_single_opaque():
+ o.rxsrc("\t", p.ty.c_name, " a_", p.name, ";\n")
+ elif p.is_single_int() or p.is_single_struct():
+ o.rxsrc("\t", p.ty.c_name, " a_", p.name, ";\n")
+ elif p.is_single_union():
+ o.rxsrc("\t", p.ty.c_name, " a_", p.name, " = {};\n")
+ elif p.is_single_uuid():
+ o.rxsrc("\t", p.ty.c_name, " a_", p.name, ";\n")
+ else:
+ print(p.name)
+ raise RuntimeError("No local vars for type '" + str(p.ty) + "'")
+ if need_i:
+ o.rxsrc("\tsize_t count;\n")
+
+ o.rxsrc("\n");
+ o.rxsrc("\ttry {\n");
+
+ # Decode the data.
+ if params:
+ o.rxsrc("\t\trxrpc::Rx_queue &z_rxq = *z_call;\n")
+ for p in params:
+ if p.is_single_string():
+ o.rxsrc("\t\trxrpc::dec_string(z_rxq, a_", p.name)
+ if p.max_obj != None:
+ o.rxsrc(", ", p.max_obj)
+ o.rxsrc(");\n");
+ elif p.is_single_opaque():
+ o.rxsrc("\t\trxrpc::dec_opaque(z_rxq, a_", p.name)
+ if p.max_obj != None:
+ o.rxsrc(", ", p.max_obj)
+ o.rxsrc(");\n")
+ elif p.is_bulk():
+ o.rxsrc("\t\t/* ", str(p.ty), " a_", p.name, " */\n");
+ o.rxsrc("\t\tcount = rxrpc::dec(z_rxq")
+ if p.max_count != None:
+ o.rxsrc(", ", p.max_count)
+ o.rxsrc(");\n")
+
+ o.rxsrc("\t\ta_", p.name, ".resize(count);\n")
+ if p.is_bulk_int():
+ o.rxsrc("\t\tfor (size_t i = 0; i < count; i++)\n")
+ o.rxsrc("\t\t\ta_", p.name, "[i] = rxrpc::dec(z_rxq);\n")
+ nomem = True
+ elif p.is_bulk_struct():
+ o.rxsrc("\t\tfor (size_t i = 0; i < count; i++)\n")
+ o.rxsrc("\t\t\txdr::decode_", p.ty.name, "(z_rxq, a_", p.name, "[i]);\n")
+ nomem = True
+ else:
+ print(func.name, p.name, str(p.ty))
+ print("is_bulk: ", p.is_bulk())
+ print("is_bulk_int", p.is_bulk_int())
+ print("is_int:", p.is_int())
+ raise RuntimeError("No decode for bulk type '" + str(p.ty) + "'")
+ elif p.is_single_int():
+ o.rxsrc("\t\ta_", p.name, " = rxrpc::dec(z_rxq);\n")
+ elif p.is_single_compound():
+ o.rxsrc("\t\txdr::decode_", p.ty.name, "(z_rxq, a_", p.name, ");\n")
+ elif p.is_single_uuid():
+ o.rxsrc("\t\tz_rxq.read(&a_", p.name, ".uuid, sizeof(a_", p.name, ".uuid));\n")
+ else:
+ print(func.name, p.name, str(p.ty))
+ print("is_bulk: ", p.is_bulk())
+ print("is_bulk_int", p.is_bulk_int())
+ print("is_int:", p.is_int())
+ raise RuntimeError("No decode for type '" + str(p.ty) + "'")
+
+ # Check for decode errors
+ o.rxsrc("\n")
+ o.rxsrc("\t\tz_call->request_received();\n")
+
+ # Invoke the server stub
+ o.rxsrc("\n")
+ o.rxsrc("\t\tS_", func.name, "(\n")
+ o.rxsrc("\t\t\tz_call")
+ for p in params:
+ o.rxsrc(",\n\t\t\t")
+ o.rxsrc("a_", p.name)
+ o.rxsrc(");\n")
+
+ o.rxsrc("\t} catch (rxrpc::rx_abort &a) {\n")
+ o.rxsrc("\t\tz_call->end(a.get_abort_code());\n")
+ o.rxsrc("\t\tthrow;\n")
+ o.rxsrc("\t} catch (...) {\n")
+ o.rxsrc("\t\tz_call->end(RX_USER_ABORT);\n")
+ o.rxsrc("\t\tthrow;\n")
+ o.rxsrc("\t}\n")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit a function to decode a reply and return it to the caller on the client
+# side.
+#
+###############################################################################
+def emit_func_receive_reply(o, func):
+ # Function definition and arguments
+ params = func.response
+ need_i = False
+
+ o.rxsrc("void decode_", func.name, "(\n")
+ o.rxsrc("\trxrpc::Call *z_call")
+ for p in params:
+ o.rxsrc(",\n\t")
+ if p.is_single_string():
+ o.rxsrc(p.ty.c_name, " &_", p.name)
+ elif p.is_single_opaque():
+ o.rxsrc(p.ty.c_name, " &_", p.name)
+ elif p.is_bulk():
+ o.rxsrc("std::vector<", p.ty.c_name, "> &_", p.name)
+ need_i = True
+ elif p.is_single_int():
+ o.rxsrc(p.ty.c_name, " &_", p.name)
+ elif p.is_single_struct():
+ o.rxsrc(p.ty.c_name, " &_", p.name)
+ elif p.is_single_uuid():
+ o.rxsrc(p.ty.c_name, " &_", p.name)
+ else:
+ raise RuntimeError("No prototype for type '" + str(p.ty) + "'")
+ o.rxsrc(")\n")
+ o.rxsrc("{\n")
+
+ # Local variables
+ if need_i:
+ o.rxsrc("\tsize_t count;\n")
+
+ # Decode the data.
+ o.rxsrc("\n")
+ if params:
+ o.rxsrc("\t\trxrpc::Rx_queue &z_rxq = *z_call;\n")
+ for p in params:
+ if p.is_single_string():
+ o.rxsrc("\trxrpc::dec_string(z_rxq, _", p.name)
+ if p.max_obj != None:
+ o.rxsrc(", ", p.max_obj)
+ o.rxsrc(");\n");
+ elif p.is_single_opaque():
+ o.rxsrc("\trxrpc::dec_opaque(z_rxq, _", p.name)
+ if p.max_obj != None:
+ o.rxsrc(", ", p.max_obj)
+ o.rxsrc(");\n");
+ elif p.is_bulk():
+ o.rxsrc("\t/* ", str(p.ty), " ", p.name, " */\n");
+ o.rxsrc("\tcount = rxrpc::dec(z_rxq")
+ if p.max_count:
+ o.rxsrc(", ", p.max_count);
+ o.rxsrc(");\n")
+ o.rxsrc("\t_", p.name, ".resize(count);\n")
+ o.rxsrc("\tfor (size_t i = 0; i < count; i++)\n")
+
+ if p.is_bulk_int():
+ o.rxsrc("\t\t_", p.name, "[i] = rxrpc::dec(z_rxq);\n")
+ elif p.is_bulk_struct():
+ o.rxsrc("\t\txdr::decode_", p.ty.name, "(z_rxq, _", p.name, "[i]);\n")
+ else:
+ print(func.name, p.name, str(p.ty))
+ print("is_bulk: ", p.is_bulk())
+ print("is_bulk_int", p.is_bulk_int())
+ print("is_int:", p.is_int())
+ raise RuntimeError("No decoding for bulk type '" + str(p.ty) + "'")
+ elif p.is_single_int():
+ o.rxsrc("\t_", p.name, " = rxrpc::dec(z_rxq);\n")
+ elif p.is_single_struct():
+ o.rxsrc("\txdr::decode_", p.ty.name, "(z_rxq, _", p.name, ");\n")
+ elif p.is_single_uuid():
+ o.rxsrc("\tz_call->read(_", p.name, ".uuid, sizeof(_", p.name, ".uuid));\n")
+ else:
+ print(func.name, p.name, str(p.ty))
+ print("is_bulk: ", p.is_bulk())
+ print("is_bulk_int", p.is_bulk_int())
+ print("is_int:", p.is_int())
+ raise RuntimeError("No decoding for type '" + str(p.ty) + "'")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit a function to switch between service calls.
+#
+###############################################################################
+def emit_package_switch(o, package):
+ o.rxsrc("\n")
+ o.rxsrc("void ", package.name, "_service(rxrpc::Call *z_call, unsigned int opcode)\n")
+ o.rxsrc("{\n")
+ o.rxsrc("\tswitch (opcode) {\n")
+ for f in package.procs:
+ o.rxsrc("\tcase ", f.opcode, ":\treturn decode_S_", f.name, "(z_call);\n")
+ o.rxsrc("\tdefault:\tthrow rxrpc::AbortRXGEN_OPCODE();\n")
+ o.rxsrc("\t}\n")
+ o.rxsrc("}\n")
+
+###############################################################################
+#
+# Emit a function to do a complete synchronous client call
+#
+###############################################################################
+def emit_func_sync_client_call(o, func):
+ protos = func.send_request_protos
+ params = func.request
+ bad_ret = "NULL"
+
+ o.rxsrc("\n")
+ o.rxsrc("void ", func.name, "(\n")
+ o.rxsrc("\trxrpc::Call_params *z_params")
+
+ # Request parameters
+ for proto in protos:
+ o.rxsrc(",\n\t", proto)
+
+ # Reply parameters
+ for p in func.response:
+ o.rxsrc(",\n\t")
+ if p.is_bulk():
+ o.rxsrc("std::vector<", p.ty.c_name, "> &_", p.name)
+ else:
+ o.rxsrc(p.ty.c_name, " &_", p.name)
+
+ o.rxsrc(")\n")
+ o.rxsrc("{\n")
+
+ # Encode the parameters
+ o.rxsrc("\n")
+ o.rxsrc("\trxrpc::ref<rxrpc::Enc_buffer> z_buf =\n")
+ o.rxsrc("\t\t encode_", func.name, "(")
+ need_sep = False
+ for p in func.request:
+ if need_sep:
+ o.rxsrc(",")
+ else:
+ need_sep = True
+ o.rxsrc("\n\t\t")
+ if p.is_single_string():
+ o.rxsrc("\t", p.name)
+ elif p.is_single_opaque():
+ o.rxsrc("\t", p.name)
+ elif p.is_bulk():
+ o.rxsrc("\t", p.name)
+ else:
+ o.rxsrc("\t", p.name)
+
+ o.rxsrc(");\n")
+
+ # Begin the call
+ o.rxsrc("\n")
+ o.rxsrc("\trxrpc::ref<rxrpc::Call> z_call =\n")
+ o.rxsrc("\t\tbegin_", func.name, "(z_params, z_buf);\n")
+
+ o.rxsrc("\tz_call->send_data(z_buf);\n")
+
+ # Wait for the reply to come in
+ o.rxsrc("\n")
+ o.rxsrc("\twhile (z_call->state != rxrpc::Call::call_completed)\n")
+ o.rxsrc("\t\tz_call->endpoint->receive();\n")
+
+ # Decode the reply
+ o.rxsrc("\n")
+ o.rxsrc("\tdecode_", func.name, "(\n")
+ o.rxsrc("\t\tz_call")
+ for p in func.response:
+ o.rxsrc(",\n\t\t_", p.name)
+
+ o.rxsrc(");\n")
+ o.rxsrc("\tz_params->service_id_used = z_call->service_id;\n")
+ o.rxsrc("\tz_call->end(0);\n")
+ o.rxsrc("}\n")
--- /dev/null
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+#
+# Tool for processing an RxRPC-based RPC API definition in a C header file to
+# produce (un)marshalling code and RPC functions to implement that API.
+#
+# It also produces a python module containing wrappers for the types, RPC
+# functions and constants in the API definition.
+
+__copyright__ = """
+Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+Written by David Howells (dhowells@redhat.com)
+
+Yacc & Lex bits based on pynfs rpcgen.py code:
+
+ Written by Fred Isaman <iisaman@citi.umich.edu>
+ Copyright (C) 2004 University of Michigan, Center for
+ Information Technology Integration
+ Based on version written by Peter Astrand <peter@cendio.se>
+ Copyright (C) 2001 Cendio Systems AB (http://www.cendio.se)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+import sys
+import keyword
+import time
+import os
+from rxgen_bits import *
+from emit_c_struct import *
+from emit_c_sync_funcs import *
+
+xdr = None # Current context
+
+##########################################################################
+# #
+# Lexical analysis #
+# #
+##########################################################################
+import ply.lex as lex
+
+basic_types = (
+ ( "char", "char", xdr_basic.int32 ),
+ ( "int8_t", "int8_t", xdr_basic.int32 ),
+ ( "int16_t", "int16_t", xdr_basic.int32 ),
+ ( "int32_t", "int32_t", xdr_basic.int32 ),
+ ( "int64_t", "int64_t", xdr_basic.int64 ),
+ ( "uint8_t", "uint8_t", xdr_basic.int32 ),
+ ( "uint16_t", "uint16_t", xdr_basic.int32 ),
+ ( "uint32_t", "uint32_t", xdr_basic.int32 ),
+ ( "uint64_t", "uint64_t", xdr_basic.int64 ),
+ ( "string", "std::string", xdr_basic.string ),
+ ( "opaque", "rxrpc::Opaque", xdr_basic.opaque ),
+ ( "opr_uuid", "rxrpc::Uuid", xdr_basic.opr_uuid ),
+ )
+
+def load_basic_types(xdr):
+ global basic_types
+ for i in basic_types:
+ name = i[0]
+ t = xdr_type(xdr, name=name, c_name=i[1], basic=i[2])
+ xdr.types[name] = t
+
+keywords = (
+ "IN",
+ "INOUT",
+ "OUT",
+ "altonly",
+ "case",
+ "const",
+ "enum",
+ "multi",
+ "package",
+ "split",
+ "struct",
+ "switch",
+ "typedef",
+ "union",
+) + tuple([i[0] for i in basic_types])
+
+# Required by lex. Each token also allows a function t_<token>.
+tokens = tuple([t.upper() for t in keywords]) + (
+ "ID", "CONST10", "CONST8", "CONST16",
+ # ( ) [ ] { }
+ "LPAREN", "RPAREN", "LSQUARE", "RSQUARE", "LBRACE", "RBRACE",
+ # ; : < > * = , :
+ "SEMI", "LT", "GT", "STAR", "EQUALS", "COMMA", "COLON",
+ "BEGIN_ERROR_CODES", "END_ERROR_CODES", "NEWFILE"
+)
+
+# t_<name> functions are used by lex. They are called with t.value==<match
+# of rule in comment>, and t.type==<name>. They expect a return value
+# with attribute type=<token>
+
+# Tell lexer to ignore Whitespace.
+t_ignore = " \t"
+
+def t_NEWFILE(t):
+ r'__NEWFILE__ [^\n]*'
+ t.lexer.source = t.value[12:]
+ t.lexer.lineno = 0
+ return t
+
+def t_ID(t):
+ r'[A-Za-z][A-Za-z0-9_]*'
+ if t.value in keywords:
+ t.type = t.value.upper()
+ return t
+
+def t_CONST16(t):
+ r'0x[0-9a-fA-F]+'
+ return t
+
+def t_CONST8(t):
+ r'0[0-7]+'
+ return t
+
+def t_CONST10(t):
+ r'-?(([1-9]\d*)|0)'
+ return t
+
+# Tokens
+t_LPAREN = r'\('
+t_RPAREN = r'\)'
+t_LSQUARE = r'\['
+t_RSQUARE = r'\]'
+t_LBRACE = r'\{'
+t_RBRACE = r'\}'
+t_SEMI = r';'
+t_LT = r'<'
+t_GT = r'>'
+t_STAR = r'\*'
+t_EQUALS = r'='
+t_COMMA = r','
+t_COLON = r':'
+t_BEGIN_ERROR_CODES = r'__BEGIN_ERROR_CODES__'
+t_END_ERROR_CODES = r'__END_ERROR_CODES__'
+
+def t_newline(t):
+ r'\n+'
+ t.lexer.lineno += t.value.count("\n")
+
+def t_error(t):
+ print("Illegal character {:s} at {:d} type {:s}".format(repr(t.value[0]),
+ t.lineno, t.type))
+ t.lexer.skip(1)
+
+# Build the lexer
+lex.lex(debug=0)
+
+##########################################################################
+# #
+# Yacc Parsing Info #
+# #
+##########################################################################
+
+def p_specification(t):
+ '''specification : NEWFILE definition_list'''
+
+def p_definition_list(t):
+ '''definition_list : definition definition_list
+ | empty'''
+
+def p_definition(t):
+ '''definition : package_def
+ | constant_def
+ | enum_def
+ | type_def
+ | error_code_list_def
+ | proc_spec
+ | ALTONLY proc_spec'''
+
+def p_package_def(t):
+ '''package_def : PACKAGE ID'''
+ prefix = t[2]
+ name = t[2]
+ if name.endswith("_"):
+ name = name[:-1]
+ global xdr
+ xdr.lineno = t.lineno(1)
+ xdr.add_package(name, prefix)
+
+###############################################################################
+#
+# Constants and values
+#
+def p_constant_def(t):
+ '''constant_def : CONST ID EQUALS constant SEMI'''
+ name = t[2]
+ value = t[4]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ t[0] = xdr.add_constant(name, value)
+
+def p_constant(t):
+ '''constant : CONST10
+ | CONST8
+ | CONST16'''
+ value = t[1]
+ if len(value) > 9:
+ value = value + 'L'
+ global xdr
+ xdr.lineno = t.lineno(1)
+ t[0] = xdr.add_number(value)
+
+def p_value_1(t):
+ '''value : constant'''
+ t[0] = t[1]
+
+def p_value_2(t):
+ '''value : ID'''
+ name = t[1]
+ global xdr
+ xdr.lineno = t.lineno(1)
+ t[0] = xdr.get_constant(name)
+
+def p_optional_value(t):
+ '''optional_value : value
+ | empty'''
+ # return value or None.
+ t[0] = t[1]
+
+def p_constant_list_1(t):
+ '''constant_list : constant_def constant_list'''
+ t[0] = [t[1]] + t[2]
+
+def p_constant_list_2(t):
+ '''constant_list : constant_def'''
+ t[0] = [t[1]]
+
+def p_error_code_list_def(t):
+ '''error_code_list_def : BEGIN_ERROR_CODES constant_list END_ERROR_CODES'''
+ global xdr
+ xdr.lineno = t.lineno(1)
+ xdr.add_error_codes(t[2])
+
+def p_enum_def(t):
+ '''enum_def : ENUM ID LBRACE enum_list RBRACE SEMI'''
+ '''enum_def : ENUM ID LBRACE enum_list COMMA RBRACE SEMI'''
+ name = t[2]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ enum = xdr_type(xdr, base=xdr.get_type("int32_t"))
+ t[0] = xdr.add_type(name, enum)
+
+def p_enum_list_1(t):
+ '''enum_list : enum_term'''
+ t[0] = [t[1]]
+
+def p_enum_list_2(t):
+ '''enum_list : enum_term COMMA enum_list'''
+ t[0] = [t[1]] + t[3]
+
+def p_enum_term(t):
+ '''enum_term : ID EQUALS constant'''
+ name = t[1]
+ value = t[3]
+ global xdr
+ xdr.lineno = t.lineno(1)
+ t[0] = xdr.add_constant(name, value)
+
+###############################################################################
+#
+# Type definition
+#
+def p_type_def_1(t):
+ '''type_def : TYPEDEF declaration SEMI'''
+ name = t[2].name
+ typespec = t[2].typespec
+ global xdr
+ xdr.lineno = t.lineno(1)
+ alias = xdr_type_alias(name, typespec, xdr)
+ xdr.add_type_alias(name, alias)
+ #xdr.debug("Typedef", name)
+
+def p_type_def_2(t):
+ '''type_def : STRUCT ID struct_body SEMI'''
+ name = t[2]
+ body = t[3]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ if name in xdr.structs:
+ xdr.error("Structure {:s} already exists".format(name))
+ else:
+ s = xdr_type(xdr, name=name, c_name="struct " + name,
+ basic=xdr_basic.struct, members=body)
+ xdr.structs[name] = s
+ xdr.all_structs.append(s)
+ xdr.add_type(name, s)
+ xdr.debug("New struct", name)
+
+def p_type_def_3(t):
+ '''type_def : UNION ID SWITCH LPAREN type_specifier ID RPAREN union_body SEMI'''
+ name = t[2]
+ body = t[8]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ if name in xdr.structs:
+ xdr.error("Structure {:s} already exists".format(name))
+ else:
+ s = xdr_type(xdr, name=name, c_name="struct " + name,
+ basic=xdr_basic.union, members=body)
+ s.selector_type = t[5]
+ s.selector_name = t[6]
+ xdr.structs[name] = s
+ xdr.all_structs.append(s)
+ xdr.add_type(name, s)
+ xdr.debug("New union", name)
+
+###############################################################################
+#
+# Type specification
+#
+def p_declaration_1(t):
+ '''declaration : type_specifier ID'''
+ typespec = t[1]
+ name = t[2]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ t[0] = xdr_member(name, typespec, xdr);
+
+def p_declaration_2(t):
+ '''declaration : type_specifier STAR ID'''
+ # We ignore the pointer type marker
+ typespec = t[1]
+ name = t[3]
+ global xdr
+ xdr.lineno = t.lineno(3)
+ ty = xdr_type(xdr, base=typespec)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_3(t):
+ '''declaration : type_specifier ID LSQUARE value RSQUARE'''
+ typespec = t[1]
+ name = t[2]
+ array_size = t[4]
+ if not isinstance(typespec, xdr_type):
+ raise RuntimeError("Type is not type" + str(typespec))
+ global xdr
+ xdr.lineno = t.lineno(2)
+ ty = xdr_type(xdr, base=typespec, array=xdr_array.fixed, dim=array_size)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_4(t):
+ '''declaration : type_specifier ID LT optional_value GT'''
+ typespec = t[1]
+ name = t[2]
+ max_count = t[4]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ ty = xdr_type(xdr, base=typespec, array=xdr_array.bulk, max_count=max_count)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_5(t):
+ '''declaration : type_specifier STAR ID LT optional_value GT'''
+ typespec = t[1]
+ name = t[3]
+ max_count = t[5]
+ global xdr
+ xdr.lineno = t.lineno(3)
+ ty = xdr_type(xdr, base=typespec, array=xdr_array.bulk, max_count=max_count)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_6(t):
+ '''declaration : type_specifier LT optional_value GT STAR ID'''
+ typespec = t[1]
+ max_count = t[3]
+ name = t[6]
+ global xdr
+ xdr.lineno = t.lineno(6)
+ ty = xdr_type(xdr, base=typespec, array=xdr_array.bulk, max_count=max_count)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_7(t):
+ '''declaration : type_blob ID'''
+ typespec = t[1]
+ name = t[2]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ t[0] = xdr_member(name, typespec, xdr);
+
+def p_declaration_8(t):
+ '''declaration : type_blob STAR ID'''
+ # We ignore the pointer type marker
+ typespec = t[1]
+ name = t[3]
+ global xdr
+ xdr.lineno = t.lineno(3)
+ ty = xdr_type(xdr, base=typespec)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_9(t):
+ '''declaration : type_blob ID LSQUARE value RSQUARE'''
+ typespec = t[1]
+ name = t[2]
+ array_size = t[4]
+ if not isinstance(typespec, xdr_type):
+ raise RuntimeError("Type is not type" + str(typespec))
+ global xdr
+ xdr.lineno = t.lineno(2)
+ ty = xdr_type(xdr, base=typespec, array=xdr_array.fixed, dim=array_size)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_10(t):
+ '''declaration : type_blob ID LT optional_value GT'''
+ typespec = t[1]
+ name = t[2]
+ max_obj = t[4]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ ty = xdr_type(xdr, base=typespec, max_obj=max_obj)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_11(t):
+ '''declaration : type_blob STAR ID LT optional_value GT'''
+ typespec = t[1]
+ name = t[3]
+ max_obj = t[5]
+ global xdr
+ xdr.lineno = t.lineno(3)
+ ty = xdr_type(xdr, base=typespec, max_obj=max_obj)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_declaration_12(t):
+ '''declaration : type_blob LT optional_value GT STAR ID'''
+ typespec = t[1]
+ max_count = t[3]
+ name = t[6]
+ global xdr
+ xdr.lineno = t.lineno(6)
+ ty = xdr_type(xdr, base=typespec, array=xdr_array.bulk, max_count=max_count)
+ t[0] = xdr_member(name, ty, xdr)
+
+def p_type_blob(t):
+ '''type_blob : STRING
+ | OPAQUE'''
+ name = t[1]
+ global xdr
+ xdr.lineno = t.lineno(1)
+ t[0] = xdr.types[name]
+ if not isinstance(t[0], xdr_type):
+ raise RuntimeError("Type is not type" + typespec);
+
+def p_type_specifier_1(t):
+ '''type_specifier : CHAR
+ | INT8_T
+ | INT16_T
+ | INT32_T
+ | INT64_T
+ | UINT8_T
+ | UINT16_T
+ | UINT32_T
+ | UINT64_T
+ | OPR_UUID'''
+ name = t[1]
+ global xdr
+ xdr.lineno = t.lineno(1)
+ t[0] = xdr.types[name]
+ if not isinstance(t[0], xdr_type):
+ raise RuntimeError("Type is not type" + typespec);
+
+def p_type_specifier_2(t):
+ '''type_specifier : ID'''
+ name = t[1]
+ global xdr
+ xdr.lineno = t.lineno(1)
+ t[0] = xdr.get_type(t[1])
+
+def p_type_specifier_3(t):
+ '''type_specifier : struct_type_spec'''
+ t[0] = t[1]
+
+def p_type_specifier_4(t):
+ '''type_specifier : STRUCT ID'''
+ name = t[2]
+ global xdr
+ xdr.lineno = t.lineno(2)
+ t[0] = xdr.get_type(name)
+
+
+###############################################################################
+#
+# Structure specification
+#
+def p_struct_type_spec(t):
+ '''struct_type_spec : STRUCT struct_body'''
+ t[0] = xdr_type(xdr, name="<anon struct {:s}>".format(t.lineno), c_name="struct",
+ compound=xdr_compound.struct, basic_type="struct", members=t[2])
+
+def p_struct_body(t):
+ '''struct_body : LBRACE member_list RBRACE'''
+ t[0] = t[2]
+
+def p_member_list_1(t):
+ '''member_list : declaration SEMI'''
+ t[0] = [t[1]]
+
+def p_member_list_2(t):
+ '''member_list : declaration SEMI member_list'''
+ t[0] = [t[1]] + t[3]
+
+def p_union_body(t):
+ '''union_body : LBRACE union_case_list RBRACE'''
+ t[0] = t[2]
+
+def p_union_case(t):
+ '''union_case : CASE ID COLON member_list'''
+ t[0] = xdr_union_case(xdr, tag=t[2], members=t[4])
+
+def p_union_case_list_1(t):
+ '''union_case_list : union_case'''
+ t[0] = [t[1]]
+
+def p_union_case_list_2(t):
+ '''union_case_list : union_case union_case_list'''
+ t[0] = [t[1]] + t[2]
+
+###############################################################################
+#
+# Procedure specification
+#
+def p_proc_spec_1(t):
+ '''proc_spec : ID LPAREN parameters RPAREN EQUALS value SEMI'''
+ name = t[1]
+ params = t[3]
+ op = t[6]
+ global xdr
+ proc = xdr_proc(name, xdr, params, op)
+ xdr.add_proc(proc)
+ t[0] = proc
+
+def p_proc_spec_2(t):
+ '''proc_spec : ID LPAREN parameters RPAREN SPLIT EQUALS value SEMI'''
+ name = t[1]
+ params = t[3]
+ op = t[7]
+ global xdr
+ proc = xdr_proc(name, xdr, params, op, split=True)
+ xdr.add_proc(proc)
+ t[0] = proc
+
+def p_proc_spec_3(t):
+ '''proc_spec : ID LPAREN parameters RPAREN MULTI EQUALS value SEMI'''
+ name = t[1]
+ params = t[3]
+ op = t[7]
+ global xdr
+ proc = xdr_proc(name, xdr, params, op, multi=True)
+ xdr.add_proc(proc)
+ t[0] = proc
+
+def p_parameters_0(t):
+ '''parameters : '''
+ t[0] = []
+
+def p_parameters_1(t):
+ '''parameters : parameter'''
+ t[0] = [t[1]]
+
+def p_parameters_2(t):
+ '''parameters : parameter COMMA parameters'''
+ t[0] = [t[1]] + t[3]
+
+def p_parameter_1(t):
+ '''parameter : IN declaration'''
+ t[2].direction = xdr_direction.IN
+ t[0] = t[2]
+
+def p_parameter_2(t):
+ '''parameter : INOUT declaration'''
+ t[2].direction = xdr_direction.INOUT
+ t[0] = t[2]
+
+def p_parameter_3(t):
+ '''parameter : OUT declaration'''
+ t[2].direction = xdr_direction.OUT
+ t[0] = t[2]
+
+###############################################################################
+#
+# Miscellany
+#
+def p_empty(t):
+ 'empty :'
+
+def p_error(t):
+ global error_occurred
+ error_occurred = True
+ if t:
+ print(t)
+ print("Syntax error at '{:s}' (lineno {:d})".format(t.value, t.lineno))
+ else:
+ print("Syntax error: unexpectedly hit EOF")
+
+##########################################################################
+# #
+# Global Variables #
+# #
+##########################################################################
+
+error_occurred = False # Parsing of infile status
+
+
+
+##########################################################################
+# #
+# C Preprocessor #
+# #
+##########################################################################
+def cpp(data, filename):
+ # Remove C comments
+ lines = data.splitlines()
+ inside_C_comment = False
+ inside_error_code_list = False
+
+ for i in range(0, len(lines)):
+ l = lines[i]
+ begin = None
+ if inside_C_comment:
+ begin = 0
+ cursor = 0
+
+ # Capture the error code list
+ #
+ if not inside_C_comment:
+ if l == "/* Error codes */" and not inside_error_code_list:
+ inside_error_code_list = True
+ lines[i] = "__BEGIN_ERROR_CODES__"
+ continue
+
+ if inside_error_code_list and l == "":
+ inside_error_code_list = False
+ lines[i] = "__END_ERROR_CODES__"
+ continue
+
+ while True:
+ if inside_C_comment:
+ p = l.find("*/", cursor)
+ if p == -1:
+ l = l[:begin]
+ lines[i] = l
+ break
+ l = l[:begin] + l[p + 2:]
+ lines[i] = l
+ cursor = begin
+ begin = None
+ inside_C_comment = False
+ else:
+ p = l.find("/*");
+ if p == -1:
+ break
+ inside_C_comment = True
+ begin = p
+ cursor += 2
+
+ if inside_error_code_list:
+ lines.append("__END_ERROR_CODES__")
+
+ # Remove C++ comments
+ for i in range(0, len(lines)):
+ l = lines[i]
+ p = l.find("//")
+ if p != -1:
+ lines[i] = l[:p]
+
+ # Remove directives
+ skipping = False
+ for i in range(0, len(lines)):
+ l = lines[i]
+ if skipping:
+ if l == "#endif":
+ skipping = False;
+ lines[i] = ""
+ continue
+ if l == "#if 0":
+ skipping = True;
+ lines[i] = ""
+ continue
+ if (l.startswith("#include") or
+ l.startswith("#define") or
+ l.startswith("%")):
+ lines[i] = ""
+ continue
+
+ lines.insert(0, "__NEWFILE__ {:s}".format(filename))
+ return "\n".join(lines)
+
+##########################################################################
+# #
+# Main Loop #
+# #
+##########################################################################
+xdr = xdr_context()
+load_basic_types(xdr)
+#xdr.add_constant("RXRPC_SECURITY_PLAIN", "0")
+#xdr.add_constant("RXRPC_SECURITY_AUTH", "1")
+#xdr.add_constant("RXRPC_SECURITY_ENCRYPT", "2")
+
+# Parse the input data with yacc
+import ply.yacc as yacc
+yacc.yacc(debug=0)
+
+def parse(infile, debug=False):
+ global xdr
+ xdr.source = infile
+ xdr.lineno = 0
+
+ f = open(infile, encoding="utf-8")
+ data = f.read()
+ f.close()
+
+ data = cpp(data, infile)
+
+ print("Parsing", infile);
+ global yacc
+ yacc.parse(data, debug=debug)
+
+ if error_occurred:
+ print
+ print("Error occurred, did not write output files")
+ return False
+ return True
+
+def gen_abort_name(package, ac):
+ pname = package.name
+ acname = ac.name
+ #if acname.startswith(pname):
+ # acname = acname[len(pname):]
+ #if acname.startswith("_"):
+ # acname = acname[1:]
+ return acname
+
+#
+# Section: main
+#
+def run(files, out_file_prefix):
+ for f in files:
+ if not parse(f):
+ break
+
+ xdr.finished_parsing()
+
+ o = file_generator(xdr, out_file_prefix)
+ o.rxhdr("/* AUTOGENERATED */\n")
+ o.rxhdr("#ifndef _RXGEN_AFS_XG_H\n");
+ o.rxhdr("#define _RXGEN_AFS_XG_H\n");
+ o.rxhdr("\n")
+ #o.rxhdr("#define _XOPEN_SOURCE\n";
+ o.rxhdr("#include <stdint.h>\n")
+ o.rxhdr("#include <stdlib.h>\n")
+ o.rxhdr("#include \"rxrpc.H\"\n")
+ o.rxhdr("\n")
+ o.rxhdr("namespace kafs::afs {\n")
+
+ o.rxsrc("/* AUTOGENERATED */\n")
+ o.rxsrc("#include \"afs_xg.H\"\n")
+ o.rxsrc("\n")
+ o.rxsrc("namespace kafs::afs {\n")
+
+ # Declare constants
+ o.rxhdr("\n")
+ for name in xdr.all_constants:
+ c = xdr.constants[name]
+ o.rxhdr("constexpr int ", c.name, " = ", c.value, ";\n")
+
+ # Declare structure types
+ for s in xdr.all_structs:
+ emit_struct_decl(o, s)
+
+ o.rxhdr("\n")
+ o.rxhdr("namespace xdr {\n")
+ for s in xdr.all_structs:
+ emit_struct_encdec_decl(o, s);
+ o.rxhdr("\n")
+ o.rxhdr("} /* end namespace xdr */\n")
+
+ o.rxsrc("\n")
+ o.rxsrc("namespace xdr {\n")
+ for s in xdr.all_structs:
+ emit_struct_encdec(o, s);
+ o.rxsrc("\n")
+ o.rxsrc("} /* end namespace xdr */\n")
+
+ # Emit RPC call functions. For this we need to classify parameters according
+ # to input and output usage and work out how big the RPC messages will be.
+ #
+ for package in xdr.packages.values():
+ o.rxhdr("\n")
+ o.rxhdr("namespace ", package.name, " {\n")
+ o.rxsrc("\n")
+ o.rxsrc("namespace ", package.name, " {\n")
+
+ for f in package.procs:
+ # Dump the banner comment block
+ o.rxsrc("\n")
+ o.rxsrc("/*\n")
+ o.rxsrc(" * RPC Call ", f.name, "\n")
+ o.rxsrc(" */\n")
+
+ # Find the Operation ID
+ if not f.opcode:
+ raise RuntimeError("Operation ID unspecified for " + f.name)
+
+ # Filter the parameters into request and response
+ f.request = list()
+ f.response = list()
+
+ for p in f.params:
+ o.where(f.name + ":" + p.name)
+ if p.is_single_basic():
+ pass
+ elif p.is_compound():
+ pass
+ elif p.is_single_string() or p.is_single_opaque():
+ # Could validate max_obj attribute
+ pass
+ elif p.is_bulk():
+ pass
+ else:
+ raise RuntimeError("Unsupported param type \"" + str(p.ty) + "\"")
+
+ if p.direction == xdr_direction.IN:
+ f.request.append(p)
+ elif p.direction == xdr_direction.OUT:
+ f.response.append(p)
+ elif p.direction == xdr_direction.INOUT:
+ f.request.append(p)
+ f.response.append(p)
+
+ emit_func_prototype(o, f)
+ emit_func_encode(o, f, "request")
+ emit_func_encode(o, f, "response")
+ emit_func_send(o, f, "request")
+ emit_func_server_stub(o, f)
+ emit_func_receive_request(o, f)
+ emit_func_receive_reply(o, f)
+ emit_func_sync_client_call(o, f)
+
+ # Emit RPC service switch functions.
+ if package.procs:
+ emit_package_switch(o, package)
+
+ o.rxhdr("\n")
+ o.rxhdr("} /* end namespace ", package.name, " */\n")
+ o.rxsrc("\n")
+ o.rxsrc("} /* end namespace ", package.name, " */\n")
+
+ # Emit an abort throwing function
+ o.rxhdr("extern void afs_throw_abort(int ac, const char *op=NULL);\n");
+ o.rxsrc("\n")
+ o.rxsrc("void afs_throw_abort(int ac, const char *op)\n");
+ o.rxsrc("{\n")
+ o.rxsrc("\tswitch (ac) {\n")
+ for package in xdr.packages.values():
+ if package.abort_codes:
+ pabort = "Abort" + package.name;
+ o.rxhdr("\n")
+ o.rxhdr("namespace ", package.name, " {\n")
+ o.rxhdr("\tclass ", pabort, " : public rxrpc::rx_abort { public:\n")
+ o.rxhdr("\t\t", pabort, "(int ac, const char *sym, const char *desc, const char *op)\n"),
+ o.rxhdr("\t\t\t: rx_abort(ac, sym, desc, op) {}\n")
+ o.rxhdr("\t};\n")
+ for ac in package.abort_codes:
+ acclass = "Abort" + gen_abort_name(package, ac)
+ o.rxhdr("\tclass ", acclass, " : public ", pabort, " { public:\n")
+ o.rxhdr("\t\t", acclass, "(const char *op = NULL)\n")
+ o.rxhdr("\t\t\t: ", pabort, "(", ac.name, ", \"", ac.name, "\", \"\", op) {}\n")
+ o.rxhdr("\t};\n")
+ o.rxhdr("}\n")
+
+ for ac in package.abort_codes:
+ acclass = "Abort" + gen_abort_name(package, ac)
+ o.rxsrc("\tcase ", ac.name, ":\tthrow ", package.name, "::", acclass, "(op);\n")
+
+ o.rxsrc("\tdefault: rxrpc::throw_abort(ac, op);\n")
+ o.rxsrc("\t}\n")
+ o.rxsrc("}\n")
+ o.rxsrc("\n")
+ o.rxsrc("} /* end namespace kafs::afs */\n")
+
+ o.rxhdr("\n")
+ o.rxhdr("} /* end namespace kafs::afs */\n")
+ o.rxhdr("\n")
+ o.rxhdr("#endif /* _RXGEN_AFS_XG_H */\n");
+
+#
+# Drive the program if executed as a standalone process
+#
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print("Usage: {:s} <filename>*".format(sys.argv[0]))
+ sys.exit(1)
+
+ run(sys.argv[1:], "")
--- /dev/null
+# Bits for rxgen implementation
+# -*- coding: utf-8 -*-
+
+__copyright__ = """
+Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
+Written by David Howells (dhowells@redhat.com)
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public Licence version 2 as
+published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public Licence for more details.
+
+You should have received a copy of the GNU General Public Licence
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""
+
+import sys
+from enum import Enum
+
+class xdr_basic(Enum):
+ int32 = 1
+ int64 = 2
+ string = 3
+ opaque = 4
+ struct = 5
+ union = 6
+ opr_uuid = 7
+
+class xdr_array(Enum):
+ # single object is represented by None
+ fixed = 1
+ bulk = 2
+
+class xdr_direction(Enum):
+ IN = 1
+ OUT = 2
+ INOUT = 3
+
+class xdr_context:
+ def __init__(self):
+ self.source = None # Current source file
+ self.lineno = None # Current line number
+ self.types = dict() # List of types
+ self.typedefs = dict() # List of type aliases
+ self.structs = dict() # Structure definitions
+ self.struct_sizes = dict() # Structure sizes
+ self.all_structs = list() # Structures in order of declaration
+ self.constants = dict() # Constants
+ self.packages = dict() # Packages
+ self.pkg = None # Current package
+ self.abort_syms = dict() # Abort symbol to code map
+ self.abort_ids = dict() # Abort code to symbol map
+ self.abort_count = 0 # Number of abort codes
+ self.error_codes = False # True if parsing error code list
+ self.debug_level = False
+ self.zero = xdr_constant("0", "0", self)
+ self.typespecs = dict()
+
+ def debug(self, *s):
+ if (self.debug_level):
+ print(*s)
+
+ def error(self, *s):
+ print("{:s}:{:d}: Error".format(self.source, self.lineno), *s)
+
+ def add_package(self, name, prefix):
+ if name in self.packages:
+ self.error("Package {:s} already exists".format(name))
+ else:
+ pkg = xdr_package(name, prefix, self)
+ self.packages[name] = pkg
+ self.pkg = pkg
+ self.debug("New package", name)
+
+ def add_error_codes(self, codes):
+ self.abort_count += len(codes)
+ self.pkg.abort_codes += codes
+ for code in codes:
+ if not isinstance(code, xdr_constant):
+ raise TypeError("Expecting xdr_constant, got " + str(type(code)))
+ self.abort_syms[code.name] = code
+ value = code.value
+ suffix = ""
+ if value.endswith("L"):
+ value = value[0:-1]
+ suffix = "L"
+ if int(value, 0) < 0:
+ value = str(int(value, 0) + 0x100000000)
+ code.u32 = int(value, 0)
+ self.abort_ids[code.u32] = code
+
+ def add_constant(self, name, value):
+ if name in self.constants:
+ self.error("Constant {:s} already exists".format(name))
+ elif isinstance(value, xdr_constant):
+ self.constants[name] = xdr_constant(name, value.value, self)
+ else:
+ self.constants[name] = xdr_constant(name, value, self)
+ self.debug("New constant", name)
+ return self.constants[name]
+
+ def add_number(self, value):
+ if value == 0:
+ return self.zero
+ return xdr_constant(value, value, self)
+
+ def get_constant(self, name):
+ if name not in self.constants:
+ self.error("Constant {:s} undefined".format(name))
+ return self.zero
+ return self.constants[name]
+
+ def add_type(self, name, typespec):
+ if name in self.types:
+ self.error("Type {:s} already exists".format(name))
+ else:
+ self.types[name] = typespec
+ self.debug("New type", name)
+ return self.types[name]
+
+ def add_type_alias(self, name, alias):
+ if name in self.typedefs:
+ self.error("Type alias {:s} already exists".format(name))
+ return self.typedefs[name]
+ if name in self.structs:
+ self.error("struct {:s} already exists, cannot shadow with alias".format(name))
+ return alias
+
+ self.typedefs[name] = alias
+ self.debug("New typedef", name)
+
+ def get_type(self, name):
+ if name in self.types:
+ typespec = self.types[name]
+ elif name in self.typedefs:
+ typespec = self.typedefs[name].typespec
+ else:
+ raise RuntimeError("Undefined type requested '" + name + "'");
+ if not isinstance(typespec, xdr_type):
+ raise TypeError("Retrieved type object is not xdr_type " + name + str(typespec));
+ typespec.referenced = True
+ return typespec
+
+ def add_proc(self, proc):
+ if not isinstance(proc, xdr_proc):
+ raise KeyError("proc is not an xdr_proc ", name, proc);
+ name = proc.name
+ if name in self.pkg.proc_names:
+ self.error("Proc {:s} already exists".format(name))
+ return self.pkg.proc_names[name]
+ else:
+ self.pkg.proc_names[name] = proc
+ self.pkg.procs.append(proc)
+ self.debug("New proc", name)
+ return proc
+
+ def finished_parsing(self):
+ self.all_constants = list(self.constants.keys())
+ self.all_constants.sort()
+ self.all_types = list(self.types.keys())
+ self.all_types.sort()
+
+
+###############################################################################
+#
+# Token base class
+#
+###############################################################################
+class token_base(object):
+ def __init__(self):
+ self.source = None
+ self.lineno = None
+ self.name = None
+ self.type = None
+
+ def __str__(self):
+ return "{:s} {:s} at {:s}:{:d}".format(
+ self.type, self.name, self.source, self.lineno)
+
+###############################################################################
+#
+# XDR package
+#
+###############################################################################
+class xdr_package(token_base):
+ """The result of 'package ID'"""
+ def __init__(self, name, prefix, xdr):
+ self.type = 'package'
+ self.name = name
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+ self.prefix = prefix
+ self.abort_codes = list()
+ self.procs = list() # RPC procedures in declaration order
+ self.proc_names = dict() # RPC procedure name uniquifier
+
+###############################################################################
+#
+# XDR constant
+#
+###############################################################################
+class xdr_constant(token_base):
+ """The result of 'CONST ID EQUALS constant SEMI'"""
+ def __init__(self, name, value, xdr):
+ self.type = 'const'
+ self.name = name
+ self.value = value
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+ if not isinstance(value, str):
+ raise RuntimeError("Value should be a string");
+
+ def get_value(self):
+ if isinstance(self.value, xdr_constant):
+ return self.value.get_value()
+ return int(self.value)
+
+ def __str__(self):
+ return self.value
+
+ def __repr__(self):
+ return "constant {:s}={:s} at {:s}:{:d}".format(
+ self.name, self.value, self.source, self.lineno)
+
+###############################################################################
+#
+# XDR type definition
+#
+# Each type is specified by a hash of the following elements:
+#
+# name Name of non-anonymous type (char, {u,}int{8,16,32,64}_t, struct name)
+# basic Basic XDR type (int32, int64, string, opaque, struct)
+# array Array class (single, array, bulk)
+# dim Number of elements in fixed-size array (or None)
+# max_obj Max size of string/opaque
+# max_count Max elements in bulk array
+# members Members of struct
+# source/lineno Where defined in which file
+#
+# Members/parameters take a copy of their parent type's hash and add:
+#
+# name Member or parameter name (overrides type name)
+# direction Direction of parameter (IN, OUT or INOUT)
+#
+###############################################################################
+class xdr_type(token_base):
+ def __init__(self, xdr, base=None, name=None, c_name=None,
+ basic=None, array=None, dim=None, max_obj=None, max_count=None,
+ members=None):
+ if not isinstance(xdr, xdr_context):
+ raise TypeError("XDR context isn't")
+ if array:
+ if not isinstance(array, xdr_array):
+ raise TypeError("Invalid array class")
+ if array == xdr_array.fixed and not dim:
+ raise RuntimeError("Dimension required for fixed-size array")
+ if dim and max_count:
+ raise RuntimeError("Can't be both variable and fixed-size array")
+ elif basic == "string" or basic == "opaque" or \
+ base and (base.is_string() or base.is_opaque):
+ if dim:
+ raise RuntimeError("Can't specify fixed dimension limits on string/opaque")
+ else:
+ if dim or max_obj or max_count:
+ raise RuntimeError("Can't specify dimension limits on non-array")
+
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+ self.referenced = False
+ self.flat = None
+
+ if base:
+ if name:
+ raise RuntimeError("Type basic name can't be changed on an extant type")
+ if c_name:
+ raise RuntimeError("Type C name can't be changed on an extant type")
+ if basic:
+ raise RuntimeError("Basic type can't be changed on an extant type")
+ if members:
+ raise RuntimeError("Members can't be added to an extant type")
+ if not isinstance(base, xdr_type):
+ raise TypeError("Base type is not a type", type(base))
+ base.referenced = True
+ self.referenced = True
+ self.name = base.name
+ self.c_name = base.c_name
+ self.basic = base.basic
+ self.array = base.array
+ self.dim = base.dim
+ self.max_count = base.max_count
+ self.max_obj = base.max_obj
+ self.members = base.members
+
+ if array:
+ if base.array:
+ xdr.error("Array-of-array not supported")
+ self.array = array
+ self.dim = dim
+ self.max_count = max_count
+ elif (self.is_single_string() or self.is_single_opaque()) and max_obj:
+ if self.max_obj:
+ xdr.error("Maximum size already set on string/opaque")
+ self.max_obj = max_obj
+ else:
+ if name and not isinstance(name, str):
+ raise TypeError("Type name is not a string")
+ if c_name and not isinstance(c_name, str):
+ raise TypeError("C type name is not a string")
+ if basic and not isinstance(basic, xdr_basic):
+ raise TypeError("Invalid basic XDR type")
+ self.name = name
+ self.c_name = c_name
+ self.basic = basic
+ self.array = array
+ self.array = array
+ self.dim = dim
+ self.max_obj = max_obj
+ self.max_count = max_count
+ self.members = members
+ if members:
+ if not isinstance(members, list):
+ raise RuntimeError("Members should be a list")
+
+ if not self.basic:
+ raise RuntimeError("basic type unset")
+
+ typespec = str(self)
+ if typespec not in xdr.typespecs:
+ xdr.typespecs[typespec] = self
+
+
+ def is_int(self):
+ return self.basic == xdr_basic.int32 or self.basic == xdr_basic.int64
+
+ def is_int32(self):
+ return self.basic == xdr_basic.int32
+
+ def is_int64(self):
+ return self.basic == xdr_basic.int64
+
+ def is_string(self):
+ return self.basic == xdr_basic.string
+
+ def is_opaque(self):
+ return self.basic == xdr_basic.opaque
+
+ def is_struct(self):
+ return self.basic == xdr_basic.struct
+
+ def is_union(self):
+ return self.basic == xdr_basic.union
+
+ def is_compound(self):
+ return self.is_struct() or self.is_union()
+
+ def is_uuid(self):
+ return self.basic == xdr_basic.opr_uuid
+
+ def is_single_int(self):
+ return not self.array and self.is_int()
+
+ def is_single_int32(self):
+ return not self.array and self.is_int32()
+
+ def is_single_int64(self):
+ return not self.array and self.is_int64()
+
+ def is_single_string(self):
+ return not self.array and self.is_string()
+
+ def is_single_opaque(self):
+ return not self.array and self.is_opaque()
+
+ def is_single_basic(self):
+ return not self.array and not self.is_compound()
+
+ def is_single_struct(self):
+ return not self.array and self.is_struct()
+
+ def is_single_union(self):
+ return not self.array and self.is_union()
+
+ def is_single_compound(self):
+ return not self.array and self.is_compound()
+
+ def is_single_uuid(self):
+ return not self.array and self.is_uuid()
+
+ def is_single(self):
+ return not self.array
+
+ def is_array(self):
+ return self.array == xdr_array.fixed
+
+ def is_char_array(self):
+ return self.array == xdr_array.fixed and self.name == "char"
+
+ def is_int32_array(self):
+ return self.array == xdr_array.fixed and self.is_int32()
+
+ def is_int64_array(self):
+ return self.array == xdr_array.fixed and self.is_int64()
+
+ def is_int_array(self):
+ return self.array == xdr_array.fixed and self.is_int()
+
+ def is_struct_array(self):
+ return self.array == xdr_array.fixed and self.is_struct()
+
+ def is_bulk(self):
+ return self.array == xdr_array.bulk
+
+ def is_bulk_char(self):
+ return self.is_bulk() and self.name == "char"
+
+ def is_bulk_int32(self):
+ return self.is_bulk() and self.is_int32()
+
+ def is_bulk_int64(self):
+ return self.is_bulk() and self.is_int64()
+
+ def is_bulk_int(self):
+ return self.is_bulk() and self.is_int()
+
+ def is_bulk_struct(self):
+ return self.is_bulk() and self.is_struct()
+
+ def is_flat(self):
+ if self.flat != None:
+ return self.flat
+ if self.is_bulk() or self.is_string() or self.is_opaque():
+ self.flat = False
+ return False
+ if self.members:
+ for i in self.members:
+ if not i.is_flat():
+ self.flat = False
+ return False
+ self.flat = True
+ return True
+
+ def what_max_obj(self):
+ if self.max_obj != None:
+ return self.max_obj
+ return "UINT_MAX"
+
+ def what_max_count(self):
+ if self.max_count != None:
+ return self.max_count
+ return "UINT_MAX"
+
+ def __str__(self):
+ t = self.name
+ if self.is_array():
+ t += "[{:s}]".format(str(self.dim))
+ elif self.is_bulk() or self.is_string() or self.is_opaque():
+ if self.max_count:
+ t += "<{:s}>".format(str(self.max_count))
+ if self.max_obj:
+ t += "<{:s}>".format(str(self.max_obj))
+ else:
+ t += "<>"
+ return t
+
+###############################################################################
+#
+# XDR structure member definition
+#
+###############################################################################
+class xdr_member(token_base):
+ """A structure member"""
+ def __init__(self, name, typespec, xdr):
+ self.typespec = typespec
+ self.ty = typespec
+ self.dim = typespec.dim
+ self.max_obj = typespec.max_obj
+ self.max_count = typespec.max_count
+ self.name = name
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+ self.special = None
+
+ def is_int(self): return self.ty.is_int()
+ def is_int32(self): return self.ty.is_int32()
+ def is_int64(self): return self.ty.is_int64()
+ def is_string(self): return self.ty.is_string()
+ def is_opaque(self): return self.ty.is_opaque()
+ def is_struct(self): return self.ty.is_struct()
+ def is_union(self): return self.ty.is_union()
+ def is_compound(self): return self.ty.is_compound()
+ def is_single_int(self): return self.ty.is_single_int()
+ def is_single_int32(self): return self.ty.is_single_int32()
+ def is_single_int64(self): return self.ty.is_single_int64()
+ def is_single_string(self): return self.ty.is_single_string()
+ def is_single_opaque(self): return self.ty.is_single_opaque()
+ def is_single_basic(self): return self.ty.is_single_basic()
+ def is_single_struct(self): return self.ty.is_single_struct()
+ def is_single_union(self): return self.ty.is_single_union()
+ def is_single_uuid(self): return self.ty.is_single_uuid()
+ def is_single_compound(self): return self.ty.is_single_compound()
+ def is_single(self): return self.ty.is_single()
+ def is_array(self): return self.ty.is_array()
+ def is_char_array(self): return self.ty.is_char_array()
+ def is_int32_array(self): return self.ty.is_int32_array()
+ def is_int64_array(self): return self.ty.is_int64_array()
+ def is_int_array(self): return self.ty.is_int_array()
+ def is_struct_array(self): return self.ty.is_struct_array()
+ def is_bulk(self): return self.ty.is_bulk()
+ def is_bulk_char(self): return self.ty.is_bulk_char()
+ def is_bulk_int32(self): return self.ty.is_bulk_int32()
+ def is_bulk_int64(self): return self.ty.is_bulk_int64()
+ def is_bulk_int(self): return self.ty.is_bulk_int()
+ def is_bulk_struct(self): return self.ty.is_bulk_struct()
+ def is_flat(self): return self.ty.is_flat()
+ def what_max_obj(self): return self.ty.what_max_obj()
+ def what_max_count(self): return self.ty.what_max_count()
+
+
+###############################################################################
+#
+# XDR type alias definition
+#
+###############################################################################
+class xdr_type_alias(token_base):
+ """A type alias"""
+ def __init__(self, name, typespec, xdr):
+ if not isinstance(typespec, xdr_type):
+ raise TypeError("Base type is not a type")
+ self.name = name
+ self.typespec = typespec
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+
+###############################################################################
+#
+# XDR union case definition
+#
+###############################################################################
+class xdr_union_case(token_base):
+ """An XDR union case"""
+ def __init__(self, xdr, tag, members):
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+ self.tag = tag
+ self.members = members
+
+###############################################################################
+#
+# XDR procedure member definition
+#
+###############################################################################
+class xdr_proc(token_base):
+ """An XDR procedure"""
+ def __init__(self, name, xdr, params, opcode, multi=False, split=False):
+ self.package = xdr.pkg
+ self.name = name
+ self.source = xdr.source
+ self.lineno = xdr.lineno
+ self.params = params
+ self.opcode = opcode
+ self.multi = multi
+ self.split = split
+
+###############################################################################
+#
+# Generated file writer class
+#
+###############################################################################
+class file_generator:
+ """File generator class"""
+ def __init__(self, xdr, prefix):
+ self.xdr = xdr
+ self._rxhdr = open(prefix + "afs_xg.H", "w", encoding="utf-8")
+ self._rxsrc = open(prefix + "afs_xg.C", "w", encoding="utf-8")
+
+ def rxhdr(self, *va):
+ for i in va:
+ self._rxhdr.write(str(i))
+
+ def rxsrc(self, *va):
+ for i in va:
+ self._rxsrc.write(str(i))
+
+ def rxhdrf(self, fmt, *va):
+ self._rxhdr.write(fmt.format(*va))
+
+ def rxsrcf(self, fmt, *va):
+ self._rxsrc.write(fmt.format(*va))
+
+ def where(self, loc):
+ self._where = loc + ": "
+
+ def error(self, *va):
+ if self._where:
+ sys.stdout.write(self._where)
+ for i in va:
+ sys.stdout.write(str(i))
+ sys.stdout.write("\n")