[master] da62191 First compiler now recoginize what will become "VMOD objects" once I get the other compiler to cope too.

Poul-Henning Kamp phk at varnish-cache.org
Wed Feb 6 15:32:47 CET 2013


commit da621917058b23215cb47ee1ac933ef57e288f74
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Feb 6 14:31:56 2013 +0000

    First compiler now recoginize what will become "VMOD objects"
    once I get the other compiler to cope too.
    
    This snapshot is committed to solicit feedback, so please do :-)

diff --git a/lib/libvcl/vcc_vmod.c b/lib/libvcl/vcc_vmod.c
index c3a2a83..839577d 100644
--- a/lib/libvcl/vcc_vmod.c
+++ b/lib/libvcl/vcc_vmod.c
@@ -167,7 +167,13 @@ vcc_ParseImport(struct vcc *tl)
 	Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
 	for (; *spec != NULL; spec++) {
 		p = *spec;
-		if (!strcmp(p, "INIT")) {
+		if (!strcmp(p, "OBJ")) {
+			// Nothing yet
+		} else if (!strcmp(p, "METHOD")) {
+			// Nothing yet
+		} else if (!strcmp(p, "FINI")) {
+			// Nothing yet
+		} else if (!strcmp(p, "INIT")) {
 			p += strlen(p) + 1;
 			Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n",
 			    p, PF(mod));
diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py
index 284848f..d1dfb68 100755
--- a/lib/libvcl/vmodtool.py
+++ b/lib/libvcl/vmodtool.py
@@ -91,6 +91,8 @@ class token(object):
 	def __repr__(self):
 		return "<@%d \"%s\">" % (self.ln, self.str)
 
+#######################################################################
+
 class vmod(object):
 	def __init__(self, nam):
 		if not is_c_name(nam):
@@ -99,6 +101,7 @@ class vmod(object):
 		self.init = None
 		self.fini = None
 		self.funcs = list()
+		self.objs = list()
 
 	def set_init(self, nam):
 		if self.init != None:
@@ -117,7 +120,12 @@ class vmod(object):
 	def add_func(self, fn):
 		self.funcs.append(fn)
 
+	def add_obj(self, fn):
+		self.objs.append(fn)
+
 	def c_proto(self, fo):
+		for o in self.objs:
+			o.c_proto(fo)
 		for f in self.funcs:
 			f.c_proto(fo)
 		if self.init != None:
@@ -130,105 +138,217 @@ class vmod(object):
 			    "(struct vmod_priv *, const struct VCL_conf *);\n")
 		fo.write("extern const void * const Vmod_Id;\n")
 
-	def c_typedefs(self, fo):
+	def c_typedefs_(self):
+		l = list()
+		for o in self.objs:
+			for t in o.c_typedefs(self.nam):
+				l.append(t)
+		l.append("")
+		l.append("/* Functions */")
 		for f in self.funcs:
-			fo.write(f.c_typedefs(fo, self.nam) + "\n")
+			l.append(f.c_typedef(self.nam))
+		return l
+
+	def c_typedefs(self, fo):
+		for i in self.c_typedefs_():
+			fo.write(i + "\n")
 
 	def c_vmod(self, fo):
 		fo.write('const char Vmod_Name[] = \"' + self.nam + '";\n')
 		fo.write("\n")
 
 		cs = self.c_struct()
-		fo.write("const " + cs + ' Vmod_Func = {\n')
+		fo.write("const " + cs + ' Vmod_Func = ')
+		fo.write(self.c_initializer())
+		fo.write("\n")
 
-		for f in self.funcs:
-			fo.write("\tvmod_" + f.nam + ",\n")
-		if self.init != None:
-			fo.write("\t" + self.init + ",\n")
-		if self.fini != None:
-			fo.write("\t" + self.fini + ",\n")
-		fo.write("};\n")
 		fo.write("\n")
 		fo.write("const int Vmod_Len = sizeof(Vmod_Func);\n")
 		fo.write("\n")
+
+
 		fo.write("const char Vmod_Proto[] =\n")
-		for f in self.funcs:
-			fo.write('\t"' + f.c_typedefs(fo, self.nam) + '\\n"\n')
+		for t in self.c_typedefs_():
+			fo.write('\t"' + t + '\\n"\n')
 		fo.write('\t"\\n"\n')
 		for i in (cs + " Vmod_Func_" + self.nam + ';').split("\n"):
 			fo.write('\n\t"' + i + '\\n"')
 		fo.write(";\n\n")
 
-		fo.write("const char * const Vmod_Spec[] = {\n")
-		for f in self.funcs:
-			fo.write('\t"' + f.strspec(self.nam) + '",\n')
-		if self.init != None:
-			fo.write(
-			    '\t"INIT\\0Vmod_Func_' + self.nam + '._init",\n')
-		if self.fini != None:
-			fo.write(
-			    '\t"FINI\\0Vmod_Func_' + self.nam + '._fini",\n')
-		fo.write("\t0\n")
-		fo.write("};\n")
+		fo.write(self.c_strspec())
+
 		fo.write("\n")
 		fo.write('const char Vmod_Varnish_ABI[] = VMOD_ABI_Version;\n')
 		fo.write("\n")
 		fo.write('const void * const Vmod_Id = &Vmod_Id;\n')
 
+	def c_initializer(self):
+		s = '{\n'
+		for o in self.objs:
+			s += o.c_initializer()
+
+		s += "\n\t/* Functions */\n"
+		for f in self.funcs:
+			s += f.c_initializer()
+
+		s += "\n\t/* Init/Fini */\n"
+		if self.init != None:
+			s += "\t" + self.init + ",\n"
+		if self.fini != None:
+			s += "\t" + self.fini + ",\n"
+		s += "};"
+
+		return s
+
 	def c_struct(self):
 		s = 'struct Vmod_Func_' + self.nam + ' {\n'
+		for o in self.objs:
+			s += o.c_struct(self.nam)
+
+		s += "\n\t/* Functions */\n"
 		for f in self.funcs:
-			s += '\ttd_' + self.nam + "_" + f.nam
-			s += "\t*" + f.nam + ";\n"
+			s += f.c_struct(self.nam)
+
+		s += "\n\t/* Init/Fini */\n"
 		if self.init != None:
 			s += "\tvmod_init_f\t*_init;\n"
 		if self.fini != None:
 			s += "\tvmod_fini_f\t*_fini;\n"
 		s += '}'
 		return s
-	
+
+	def c_strspec(self):
+		s = "const char * const Vmod_Spec[] = {\n"
+
+		for o in self.objs:
+			s += o.c_strspec(self.nam)
+
+		s += "\n\t/* Functions */\n"
+		for f in self.funcs:
+			s += '\t"' + f.c_strspec(self.nam) + '",\n'
+
+		s += "\n\t/* Init/Fini */\n"
+		if self.init != None:
+			s += '\t"INIT\\0Vmod_Func_' + self.nam + '._init",\n'
+		if self.fini != None:
+			s += '\t"FINI\\0Vmod_Func_' + self.nam + '._fini",\n'
+
+		s += "\t0\n"
+		s += "};\n"
+		return s
+
+#######################################################################
 
 class func(object):
 	def __init__(self, nam, retval, al):
-		if not is_c_name(nam):
-			raise Exception("Func name '%s' is illegal" % nam)
+		#if not is_c_name(nam):
+		#	raise Exception("Func name '%s' is illegal" % nam)
 		if retval not in ctypes:
 			raise Exception(
 			    "Return type '%s' not a valid type" % retval)
 		self.nam = nam
+		self.cnam = nam.replace(".", "__")
 		self.al = al
 		self.retval = retval
+		self.pfx = None
 
 	def __repr__(self):
 		return "<FUNC %s %s>" % (self.retval, self.nam)
 
+	def set_pfx(self, s):
+		self.pfx = s
+
 	def c_proto(self, fo):
 		fo.write(ctypes[self.retval])
-		fo.write(" vmod_" + self.nam)
+		fo.write(" vmod_" + self.cnam)
 		fo.write("(struct req *")
+		if self.pfx != None:
+			fo.write(self.pfx)
 		for a in self.al:
 			fo.write(", " + ctypes[a.typ])
 		fo.write(");\n")
 
-	def c_typedefs(self, fo, modname):
+	def c_typedef(self, modname):
 		s = "typedef "
 		s += ctypes[self.retval]
-		s += " td_" + modname + "_" + self.nam
+		s += " td_" + modname + "_" + self.cnam
 		s += "(struct req *"
+		if self.pfx != None:
+			s += self.pfx
 		for a in self.al:
 			s += ", " + ctypes[a.typ]
 		s += ");"
 		return s
 
-	def strspec(self, modname):
-		s = modname + "." + self.nam
+	def c_struct(self, modname):
+		s = '\ttd_' + modname + "_" + self.cnam
+		while len(s.expandtabs()) < 40:
+			s += "\t"
+		s += "*" + self.cnam + ";\n"
+		return s
+
+	def c_initializer(self):
+		return "\tvmod_" + self.cnam + ",\n"
+
+	def c_strspec(self, modnam):
+		s = modnam + "." + self.nam
 		s += "\\0"
-		s += "Vmod_Func_" + modname + "." + self.nam + "\\0"
+		s += "Vmod_Func_" + modnam + "." + self.cnam + "\\0"
 		s += self.retval + "\\0"
 		for a in self.al:
-			s += a.strspec()
+			s += a.c_strspec()
 		return s
 		
+#######################################################################
+
+class obj(object):
+	def __init__(self, nam):
+		self.nam = nam
+		self.init_fini = None
+		self.methods = list()
+
+	def set_init_fini(self, f):
+		self.init_fini = f
+
+	def add_method(self, m):
+		self.methods.append(m)
+
+	def c_typedefs(self, modname):
+		l = list()
+		l.append("/* Object " + self.nam + " */")
+		l.append(self.init_fini.c_typedef(modname) + "")
+		for m in self.methods:
+			l.append(m.c_typedef(modname) + "")
+		return l
+
+	def c_proto(self, fo):
+		fo.write("struct vmod_" + self.nam + ";\n")
+		self.init_fini.c_proto(fo)
+		for m in o.methods:
+			m.c_proto(fo)
+
+	def c_struct(self, modnam):
+		s = "\t/* Object " + self.nam + " */\n"
+		s += self.init_fini.c_struct(modnam)
+		for m in self.methods:
+			s += m.c_struct(modnam)
+		return s
+
+	def c_initializer(self):
+		s = "\t/* Object " + self.nam + " */\n"
+		s += self.init_fini.c_initializer()
+		for m in self.methods:
+			s += m.c_initializer()
+		return s
+
+	def c_strspec(self, modnam):
+		s = "\t/* Object " + self.nam + " */\n"
+		s += '\t"OBJ\\0' + self.init_fini.c_strspec(modnam) + '",\n'
+		for m in self.methods:
+			s += '\t"METHOD\\0' + m.c_strspec(modnam) + '",\n'
+		return s
+
+#######################################################################
 
 class arg(object):
 	def __init__(self, typ, nam = None, det = None):
@@ -239,13 +359,15 @@ class arg(object):
 	def __repr__(self):
 		return "<ARG %s %s %s>" % (self.nam, self.typ, str(self.det))
 
-	def strspec(self):
+	def c_strspec(self):
 		if self.det == None:
 			return self.typ + "\\0"
 		else:
 			return self.det
 		return "??"
 
+#######################################################################
+
 f = open(specfile, "r")
 tl = list()
 lines = list()
@@ -285,6 +407,70 @@ def parse_enum2(tl):
 	return arg("ENUM", det=s)
 
 #######################################################################
+#
+#
+
+def parse_func(tl, rt_type = None, obj=None):
+	al = list()
+	if rt_type == None:
+		t = tl.pop(0)
+		rt_type = t.str
+	if rt_type not in ctypes:
+		raise Exception(
+		    "Return type '%s' not a valid type" % rt_type)
+
+	t = tl.pop(0)
+	fname = t.str
+	if obj != None and fname[0] == "." and is_c_name(fname[1:]):
+		fname = obj + fname
+	elif not is_c_name(fname):
+		raise Exception("Function name '%s' is illegal" % fname)
+
+	t = tl.pop(0)
+	if t.str != "(":
+		raise Exception("Expected \"(\" got \"%s\"", t.str)
+
+	while True:
+		t = tl.pop(0)
+		if t.str == ")":
+			break
+		if t.str == "ENUM":
+			al.append(parse_enum2(tl))
+		elif t.str in ctypes:
+			al.append(arg(t.str))
+		else:
+			raise Exception("ARG? %s" % t.str)
+		if tl[0].str == ",":
+			tl.pop(0)
+		elif tl[0].str != ")":
+			raise Exception("Expceted \")\" or \",\"")
+	if t.str != ")":
+		raise Exception("End Of Input looking for ')'")
+	f = func(fname, rt_type, al)
+	return f
+
+#######################################################################
+#
+#
+
+def parse_obj(tl):
+	o = obj(tl[0].str)
+	f = parse_func(tl, "VOID")
+	f.set_pfx(", struct vmod_" + o.nam + " **")
+	o.set_init_fini(f)
+	t = tl.pop(0)
+	assert t.str == "{"
+	while True:
+		t = tl.pop(0)
+		if t.str == "}":
+			break
+		assert t.str == "Method"
+		f = parse_func(tl, obj=o.nam)
+		f.set_pfx(", struct vmod_" + o.nam + " *")
+		o.add_method(f)
+	return o
+
+#######################################################################
 # The first thing in the file must be the Module declaration
 #
 
@@ -304,51 +490,17 @@ while len(tl) > 0:
 	if t.str == "Init":
 		t = tl.pop(0)
 		vmod.set_init(t.str)
-		continue
-
-	if t.str == "Fini":
+	elif t.str == "Fini":
 		t = tl.pop(0)
 		vmod.set_fini(t.str)
-		continue
-
-	if t.str == "Function":
-		al = list()
-		t = tl.pop(0)
-		rt_type = t.str
-		if rt_type not in ctypes:
-			raise Exception(
-			    "Return type '%s' not a valid type" % rt_type)
-
-		t = tl.pop(0)
-		fname = t.str
-		if not is_c_name(fname):
-			raise Exception("Function name '%s' is illegal" % fname)
-
-		t = tl.pop(0)
-		if t.str != "(":
-			raise Exception("Expected \"(\" got \"%s\"", t.str)
-
-		while True:
-			t = tl.pop(0)
-			if t.str == ")":
-				break
-			if t.str == "ENUM":
-				al.append(parse_enum2(tl))
-			elif t.str in ctypes:
-				al.append(arg(t.str))
-			else:
-				raise Exception("ARG? %s" % t.str)
-			if tl[0].str == ",":
-				tl.pop(0)
-			elif tl[0].str != ")":
-				raise Exception("Expceted \")\" or \",\"")
-		if t.str != ")":
-			raise Exception("End Of Input looking for ')'")
-		f = func(fname, rt_type, al)
+	elif t.str == "Function":
+		f = parse_func(tl)
 		vmod.add_func(f)
-		continue
-
-	raise Exception("Expected \"Init\", \"Fini\" or \"Function\"")
+	elif t.str == "Object":
+		o = parse_obj(tl)
+		vmod.add_obj(o)
+	else:
+		raise Exception("Expected \"Init\", \"Fini\" or \"Function\"")
 
 #######################################################################
 # Parsing done, now process
diff --git a/lib/libvmod_debug/Makefile.am b/lib/libvmod_debug/Makefile.am
index 25b3f3f..7e2c849 100644
--- a/lib/libvmod_debug/Makefile.am
+++ b/lib/libvmod_debug/Makefile.am
@@ -14,7 +14,8 @@ noinst_LTLIBRARIES = libvmod_debug.la
 libvmod_debug_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere
 
 libvmod_debug_la_SOURCES = \
-	vmod_debug.c
+	vmod_debug.c \
+	vmod_debug_obj.c
 
 nodist_libvmod_debug_la_SOURCES = \
 	vcc_if.c \
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index 2e3c33e..653f168 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -31,3 +31,7 @@ Function VOID panic(STRING_LIST)
 Function STRING author(ENUM { phk, des, kristian, mithrandir })
 Function VOID test_priv_call(PRIV_CALL)
 Function VOID test_priv_vcl(PRIV_VCL)
+Object obj(STRING) {
+	Method STRING .foo(STRING)
+	Method TIME .date()
+}



More information about the varnish-commit mailing list