From: phk Date: Fri, 30 Mar 2007 21:11:15 +0000 (+0000) Subject: Overhaul compiler to get rid of memory leaks and other bogons. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fe885f422c26d3e33476d7d824bec296b4a7199c;p=varnish Overhaul compiler to get rid of memory leaks and other bogons. Add a memlist to the tokenlist and a function which allocates with malloc(3) and hangs the piece on the memlist of tokenlist. At the end of compilation, we ditch everything on the list. Handle vrt_obj.h like the other #includes, and stuff these into a vsb instead of directly to a file. Free decoded token string, if any. Pull creation and destruction of tokenlist into separate functions for code clarity. Remember to destry everything in the tokenlist. Pull invocation of cc(1) into a separate function and change the way we do it, so we get any cc(1) groans and whines back in the vsb so a CLI user will see them. More errorchecks than before. More comments throughout. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1289 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/lib/libvcl/flint.lnt b/varnish-cache/lib/libvcl/flint.lnt index e1bd6488..d04ad898 100644 --- a/varnish-cache/lib/libvcl/flint.lnt +++ b/varnish-cache/lib/libvcl/flint.lnt @@ -10,6 +10,7 @@ -header(../../config.h) -sem(lbv_assert, r_no) -sem(strchr, 1p, type(1), 2n == 0 ? (@p < 1p) : (@p < 1p || @p == 0 )) +-sem(vcc_new_source, custodial(1)) -ffc // No automatic custody diff --git a/varnish-cache/lib/libvcl/vcc_compile.c b/varnish-cache/lib/libvcl/vcc_compile.c index dfc4163d..6bbfbd5e 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.c +++ b/varnish-cache/lib/libvcl/vcc_compile.c @@ -100,6 +100,23 @@ static const char *vcc_default_vcl_b, *vcc_default_vcl_e; /*--------------------------------------------------------------------*/ +void * +TlAlloc(struct tokenlist *tl, unsigned len) +{ + struct membit *mb; + void *p; + + p = calloc(len, 1); + assert(p != NULL); + mb = calloc(sizeof *mb, 1); + assert(mb != NULL); + mb->ptr = p; + TAILQ_INSERT_TAIL(&tl->membits, mb, list); + return (p); +} + +/*--------------------------------------------------------------------*/ + int IsMethod(struct token *t) { @@ -235,7 +252,7 @@ FindRef(struct tokenlist *tl, struct token *t, enum ref_type type) if (vcc_Teq(r->name, t)) return (r); } - r = calloc(sizeof *r, 1); + r = TlAlloc(tl, sizeof *r); assert(r != NULL); r->name = t; r->type = type; @@ -271,10 +288,10 @@ HeaderVar(struct tokenlist *tl, struct token *t, struct var *vh) (void)tl; - v = calloc(sizeof *v, 1); + v = TlAlloc(tl, sizeof *v); assert(v != NULL); i = t->e - t->b; - p = malloc(i + 1); + p = TlAlloc(tl, i + 1); assert(p != NULL); memcpy(p, t->b, i); p[i] = '\0'; @@ -332,7 +349,7 @@ AddProc(struct tokenlist *tl, struct token *t, int def) p->name = t; return (p); } - p = calloc(sizeof *p, 1); + p = TlAlloc(tl, sizeof *p); assert(p != NULL); p->name = t; TAILQ_INIT(&p->calls); @@ -351,7 +368,7 @@ AddCall(struct tokenlist *tl, struct token *t) if (pc->p == p) return; } - pc = calloc(sizeof *pc, 1); + pc = TlAlloc(tl, sizeof *pc); assert(pc != NULL); pc->p = p; pc->t = t; @@ -541,6 +558,7 @@ EmitInitFunc(struct tokenlist *tl) Fc(tl, 0, "\nstatic void\nVGC_Init(void)\n{\n\n"); vsb_finish(tl->fi); + /* XXX: check vsb_overflowed ? */ vsb_cat(tl->fc, vsb_data(tl->fi)); Fc(tl, 0, "}\n"); } @@ -551,6 +569,7 @@ EmitFiniFunc(struct tokenlist *tl) Fc(tl, 0, "\nstatic void\nVGC_Fini(void)\n{\n\n"); vsb_finish(tl->ff); + /* XXX: check vsb_overflowed ? */ vsb_cat(tl->fc, vsb_data(tl->ff)); Fc(tl, 0, "}\n"); } @@ -704,24 +723,19 @@ vcc_resolve_includes(struct tokenlist *tl) /*--------------------------------------------------------------------*/ -static char * -vcc_CompileSource(struct vsb *sb, struct source *sp) +static struct tokenlist * +vcc_NewTokenList(void) { - struct tokenlist tokenlist, *tl; - struct ref *r; - struct token *t; - FILE *fo; - char *of = NULL; - char buf[BUFSIZ]; + struct tokenlist *tl; int i; - memset(&tokenlist, 0, sizeof tokenlist); - tl = &tokenlist; + tl = calloc(sizeof *tl, 1); + assert(tl != NULL); + TAILQ_INIT(&tl->membits); TAILQ_INIT(&tl->tokens); TAILQ_INIT(&tl->refs); TAILQ_INIT(&tl->procs); TAILQ_INIT(&tl->sources); - tl->sb = sb; tl->nsources = 0; @@ -746,36 +760,187 @@ vcc_CompileSource(struct vsb *sb, struct source *sp) tl->fm[i] = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND); \ assert(tl->fm[i] != NULL); } + return (tl); +} + +/*--------------------------------------------------------------------*/ + +static char * +vcc_DestroyTokenList(struct tokenlist *tl, char *ret) +{ + struct membit *mb; + int i; + + while (!TAILQ_EMPTY(&tl->membits)) { + mb = TAILQ_FIRST(&tl->membits); + TAILQ_REMOVE(&tl->membits, mb, list); + free(mb->ptr); + free(mb); + } + + vsb_delete(tl->fh); + vsb_delete(tl->fc); + vsb_delete(tl->fi); + vsb_delete(tl->ff); + for (i = 0; i < N_METHODS; i++) + vsb_delete(tl->fm[i]); + + free(tl); + return (ret); +} + +/*-------------------------------------------------------------------- + * Invoke system C compiler on source and return resulting dlfile. + * Errors goes in sb; + */ + +static char * +vcc_CallCc(char *source, struct vsb *sb) +{ + FILE *fo, *fs; + char *of, *sf, buf[BUFSIZ]; + int i, j, sfd; + + /* Create temporary C source file */ + sf = strdup("/tmp/vcl.XXXXXXXX"); + assert(sf != NULL); + sfd = mkstemp(sf); + if (sfd < 0) { + vsb_printf(sb, + "Cannot open temporary source file \"%s\": %s\n", + sf, strerror(errno)); + free(sf); + return (NULL); + } + fs = fdopen(sfd, "r+"); + assert(fs != NULL); + + if (fputs(source, fs) || fflush(fs)) { + vsb_printf(sb, + "Write error to C source file: %s\n", + strerror(errno)); + unlink(sf); + fclose(fs); + return (NULL); + } + rewind(fs); + + /* Name the output shared library */ + of = strdup("/tmp/vcl.XXXXXXXX"); + assert(of != NULL); + of = mktemp(of); + assert(of != NULL); + + /* Attempt to open a pipe to the system C-compiler */ + sprintf(buf, + "ln -f %s /tmp/_.c ;" /* XXX: for debugging */ + "exec cc -fpic -shared -Wl,-x -o %s -x c - < %s 2>&1", + sf, of, sf); + + fo = popen(buf, "r"); + if (fo == NULL) { + vsb_printf(sb, + "Internal error: Cannot execute cc(1): %s\n", + strerror(errno)); + free(of); + unlink(sf); + fclose(fs); + return (NULL); + } + + /* If we get any output, it's bad */ + j = 0; + while (1) { + if (fgets(buf, sizeof buf, fo) == NULL) + break; + if (!j) { + vsb_printf(sb, "Internal error: cc(1) complained:\n"); + j++; + } + vsb_cat(sb, buf); + } + + i = pclose(fo); + if (j == 0 && i != 0) + vsb_printf(sb, + "Internal error: cc(1) exit status 0x%04x\n", i); + + /* If the compiler complained, or exited non-zero, fail */ + if (i || j) { + unlink(of); + free(of); + of = NULL; + } + + /* clean up and return */ + unlink(sf); + free(sf); + fclose(fs); + return (of); +} + +/*-------------------------------------------------------------------- + * Compile the VCL code from the given source and return the filename + * of the resulting shared library. + */ +static char * +vcc_CompileSource(struct vsb *sb, struct source *sp) +{ + struct tokenlist *tl; + char *of; + int i; + + tl = vcc_NewTokenList(); + tl->sb = sb; + + vcl_output_lang_h(tl->fh); Fh(tl, 0, "extern struct VCL_conf VCL_conf;\n"); Fi(tl, 0, "\tVRT_alloc_backends(&VCL_conf);\n"); + /* Register and lex the main source */ TAILQ_INSERT_TAIL(&tl->sources, sp, list); sp->idx = tl->nsources++; vcc_Lexer(tl, sp); if (tl->err) - goto done; + return (vcc_DestroyTokenList(tl, NULL)); + /* Register and lex the default VCL */ sp = vcc_new_source(vcc_default_vcl_b, vcc_default_vcl_e, "Default"); + assert(sp != NULL); TAILQ_INSERT_TAIL(&tl->sources, sp, list); sp->idx = tl->nsources++; vcc_Lexer(tl, sp); + if (tl->err) + return (vcc_DestroyTokenList(tl, NULL)); + + /* Add "END OF INPUT" token */ vcc_AddToken(tl, EOI, sp->e, sp->e); if (tl->err) - goto done; + return (vcc_DestroyTokenList(tl, NULL)); + /* Expand and lex any includes in the token string */ vcc_resolve_includes(tl); if (tl->err) - goto done; + return (vcc_DestroyTokenList(tl, NULL)); + /* Parse the token string */ tl->t = TAILQ_FIRST(&tl->tokens); vcc_Parse(tl); if (tl->err) - goto done; + return (vcc_DestroyTokenList(tl, NULL)); + + /* Perform consistency checks */ Consistency(tl); if (tl->err) - goto done; + return (vcc_DestroyTokenList(tl, NULL)); + + /* Check for orphans */ + if (CheckRefs(tl)) + return (vcc_DestroyTokenList(tl, NULL)); + + Ff(tl, 0, "\tVRT_free_backends(&VCL_conf);\n"); /* Emit method functions */ for (i = 0; i < N_METHODS; i++) { @@ -783,6 +948,7 @@ vcc_CompileSource(struct vsb *sb, struct source *sp) Fc(tl, 1, "VGC_function_%s (struct sess *sp)\n", method_tab[i].name); vsb_finish(tl->fm[i]); + /* XXX: check vsb_overflowed ? */ Fc(tl, 1, "{\n"); Fc(tl, 1, "%s", vsb_data(tl->fm[i])); Fc(tl, 1, "}\n\n"); @@ -790,69 +956,29 @@ vcc_CompileSource(struct vsb *sb, struct source *sp) LocTable(tl); - Ff(tl, 0, "\tVRT_free_backends(&VCL_conf);\n"); - EmitInitFunc(tl); EmitFiniFunc(tl); EmitStruct(tl); - if (CheckRefs(tl)) - goto done; - - of = strdup("/tmp/vcl.XXXXXXXX"); - assert(of != NULL); - mktemp(of); - - sprintf(buf, - "tee /tmp/_.c |" - "cc -fpic -shared -Wl,-x -o %s -x c - ", of); - - fo = popen(buf, "w"); - assert(fo != NULL); - - vcl_output_lang_h(fo); - fputs(vrt_obj_h, fo); - - vsb_finish(tl->fh); - fputs(vsb_data(tl->fh), fo); - vsb_delete(tl->fh); - + /* Combine it all in the fh vsb */ vsb_finish(tl->fc); - fputs(vsb_data(tl->fc), fo); - vsb_delete(tl->fc); - - i = pclose(fo); - fprintf(stderr, "pclose=%d\n", i); - if (i) { - vsb_printf(sb, "Internal error: GCC returned 0x%04x\n", i); - unlink(of); - free(of); - return (NULL); - } -done: + /* XXX: check vsb_overflowed ? */ + vsb_cat(tl->fh, vsb_data(tl->fc)); + vsb_finish(tl->fh); - for (i = 0; i < N_METHODS; i++) - vsb_delete(tl->fm[i]); + /* Grind it through cc(1) */ + of = vcc_CallCc(vsb_data(tl->fh), sb); - /* Free References */ - while (!TAILQ_EMPTY(&tl->refs)) { - r = TAILQ_FIRST(&tl->refs); - TAILQ_REMOVE(&tl->refs, r, list); - free(r); - } - - /* Free Tokens */ - while (!TAILQ_EMPTY(&tl->tokens)) { - t = TAILQ_FIRST(&tl->tokens); - TAILQ_REMOVE(&tl->tokens, t, list); - vcc_FreeToken(t); - } - return (of); + /* done */ + return (vcc_DestroyTokenList(tl, of)); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * Compile the VCL code in the argument. Error messages, if any are + * formatted into the vsb. + */ char * VCC_Compile(struct vsb *sb, const char *b, const char *e) @@ -868,7 +994,10 @@ VCC_Compile(struct vsb *sb, const char *b, const char *e) return (r); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * Compile the VCL code from the file named. Error messages, if any + * are formatted into the vsb. + */ char * VCC_CompileFile(struct vsb *sb, const char *fn) @@ -884,7 +1013,10 @@ VCC_CompileFile(struct vsb *sb, const char *fn) return (r); } -/*--------------------------------------------------------------------*/ +/*-------------------------------------------------------------------- + * Initialize the compiler and register the default VCL code for later + * compilation runs. + */ void VCC_InitCompile(const char *default_vcl) diff --git a/varnish-cache/lib/libvcl/vcc_compile.h b/varnish-cache/lib/libvcl/vcc_compile.h index f6307a74..af350442 100644 --- a/varnish-cache/lib/libvcl/vcc_compile.h +++ b/varnish-cache/lib/libvcl/vcc_compile.h @@ -34,6 +34,11 @@ #define INDENT 2 +struct membit { + TAILQ_ENTRY(membit) list; + void *ptr; +}; + struct source { TAILQ_ENTRY(source) list; char *name; @@ -57,6 +62,7 @@ TAILQ_HEAD(tokenhead, token); struct tokenlist { struct tokenhead tokens; TAILQ_HEAD(, source) sources; + TAILQ_HEAD(, membit) membits; unsigned nsources; struct source *src; struct token *t; @@ -156,11 +162,11 @@ 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); /* vcc_obj.c */ extern struct var vcc_be_vars[]; extern struct var vcc_vars[]; -extern const char *vrt_obj_h; /* vcc_parse.c */ void vcc_Parse(struct tokenlist *tl); diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 13094c85..131a67d7 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -9,6 +9,7 @@ #include #include #include "vcc_priv.h" +#include "vsb.h" unsigned vcl_fixed_token(const char *p, const char **q) @@ -427,147 +428,183 @@ vcl_init_tnames(void) } void -vcl_output_lang_h(FILE *f) +vcl_output_lang_h(struct vsb *sb) { - fputs("#define VCL_RET_ERROR (1 << 0)\n", f); - fputs("#define VCL_RET_LOOKUP (1 << 1)\n", f); - fputs("#define VCL_RET_HASH (1 << 2)\n", f); - fputs("#define VCL_RET_PIPE (1 << 3)\n", f); - fputs("#define VCL_RET_PASS (1 << 4)\n", f); - fputs("#define VCL_RET_FETCH (1 << 5)\n", f); - fputs("#define VCL_RET_INSERT (1 << 6)\n", f); - fputs("#define VCL_RET_DELIVER (1 << 7)\n", f); - fputs("#define VCL_RET_DISCARD (1 << 8)\n", f); - fputs("/*\n", f); - fputs(" * $Id$\n", f); - fputs(" *\n", f); - fputs(" * NB: This file is machine generated, DO NOT EDIT!\n", f); - fputs(" *\n", f); - fputs(" * Edit vcc_gen_fixed_token.tcl instead\n", f); - fputs(" */\n", f); - fputs("\n", f); - fputs("struct sess;\n", f); - fputs("\n", f); - fputs("typedef void vcl_init_f(void);\n", f); - fputs("typedef void vcl_fini_f(void);\n", f); - fputs("typedef int vcl_func_f(struct sess *sp);\n", f); - fputs("\n", f); - fputs("struct VCL_conf {\n", f); - fputs(" unsigned magic;\n", f); - fputs("#define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */\n", f); - fputs("\n", f); - fputs(" struct backend **backend;\n", f); - fputs(" unsigned nbackend;\n", f); - fputs(" struct vrt_ref *ref;\n", f); - fputs(" unsigned nref;\n", f); - fputs(" unsigned busy;\n", f); - fputs("\n", f); - fputs(" unsigned nsrc;\n", f); - fputs(" const char **srcname;\n", f); - fputs(" const char **srcbody;\n", f); - fputs("\n", f); - fputs(" void *priv;\n", f); - fputs("\n", f); - fputs(" vcl_init_f *init_func;\n", f); - fputs(" vcl_fini_f *fini_func;\n", f); - fputs("\n", f); - fputs(" vcl_func_f *recv_func;\n", f); - fputs(" vcl_func_f *pipe_func;\n", f); - fputs(" vcl_func_f *pass_func;\n", f); - fputs(" vcl_func_f *hash_func;\n", f); - fputs(" vcl_func_f *miss_func;\n", f); - fputs(" vcl_func_f *hit_func;\n", f); - fputs(" vcl_func_f *fetch_func;\n", f); - fputs(" vcl_func_f *timeout_func;\n", f); - fputs("};\n", f); - fputs("/*-\n", f); - fputs(" * Copyright (c) 2006 Verdens Gang AS\n", f); - fputs(" * Copyright (c) 2006 Linpro AS\n", f); - fputs(" * All rights reserved.\n", f); - fputs(" *\n", f); - fputs(" * Author: Poul-Henning Kamp \n", f); - fputs(" *\n", f); - fputs(" * Redistribution and use in source and binary forms, with or without\n", f); - fputs(" * modification, are permitted provided that the following conditions\n", f); - fputs(" * are met:\n", f); - fputs(" * 1. Redistributions of source code must retain the above copyright\n", f); - fputs(" * notice, this list of conditions and the following disclaimer.\n", f); - fputs(" * 2. Redistributions in binary form must reproduce the above copyright\n", f); - fputs(" * notice, this list of conditions and the following disclaimer in the\n", f); - fputs(" * documentation and/or other materials provided with the distribution.\n", f); - fputs(" *\n", f); - fputs(" * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n", f); - fputs(" * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n", f); - fputs(" * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n", f); - fputs(" * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE\n", f); - fputs(" * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n", f); - fputs(" * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n", f); - fputs(" * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n", f); - fputs(" * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n", f); - fputs(" * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n", f); - fputs(" * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n", f); - fputs(" * SUCH DAMAGE.\n", f); - fputs(" *\n", f); - fputs(" * $Id$\n", f); - fputs(" *\n", f); - fputs(" * Runtime support for compiled VCL programs.\n", f); - fputs(" *\n", f); - fputs(" * XXX: When this file is changed, lib/libvcl/vcc_gen_fixed_token.tcl\n", f); - fputs(" * XXX: *MUST* be rerun.\n", f); - fputs(" */\n", f); - fputs("\n", f); - fputs("struct sess;\n", f); - fputs("struct vsb;\n", f); - fputs("struct backend;\n", f); - fputs("struct VCL_conf;\n", f); - fputs("\n", f); - fputs("struct vrt_ref {\n", f); - fputs(" unsigned source;\n", f); - fputs(" unsigned offset;\n", f); - fputs(" unsigned line;\n", f); - fputs(" unsigned pos;\n", f); - fputs(" unsigned count;\n", f); - fputs(" const char *token;\n", f); - fputs("};\n", f); - fputs("\n", f); - fputs("struct vrt_acl {\n", f); - fputs(" unsigned char not;\n", f); - fputs(" unsigned char mask;\n", f); - fputs(" unsigned char paren;\n", f); - fputs(" const char *name;\n", f); - fputs(" const char *desc;\n", f); - fputs(" void *priv;\n", f); - fputs("};\n", f); - fputs("\n", f); - fputs("/* ACL related */\n", f); - fputs("int VRT_acl_match(struct sess *, const char *, struct vrt_acl *);\n", f); - fputs("void VRT_acl_init(struct vrt_acl *);\n", f); - fputs("void VRT_acl_fini(struct vrt_acl *);\n", f); - fputs("\n", f); - fputs("/* Regexp related */\n", f); - fputs("void VRT_re_init(void **, const char *);\n", f); - fputs("void VRT_re_fini(void *);\n", f); - fputs("int VRT_re_match(const char *, void *re);\n", f); - fputs("int VRT_re_test(struct vsb *, const char *);\n", f); - fputs("\n", f); - fputs("void VRT_count(struct sess *, unsigned);\n", f); - fputs("int VRT_rewrite(const char *, const char *);\n", f); - fputs("void VRT_error(struct sess *, unsigned, const char *);\n", f); - fputs("int VRT_switch_config(const char *);\n", f); - fputs("\n", f); - fputs("char *VRT_GetHdr(struct sess *, int where, const char *);\n", f); - fputs("void VRT_handling(struct sess *sp, unsigned hand);\n", f); - fputs("\n", f); - fputs("/* Backend related */\n", f); - fputs("void VRT_set_backend_name(struct backend *, const char *);\n", f); - fputs("void VRT_alloc_backends(struct VCL_conf *cp);\n", f); - fputs("void VRT_free_backends(struct VCL_conf *cp);\n", f); - fputs("void VRT_fini_backend(struct backend *be);\n", f); - fputs("\n", f); - fputs("\n", f); - fputs("#define VRT_done(sp, hand) \\\n", f); - fputs(" do { \\\n", f); - fputs(" VRT_handling(sp, hand); \\\n", f); - fputs(" return (1); \\\n", f); - fputs(" } while (0)\n", f); + vsb_cat(sb, "#define VCL_RET_ERROR (1 << 0)\n"); + vsb_cat(sb, "#define VCL_RET_LOOKUP (1 << 1)\n"); + vsb_cat(sb, "#define VCL_RET_HASH (1 << 2)\n"); + vsb_cat(sb, "#define VCL_RET_PIPE (1 << 3)\n"); + vsb_cat(sb, "#define VCL_RET_PASS (1 << 4)\n"); + vsb_cat(sb, "#define VCL_RET_FETCH (1 << 5)\n"); + vsb_cat(sb, "#define VCL_RET_INSERT (1 << 6)\n"); + vsb_cat(sb, "#define VCL_RET_DELIVER (1 << 7)\n"); + vsb_cat(sb, "#define VCL_RET_DISCARD (1 << 8)\n"); + vsb_cat(sb, "/*\n"); + vsb_cat(sb, " * $Id$\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * NB: This file is machine generated, DO NOT EDIT!\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * Edit vcc_gen_fixed_token.tcl instead\n"); + vsb_cat(sb, " */\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "struct sess;\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "typedef void vcl_init_f(void);\n"); + vsb_cat(sb, "typedef void vcl_fini_f(void);\n"); + vsb_cat(sb, "typedef int vcl_func_f(struct sess *sp);\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "struct VCL_conf {\n"); + vsb_cat(sb, " unsigned magic;\n"); + vsb_cat(sb, "#define VCL_CONF_MAGIC 0x7406c509 /* from /dev/random */\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, " struct backend **backend;\n"); + vsb_cat(sb, " unsigned nbackend;\n"); + vsb_cat(sb, " struct vrt_ref *ref;\n"); + vsb_cat(sb, " unsigned nref;\n"); + vsb_cat(sb, " unsigned busy;\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, " unsigned nsrc;\n"); + vsb_cat(sb, " const char **srcname;\n"); + vsb_cat(sb, " const char **srcbody;\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, " void *priv;\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, " vcl_init_f *init_func;\n"); + vsb_cat(sb, " vcl_fini_f *fini_func;\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, " vcl_func_f *recv_func;\n"); + vsb_cat(sb, " vcl_func_f *pipe_func;\n"); + vsb_cat(sb, " vcl_func_f *pass_func;\n"); + vsb_cat(sb, " vcl_func_f *hash_func;\n"); + vsb_cat(sb, " vcl_func_f *miss_func;\n"); + vsb_cat(sb, " vcl_func_f *hit_func;\n"); + vsb_cat(sb, " vcl_func_f *fetch_func;\n"); + vsb_cat(sb, " vcl_func_f *timeout_func;\n"); + vsb_cat(sb, "};\n"); + vsb_cat(sb, "/*-\n"); + vsb_cat(sb, " * Copyright (c) 2006 Verdens Gang AS\n"); + vsb_cat(sb, " * Copyright (c) 2006 Linpro AS\n"); + vsb_cat(sb, " * All rights reserved.\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * Author: Poul-Henning Kamp \n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * Redistribution and use in source and binary forms, with or without\n"); + vsb_cat(sb, " * modification, are permitted provided that the following conditions\n"); + vsb_cat(sb, " * are met:\n"); + vsb_cat(sb, " * 1. Redistributions of source code must retain the above copyright\n"); + vsb_cat(sb, " * notice, this list of conditions and the following disclaimer.\n"); + vsb_cat(sb, " * 2. Redistributions in binary form must reproduce the above copyright\n"); + vsb_cat(sb, " * notice, this list of conditions and the following disclaimer in the\n"); + vsb_cat(sb, " * documentation and/or other materials provided with the distribution.\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n"); + vsb_cat(sb, " * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"); + vsb_cat(sb, " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"); + vsb_cat(sb, " * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE\n"); + vsb_cat(sb, " * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"); + vsb_cat(sb, " * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"); + vsb_cat(sb, " * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n"); + vsb_cat(sb, " * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n"); + vsb_cat(sb, " * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n"); + vsb_cat(sb, " * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n"); + vsb_cat(sb, " * SUCH DAMAGE.\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * $Id$\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * Runtime support for compiled VCL programs.\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * XXX: When this file is changed, lib/libvcl/vcc_gen_fixed_token.tcl\n"); + vsb_cat(sb, " * XXX: *MUST* be rerun.\n"); + vsb_cat(sb, " */\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "struct sess;\n"); + vsb_cat(sb, "struct vsb;\n"); + vsb_cat(sb, "struct backend;\n"); + vsb_cat(sb, "struct VCL_conf;\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "struct vrt_ref {\n"); + vsb_cat(sb, " unsigned source;\n"); + vsb_cat(sb, " unsigned offset;\n"); + vsb_cat(sb, " unsigned line;\n"); + vsb_cat(sb, " unsigned pos;\n"); + vsb_cat(sb, " unsigned count;\n"); + vsb_cat(sb, " const char *token;\n"); + vsb_cat(sb, "};\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "struct vrt_acl {\n"); + vsb_cat(sb, " unsigned char not;\n"); + vsb_cat(sb, " unsigned char mask;\n"); + vsb_cat(sb, " unsigned char paren;\n"); + vsb_cat(sb, " const char *name;\n"); + vsb_cat(sb, " const char *desc;\n"); + vsb_cat(sb, " void *priv;\n"); + vsb_cat(sb, "};\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "/* ACL related */\n"); + vsb_cat(sb, "int VRT_acl_match(struct sess *, const char *, struct vrt_acl *);\n"); + vsb_cat(sb, "void VRT_acl_init(struct vrt_acl *);\n"); + vsb_cat(sb, "void VRT_acl_fini(struct vrt_acl *);\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "/* Regexp related */\n"); + vsb_cat(sb, "void VRT_re_init(void **, const char *);\n"); + vsb_cat(sb, "void VRT_re_fini(void *);\n"); + vsb_cat(sb, "int VRT_re_match(const char *, void *re);\n"); + vsb_cat(sb, "int VRT_re_test(struct vsb *, const char *);\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "void VRT_count(struct sess *, unsigned);\n"); + vsb_cat(sb, "int VRT_rewrite(const char *, const char *);\n"); + vsb_cat(sb, "void VRT_error(struct sess *, unsigned, const char *);\n"); + vsb_cat(sb, "int VRT_switch_config(const char *);\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "char *VRT_GetHdr(struct sess *, int where, const char *);\n"); + vsb_cat(sb, "void VRT_handling(struct sess *sp, unsigned hand);\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "/* Backend related */\n"); + vsb_cat(sb, "void VRT_set_backend_name(struct backend *, const char *);\n"); + vsb_cat(sb, "void VRT_alloc_backends(struct VCL_conf *cp);\n"); + vsb_cat(sb, "void VRT_free_backends(struct VCL_conf *cp);\n"); + vsb_cat(sb, "void VRT_fini_backend(struct backend *be);\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "#define VRT_done(sp, hand) \\\n"); + vsb_cat(sb, " do { \\\n"); + vsb_cat(sb, " VRT_handling(sp, hand); \\\n"); + vsb_cat(sb, " return (1); \\\n"); + vsb_cat(sb, " } while (0)\n"); + vsb_cat(sb, "/*\n"); + vsb_cat(sb, " * $Id$\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * NB: This file is machine generated, DO NOT EDIT!\n"); + vsb_cat(sb, " *\n"); + vsb_cat(sb, " * Edit vcc_gen_obj.tcl instead\n"); + vsb_cat(sb, " */\n"); + vsb_cat(sb, "\n"); + vsb_cat(sb, "const char * VRT_r_backend_host(struct backend *);\n"); + vsb_cat(sb, "void VRT_l_backend_host(struct backend *, const char *);\n"); + vsb_cat(sb, "const char * VRT_r_backend_port(struct backend *);\n"); + vsb_cat(sb, "void VRT_l_backend_port(struct backend *, const char *);\n"); + vsb_cat(sb, "double VRT_r_backend_dnsttl(struct backend *);\n"); + vsb_cat(sb, "void VRT_l_backend_dnsttl(struct backend *, double);\n"); + vsb_cat(sb, "const unsigned char * VRT_r_client_ip(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_client_ip(struct sess *, const unsigned char *);\n"); + vsb_cat(sb, "const char * VRT_r_req_request(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_req_request(struct sess *, const char *);\n"); + vsb_cat(sb, "const char * VRT_r_req_host(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_req_host(struct sess *, const char *);\n"); + vsb_cat(sb, "const char * VRT_r_req_url(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_req_url(struct sess *, const char *);\n"); + vsb_cat(sb, "const char * VRT_r_req_proto(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_req_proto(struct sess *, const char *);\n"); + vsb_cat(sb, "struct backend * VRT_r_req_backend(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_req_backend(struct sess *, struct backend *);\n"); + vsb_cat(sb, "double VRT_r_obj_valid(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_obj_valid(struct sess *, double);\n"); + vsb_cat(sb, "double VRT_r_obj_cacheable(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_obj_cacheable(struct sess *, double);\n"); + vsb_cat(sb, "double VRT_r_obj_ttl(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_obj_ttl(struct sess *, double);\n"); + vsb_cat(sb, "const char * VRT_r_req_http_(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_req_http_(struct sess *, const char *);\n"); + vsb_cat(sb, "const char * VRT_r_resp_http_(struct sess *);\n"); + vsb_cat(sb, "void VRT_l_resp_http_(struct sess *, const char *);\n"); } diff --git a/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl b/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl index 317d3c1b..1a341d0b 100755 --- a/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl +++ b/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl @@ -214,6 +214,7 @@ warns $foh puts $fo "#include " puts $fo "#include " puts $fo "#include \"vcc_priv.h\"" +puts $fo "#include \"vsb.h\"" set tn 128 puts $foh "#define LOW_TOKEN $tn" @@ -338,23 +339,24 @@ proc copy_include {n} { set fi [open $n] while {[gets $fi a] >= 0} { regsub -all {\\} $a {\\\\} a - puts $fo "\tfputs(\"$a\\n\", f);" + puts $fo "\tvsb_cat(sb, \"$a\\n\");" } close $fi } puts $fo "" puts $fo "void" -puts $fo "vcl_output_lang_h(FILE *f)" +puts $fo "vcl_output_lang_h(struct vsb *sb)" puts $fo "{" set i 0 foreach k $returns { - puts $fo "\tfputs(\"#define VCL_RET_[string toupper $k] (1 << $i)\\n\", f);" + puts $fo "\tvsb_cat(sb, \"#define VCL_RET_[string toupper $k] (1 << $i)\\n\");" incr i } copy_include ../../include/vcl.h copy_include ../../include/vrt.h +copy_include ../../include/vrt_obj.h puts $fo "}" diff --git a/varnish-cache/lib/libvcl/vcc_gen_obj.tcl b/varnish-cache/lib/libvcl/vcc_gen_obj.tcl index 24534576..2364bed1 100755 --- a/varnish-cache/lib/libvcl/vcc_gen_obj.tcl +++ b/varnish-cache/lib/libvcl/vcc_gen_obj.tcl @@ -115,14 +115,3 @@ vars $spobj "struct sess *" "sp" puts $fo "};" close $fp -set fp [open ../../include/vrt_obj.h] - -puts $fo "" -puts $fo "const char *vrt_obj_h = " -while {[gets $fp a] >= 0} { - puts $fo "\t\"$a\\n\"" -} -puts $fo ";" - -close $fo -close $fp diff --git a/varnish-cache/lib/libvcl/vcc_obj.c b/varnish-cache/lib/libvcl/vcc_obj.c index dddc1714..bed7a67f 100644 --- a/varnish-cache/lib/libvcl/vcc_obj.c +++ b/varnish-cache/lib/libvcl/vcc_obj.c @@ -72,42 +72,3 @@ struct var vcc_vars[] = { }, { NULL } }; - -const char *vrt_obj_h = - "/*\n" - " * $Id$\n" - " *\n" - " * NB: This file is machine generated, DO NOT EDIT!\n" - " *\n" - " * Edit vcc_gen_obj.tcl instead\n" - " */\n" - "\n" - "const char * VRT_r_backend_host(struct backend *);\n" - "void VRT_l_backend_host(struct backend *, const char *);\n" - "const char * VRT_r_backend_port(struct backend *);\n" - "void VRT_l_backend_port(struct backend *, const char *);\n" - "double VRT_r_backend_dnsttl(struct backend *);\n" - "void VRT_l_backend_dnsttl(struct backend *, double);\n" - "const unsigned char * VRT_r_client_ip(struct sess *);\n" - "void VRT_l_client_ip(struct sess *, const unsigned char *);\n" - "const char * VRT_r_req_request(struct sess *);\n" - "void VRT_l_req_request(struct sess *, const char *);\n" - "const char * VRT_r_req_host(struct sess *);\n" - "void VRT_l_req_host(struct sess *, const char *);\n" - "const char * VRT_r_req_url(struct sess *);\n" - "void VRT_l_req_url(struct sess *, const char *);\n" - "const char * VRT_r_req_proto(struct sess *);\n" - "void VRT_l_req_proto(struct sess *, const char *);\n" - "struct backend * VRT_r_req_backend(struct sess *);\n" - "void VRT_l_req_backend(struct sess *, struct backend *);\n" - "double VRT_r_obj_valid(struct sess *);\n" - "void VRT_l_obj_valid(struct sess *, double);\n" - "double VRT_r_obj_cacheable(struct sess *);\n" - "void VRT_l_obj_cacheable(struct sess *, double);\n" - "double VRT_r_obj_ttl(struct sess *);\n" - "void VRT_l_obj_ttl(struct sess *, double);\n" - "const char * VRT_r_req_http_(struct sess *);\n" - "void VRT_l_req_http_(struct sess *, const char *);\n" - "const char * VRT_r_resp_http_(struct sess *);\n" - "void VRT_l_resp_http_(struct sess *, const char *);\n" -; diff --git a/varnish-cache/lib/libvcl/vcc_priv.h b/varnish-cache/lib/libvcl/vcc_priv.h index 6157c223..ece948a8 100644 --- a/varnish-cache/lib/libvcl/vcc_priv.h +++ b/varnish-cache/lib/libvcl/vcc_priv.h @@ -33,12 +33,14 @@ #include "vcc_token_defs.h" +struct vsb; + #define isident1(c) (isalpha(c)) #define isident(c) (isalpha(c) || isdigit(c) || (c) == '_' || (c) == '-') #define isvar(c) (isident(c) || (c) == '.') unsigned vcl_fixed_token(const char *p, const char **q); extern const char *vcl_tnames[256]; void vcl_init_tnames(void); -void vcl_output_lang_h(FILE *f); +void vcl_output_lang_h(struct vsb *sb); #define PF(t) ((t)->e - (t)->b), (t)->b diff --git a/varnish-cache/lib/libvcl/vcc_token.c b/varnish-cache/lib/libvcl/vcc_token.c index 44f80f46..5f16d448 100644 --- a/varnish-cache/lib/libvcl/vcc_token.c +++ b/varnish-cache/lib/libvcl/vcc_token.c @@ -285,6 +285,8 @@ vcc_FreeToken(struct token *t) { /* XXX: more */ + if (t->dec != NULL) + free(t->dec); free(t); }