[master] f7860ad Simplify VCC's handling of procedures.

Poul-Henning Kamp phk at FreeBSD.org
Tue Dec 5 22:34:11 UTC 2017


commit f7860ad011378b60c8168726dec4462da668832f
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Dec 5 22:31:30 2017 +0000

    Simplify VCC's handling of procedures.
    
    Give procedures proper data structures and stick the VCL methods into
    the symbol table up front and GC a lot of small hacks and workarounds.

diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c
index e07ee9b..53fc9b9 100644
--- a/lib/libvcc/vcc_compile.c
+++ b/lib/libvcc/vcc_compile.c
@@ -62,7 +62,7 @@
 #include "libvcc.h"
 #include "vfil.h"
 
-struct method method_tab[] = {
+static const struct method method_tab[] = {
 	{ "none", 0U, 0},
 #define VCL_MET_MAC(l,U,t,b)	{ "vcl_"#l, b, VCL_MET_##U },
 #include "tbl/vcl_returns.h"
@@ -95,6 +95,24 @@ TlDup(struct vcc *tl, const char *s)
 
 /*--------------------------------------------------------------------*/
 
+struct proc *
+vcc_NewProc(struct vcc *tl, struct symbol *sym)
+{
+	struct proc *p;
+
+	ALLOC_OBJ(p, PROC_MAGIC);
+	AN(p);
+	VTAILQ_INIT(&p->calls);
+	VTAILQ_INIT(&p->uses);
+	VTAILQ_INSERT_TAIL(&tl->procs, p, list);
+	p->body = VSB_new_auto();
+	AN(p->body);
+	sym->proc = p;
+	return (p);
+}
+
+/*--------------------------------------------------------------------*/
+
 struct inifin *
 New_IniFin(struct vcc *tl)
 {
@@ -111,25 +129,6 @@ New_IniFin(struct vcc *tl)
 	return (p);
 }
 
-/*--------------------------------------------------------------------*/
-
-int
-IsMethod(const struct token *t)
-{
-	int i;
-
-	assert(t->tok == ID);
-	for (i = 1; method_tab[i].name != NULL; i++) {
-		if (vcc_IdIs(t, method_tab[i].name))
-			return (i);
-	}
-	if ((t->b[0] == 'v'|| t->b[0] == 'V') &&
-	    (t->b[1] == 'c'|| t->b[1] == 'C') &&
-	    (t->b[2] == 'l'|| t->b[2] == 'L'))
-		return (-2);
-	return (-1);
-}
-
 /*--------------------------------------------------------------------
  * Printf output to the vsbs, possibly indented
  */
@@ -535,10 +534,10 @@ static struct vsb *
 vcc_CompileSource(struct vcc *tl, struct source *sp)
 {
 	struct symbol *sym;
+	struct proc *p;
 	const struct var *v;
 	struct vsb *vsb;
 	struct inifin *ifp;
-	int i;
 
 	vcc_Expr_Init(tl);
 
@@ -626,26 +625,19 @@ vcc_CompileSource(struct vcc *tl, struct source *sp)
 
 	/* Emit method functions */
 	Fh(tl, 1, "\n");
-	for (i = 1; i < VCL_MET_MAX; i++) {
+	VTAILQ_FOREACH(p, &tl->procs, list) {
+		if (p->method == NULL)
+			continue;
 		Fh(tl, 1,
 		    "void v_matchproto_(vcl_func_f) "
 		    "VGC_function_%s(VRT_CTX);\n",
-		    method_tab[i].name);
+		    p->method->name);
 		Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_f)\n");
-		Fc(tl, 1,
-		    "VGC_function_%s(VRT_CTX)\n",
-		    method_tab[i].name);
-		AZ(VSB_finish(tl->fm[i]));
-		Fc(tl, 1, "{\n");
-		/*
-		 * We want vmods to be able set a FAIL return value
-		 * in members called from vcl_init, so set OK up front
-		 * and return with whatever was set last.
-		 */
-		Fc(tl, 1, "%s", VSB_data(tl->fm[i]));
-		if (method_tab[i].bitval == VCL_MET_INIT)
-			Fc(tl, 1, "  return;\n");
-		Fc(tl, 1, "}\n");
+		Fc(tl, 1, "VGC_function_%s(VRT_CTX)\n",
+		    p->method->name);
+		AZ(VSB_finish(p->body));
+		Fc(tl, 1, "{\n%s}\n", VSB_data(p->body));
+		VSB_destroy(&p->body);
 	}
 
 	EmitInitFini(tl);
@@ -710,6 +702,8 @@ struct vcc *
 VCC_New(void)
 {
 	struct vcc *tl;
+	struct symbol *sym;
+	struct proc *p;
 	int i;
 
 	ALLOC_OBJ(tl, VCC_MAGIC);
@@ -717,6 +711,7 @@ VCC_New(void)
 	VTAILQ_INIT(&tl->inifin);
 	VTAILQ_INIT(&tl->tokens);
 	VTAILQ_INIT(&tl->sources);
+	VTAILQ_INIT(&tl->procs);
 
 	tl->nsources = 0;
 
@@ -729,9 +724,11 @@ VCC_New(void)
 	tl->fh = VSB_new_auto();
 	assert(tl->fh != NULL);
 
-	for (i = 0; i < VCL_MET_MAX; i++) {
-		tl->fm[i] = VSB_new_auto();
-		assert(tl->fm[i] != NULL);
+	for (i = 1; i < VCL_MET_MAX; i++) {
+		sym = VCC_Symbol(tl, NULL,
+		    method_tab[i].name, NULL, SYM_SUB, 1);
+		p = vcc_NewProc(tl, sym);
+		p->method = &method_tab[i];
 	}
 	tl->sb = VSB_new_auto();
 	AN(tl->sb);
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 47e3033..7f09b47 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -49,6 +49,7 @@
 struct vsb;
 struct token;
 struct sockaddr_storage;
+struct method;
 
 unsigned vcl_fixed_token(const char *p, const char **q);
 extern const char * const vcl_tnames[256];
@@ -146,6 +147,21 @@ struct symbol {
 
 VTAILQ_HEAD(tokenhead, token);
 
+struct proc {
+	unsigned		magic;
+#define PROC_MAGIC		0xd1d98499
+	const struct method	*method;
+	VTAILQ_HEAD(,proccall)	calls;
+	VTAILQ_HEAD(,procuse)	uses;
+	VTAILQ_ENTRY(proc)	list;
+	struct token		*name;
+	unsigned		ret_bitmap;
+	unsigned		called;
+	unsigned		active;
+	struct token		*return_tok[VCL_RET_MAX];
+	struct vsb		*body;
+};
+
 struct inifin {
 	unsigned		magic;
 #define INIFIN_MAGIC		0x583c274c
@@ -191,11 +207,10 @@ struct vcc {
 	struct vsb		*fb;		/* Body of current sub
 						 * NULL otherwise
 						 */
-	struct vsb		*fm[VCL_MET_MAX];	/* Method bodies */
 	struct vsb		*sb;
 	int			err;
 	struct proc		*curproc;
-	struct proc		*mprocs[VCL_MET_MAX];
+	VTAILQ_HEAD(, proc)	procs;
 
 	VTAILQ_HEAD(, acl_e)	acl;
 
@@ -244,8 +259,8 @@ void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs);
 void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs);
 
 /* vcc_compile.c */
-extern struct method method_tab[];
-struct inifin *New_IniFin(struct vcc *tl);
+struct inifin *New_IniFin(struct vcc *);
+struct proc *vcc_NewProc(struct vcc*, struct symbol*);
 
 /*
  * H -> Header, before the C code
@@ -261,7 +276,6 @@ void Fc(const struct vcc *tl, int indent, const char *fmt, ...)
 void Fb(const struct vcc *tl, int indent, const char *fmt, ...)
     v_printflike_(3, 4);
 void EncToken(struct vsb *sb, const struct token *t);
-int IsMethod(const struct token *t);
 void *TlAlloc(struct vcc *tl, unsigned len);
 char *TlDup(struct vcc *tl, const char *s);
 
@@ -346,7 +360,6 @@ int vcc_CheckReferences(struct vcc *tl);
 void VCC_XrefTable(struct vcc *);
 
 void vcc_AddCall(struct vcc *tl, struct token *t);
-struct proc *vcc_AddProc(struct vcc *tl, struct token *t);
 void vcc_ProcAction(struct proc *p, unsigned action, struct token *t);
 int vcc_CheckAction(struct vcc *tl);
 void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask,
diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c
index 2466431..13615cd 100644
--- a/lib/libvcc/vcc_parse.c
+++ b/lib/libvcc/vcc_parse.c
@@ -209,48 +209,58 @@ static void
 vcc_ParseFunction(struct vcc *tl)
 {
 	struct symbol *sym;
-	int m, i;
+	struct proc *p;
 
 	vcc_NextToken(tl);
 	vcc_ExpectVid(tl, "function");
 	ERRCHK(tl);
 
-	m = IsMethod(tl->t);
-	if (m == -2) {
-		VSB_printf(tl->sb,
-		    "VCL sub's named 'vcl*' are reserved names.\n");
+	sym = vcc_AddDef(tl, tl->t, SYM_SUB);
+	AN(sym);
+	p = sym->proc;
+	if (p == NULL) {
+		if ((tl->t->b[0] == 'v'|| tl->t->b[0] == 'V') &&
+		    (tl->t->b[1] == 'c'|| tl->t->b[1] == 'C') &&
+		    (tl->t->b[2] == 'l'|| tl->t->b[2] == 'L')) {
+			VSB_printf(tl->sb,
+			    "VCL sub's named 'vcl*' are reserved names.\n");
+			vcc_ErrWhere(tl, tl->t);
+			VSB_printf(tl->sb, "Valid vcl_* methods are:\n");
+			VTAILQ_FOREACH(p, &tl->procs, list) {
+				if (p->method != NULL)
+					VSB_printf(tl->sb, "\t%s\n",
+					    p->method->name);
+			}
+			return;
+		}
+		VCC_GlobalSymbol(sym, SUB, "VGC_function");
+		p = vcc_NewProc(tl, sym);
+		p->name = tl->t;
+		tl->fb = tl->fc;
+		Fh(tl, 0, "void %s(VRT_CTX);\n", sym->rname);
+		Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_t)\n");
+		Fc(tl, 1, "%s(VRT_CTX)\n", sym->rname);
+	} else if (p->method == NULL) {
+		VSB_printf(tl->sb, "Function '%s' redefined\n", sym->name);
 		vcc_ErrWhere(tl, tl->t);
-		VSB_printf(tl->sb, "Valid vcl_* methods are:\n");
-		for (i = 1; method_tab[i].name != NULL; i++)
-			VSB_printf(tl->sb, "\t%s\n", method_tab[i].name);
+		VSB_printf(tl->sb, "Previously defined here:\n");
+		vcc_ErrWhere(tl, p->name);
 		return;
-	} else if (m != -1) {
-		assert(m < VCL_MET_MAX);
-		tl->fb = tl->fm[m];
-		if (tl->mprocs[m] == NULL) {
+	} else {
+		/* Add to VCL sub */
+		AN(p->method);
+		if (p->name == NULL) {
 			(void)vcc_AddDef(tl, tl->t, SYM_SUB);
 			(void)vcc_AddRef(tl, tl->t, SYM_SUB);
-			tl->mprocs[m] = vcc_AddProc(tl, tl->t);
+			p->name = tl->t;
 		}
-		tl->curproc = tl->mprocs[m];
+		tl->fb = p->body;
 		Fb(tl, 1, "  /* ... from ");
 		vcc_Coord(tl, tl->fb, NULL);
 		Fb(tl, 0, " */\n");
-	} else {
-		tl->fb = tl->fc;
-		sym = vcc_AddDef(tl, tl->t, SYM_SUB);
-		VCC_GlobalSymbol(sym, SUB, "VGC_function");
-		if (sym->ndef > 1) {
-			VSB_printf(tl->sb,
-			    "Function '%s' redefined\n", sym->name);
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-		tl->curproc = vcc_AddProc(tl, tl->t);
-		Fh(tl, 0, "void %s(VRT_CTX);\n", sym->rname);
-		Fc(tl, 1, "\nvoid v_matchproto_(vcl_func_t)\n");
-		Fc(tl, 1, "%s(VRT_CTX)\n", sym->rname);
 	}
+	CHECK_OBJ_NOTNULL(p, PROC_MAGIC);
+	tl->curproc = p;
 	vcc_NextToken(tl);
 	tl->indent += INDENT;
 	Fb(tl, 1, "{\n");
diff --git a/lib/libvcc/vcc_xref.c b/lib/libvcc/vcc_xref.c
index 267c949..fff066c 100644
--- a/lib/libvcc/vcc_xref.c
+++ b/lib/libvcc/vcc_xref.c
@@ -45,7 +45,7 @@
 
 struct proccall {
 	VTAILQ_ENTRY(proccall)	list;
-	struct proc		*p;
+	struct symbol		*sym;
 	struct token		*t;
 };
 
@@ -56,17 +56,6 @@ struct procuse {
 	const char		*use;
 };
 
-struct proc {
-	VTAILQ_HEAD(,proccall)	calls;
-	VTAILQ_HEAD(,procuse)	uses;
-	struct token		*name;
-	unsigned		ret_bitmap;
-	unsigned		exists;
-	unsigned		called;
-	unsigned		active;
-	struct token		*return_tok[VCL_RET_MAX];
-};
-
 /*--------------------------------------------------------------------
  * Keep track of definitions and references
  */
@@ -132,38 +121,6 @@ vcc_CheckReferences(struct vcc *tl)
  * Returns checks
  */
 
-static struct proc *
-vcc_findproc(struct vcc *tl, struct token *t)
-{
-	struct symbol *sym;
-	struct proc *p;
-
-
-	sym = VCC_SymbolTok(tl, NULL, t, SYM_SUB, 1);
-	AN(sym);
-	if (sym->proc != NULL)
-		return (sym->proc);
-
-	p = TlAlloc(tl, sizeof *p);
-	assert(p != NULL);
-	VTAILQ_INIT(&p->calls);
-	VTAILQ_INIT(&p->uses);
-	p->name = t;
-	sym->proc = p;
-	return (p);
-}
-
-struct proc *
-vcc_AddProc(struct vcc *tl, struct token *t)
-{
-	struct proc *p;
-
-	p = vcc_findproc(tl, t);
-	p->name = t;	/* make sure the name matches the definition */
-	p->exists++;
-	return (p);
-}
-
 void
 vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask,
     const char *use)
@@ -184,12 +141,11 @@ void
 vcc_AddCall(struct vcc *tl, struct token *t)
 {
 	struct proccall *pc;
-	struct proc *p;
 
-	p = vcc_findproc(tl, t);
 	pc = TlAlloc(tl, sizeof *pc);
 	assert(pc != NULL);
-	pc->p = p;
+	pc->sym = VCC_SymbolTok(tl, NULL, t, SYM_SUB, 1);
+	AN(pc->sym);
 	pc->t = t;
 	VTAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list);
 }
@@ -211,11 +167,7 @@ vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap)
 	unsigned u;
 	struct proccall *pc;
 
-	if (!p->exists) {
-		VSB_printf(tl->sb, "Function %.*s does not exist\n",
-		    PF(p->name));
-		return (1);
-	}
+	AN(p);
 	if (p->active) {
 		VSB_printf(tl->sb, "Function recurses on\n");
 		vcc_ErrWhere(tl, p->name);
@@ -238,9 +190,15 @@ vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap)
 	}
 	p->active = 1;
 	VTAILQ_FOREACH(pc, &p->calls, list) {
-		if (vcc_CheckActionRecurse(tl, pc->p, bitmap)) {
-			VSB_printf(tl->sb, "\n...called from \"%.*s\"\n",
-			    PF(p->name));
+		if (pc->sym->proc == NULL) {
+			VSB_printf(tl->sb, "Function %s does not exist\n",
+			    pc->sym->name);
+			vcc_ErrWhere(tl, pc->t);
+			return (1);
+		}
+		if (vcc_CheckActionRecurse(tl, pc->sym->proc, bitmap)) {
+			VSB_printf(tl->sb, "\n...called from \"%s\"\n",
+			    pc->sym->name);
 			vcc_ErrWhere(tl, pc->t);
 			return (1);
 		}
@@ -256,21 +214,18 @@ static void
 vcc_checkaction1(struct vcc *tl, const struct symbol *sym)
 {
 	struct proc *p;
-	struct method *m;
-	int i;
 
 	p = sym->proc;
 	AN(p);
-	i = IsMethod(p->name);
-	if (i < 0)
+	AN(p->name);
+	if(p->method == NULL)
 		return;
-	m = method_tab + i;
-	if (vcc_CheckActionRecurse(tl, p, m->ret_bitmap)) {
+	if (vcc_CheckActionRecurse(tl, p, p->method->ret_bitmap)) {
 		VSB_printf(tl->sb,
-		    "\n...which is the \"%s\" method\n", m->name);
+		    "\n...which is the \"%s\" method\n", p->method->name);
 		VSB_printf(tl->sb, "Legal returns are:");
 #define VCL_RET_MAC(l, U, B)						\
-		if (m->ret_bitmap & ((1 << VCL_RET_##U)))	\
+		if (p->method->ret_bitmap & ((1 << VCL_RET_##U)))	\
 			VSB_printf(tl->sb, " \"%s\"", #l);
 
 #include "tbl/vcl_returns.h"
@@ -324,7 +279,7 @@ vcc_FindIllegalUse(const struct proc *p, const struct method *m)
 
 static int
 vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p,
-    struct method *m)
+    const struct method *m)
 {
 	struct proccall *pc;
 	struct procuse *pu;
@@ -341,9 +296,9 @@ vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p,
 		return (1);
 	}
 	VTAILQ_FOREACH(pc, &p->calls, list) {
-		if (vcc_CheckUseRecurse(tl, pc->p, m)) {
-			VSB_printf(tl->sb, "\n...called from \"%.*s\"\n",
-			    PF(p->name));
+		if (vcc_CheckUseRecurse(tl, pc->sym->proc, m)) {
+			VSB_printf(tl->sb, "\n...called from \"%s\"\n",
+			    pc->sym->name);
 			vcc_ErrWhere(tl, pc->t);
 			return (1);
 		}
@@ -355,29 +310,23 @@ static void
 vcc_checkuses(struct vcc *tl, const struct symbol *sym)
 {
 	struct proc *p;
-	struct method *m;
 	struct procuse *pu;
-	int i;
 
 	p = sym->proc;
 	AN(p);
-
-	i = IsMethod(p->name);
-	if (i < 0)
+	if (p->method == NULL)
 		return;
-	m = method_tab + i;
-	pu = vcc_FindIllegalUse(p, m);
+	pu = vcc_FindIllegalUse(p, p->method);
 	if (pu != NULL) {
-		VSB_printf(tl->sb,
-		    "'%.*s': %s in method '%.*s'.",
+		VSB_printf(tl->sb, "'%.*s': %s in method '%.*s'.",
 		    PF(pu->t), pu->use, PF(p->name));
 		VSB_cat(tl->sb, "\nAt: ");
 		vcc_ErrWhere(tl, pu->t);
 		return;
 	}
-	if (vcc_CheckUseRecurse(tl, p, m)) {
+	if (vcc_CheckUseRecurse(tl, p, p->method)) {
 		VSB_printf(tl->sb,
-		    "\n...which is the \"%s\" method\n", m->name);
+		    "\n...which is the \"%s\" method\n", p->method->name);
 		return;
 	}
 }


More information about the varnish-commit mailing list