Commit e446c076 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

More restructuring

parent 98388b66
......@@ -45,8 +45,6 @@ import random
import copy
import json
strict_abi = True
AMBOILERPLATE = '''
# Boilerplate generated by vmodtool.py - changes will be overwritten
......@@ -166,9 +164,18 @@ def lwrap(s, width=64):
p = " "
if len(s) > 0:
ll.append(p + s)
return ll
return "\n".join(ll) + "\n"
def fmt_cstruct(fo, mn, x):
"""
Align fields in C struct
"""
a = "\ttd_" + mn + "_" + x
while len(a.expandtabs()) < 40:
a += "\t"
fo.write("%s*%s;\n" % (a, x))
#######################################################################
......@@ -184,21 +191,11 @@ def err(str, warn=True):
else:
print("WARNING: " + str, file=sys.stderr)
def fmt_cstruct(fo, mn, x):
a = "\ttd_" + mn + "_" + x
while len(a.expandtabs()) < 40:
a += "\t"
fo.write("%s*%s;\n" % (a, x))
#######################################################################
enum_values = {}
class ctype(object):
def __init__(self, wl):
def __init__(self, wl, enums):
self.nm = None
self.defval = None
self.spec = None
......@@ -210,7 +207,7 @@ class ctype(object):
if len(wl) > 0 and wl[0] == "{":
if self.vt != "ENUM":
err("Only ENUMs take {...} specs", warn=False)
self.add_spec(wl)
self.add_spec(wl, enums)
def __str__(self):
s = "<" + self.vt
......@@ -222,15 +219,7 @@ class ctype(object):
s += " SPEC=" + str(self.spec)
return s + ">"
def set_defval(self, x):
if self.vt == "ENUM":
if x[0] == '"' and x[-1] == '"':
x = x[1:-1]
elif x[0] == "'" and x[-1] == "'":
x = x[1:-1]
self.defval = x
def add_spec(self, wl):
def add_spec(self, wl, enums):
assert self.vt == "ENUM"
assert wl.pop(0) == "{"
self.spec = []
......@@ -242,7 +231,7 @@ class ctype(object):
x = x[1:-1]
assert len(x) > 0
self.spec.append(x)
enum_values[x] = True
enums[x] = True
w = wl.pop(0)
if w == "}":
break
......@@ -261,10 +250,48 @@ class ctype(object):
return self.vt
def json(self, jl):
jl.append([self.vt, self.nm, self.defval, self.spec])
jl.append([self.vt])
while jl[-1][-1] is None:
jl[-1].pop(-1)
#######################################################################
class arg(ctype):
def __init__(self, wl, argnames, enums, end):
super(arg, self).__init__(wl, enums)
if wl[0] == end:
return
x = wl.pop(0)
if x in argnames:
err("Duplicate argument name '%s'" % x, warn=False)
argnames[x] = True
self.nm = x
if wl[0] == end:
return
x = wl.pop(0)
if x != "=":
err("Expected '=' got '%s'" % x, warn=False)
x = wl.pop(0)
if self.vt == "ENUM":
if x[0] == '"' and x[-1] == '"':
x = x[1:-1]
elif x[0] == "'" and x[-1] == "'":
x = x[1:-1]
self.defval = x
def json(self, jl):
jl.append([self.vt, self.nm, self.defval, self.spec])
while jl[-1][-1] is None:
jl[-1].pop(-1)
#######################################################################
def lex(l):
wl = []
......@@ -309,65 +336,49 @@ def lex(l):
err("Syntax error at char", i, "'%s'" % c, warn=False)
return wl
#######################################################################
class prototype(object):
def __init__(self, st, retval=True, prefix=""):
global inputline
self.st = st
self.obj = None
inputline = st.line[1]
self.args = []
wl = lex(st.line[1])
if retval:
self.retval = ctype(wl)
self.retval = ctype(wl, st.vcc.enums)
else:
self.retval = ctype(['VOID'], st.vcc.enums)
self.bname = wl.pop(0)
if not re.match("^[a-zA-Z.][a-zA-Z0-9_]*$", self.bname):
err("%s(): Illegal name\n" % self.nname, warn=False)
self.prefix = prefix
self.name = self.prefix + self.bname
self.vcc = st.vcc
self.name = prefix + self.bname
if not re.match('^[a-zA-Z_][a-zA-Z0-9_]*$', self.cname()):
err("%s(): Illegal C-name\n" % self.cname(), warn=False)
x = wl.pop(0)
if x != "(":
err("Syntax error: Expected '(', got '%s'" % x, warn=False)
if len(wl) == 2 and wl[0] == '(' and wl[1] == ')':
return
x = wl.pop(-1)
if x != ")":
err("Syntax error: Expected ')', got '%s'" % x, warn=False)
if wl[0] != "(":
err("Syntax error: Expected '(', got '%s'" % wl[0], warn=False)
wl[0] = ','
if wl[-1] != ")":
err("Syntax error: Expected ')', got '%s'" % wl[-1], warn=False)
wl[-1] = ','
names = {}
self.args = []
while len(wl) > 0:
t = ctype(wl)
self.args.append(t)
if not len(wl):
break
x = wl.pop(0)
if x == ",":
continue
if x in names:
err("%s(): Duplicate argument name" % x, warn=False)
names[x] = True
t.nm = x
if not len(wl):
break
if wl[0] == "=":
wl.pop(0)
t.set_defval(wl.pop(0))
if not len(wl):
if x != ',':
err("Expected ',' found '%s'" % x, warn=False)
if len(wl) == 0:
break
assert wl.pop(0) == ","
inputline = None
def cname(self, pfx=False):
r = self.name.replace(".", "_")
if pfx:
return self.vcc.sympfx + r
return r
t = arg(wl, names, st.vcc.enums, ',')
self.args.append(t)
def vcl_proto(self, short, pfx=""):
if type(self.st) == s_method:
......@@ -420,28 +431,39 @@ class prototype(object):
fo.write(self.vcl_proto(True, pfx=" ") + "\n")
fo.write(" \n")
def c_ret(self):
return self.retval.ct
def cname(self, pfx=False):
r = self.name.replace(".", "_")
if pfx:
return self.st.vcc.sympfx + r
return r
def c_args(self, a=[]):
ll = list(a)
def proto(self, args, name):
s = self.retval.ct + " " + name + '('
ll = args
for i in self.args:
ll.append(i.ct)
return ", ".join(ll)
def c_fn(self, args=[], h=False):
s = fn = ''
if not h:
s += 'typedef '
fn += 'td_' + self.vcc.modname + '_'
fn += self.cname(pfx=h)
s += '%s %s(%s);' % (self.c_ret(), fn, self.c_args(args))
return "\n".join(lwrap(s)) + "\n"
s += ", ".join(ll)
return s + ');'
def typedef(self, args):
tn = 'td_' + self.st.vcc.modname + '_' + self.cname()
return "typedef " + self.proto(args, name=tn)
def cstuff(self, args, where):
if where == 'h':
s = self.proto(args, self.cname(True))
elif where == 'c':
s = self.typedef(args)
elif where == 'o':
s = self.typedef(args)
else:
assert False
return lwrap(s)
def json(self, jl, cfunc):
ll = []
self.retval.json(ll)
ll.append('Vmod_%s_Func.%s' % (self.vcc.modname, cfunc))
ll.append('Vmod_%s_Func.%s' % (self.st.vcc.modname, cfunc))
for i in self.args:
i.json(ll)
jl.append(ll)
......@@ -492,13 +514,10 @@ class stanza(object):
if self.proto is not None:
self.proto.synopsis(fo, man)
def hfile(self, fo):
def cstuff(self, fo, where):
return
def cstruct(self, fo):
return
def cstruct_init(self, fo):
def cstruct(self, fo, define):
return
def json(self, jl):
......@@ -566,11 +585,10 @@ class s_module(stanza):
class s_abi(stanza):
def parse(self):
global strict_abi
if self.line[1] not in ('strict', 'vrt'):
err("Valid ABI types are 'strict' or 'vrt', got '%s'\n" %
self.line[1])
strict_abi = self.line[1] == 'strict'
self.vcc.strict_abi = self.line[1] == 'strict'
self.vcc.contents.append(self)
......@@ -590,14 +608,15 @@ class s_event(stanza):
err("Not emitting .RST for $Event %s\n" %
self.event_func)
def hfile(self, fo):
fo.write("vmod_event_f %s;\n" % self.event_func)
def cstruct(self, fo):
fo.write("\tvmod_event_f\t\t\t*_event;\n")
def cstuff(self, fo, where):
if where == 'h':
fo.write("vmod_event_f %s;\n" % self.event_func)
def cstruct_init(self, fo):
fo.write("\t%s,\n" % self.event_func)
def cstruct(self, fo, define):
if define:
fo.write("\tvmod_event_f\t\t\t*_event;\n")
else:
fo.write("\t%s,\n" % self.event_func)
def json(self, jl):
jl.append([
......@@ -612,17 +631,15 @@ class s_function(stanza):
self.rstlbl = "func_" + self.proto.name
self.vcc.contents.append(self)
def hfile(self, fo):
fo.write(self.proto.c_fn(['VRT_CTX'], True))
def cfile(self, fo):
fo.write(self.proto.c_fn(['VRT_CTX']))
def cstuff(self, fo, where):
if where in ('h', 'c'):
fo.write(self.proto.cstuff(['VRT_CTX'], where))
def cstruct(self, fo):
fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
def cstruct_init(self, fo):
fo.write("\t" + self.proto.cname(pfx=True) + ",\n")
def cstruct(self, fo, define):
if define:
fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
else:
fo.write("\t" + self.proto.cname(pfx=True) + ",\n")
def json(self, jl):
jl.append(["$FUNC", "%s" % self.proto.name])
......@@ -632,7 +649,6 @@ class s_function(stanza):
class s_object(stanza):
def parse(self):
self.proto = prototype(self, retval=False)
self.proto.retval = ctype(['VOID'])
self.proto.obj = "x" + self.proto.name
self.init = copy.copy(self.proto)
......@@ -662,35 +678,27 @@ class s_object(stanza):
for i in self.methods:
i.proto.synopsis(fo, man)
def chfile(self, fo, h):
def cstuff(self, fo, w):
sn = self.vcc.sympfx + self.vcc.modname + "_" + self.proto.name
fo.write("struct %s;\n" % sn)
fo.write(self.init.c_fn(
['VRT_CTX', 'struct %s **' % sn, 'const char *'], h))
fo.write(self.fini.c_fn(['struct %s **' % sn], h))
fo.write(self.init.cstuff(
['VRT_CTX', 'struct %s **' % sn, 'const char *'], w))
fo.write(self.fini.cstuff(['struct %s **' % sn], w))
for i in self.methods:
fo.write(i.proto.c_fn(['VRT_CTX', 'struct %s *' % sn], h))
fo.write(i.proto.cstuff(['VRT_CTX', 'struct %s *' % sn], w))
fo.write("\n")
def hfile(self, fo):
self.chfile(fo, True)
def cfile(self, fo):
self.chfile(fo, False)
def cstruct(self, fo):
fmt_cstruct(fo, self.vcc.modname, self.init.name)
fmt_cstruct(fo, self.vcc.modname, self.fini.name)
for i in self.methods:
i.cstruct(fo)
def cstruct_init(self, fo):
p = "\t" + self.vcc.sympfx
fo.write(p + self.init.name + ",\n")
fo.write(p + self.fini.name + ",\n")
def cstruct(self, fo, define):
if define:
fmt_cstruct(fo, self.vcc.modname, self.init.name)
fmt_cstruct(fo, self.vcc.modname, self.fini.name)
else:
p = "\t" + self.vcc.sympfx
fo.write(p + self.init.name + ",\n")
fo.write(p + self.fini.name + ",\n")
for i in self.methods:
i.cstruct_init(fo)
i.cstruct(fo, define)
fo.write("\n")
def json(self, jl):
......@@ -719,6 +727,8 @@ class s_object(stanza):
for i in self.methods:
i.dump()
#######################################################################
class s_method(stanza):
def parse(self):
......@@ -730,11 +740,11 @@ class s_method(stanza):
self.rstlbl = "func_" + self.proto.name
p.methods.append(self)
def cstruct(self, fo):
fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
def cstruct_init(self, fo):
fo.write('\t' + self.proto.cname(pfx=True) + ",\n")
def cstruct(self, fo, define):
if define:
fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
else:
fo.write('\t' + self.proto.cname(pfx=True) + ",\n")
def json(self, jl):
jl.append(["$METHOD", self.proto.name[len(self.pfx)+1:]])
......@@ -763,6 +773,8 @@ class vcc(object):
self.contents = []
self.commit_files = []
self.copyright = ""
self.enums = {}
self.strict_abi = True
def openfile(self, fn):
self.commit_files.append(fn)
......@@ -773,6 +785,7 @@ class vcc(object):
os.rename(i + ".tmp", i)
def parse(self):
global inputline
a = "\n" + open(self.inputfile, "r").read()
s = a.split("\n$")
self.copyright = s.pop(0).strip()
......@@ -783,11 +796,13 @@ class vcc(object):
i += 1
else:
i = len(ss)
inputline = ss[:i]
c = ss[:i].split()
m = dispatch.get(c[0])
if m is None:
err("Unknown stanze $%s" % ss[:i])
m([c[0], " ".join(c[1:])], ss[i:].split('\n'), self)
inputline = None
def rst_copyright(self, fo):
write_rst_hdr(fo, "COPYRIGHT", "=")
......@@ -818,8 +833,7 @@ class vcc(object):
fo.close()
def amboilerplate(self):
fn = "automake_boilerplate.am"
fo = self.openfile(fn)
fo = self.openfile("automake_boilerplate.am")
fo.write(AMBOILERPLATE.replace("XXX", self.modname))
fo.close()
......@@ -835,30 +849,28 @@ class vcc(object):
fo.write("#endif\n")
fo.write("\n")
for j in sorted(enum_values):
for j in sorted(self.enums):
fo.write("extern VCL_ENUM %senum_%s;\n" % (self.sympfx, j))
fo.write("\n")
for j in self.contents:
j.hfile(fo)
j.cstuff(fo, 'h')
fo.close()
def cstruct(self, fo, csn):
fo.write("\n%s {\n" % csn)
for j in self.contents:
j.cstruct(fo)
fo.write("\n")
for j in sorted(enum_values):
j.cstruct(fo, True)
for j in sorted(self.enums):
fo.write("\tVCL_ENUM\t\t\t*enum_%s;\n" % j)
fo.write("};\n")
def cstruct_init(self, fo, csn):
fo.write("\nstatic const %s Vmod_Func = {\n" % csn)
for j in self.contents:
j.cstruct_init(fo)
j.cstruct(fo, False)
fo.write("\n")
for j in sorted(enum_values):
for j in sorted(self.enums):
fo.write("\t&%senum_%s,\n" % (self.sympfx, j))
fo.write("};\n")
......@@ -887,14 +899,13 @@ class vcc(object):
fo.write(j + "\n")
fo.write("\n")
def api(self, fo):
def vmod_data(self, fo):
vmd = "Vmod_%s_Data" % self.modname
for i in (714, 759, 765):
fo.write("\n/*lint -esym(%d, Vmod_%s_Data) */\n" %
(i, self.modname))
fo.write("\nextern const struct vmod_data Vmod_%s_Data;\n" %
(self.modname))
fo.write("\nconst struct vmod_data Vmod_%s_Data = {\n" % self.modname)
if strict_abi:
fo.write("\n/*lint -esym(%d, %s) */\n" % (i, vmd))
fo.write("\nextern const struct vmod_data %s;\n" % vmd)
fo.write("\nconst struct vmod_data %s = {\n" % vmd)
if self.strict_abi:
fo.write("\t.vrt_major =\t0,\n")
fo.write("\t.vrt_minor =\t0,\n")
else:
......@@ -917,59 +928,55 @@ class vcc(object):
fo.write("};\n")
def cfile(self):
fn = self.pfx + ".c"
fo = self.openfile(fn)
write_c_file_warning(fo)
fno = self.pfx + ".c"
fo = self.openfile(fno)
fnx = fno + ".tmp2"
fx = open(fnx, "w")
fn2 = fn + ".tmp2"
write_c_file_warning(fo)
fo.write('#include "config.h"\n')
fo.write('#include <stdio.h>\n')
for i in ["vdef", "vrt", self.pfx, "vmod_abi"]:
fo.write('#include "%s.h"\n' % i)
fo.write("\n")
for j in sorted(enum_values):
for j in sorted(self.enums):
fo.write('VCL_ENUM %senum_%s = "%s";\n' % (self.sympfx, j, j))
fo.write("\n")
fx = open(fn2, "w")
for i in self.contents:
if type(i) == s_object:
i.cfile(fo)
i.cfile(fx)
i.cstuff(fo, 'c')
i.cstuff(fx, 'c')
fx.write("/* Functions */\n")
for i in self.contents:
if type(i) == s_function:
i.cfile(fo)
i.cfile(fx)
i.cstuff(fo, 'c')
i.cstuff(fx, 'c')
csn = "Vmod_%s_Func" % self.modname
scsn = "struct " + csn
self.cstruct(fo, "struct " + csn)
self.cstruct(fx, "struct " + csn)
self.cstruct(fo, scsn)
self.cstruct(fx, scsn)
fo.write("\n/*lint -esym(754, Vmod_" + self.modname + "_Func::*) */\n")
self.cstruct_init(fo, "struct " + csn)
fo.write("\n/*lint -esym(754, " + csn + "::*) */\n")
self.cstruct_init(fo, scsn)
fx.close()
fo.write("\nstatic const char Vmod_Proto[] =\n")
fi = open(fn2)
for i in fi:
for i in open(fnx):
fo.write('\t"%s\\n"\n' % i.rstrip())
fi.close()
fo.write('\t"static struct %s %s;";\n' % (csn, csn))
os.remove(fn2)
os.remove(fnx)
self.json(fo)
self.api(fo)
self.vmod_data(fo)
fo.close()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment