From 829bfb392fb33a727196fc8beb64f10cb0953c73 Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Fri, 8 Mar 2024 15:01:57 +0100 Subject: [PATCH] scripts: add generator for extension marshal glue code Automatically generate extension marshal glue code like the infamous SProc*()'s for byte swapping, dispatch functions, etc, based on a tiny yaml discription. Signed-off-by: Enrico Weigelt, metux IT consult --- meson.build | 3 + scripts/generate-ext-marshal | 104 +++++++++++++++++++++++++++++++++++ scripts/meson.build | 6 ++ 3 files changed, 113 insertions(+) create mode 100755 scripts/generate-ext-marshal create mode 100644 scripts/meson.build diff --git a/meson.build b/meson.build index 858d0de978..1da3695ddb 100644 --- a/meson.build +++ b/meson.build @@ -775,6 +775,9 @@ if build_docs or build_docs_devel ] endif +# init tool scripts +subdir('scripts') + # Include must come first, as it sets up dix-config.h subdir('include') diff --git a/scripts/generate-ext-marshal b/scripts/generate-ext-marshal new file mode 100755 index 0000000000..e9f387ed8a --- /dev/null +++ b/scripts/generate-ext-marshal @@ -0,0 +1,104 @@ +#!/usr/bin/env python3 + +# +# generator for extension marshal glue code +# + +import sys +import yaml + +def fixup_reqspec(reqname, reqspec): + if not 'name' in reqspec: + reqspec['name'] = reqname + if not 'sproc' in reqspec: + reqspec['sproc'] = "SProc%s" % reqspec['name'] + if not 'proc' in reqspec: + reqspec['proc'] = "Proc%s" % reqspec['name'] + if not 'struct' in reqspec: + reqspec['struct'] = "x%sReq" % reqspec['name'] + if not 'code' in reqspec: + reqspec['code'] = "X_%s" % reqspec['name'] + + return reqspec + +def gen_sproc(reqspec): + txt = ("static int _X_COLD %s(ClientPtr client)\n" % reqspec['sproc'] + + "{\n" + + " REQUEST(%s);\n\n" % reqspec['struct'] + + " swaps(&stuff->length);\n") + + if 'payload' in reqspec and reqspec['payload'] is not None: + for pl in reqspec['payload']: + if pl['type'] == "CARD8": + # nothing to do + pass + elif pl['type'] == "CARD16": + txt = txt + " swaps(&stuff->%s);\n" % pl['name'] + elif pl['type'] == "CARD32": + txt = txt + " swapl(&stuff->%s);\n" % pl['name'] + else: + raise Exception("unknown payload type %s in %s field of %s" % (pl['type'], pl['name'], reqspec['name'])) + + txt = (txt + " return %s(client);\n" % reqspec['proc'] + + "}\n\n") + + return txt + +def gen_sdispatch(spec): + procname = "SProc%sDispatch" % spec['extension'] + + txt = ("static int _X_COLD %s(ClientPtr client)\n" % procname + + "{\n" + + " REQUEST(xReq);\n" + + " switch (stuff->data) {\n") + + for rname in spec['requests']: + rspec = fixup_reqspec(rname, spec['requests'][rname]) + txt = txt + " case %s:\n" % rspec['code'] + txt = txt + " return %s(client);\n" % rspec['sproc'] + + return txt + ( + " default:\n" + + " return BadRequest;\n" + + " }\n" + + "}\n") + +def gen_dispatch(spec): + procname = "Proc%sDispatch" % spec['extension'] + + txt = ("static int _X_COLD %s(ClientPtr client)\n" % procname + + "{\n" + + " REQUEST(xReq);\n" + + " switch (stuff->data) {\n") + + for rname in spec['requests']: + rspec = fixup_reqspec(rname, spec['requests'][rname]) + txt = txt + " case %s:\n" % rspec['code'] + txt = txt + " REQUEST_SIZE_MATCH(%s);\n" % rspec['struct'] + txt = txt + " return %s(client);\n" % rspec['sproc'] + + return txt + ( + " default:\n" + + " return BadRequest;\n" + + " }\n" + + "}\n") + +def gen_include(specfile, outfile): + + print("%s: in=%s out=%s" % (sys.argv[0], specfile, outfile)) + + with open(specfile, 'r') as f: + spec = yaml.safe_load(f) + + outf = open(outfile, "w") + + requests = spec['requests'] + for rname in requests: + rspec = fixup_reqspec(rname, requests[rname]) + outf.write(gen_sproc(rspec)) + + outf.write(gen_sdispatch(spec)) + outf.write(gen_dispatch(spec)) + outf.close() + +gen_include(sys.argv[1], sys.argv[2]) diff --git a/scripts/meson.build b/scripts/meson.build new file mode 100644 index 0000000000..217500634c --- /dev/null +++ b/scripts/meson.build @@ -0,0 +1,6 @@ + +extension_marshal_cmd = find_program('generate-ext-marshal') + +extension_marshal_generator = generator(extension_marshal_cmd, + output : '@BASENAME@-marshal.h', + arguments : ['@INPUT@', '@OUTPUT@'])