[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