r1334 - in branches/1.0: . lib/libvcl

des at projects.linpro.no des at projects.linpro.no
Thu Apr 19 16:50:56 CEST 2007


Author: des
Date: 2007-04-19 16:50:56 +0200 (Thu, 19 Apr 2007)
New Revision: 1334

Added:
   branches/1.0/lib/libvcl/vcc_xref.c
Modified:
   branches/1.0/
   branches/1.0/lib/libvcl/Makefile.am
   branches/1.0/lib/libvcl/flint.lnt
   branches/1.0/lib/libvcl/vcc_acl.c
   branches/1.0/lib/libvcl/vcc_compile.c
   branches/1.0/lib/libvcl/vcc_compile.h
   branches/1.0/lib/libvcl/vcc_parse.c
Log:
 r37067 at cat (orig r1291):  phk | 2007-03-31 10:36:31 +0200
 Overhaul cross reference checks in vcc compiler
 
 Move and isolate cross reference stuff to it's own source file
 (vcc_xref.c) and use vcc_ prefix as originally intended.
 
 Also warn about multiple definitions of objects.
 
 



Property changes on: branches/1.0
___________________________________________________________________
Name: svk:merge
   - d4fa192b-c00b-0410-8231-f00ffab90ce4:/trunk/varnish-cache:1290
   + d4fa192b-c00b-0410-8231-f00ffab90ce4:/trunk/varnish-cache:1291

Modified: branches/1.0/lib/libvcl/Makefile.am
===================================================================
--- branches/1.0/lib/libvcl/Makefile.am	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/Makefile.am	2007-04-19 14:50:56 UTC (rev 1334)
@@ -14,6 +14,7 @@
 	vcc_parse.c \
 	vcc_fixed_token.c \
 	vcc_obj.c \
-	vcc_token.c
+	vcc_token.c \
+	vcc_xref.c
 
 libvcl_la_CFLAGS = -include config.h

Modified: branches/1.0/lib/libvcl/flint.lnt
===================================================================
--- branches/1.0/lib/libvcl/flint.lnt	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/flint.lnt	2007-04-19 14:50:56 UTC (rev 1334)
@@ -18,7 +18,7 @@
 -e763	// Redundant declaration for symbol '...' previously declared
 
 
--e737	//  Loss of sign in promotion from int to unsigned int
+-e737	// Loss of sign in promotion from int to unsigned int
 -e715	// Symbol 'arg' (line 43) not referenced
 -e818	// Pointer parameter '...' could be declared as pointing to const
 

Modified: branches/1.0/lib/libvcl/vcc_acl.c
===================================================================
--- branches/1.0/lib/libvcl/vcc_acl.c	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/vcc_acl.c	2007-04-19 14:50:56 UTC (rev 1334)
@@ -60,7 +60,7 @@
 	case '~':
 		vcc_NextToken(tl);
 		ExpectErr(tl, ID);
-		AddRef(tl, tl->t, R_ACL);
+		vcc_AddRef(tl, tl->t, R_ACL);
 		Fc(tl, 1, "VRT_acl_match(sp, \"%.*s\", acl_%.*s)\n",
 		    PF(tl->t), PF(tl->t));
 		vcc_NextToken(tl);
@@ -87,7 +87,7 @@
 	an = tl->t;
 	vcc_NextToken(tl);
 
-	AddDef(tl, an, R_ACL);
+	vcc_AddDef(tl, an, R_ACL);
 	Fh(tl, 0, "static struct vrt_acl acl_%.*s[];\n", PF(an));
 	Fc(tl, 1, "static struct vrt_acl acl_%.*s[] = {\n", PF(an));
 

Modified: branches/1.0/lib/libvcl/vcc_compile.c
===================================================================
--- branches/1.0/lib/libvcl/vcc_compile.c	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/vcc_compile.c	2007-04-19 14:50:56 UTC (rev 1334)
@@ -85,7 +85,7 @@
 #include "vrt.h"
 #include "libvcl.h"
 
