From 2e4973ec66cd8ae12d4253e3c3ad9e36a8a4bca6 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 12 Oct 2009 09:10:47 +0000 Subject: [PATCH] Rewrite genwrap.py to use external templates for more flexibility --- Makefile | 7 +- genwrap.py | 554 ++++++++++++++++++-------------------- gl.io | 24 ++ source/functions.enum.t | 9 + source/gldecoder.funcs.t | 37 +++ source/gldecoder.struct.t | 15 ++ source/glprint.funcs.t | 36 +++ source/glwrap.funcs.t | 29 ++ 8 files changed, 417 insertions(+), 294 deletions(-) create mode 100644 gl.io create mode 100644 source/functions.enum.t create mode 100644 source/gldecoder.funcs.t create mode 100644 source/gldecoder.struct.t create mode 100644 source/glprint.funcs.t create mode 100644 source/glwrap.funcs.t diff --git a/Makefile b/Makefile index 736f05a..33a2f4e 100644 --- a/Makefile +++ b/Makefile @@ -35,8 +35,11 @@ source/commandinterpreter.o: source/commandinterpreter.cpp source/gldbg.h source/process.o: source/process.cpp source/process.h $(CXX) -c $(CXXFLAGS) $(CXXFLAGS_gldbg) -o $@ $< -gensrc/functions.enum gensrc/gldecoder.funcs gensrc/gldecoder.struct gensrc/glwrap.funcs gensrc/glprint.funcs: gensrc/.created genwrap.py gl.spec gl.tm - python ./genwrap.py +gensrc/%: source/%.t gensrc/.created genwrap.py + python ./genwrap.py $< >$@ + +#gensrc/functions.enum gensrc/gldecoder.funcs gensrc/gldecoder.struct gensrc/glwrap.funcs gensrc/glprint.funcs: gensrc/.created genwrap.py gl.spec gl.tm +# python ./genwrap.py gensrc/.created: mkdir -p gensrc diff --git a/genwrap.py b/genwrap.py index c388f7c..f507ce2 100755 --- a/genwrap.py +++ b/genwrap.py @@ -4,318 +4,288 @@ import sys import os -outdir="gensrc" - -typemap = {} -for line in open("gl.tm"): - if line[0]=='#': - continue - parts = [p.strip() for p in line.split(',')] - typemap[parts[0]] = parts[3] -typemap["void"] = "void" - -def getparam(func, name): - for p in func[2]: - if p[0]==name: - return p - -funcs = [] -cur_func = None -for line in open("gl.spec"): - if line[0]=='#' or line.find(':')>=0: - continue - elif line[0]=='\t' and cur_func: - parts = line.split() - if parts[0]=="return": - cur_func[1] = typemap[parts[1]] - elif parts[0]=="param": - p = getparam(cur_func, parts[1]) - p[2] = parts[2] - p[1] = typemap[parts[2]] - if parts[4]=="array": - p[1] += " *" - if parts[3]=="in": - p[1] = "const "+p[1] - s = parts[5][1:-1] - if s.isdigit(): - p[3] = int(s) - elif s=="" or (len(parts)>=7 and parts[6]=="retained"): - p[3] = "~" - else: - p[3] = s +def strip_name(name): + """Strips any vendor suffix and GL prefix from a name (but not GLX prefix)""" + + suffix = "" + if name.endswith(" *"): + suffix = " *" + name = name[:-2] + elif name.endswith("Pointer"): + suffix = "Pointer" + name = name[:-7] + + prefix = "" + if name.startswith("const "): + prefix = "const " + name = name[6:] + + if name.startswith("GL") and not name.startswith("GLX"): + name = name[2:] + if name.endswith(("EXT", "ARB", "SGI", "IBM", "ATI")): + return prefix+name[:-3]+suffix + elif name.endswith("SGIX"): + return prefix+name[:-4]+suffix + elif name.endswith(("NV", "HP")): + return prefix+name[:-2]+suffix else: - paren = line.find('(') - if paren>0: - cparen = line.rfind(')') - if cparen>paren+1: - args = line[paren+1:cparen].split(", ") + return prefix+name+suffix + + +class Typemap: + def __init__(self, fn): + self.map = {} + for line in open(fn): + if line[0]=='#': + continue + parts = [p.strip() for p in line.split(',')] + if parts[3]=="*": + parts[3] = parts[0] + elif parts[3][-1]=='*' and parts[3][-2]!=' ': + parts[3] = parts[3][:-1]+" *" + self.map[tuple(parts[0:3])] = tuple(parts[3:6]) + + def wildcard_match(self, a, b): + if a=="*" or b=="*": + return True + return a==b + + def __getitem__(self, key): + return self.map[(key[0], "*", "*")] + for k, v in self.map.iteritems(): + if strip_name(k[0])==strip_name(key[0]) and self.wildcard_match(k[1], key[1]) and self.wildcard_match(k[2], key[2]): + return v + raise KeyError, key + + def update(self, other): + self.map.update(other.map) + + +class IOmap: + def __init__(self, fn): + self.map = {} + self.map["void"] = None + for line in open(fn): + if line[0]=='#': + continue + parts = [p.strip() for p in line.split(',')] + self.map[parts[0]] = tuple(parts[1:]) + + def __getitem__(self, key): + return self.map[strip_name(key)] + + +class Function: + class Parameter: + def __init__(self, func, name): + self.func = func + self.name = name + self.type = None + self.direction = "in" + self.kind = "value" + self.size = None + self.ctype = None + self.csize = None + self.io = None + + def set_type(self, type, dir, kind): + self.type = type + self.direction = dir + self.kind = kind + self.ctype = typemap[(type, dir, kind)][0] + self.base_ctype = self.ctype + if self.kind=="value": + if self.base_ctype.startswith("const "): + self.base_ctype = self.base_ctype[6:] + self.io = iomap[self.base_ctype] + else: + if self.direction=="in": + self.ctype = "const "+self.ctype + self.ctype = self.ctype+" *" + #print "%s | %s | %s | %s | %s"%(self.func.name, self.name, self.type, self.ctype, self.base_ctype) + + def set_size(self, size): + if type(size)==str and size.isdigit(): + self.size = int(size) else: - args = [] - cur_func = [line[:paren], None, [[a, None, None, 0] for a in args]] - funcs.append(cur_func) - -fmtmap = {"GLenum":"%#x", - "GLboolean":"%i", - "GLbitfield":"%#x", - "GLbyte":"%i", - "GLshort":"%i", - "GLint":"%i", - "GLubyte":"%u", - "GLushort":"%u", - "GLuint":"%u", - "GLsizei":"%i", - "GLfloat":"%g", - "GLclampf":"%g", - "GLdouble":"%lg", - "GLclampd":"%lg", - "const GLubyte *":"%s", - "GLchar *":"%s", - "GLcharARB *":"%s", - "GLvoid*":"%p", - "GLsizeiptr":"%d", - "GLsizeiptrARB":"%d", - "GLintptr":"%d", - "GLintptrARB":"%d", - "GLhandleARB":"%i", - "GLhalfNV":"%#x", - "GLuint64EXT":"%lld"} - -iomap = {"GLenum":"int", - "GLboolean":"char", - "GLbitfield":"int", - "GLbyte":"char", - "GLshort":"short", - "GLint":"int", - "GLubyte":"char", - "GLushort":"short", - "GLuint":"int", - "GLsizei":"int", - "GLfloat":"float", - "GLclampf":"float", - "GLdouble":"double", - "GLclampd":"double", - "const GLubyte *":"string", - "GLchar *":"string", - "GLcharARB *":"string", - "GLvoid*":"pointer", - "GLsizeiptr":"int", - "GLsizeiptrARB":"int", - "GLintptr":"int", - "GLintptrARB":"int", - "GLhandleARB":"int", - "GLhalfNV":"short", - "GLuint64EXT":"longlong"} - -def basetype(type, is_array): - if type.startswith("const "): - type = type[6:] - if is_array and type.endswith(" *"): - type = type[:-2] - return type - -def compsize(func, size, ptype): + self.size = size + + def finalize(self): + if self.kind=="array": + self.csize = None + if type(self.size)==int: + self.csize = "%d*sizeof(%s)"%(self.size, self.base_ctype) + elif self.size.startswith("COMPSIZE("): + self.csize = compsize(self.func, self.size[9:-1], self.base_ctype) + elif self.size=="" and (self.type=="charARB" or self.type=="Char"): + self.csize = "strlen" + else: + s = self.func.get_param(self.size.split('*')[0]) + if (s.type=="SizeI" or s.type.endswith("Int32") or s.type.startswith("BufferSize")) and s.kind=="value": + self.csize = "%s*sizeof(%s)"%(self.size, self.base_ctype) + if self.func.name.startswith("Uniform") and self.func.name[7].isdigit(): + self.csize += "*%s"%func.name[7] + if not self.csize: + sys.stderr.write("Could not determine size for array parameter '%s[%s]' of function '%s'\n"%(self.name, self.size, self.func.name)) + elif self.kind=="reference": + self.csize = "sizeof(%s)"%self.base_ctype + + def __init__(self, name, pnames): + self.name = name + self.ret = Function.Parameter(self, "ret") + self.params = [Function.Parameter(self, n) for n in pnames] + self.category = None + + def get_param(self, pname): + for p in self.params: + if p.name==pname: + return p + raise KeyError, pname + + def set_category(self, cat): + self.category = cat + + def finalize(self): + for p in self.params: + p.finalize() + + +def read_spec(fn, prefix): + funcs = [] + cur_func = None + for line in open(fn): + if line[0]=='#' or line.find(':')>=0: + continue + elif line[0]=='\t' and cur_func: + parts = line.split() + if parts[0]=="return": + cur_func.ret.set_type(parts[1], "out", "value") + elif parts[0]=="param": + bracket = parts[4].find('[') + if bracket>=0: + parts.insert(5, parts[4][bracket:]) + parts[4] = parts[4][:bracket] + + param = cur_func.get_param(parts[1]) + param.set_type(parts[2], parts[3], parts[4]) + if len(parts)>=6: + param.set_size(parts[5][1:-1]) + elif parts[0]=="category": + cur_func.set_category(parts[1]) + elif parts[0]=="glxvendorglx" and cur_func.category=="glx": + cur_func.set_category("glxext") + else: + paren = line.find('(') + if paren>0: + cparen = line.rfind(')') + if cparen>paren+1: + pnames = [n.strip() for n in line[paren+1:cparen].split(",")] + else: + pnames = [] + cur_func = Function(prefix+line[:paren], pnames) + funcs.append(cur_func) + for f in funcs: + f.finalize() + return funcs + +typemap = None +iomap = None +functions = [] +sections = [] + +def add_section(text, literal): + global sections + + if literal: + sections.append(text) + else: + sections.append(compile(text, "-", "exec")) + +def read_template(fn): + global typemap + global iomap + global functions + + literal = True + text = "" + for line in open(fn): + if line[0]=='#': + continue + elif line[0]=='^': + parts = line[1:].split() + if parts[0]=="typemap": + typemap = Typemap(parts[1]) + elif parts[0]=="iomap": + iomap = IOmap(parts[1]) + elif parts[0]=="spec": + functions = read_spec(parts[2], parts[1]) + elif line[0]==':': + if not literal and text: + add_section(text, literal) + text = "" + text += line[1:] + literal = True + else: + if literal and text: + add_section(text, literal) + text = "" + text += line + literal = False + if text: + add_section(text, literal) + +def compsize(func, size, btype): if not size: return res = "" have_type = False - for c in size.split('/'): - p = getparam(func, c) - if not p: + for c in size.replace(',', '/').split('/'): + param = func.get_param(c) + if not param: + sys.stderr.write("Compsize '%s' for function '%s' failed: No parameter '%s'\n"%(size, func.name, c)) return if res: res += "*" - cn = p[2] - if cn.endswith(("EXT", "ARB", "SGI", "IBM", "ATI")): - cn = cn[:-3] - elif cn.endswith("SGIX"): - cn = cn[:-4] - elif cn.endswith(("NV", "HP")): - cn = cn[:-2] + cn = strip_name(param.type) if cn.endswith("Type"): - res += "typesize(%s)"%p[0] + res += "typesize(%s)"%param.name have_type = True elif cn.endswith("Format"): - res += "formatsize(%s)"%p[0] + res += "formatsize(%s)"%param.name elif cn.endswith(("Parameter", "ParameterPName", "ParameterName")) or cn=="GetPName": - res += "paramsize(%s)"%p[0] + res += "paramsize(%s)"%param.name elif cn=="MapTarget": - res += "mapsize(%s)"%p[0] - elif (cn=="SizeI" or cn.endswith("Int32")) and p[3]==0: - res += p[0] + res += "mapsize(%s)"%param.name + elif (cn=="SizeI" or cn.endswith("Int32")) and not param.size: + res += param.name else: + sys.stderr.write("Compsize '%s' for function '%s' failed: Parameter '%s' has unknown type '%s'\n"%(size, func.name, param.name, param.type)) return if not have_type: - res += "*sizeof(%s)"%ptype + res += "*sizeof(%s)"%param.ctype return res -def getfmt(param): - ptype = basetype(param[1], param[3]!=0) - if param[3]: - if type(param[3])==int: - return ("{%s}"%(", ".join([fmtmap[ptype]]*param[3])), ", ".join("%s[%d]"%(param[0], i) for i in range(param[3]))) - else: - return ("%p", param[0]) - else: - return (fmtmap[ptype], param[0]) - -def getrwinfo(func, param): - ptype = basetype(param[1], param[3]!=0) - if param[3]: - if type(param[3])==int: - size = "%d*sizeof(%s)"%(param[3], ptype) - elif param[3].startswith("COMPSIZE("): - size = compsize(func, param[3][9:-1], ptype) - if not size: - print "Compsize '%s' for function '%s' failed"%(param[3][9:-1], func[0]) - return ("pointer", None, "void **") - elif param[3]=="~": - if param[2]=="charARB" or param[2]=="Char": - return ("string", None, "const unsigned char **") - else: - return ("pointer", None, "void **") - else: - s = getparam(func, param[3].split('*')[0]) - if s and (s[2]=="SizeI" or s[2].endswith("Int32") or s[2].startswith("BufferSize")) and s[3]==0: - size = "%s*sizeof(%s)"%(param[3], ptype) - if func[0].startswith("Uniform") and func[0][8]!='u' and func[0][7].isdigit(): - size += "*%s"%func[0][7] - else: - print "Could not determine size for array parameter '%s[%s]' of function '%s'"%(param[0], param[3], func[0]) - return ("pointer", None, "void **") - return ("data", size, "const void **") +read_template(sys.argv[1]) + +def write(str, *args): + sys.stdout.write(str%args) + +def writeln(str, *args): + sys.stdout.write(str%args+"\n") + +for sect in sections: + if type(sect)==str: + print sect else: - return (iomap[ptype], None, None) - -# Write out function enums - -out = open(os.path.join(outdir, "functions.enum"), "w"); -out.write("""enum Function -{ - FUNC_NONE, -""") -for f in funcs: - out.write("\tFUNC_%s,\n"%f[0].upper()) -out.write("};\n") -out.close() - -# Write out wrapper functions for transmitting side - -out = open(os.path.join(outdir, "glwrap.funcs"), "w") -for f in funcs: - out.write("%s APIENTRY gl%s(%s)\n{\n"%(f[1], f[0], ", ".join("%s %s"%(p[1], p[0]) for p in f[2]))) - - out.write("\tstatic %s (*orig)(%s) = NULL;\n"%(f[1], ", ".join(p[1] for p in f[2]))) - if f[1]!="void": - out.write("\t%s ret;\n"%f[1]) - out.write("\tif(!orig)\n\t\torig = glsym(\"gl%s\");\n"%f[0]) - - out.write("\t") - if f[1]!="void": - out.write("ret = ") - out.write("orig(%s);\n"%(", ".join(p[0] for p in f[2]))) - - out.write("\tbegin_packet(FUNC_%s);\n"%f[0].upper()) - if f[1]!="void": - out.write("\twrite_%s(ret);\n"%iomap[f[1]]) - for p in f[2]: - (t, s, c) = getrwinfo(f, p) - out.write("\twrite_%s(%s"%(t, p[0])) - if s: - out.write(", %s"%s) - out.write(");\n") - out.write("\tsend_packet();\n") - - if f[1]!="void": - out.write("\treturn ret;\n") - out.write("}\n\n") -out.close() - -# Write out decoder stuff - -out = open(os.path.join(outdir, "gldecoder.struct"), "w") -out.write("typedef struct sGlDecoder\n{\n") -out.write("\tvoid *user_data;\n") -out.write("\tvoid (*destroy)(void *);\n") -for f in funcs: - out.write("\tvoid (*%s)(void *"%f[0]) - if f[1]!="void": - out.write(", %s"%f[1]) - if f[2]: - out.write(", %s"%(", ".join(p[1] for p in f[2]))) - out.write(");\n") -out.write("} GlDecoder;\n") - -out = open(os.path.join(outdir, "gldecoder.funcs"), "w") -for f in funcs: - out.write("static unsigned decode_%s(GlDecoder *dec, const char *data)\n{\n"%(f[0])) - out.write("\tunsigned pos = 0;\n") - if f[1]!="void": - out.write("\t%s ret;\n"%f[1]) - for p in f[2]: - out.write("\t%s arg_%s;\n"%(p[1], p[0])) - if f[1]!="void": - out.write("\tpos += read_%s(&ret, data+pos);\n"%iomap[f[1]]) - for p in f[2]: - (t, s, c) = getrwinfo(f, p) - if c: - c="(%s)"%c - else: - c="" - out.write("\tpos += read_%s(%s&arg_%s, data+pos);\n"%(t, c, p[0])) - out.write("\tif(dec->%s)\n"%f[0]) - out.write("\t\tdec->%s(dec->user_data"%f[0]) - if f[1]!="void": - out.write(", ret") - if f[2]: - out.write(", %s"%(", ".join("arg_"+p[0] for p in f[2]))) - out.write(");\n") - out.write("\treturn pos;\n") - out.write("}\n\n") - -out.write("""static int decode_func(GlDecoder *dec, short func, const char *data) -{ - switch(func) - { -""") -for f in funcs: - out.write("\t\tcase FUNC_%s: return decode_%s(dec, data);\n"%(f[0].upper(), f[0])) -out.write(""" } - - return -1; -} -""") -out.close() - -# Write out print stuff - -out = open(os.path.join(outdir, "glprint.funcs"), "w") -for f in funcs: - out.write("static void print_%s(void *user_data"%f[0]) - if f[1]!="void": - out.write(", %s ret"%f[1]) - if f[2]: - out.write(", %s"%(", ".join("%s %s"%(p[1], p[0]) for p in f[2]))) - out.write(")\n{\n") - out.write("\tGlPrintData *gpd = (GlPrintData *)user_data;\n") - - m = [getfmt(p) for p in f[2]] - out.write("\tsnprintf(gpd->buffer, gpd->bufsize, \"%s(%s)"%(f[0], ", ".join(p[0] for p in m))) - if f[1]!="void": - out.write(" = %s"%fmtmap[f[1]]) - out.write("\"") - if m: - out.write(", %s"%(", ".join(p[1] for p in m))) - if f[1]!="void": - out.write(", ret") - out.write(");\n") - - out.write("}\n\n") - -out.write("static void init_print(GlDecoder *dec)\n{\n") -for f in funcs: - out.write("\tdec->%s = print_%s;\n"%(f[0], f[0])) -out.write("}\n") -out.close() + for func in functions: + globals = { + "w": write, + "wl": writeln, + "func": func, + "ret": func.ret, + "params": func.params + } + eval(sect, globals) diff --git a/gl.io b/gl.io new file mode 100644 index 0000000..85c9aaf --- /dev/null +++ b/gl.io @@ -0,0 +1,24 @@ +enum, int, %#x +boolean, char, %i +bitfield, int, %#x +byte, char, %i +ubyte, char, %u +short, short, %i +ushort, short, %u +int, int, %i +uint, int, %u +unsigned int, int, %u +sizei, int, %i +intptr, int, %i +sizeiptr, int, %i +handle, int, %i +int64_t, longlong, %lli +uint64, longlong, %llu +half, short, %#x +float, float, %g +clampf, float, %g +double, double, %g +clampd, double, %g +ubyte *, string, %s +char *, string, %s +void *, pointer, %p diff --git a/source/functions.enum.t b/source/functions.enum.t new file mode 100644 index 0000000..92fef70 --- /dev/null +++ b/source/functions.enum.t @@ -0,0 +1,9 @@ +# $Id$ +^typemap gl.tm +^iomap gl.io +^spec gl gl.spec +:enum Function +:{ +: FUNC_NONE, +wl(' FUNC_%s,', func.name.upper()) +:}; diff --git a/source/gldecoder.funcs.t b/source/gldecoder.funcs.t new file mode 100644 index 0000000..055a272 --- /dev/null +++ b/source/gldecoder.funcs.t @@ -0,0 +1,37 @@ +# $Id$ +^typemap gl.tm +^iomap gl.io +^spec gl gl.spec +wl('static unsigned decode_%s(GlDecoder *dec, const char *data)', func.name) +wl('{') +wl(' unsigned pos = 0;') +if ret.ctype!="void": + wl(' %s ret;', ret.ctype) +for p in params: + wl(' %s p_%s;', p.ctype, p.name) +if ret.ctype!="void": + wl(' pos += read_%s(&ret, data+pos);', ret.io[0]) +for p in params: + if p.kind=="value": + wl(' pos += read_%s(&p_%s, data+pos);', p.io[0], p.name) + elif p.csize: + wl(' pos += read_data((const void **)&p_%s, data+pos);', p.name) + else: + wl(' pos += read_pointer((void **)&p_%s, data+pos);', p.name) +wl(' if(dec->%s)', func.name) +w(' dec->%s(dec->user_data', func.name) +if ret.ctype!="void": + w(', ret') +for p in params: + w(', p_%s', p.name) +wl(');') +wl(' return pos;') +wl('}') +:static int decode_func(GlDecoder *dec, short func, const char *data) +:{ +: switch(func) +: { +wl(' case FUNC_%s: return decode_%s(dec, data);', func.name.upper(), func.name) +: default: return -1; +: } +:} diff --git a/source/gldecoder.struct.t b/source/gldecoder.struct.t new file mode 100644 index 0000000..e4cf5c6 --- /dev/null +++ b/source/gldecoder.struct.t @@ -0,0 +1,15 @@ +# $Id$ +^typemap gl.tm +^iomap gl.io +^spec gl gl.spec +:typedef struct sGlDecoder +:{ +: void *user_data; +: void (*destroy)(void *); +w(' void (*%s)(void *', func.name) +if ret.ctype!="void": + w(', %s', ret.ctype) +for p in params: + w(', %s', p.ctype) +wl(');') +:} GlDecoder; diff --git a/source/glprint.funcs.t b/source/glprint.funcs.t new file mode 100644 index 0000000..927fa36 --- /dev/null +++ b/source/glprint.funcs.t @@ -0,0 +1,36 @@ +# $Id$ +^typemap gl.tm +^iomap gl.io +^spec gl gl.spec +w('static void print_%s(void *user_data', func.name) +if ret.ctype!="void": + w(', %s ret', ret.ctype) +for p in params: + w(', %s %s', p.ctype, p.name) +wl(')') +wl('{') +wl(' GlPrintData *gpd = (GlPrintData *)user_data;') +w(' snprintf(gpd->buffer, gpd->bufsize, "%s(', func.name) +first = True +for p in params: + if not first: + w(', ') + if p.kind=="value": + w("%s", p.io[1]) + else: + w("%%p") + first = False +w(')') +if ret.ctype!="void": + w(' = %s', ret.io[1]) +w('"') +for p in params: + w(', %s', p.name) +if ret.ctype!="void": + w(', ret') +wl(');') +wl('}') +:static void init_print(GlDecoder *dec) +:{ +wl(' dec->%s = print_%s;', func.name, func.name) +:} diff --git a/source/glwrap.funcs.t b/source/glwrap.funcs.t new file mode 100644 index 0000000..108f329 --- /dev/null +++ b/source/glwrap.funcs.t @@ -0,0 +1,29 @@ +# $Id$ +^typemap gl.tm +^iomap gl.io +^spec gl gl.spec +wl('%s APIENTRY %s(%s)', ret.ctype, func.name, ", ".join([p.ctype+" "+p.name for p in params])) +wl('{') +wl(' static %s (*orig)(%s);', ret.ctype, ", ".join([p.ctype for p in params])) +if ret.ctype!='void': + wl(' %s ret;', ret.ctype) +wl(' if(!orig)') +wl(' orig = glsym("%s");', func.name) +w(' ') +if ret.ctype!='void': + w('ret = ') +wl('orig(%s);', ", ".join([p.name for p in params])) +wl(' begin_packet(FUNC_%s);', func.name.upper()) +if ret.ctype!='void': + wl(' write_%s(ret);', ret.io[0]) +for p in params: + if p.kind=="value": + wl(' write_%s(%s);', p.io[0], p.name) + elif p.csize: + wl(' write_data(%s, %s);', p.name, p.csize) + else: + wl(' write_pointer(%s);', p.name) +wl(' send_packet();') +if ret.ctype!='void': + wl(' return ret;') +wl('}') -- 2.43.0