-static struct method method_tab[] = {
+struct method method_tab[] = {
 #define VCL_RET_MAC(l,U,b,n)
 #define VCL_MET_MAC(l,U,m)	{ "vcl_"#l, m },
 #include "vcl_returns.h"
@@ -237,46 +237,6 @@
 	EncString(sb, t->dec, NULL, 0);
 }
 
-/*--------------------------------------------------------------------
- * Keep track of definitions and references
- */
-
-static struct ref *
-FindRef(struct tokenlist *tl, struct token *t, enum ref_type type)
-{
-	struct ref *r;
-
-	TAILQ_FOREACH(r, &tl->refs, list) {
-		if (r->type != type)
-			continue;
-		if (vcc_Teq(r->name, t))
-			return (r);
-	}
-	r = TlAlloc(tl, sizeof *r);
-	assert(r != NULL);
-	r->name = t;
-	r->type = type;
-	TAILQ_INSERT_TAIL(&tl->refs, r, list);
-	return (r);
-}
-
-void
-AddRef(struct tokenlist *tl, struct token *t, enum ref_type type)
-{
-
-	FindRef(tl, t, type)->refcnt++;
-}
-
-void
-AddDef(struct tokenlist *tl, struct token *t, enum ref_type type)
-{
-	struct ref *r;
-
-	r = FindRef(tl, t, type);
-	r->defcnt++;
-	r->name = t;
-}
-
 /*--------------------------------------------------------------------*/
 
 static struct var *
@@ -334,182 +294,6 @@
 }
 
 /*--------------------------------------------------------------------
- * Consistency check
- */
-
-struct proc *
-AddProc(struct tokenlist *tl, struct token *t, int def)
-{
-	struct proc *p;
-
-	TAILQ_FOREACH(p, &tl->procs, list) {
-		if (!vcc_Teq(p->name, t))
-			continue;
-		if (def)
-			p->name = t;
-		return (p);
-	}
-	p = TlAlloc(tl, sizeof *p);
-	assert(p != NULL);
-	p->name = t;
-	TAILQ_INIT(&p->calls);
-	TAILQ_INSERT_TAIL(&tl->procs, p, list);
-	return (p);
-}
-
-void
-AddCall(struct tokenlist *tl, struct token *t)
-{
-	struct proccall *pc;
-	struct proc *p;
-
-	p = AddProc(tl, t, 0);
-	TAILQ_FOREACH(pc, &tl->curproc->calls, list) {
-		if (pc->p == p)
-			return;
-	}
-	pc = TlAlloc(tl, sizeof *pc);
-	assert(pc != NULL);
-	pc->p = p;
-	pc->t = t;
-	TAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list);
-}
-
-static int
-Consist_Decend(struct tokenlist *tl, struct proc *p, unsigned returns)
-{
-	unsigned u;
-	struct proccall *pc;
-
-	if (!p->exists) {
-		vsb_printf(tl->sb, "Function %.*s does not exist\n",
-		    PF(p->name));
-		return (1);
-	}
-	if (p->active) {
-		vsb_printf(tl->sb, "Function recurses on\n");
-		vcc_ErrWhere(tl, p->name);
-		return (1);
-	}
-	u = p->returns & ~returns;
-	if (u) {
-#define VCL_RET_MAC(a, b, c, d) \
-		if (u & VCL_RET_##b) { \
-			vsb_printf(tl->sb, "Illegal action \"%s\"\n", #a); \
-			vcc_ErrWhere(tl, p->returnt[d]); \
-		}
-#include "vcl_returns.h"
-#undef VCL_RET_MAC
-		vsb_printf(tl->sb, "\n...in function \"%.*s\"\n", PF(p->name));
-		vcc_ErrWhere(tl, p->name);
-		return (1);
-	}
-	p->active = 1;
-	TAILQ_FOREACH(pc, &p->calls, list) {
-		if (Consist_Decend(tl, pc->p, returns)) {
-			vsb_printf(tl->sb, "\n...called from \"%.*s\"\n",
-			    PF(p->name));
-			vcc_ErrWhere(tl, pc->t);
-			return (1);
-		}
-	}
-	p->active = 0;
-	p->called++;
-	return (0);
-}
-
-static int
-Consistency(struct tokenlist *tl)
-{
-	struct proc *p;
-	struct method *m;
-
-	TAILQ_FOREACH(p, &tl->procs, list) {
-		for(m = method_tab; m->name != NULL; m++) {
-			if (vcc_IdIs(p->name, m->name))
-				break;
-		}
-		if (m->name == NULL)
-			continue;
-		if (Consist_Decend(tl, p, m->returns)) {
-			vsb_printf(tl->sb,
-			    "\n...which is the \"%s\" method\n", m->name);
-			vsb_printf(tl->sb, "Legal actions are:");
-#define VCL_RET_MAC(a, b, c, d) \
-			if (m->returns & c) \
-				vsb_printf(tl->sb, " \"%s\"", #a);
-#define VCL_RET_MAC_E(a, b, c, d) VCL_RET_MAC(a, b, c, d)
-#include "vcl_returns.h"
-#undef VCL_RET_MAC
-#undef VCL_RET_MAC_E
-			vsb_printf(tl->sb, "\n");
-			return (1);
-		}
-	}
-	TAILQ_FOREACH(p, &tl->procs, list) {
-		if (p->called)
-			continue;
-		vsb_printf(tl->sb, "Function unused\n");
-		vcc_ErrWhere(tl, p->name);
-		return (1);
-	}
-	return (0);
-}
-
-/*--------------------------------------------------------------------*/
-
-static int
-CheckRefs(struct tokenlist *tl)
-{
-	struct ref *r;
-	const char *type;
-	int nerr = 0;
-
-	TAILQ_FOREACH(r, &tl->refs, list) {
-		if (r->defcnt != 0 && r->refcnt != 0)
-			continue;
-		nerr++;
-
-		switch(r->type) {
-		case R_FUNC:
-			type = "function";
-			break;
-		case R_ACL:
-			type = "acl";
-			break;
-		case R_BACKEND:
-			type = "backend";
-			break;
-		default:
-			ErrInternal(tl);
-			vsb_printf(tl->sb, "Ref ");
-			vcc_ErrToken(tl, r->name);
-			vsb_printf(tl->sb, " has unknown type %d\n",
-			    r->type);
-			continue;
-		}
-		if (r->defcnt == 0 && r->name->tok == METHOD) {
-			vsb_printf(tl->sb,
-			    "No definition for method %.*s\n", PF(r->name));
-			continue;
-		}
-
-		if (r->defcnt == 0) {
-			vsb_printf(tl->sb,
-			    "Undefined %s %.*s, first reference:\n",
-			    type, PF(r->name));
-			vcc_ErrWhere(tl, r->name);
-			continue;
-		}
-
-		vsb_printf(tl->sb, "Unused %s %.*s, defined:\n",
-		    type, PF(r->name));
-		vcc_ErrWhere(tl, r->name);
-	}
-	return (nerr);
-}
-
-/*--------------------------------------------------------------------
  * Output the location/profiling table.  For each counted token, we
  * record source+line+charpos for the first character in the token.
  */
@@ -939,13 +723,13 @@
 	if (tl->err)
 		return (vcc_DestroyTokenList(tl, NULL));
 
-	/* Perform consistency checks */
-	Consistency(tl);
-	if (tl->err)
+	/* Check for orphans */
+	if (vcc_CheckReferences(tl))
 		return (vcc_DestroyTokenList(tl, NULL));
 
-	/* Check for orphans */
-	if (CheckRefs(tl))
+	/* Check that all action returns are legal */
+	vcc_CheckAction(tl);
+	if (tl->err)
 		return (vcc_DestroyTokenList(tl, NULL));
 
 	Ff(tl, 0, "\tVRT_free_backends(&VCL_conf);\n");

Modified: branches/1.0/lib/libvcl/vcc_compile.h
===================================================================
--- branches/1.0/lib/libvcl/vcc_compile.h	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/vcc_compile.h	2007-04-19 14:50:56 UTC (rev 1334)
@@ -120,27 +120,11 @@
 
 struct method {
 	const char		*name;
-	unsigned		returns;
+	unsigned		actions;
 };
 
-struct proccall {
-	TAILQ_ENTRY(proccall)	list;
-	struct proc		*p;
-	struct token		*t;
-};
+struct proc;
 
-struct proc {
-	TAILQ_ENTRY(proc)	list;
-	TAILQ_HEAD(,proccall)	calls;
-	struct token		*name;
-	unsigned		returns;
-	unsigned		exists;
-	unsigned		called;
-	unsigned		active;
-	struct token		*returnt[VCL_RET_MAX];
-};
-
-
 /*--------------------------------------------------------------------*/
 
 /* vcc_acl.c */
@@ -149,18 +133,15 @@
 void vcc_Cond_Ip(struct var *vp, struct tokenlist *tl);
 
 /* vcc_compile.c */
+extern struct method method_tab[];
 void Fh(struct tokenlist *tl, int indent, const char *fmt, ...);
 void Fc(struct tokenlist *tl, int indent, const char *fmt, ...);
 void Fb(struct tokenlist *tl, int indent, const char *fmt, ...);
 void Fi(struct tokenlist *tl, int indent, const char *fmt, ...);
 void Ff(struct tokenlist *tl, int indent, const char *fmt, ...);
 unsigned UintVal(struct tokenlist *tl);
-void AddDef(struct tokenlist *tl, struct token *t, enum ref_type type);
-void AddRef(struct tokenlist *tl, struct token *t, enum ref_type type);
 void EncToken(struct vsb *sb, struct token *t);
 struct var *FindVar(struct tokenlist *tl, struct token *t, struct var *vl);
-void AddCall(struct tokenlist *tl, struct token *t);
-struct proc *AddProc(struct tokenlist *tl, struct token *t, int def);
 int IsMethod(struct token *t);
 void *TlAlloc(struct tokenlist *tl, unsigned len);
 
@@ -183,6 +164,16 @@
 void vcc_AddToken(struct tokenlist *tl, unsigned tok, const char *b, const char *e);
 void vcc_FreeToken(struct token *t);
 
+/* vcc_expr.c */
+void vcc_AddDef(struct tokenlist *tl, struct token *t, enum ref_type type);
+void vcc_AddRef(struct tokenlist *tl, struct token *t, enum ref_type type);
+int vcc_CheckReferences(struct tokenlist *tl);
+
+void vcc_AddCall(struct tokenlist *tl, struct token *t);
+struct proc *vcc_AddProc(struct tokenlist *tl, struct token *t);
+void vcc_ProcAction(struct proc *p, unsigned action, struct token *t);
+int vcc_CheckAction(struct tokenlist *tl);
+
 #define ERRCHK(tl)      do { if ((tl)->err) return; } while (0)
 #define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__)
 #define Expect(a, b) vcc__Expect(a, b, __LINE__)

Modified: branches/1.0/lib/libvcl/vcc_parse.c
===================================================================
--- branches/1.0/lib/libvcl/vcc_parse.c	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/vcc_parse.c	2007-04-19 14:50:56 UTC (rev 1334)
@@ -527,8 +527,7 @@
 		return;
 #define VCL_RET_MAC(a,b,c,d) case T_##b: \
 		Fb(tl, 1, "VRT_done(sp, VCL_RET_%s);\n", #b); \
-		tl->curproc->returns |= VCL_RET_##b; \
-		tl->curproc->returnt[d] = at; \
+		vcc_ProcAction(tl->curproc, d, at); \
 		return;
 #include "vcl_returns.h"
 #undef VCL_RET_MAC
@@ -554,8 +553,8 @@
 		return;
 	case T_CALL:
 		ExpectErr(tl, ID);
-		AddCall(tl, tl->t);
-		AddRef(tl, tl->t, R_FUNC);
+		vcc_AddCall(tl, tl->t);
+		vcc_AddRef(tl, tl->t, R_FUNC);
 		Fb(tl, 1, "if (VGC_function_%.*s(sp))\n", PF(tl->t));
 		Fb(tl, 1, "\treturn (1);\n");
 		vcc_NextToken(tl);
@@ -620,7 +619,7 @@
 		case BACKEND:
 			if (tl->t->tok == '=') {
 				vcc_NextToken(tl);
-				AddRef(tl, tl->t, R_BACKEND);
+				vcc_AddRef(tl, tl->t, R_BACKEND);
 				Fb(tl, 0, "VGC_backend_%.*s", PF(tl->t));
 				vcc_NextToken(tl);
 				Fb(tl, 0, ");\n");
@@ -717,9 +716,9 @@
 	vcc_NextToken(tl);
 	ExpectErr(tl, ID);
 	t_be = tl->t;
-	AddDef(tl, tl->t, R_BACKEND);
+	vcc_AddDef(tl, tl->t, R_BACKEND);
 	if (tl->nbackend == 0)
-		AddRef(tl, tl->t, R_BACKEND);
+		vcc_AddRef(tl, tl->t, R_BACKEND);
 	Fh(tl, 1, "#define VGC_backend_%.*s (VCL_conf.backend[%d])\n",
 	    PF(tl->t), tl->nbackend);
 	Fc(tl, 0, "\n");
@@ -837,17 +836,15 @@
 		assert(m < N_METHODS);
 		tl->fb = tl->fm[m];
 		if (tl->mprocs[m] == NULL) {
-			tl->mprocs[m] = AddProc(tl, tl->t, 1);
-			tl->mprocs[m]->exists++;
-			AddDef(tl, tl->t, R_FUNC);
-			AddRef(tl, tl->t, R_FUNC);
+			tl->mprocs[m] = vcc_AddProc(tl, tl->t);
+			vcc_AddDef(tl, tl->t, R_FUNC);
+			vcc_AddRef(tl, tl->t, R_FUNC);
 		}
 		tl->curproc = tl->mprocs[m];
 	} else {
 		tl->fb = tl->fc;
-		tl->curproc = AddProc(tl, tl->t, 1);
-		tl->curproc->exists++;
-		AddDef(tl, tl->t, R_FUNC);
+		tl->curproc = vcc_AddProc(tl, tl->t);
+		vcc_AddDef(tl, tl->t, R_FUNC);
 		Fh(tl, 0, "static int VGC_function_%.*s (struct sess *sp);\n",
 		    PF(tl->t));
 		Fc(tl, 1, "static int\n");

Added: branches/1.0/lib/libvcl/vcc_xref.c
===================================================================
--- branches/1.0/lib/libvcl/vcc_xref.c	2007-04-19 14:50:54 UTC (rev 1333)
+++ branches/1.0/lib/libvcl/vcc_xref.c	2007-04-19 14:50:56 UTC (rev 1334)
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id$
+ *
+ * This fine contains code for two cross-reference or consistency checks.
+ *
+ * The first check is simply that all functions, acls and backends are
+ * both defined and referenced.  Complaints about referenced but undefined
+ * or defined but unreferenced objects will be emitted.
+ *
+ * The second check recursively decends through function calls to make
+ * sure that action actions are correct for the methods through which
+ * they are called.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "vsb.h"
+
+#include "vcc_priv.h"
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------*/
+
+struct proccall {
+	TAILQ_ENTRY(proccall)	list;
+	struct proc		*p;
+	struct token		*t;
+};
+
+struct proc {
+	TAILQ_ENTRY(proc)	list;
+	TAILQ_HEAD(,proccall)	calls;
+	struct token		*name;
+	unsigned		actions;
+	unsigned		exists;
+	unsigned		called;
+	unsigned		active;
+	struct token		*action_tok[VCL_RET_MAX];
+};
+
+/*--------------------------------------------------------------------*/
+
+static const char *
+vcc_typename(struct tokenlist *tl, const struct ref *r)
+{
+	switch (r->type) {
+	case R_FUNC: return ("function");
+	case R_ACL: return ("acl");
+	case R_BACKEND: return ("backend");
+	default:
+		ErrInternal(tl);
+		vsb_printf(tl->sb, "Ref ");
+		vcc_ErrToken(tl, r->name);
+		vsb_printf(tl->sb, " has unknown type %d\n",
+		    r->type);
+		return "???";
+	}
+}
+
+/*--------------------------------------------------------------------
+ * Keep track of definitions and references
+ */
+
+static struct ref *
+vcc_findref(struct tokenlist *tl, struct token *t, enum ref_type type)
+{
+	struct ref *r;
+
+	TAILQ_FOREACH(r, &tl->refs, list) {
+		if (r->type != type)
+			continue;
+		if (vcc_Teq(r->name, t))
+			return (r);
+	}
+	r = TlAlloc(tl, sizeof *r);
+	assert(r != NULL);
+	r->name = t;
+	r->type = type;
+	TAILQ_INSERT_TAIL(&tl->refs, r, list);
+	return (r);
+}
+
+void
+vcc_AddRef(struct tokenlist *tl, struct token *t, enum ref_type type)
+{
+
+	vcc_findref(tl, t, type)->refcnt++;
+}
+
+void
+vcc_AddDef(struct tokenlist *tl, struct token *t, enum ref_type type)
+{
+	struct ref *r;
+	const char *tp;
+
+	r = vcc_findref(tl, t, type);
+	if (r->defcnt > 0) {
+		tp = vcc_typename(tl, r);
+		vsb_printf(tl->sb, "Multiple definitions of %s \"%.*s\"\n",
+		    tp, PF(t));
+		vcc_ErrWhere(tl, r->name);
+		vsb_printf(tl->sb, "...and\n");
+		vcc_ErrWhere(tl, t);
+	}
+	r->defcnt++;
+	r->name = t;
+}
+
+/*--------------------------------------------------------------------*/
+
+int
+vcc_CheckReferences(struct tokenlist *tl)
+{
+	struct ref *r;
+	const char *type;
+	int nerr = 0;
+
+	TAILQ_FOREACH(r, &tl->refs, list) {
+		if (r->defcnt != 0 && r->refcnt != 0)
+			continue;
+		nerr++;
+
+		type = vcc_typename(tl, r);
+		if (r->defcnt == 0 && r->name->tok == METHOD) {
+			vsb_printf(tl->sb,
+			    "No definition for method %.*s\n", PF(r->name));
+			continue;
+		}
+
+		if (r->defcnt == 0) {
+			vsb_printf(tl->sb,
+			    "Undefined %s %.*s, first reference:\n",
+			    type, PF(r->name));
+			vcc_ErrWhere(tl, r->name);
+			continue;
+		}
+
+		vsb_printf(tl->sb, "Unused %s %.*s, defined:\n",
+		    type, PF(r->name));
+		vcc_ErrWhere(tl, r->name);
+	}
+	return (nerr);
+}
+
+/*--------------------------------------------------------------------
+ * Returned action checks
+ */
+
+static struct proc *
+vcc_findproc(struct tokenlist *tl, struct token *t)
+{
+	struct proc *p;
+
+	TAILQ_FOREACH(p, &tl->procs, list)
+		if (vcc_Teq(p->name, t))
+			return (p);
+	p = TlAlloc(tl, sizeof *p);
+	assert(p != NULL);
+	TAILQ_INIT(&p->calls);
+	TAILQ_INSERT_TAIL(&tl->procs, p, list);
+	p->name = t;
+	return (p);
+}
+
+struct proc *
+vcc_AddProc(struct tokenlist *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_AddCall(struct tokenlist *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->t = t;
+	TAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list);
+}
+
+void
+vcc_ProcAction(struct proc *p, unsigned action, struct token *t)
+{
+
+	p->actions |= (1 << action);
+	/* Record the first instance of this action */
+	if (p->action_tok[action] == NULL)
+		p->action_tok[action] = t;
+}
+
+static int
+vcc_CheckActionRecurse(struct tokenlist *tl, struct proc *p, unsigned actions)
+{
+	unsigned u;
+	struct proccall *pc;
+
+	if (!p->exists) {
+		vsb_printf(tl->sb, "Function %.*s does not exist\n",
+		    PF(p->name));
+		return (1);
+	}
+	if (p->active) {
+		vsb_printf(tl->sb, "Function recurses on\n");
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	u = p->actions & ~actions;
+	if (u) {
+#define VCL_RET_MAC(a, b, c, d) \
+		if (u & VCL_RET_##b) { \
+			vsb_printf(tl->sb, "Illegal action \"%s\"\n", #a); \
+			vcc_ErrWhere(tl, p->action_tok[d]); \
+		}
+#include "vcl_returns.h"
+#undef VCL_RET_MAC
+		vsb_printf(tl->sb, "\n...in function \"%.*s\"\n", PF(p->name));
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	p->active = 1;
+	TAILQ_FOREACH(pc, &p->calls, list) {
+		if (vcc_CheckActionRecurse(tl, pc->p, actions)) {
+			vsb_printf(tl->sb, "\n...called from \"%.*s\"\n",
+			    PF(p->name));
+			vcc_ErrWhere(tl, pc->t);
+			return (1);
+		}
+	}
+	p->active = 0;
+	p->called++;
+	return (0);
+}
+
+int
+vcc_CheckAction(struct tokenlist *tl)
+{
+	struct proc *p;
+	struct method *m;
+	int i;
+
+	TAILQ_FOREACH(p, &tl->procs, list) {
+		i = IsMethod(p->name);
+		if (i < 0)
+			continue;
+		m = method_tab + i;
+		if (vcc_CheckActionRecurse(tl, p, m->actions)) {
+			vsb_printf(tl->sb,
+			    "\n...which is the \"%s\" method\n", m->name);
+			vsb_printf(tl->sb, "Legal actions are:");
+#define VCL_RET_MAC(a, b, c, d) \
+			if (m->actions & c) \
+				vsb_printf(tl->sb, " \"%s\"", #a);
+#define VCL_RET_MAC_E(a, b, c, d) VCL_RET_MAC(a, b, c, d)
+#include "vcl_returns.h"
+#undef VCL_RET_MAC
+#undef VCL_RET_MAC_E
+			vsb_printf(tl->sb, "\n");
+			return (1);
+		}
+	}
+	TAILQ_FOREACH(p, &tl->procs, list) {
+		if (p->called)
+			continue;
+		vsb_printf(tl->sb, "Function unused\n");
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	return (0);
+}
+


Property changes on: branches/1.0/lib/libvcl/vcc_xref.c
___________________________________________________________________
Name: svn:keywords
   + Id




More information about the varnish-commit mailing list