static void vcc_ByteVal(struct vcc *tl, double *d) { double v, sc; v = vcc_DoubleVal(tl); ERRCHK(tl); if (tl->t->tok != ID) { vsb_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got "); vcc_ErrToken(tl, tl->t); vsb_printf(tl->sb, "\n"); vcc_ErrWhere(tl, tl->t); return; } if (vcc_IdIs(tl->t, "B")) sc = 1.; else if (vcc_IdIs(tl->t, "KB")) sc = 1024.; else if (vcc_IdIs(tl->t, "MB")) sc = 1024. * 1024.; else if (vcc_IdIs(tl->t, "GB")) sc = 1024. * 1024. * 1024.; else if (vcc_IdIs(tl->t, "TB")) sc = 1024. * 1024. * 1024. * 1024.; else { vsb_printf(tl->sb, "Unknown BYTES unit "); vcc_ErrToken(tl, tl->t); vsb_printf(tl->sb, ". Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n"); vcc_ErrWhere(tl, tl->t); return; } vcc_NextToken(tl); *d = v * sc; }
static void cmd_http_chunkedlen(CMD_ARGS) { unsigned len; unsigned u, v; char buf[16384]; struct http *hp; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AZ(av[2]); vsb_clear(hp->vsb); len = atoi(av[1]); for (u = 0; u < sizeof buf; u++) buf[u] = (u & 7) + '0'; for (u = 0; u < len; u += 16384) { v = len - u; if (v > sizeof buf) v = sizeof buf; vsb_printf(hp->vsb, "%x%s", v, nl); vsb_printf(hp->vsb, "%*.*s%s", v, v, buf, nl); } vsb_printf(hp->vsb, "%x%s%s", 0, nl, nl); http_write(hp, 4, "chunked"); }
static double vcc_TimeUnit(struct vcc *tl) { double sc = 1.0; assert(tl->t->tok == ID); if (vcc_IdIs(tl->t, "ms")) sc = 1e-3; else if (vcc_IdIs(tl->t, "s")) sc = 1.0; else if (vcc_IdIs(tl->t, "m")) sc = 60.0; else if (vcc_IdIs(tl->t, "h")) sc = 60.0 * 60.0; else if (vcc_IdIs(tl->t, "d")) sc = 60.0 * 60.0 * 24.0; else if (vcc_IdIs(tl->t, "w")) sc = 60.0 * 60.0 * 24.0 * 7.0; else { vsb_printf(tl->sb, "Unknown time unit "); vcc_ErrToken(tl, tl->t); vsb_printf(tl->sb, ". Legal are 's', 'm', 'h' and 'd'\n"); vcc_ErrWhere(tl, tl->t); return (1.0); } vcc_NextToken(tl); return (sc); }
static void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt) { struct expr *e2; struct token *tk; *e = NULL; vcc_expr_cand(tl, e, fmt); ERRCHK(tl); if ((*e)->fmt != BOOL || tl->t->tok != T_COR) return; *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL); while (tl->t->tok == T_COR) { vcc_NextToken(tl); tk = tl->t; vcc_expr_cand(tl, &e2, fmt); ERRCHK(tl); if (e2->fmt != BOOL) { vsb_printf(tl->sb, "'||' must be followed by BOOL, found "); vsb_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); return; } *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2); } *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL); }
static void illegal_assignment(const struct tokenlist *tl, const char *type) { vsb_printf(tl->sb, "Invalid assignment operator "); vcc_ErrToken(tl, tl->t); vsb_printf(tl->sb, " only '=' is legal for %s\n", type); }
void vcc__Expect(struct tokenlist *tl, unsigned tok, int line) { if (tl->t->tok == tok) return; vsb_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]); vcc_ErrToken(tl, tl->t); vsb_printf(tl->sb, "\n(program line %u), at\n", line); vcc_ErrWhere(tl, tl->t); }
void vcc_ErrToken(const struct tokenlist *tl, const struct token *t) { if (t->tok == EOI) vsb_printf(tl->sb, "end of input"); else if (t->tok == CSRC) vsb_printf(tl->sb, "C{ ... }C"); else vsb_printf(tl->sb, "'%.*s'", PF(t)); }
void vcc_ExpectCid(struct tokenlist *tl) { ExpectErr(tl, ID); ERRCHK(tl); if (vcc_isCid(tl->t)) return; vsb_printf(tl->sb, "Identifier "); vcc_ErrToken(tl, tl->t); vsb_printf(tl->sb, " contains illegal characters, use [0-9a-zA-Z_] only.\n"); vcc_ErrWhere(tl, tl->t); }
static void vcc_icoord(struct vsb *vsb, const struct token *t, const char **ll) { unsigned lin, pos; const char *p, *b; struct source *sp; lin = 1; pos = 0; sp = t->src; b = sp->b; if (ll != NULL) *ll = b; for (p = b; p < t->b; p++) { if (*p == '\n') { lin++; pos = 0; if (ll != NULL) *ll = p + 1; } else if (*p == '\t') { pos &= ~7; pos += 8; } else pos++; } vsb_printf(vsb, "(%s Line %d Pos %d)", sp->name, lin, pos + 1); }
void vcc_Expr(struct vcc *tl, enum var_type fmt) { struct expr *e; struct token *t1; assert(fmt != VOID); t1 = tl->t; vcc_expr0(tl, &e, fmt); ERRCHK(tl); if (fmt == STRING || fmt == STRING_LIST) vcc_expr_tostring(&e, fmt); if (!tl->err && fmt != e->fmt) { vsb_printf(tl->sb, "Expression has type %s, expected %s\n", vcc_Type(e->fmt), vcc_Type(fmt)); tl->err = 1; } if (!tl->err) { if (e->fmt == STRING_LIST) { e = vcc_expr_edit(STRING_LIST, "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL); } vcc_expr_fmt(tl->fb, tl->indent, e); vsb_putc(tl->fb, '\n'); } else { if (t1 != tl->t) vcc_ErrWhere2(tl, t1, tl->t); } vcc_delete_expr(e); }
static void parse_return(struct tokenlist *tl) { int retval = 0; vcc_NextToken(tl); ExpectErr(tl, '('); vcc_NextToken(tl); ExpectErr(tl, ID); #define VCL_RET_MAC(l, U) \ do { \ if (vcc_IdIs(tl->t, #l)) { \ Fb(tl, 1, "VRT_done(sp, VCL_RET_" #U ");\n"); \ vcc_ProcAction(tl->curproc, VCL_RET_##U, tl->t);\ retval = 1; \ } \ } while (0); #include "vcl_returns.h" #undef VCL_RET_MAC if (!retval) { vsb_printf(tl->sb, "Expected return action name.\n"); vcc_ErrWhere(tl, tl->t); ERRCHK(tl); } vcc_NextToken(tl); ExpectErr(tl, ')'); vcc_NextToken(tl); }
//lint -e{818} void vtc_log(struct vtclog *vl, unsigned lvl, const char *fmt, ...) { CHECK_OBJ_NOTNULL(vl, VTCLOG_MAGIC); AZ(pthread_mutex_lock(&vl->mtx)); assert(lvl < NLEAD); vsb_clear(vl->vsb); vsb_printf(vl->vsb, "%s %-4s ", lead[lvl], vl->id); va_list ap; va_start(ap, fmt); (void)vsb_vprintf(vl->vsb, fmt, ap); va_end(ap); vsb_putc(vl->vsb, '\n'); vsb_finish(vl->vsb); AZ(vsb_overflowed(vl->vsb)); vtc_log_emit(vl, lvl); vsb_clear(vl->vsb); AZ(pthread_mutex_unlock(&vl->mtx)); if (lvl == 0) { vtc_error = 1; if (pthread_self() != vtc_thread) pthread_exit(NULL); } }
void vcc_ParseLeastBusyDirector(struct tokenlist *tl, const struct token *t_policy, const struct token *t_dir) { struct token *t_field, *t_be; int nbh, nelem; struct fld_spec *fs; const char *first; fs = vcc_FldSpec(tl, "!backend", NULL); Fc(tl, 0, "\nstatic const struct vrt_dir_least_busy_entry " "vdrre_%.*s[] = {\n", PF(t_dir)); for (nelem = 0; tl->t->tok != '}'; nelem++) { /* List of members */ first = ""; t_be = tl->t; vcc_ResetFldSpec(fs); nbh = -1; ExpectErr(tl, '{'); vcc_NextToken(tl); Fc(tl, 0, "\t{"); while (tl->t->tok != '}') { /* Member fields */ vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "backend")) { vcc_ParseBackendHost(tl, &nbh, t_dir, t_policy, nelem); Fc(tl, 0, "%s .host = &bh_%d", first, nbh); ERRCHK(tl); } else { ErrInternal(tl); } first = ", "; } vcc_FieldsOk(tl, fs); if (tl->err) { vsb_printf(tl->sb, "\nIn member host specification starting at:\n"); vcc_ErrWhere(tl, t_be); return; } Fc(tl, 0, " },\n"); vcc_NextToken(tl); } Fc(tl, 0, "};\n"); Fc(tl, 0, "\nstatic const struct vrt_dir_least_busy vdrr_%.*s = {\n", PF(t_dir)); Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(t_dir)); Fc(tl, 0, "\t.nmember = %d,\n", nelem); Fc(tl, 0, "\t.members = vdrre_%.*s,\n", PF(t_dir)); Fc(tl, 0, "};\n"); Fi(tl, 0, "\tVRT_init_dir_least_busy(" "cli, &VGC_backend_%.*s , &vdrr_%.*s);\n", PF(t_dir), PF(t_dir)); Ff(tl, 0, "\tVRT_fini_dir(cli, VGC_backend_%.*s);\n", PF(t_dir)); }
static void parse_new_syntax(struct tokenlist *tl) { vsb_printf(tl->sb, "Please change \"%.*s\" to \"return(%.*s)\".\n", PF(tl->t), PF(tl->t)); vcc_ErrWhere(tl, tl->t); }
void vcc__ErrInternal(struct tokenlist *tl, const char *func, unsigned line) { vsb_printf(tl->sb, "VCL compiler internal error at %s():%u\n", func, line); tl->err = 1; }
static void check_writebit(struct tokenlist *tl, const struct var *vp) { if (vp->access == V_RW || vp->access == V_WO) return; vsb_printf(tl->sb, "Variable %.*s cannot be modified.\n", PF(tl->t)); vcc_ErrWhere(tl, tl->t); }
static int vcc_decstr(struct tokenlist *tl) { const char *p; char *q; unsigned char u; assert(tl->t->tok == CSTR); tl->t->dec = TlAlloc(tl, (tl->t->e - tl->t->b) - 1); assert(tl->t->dec != NULL); q = tl->t->dec; for (p = tl->t->b + 1; p < tl->t->e - 1; ) { if (*p != '%') { *q++ = *p++; continue; } if (p + 4 > tl->t->e) { vcc_AddToken(tl, CSTR, p, tl->t->e); vsb_printf(tl->sb, "Incomplete %%xx escape\n"); vcc_ErrWhere(tl, tl->t); return(1); } if (!isxdigit(p[1]) || !isxdigit(p[2])) { vcc_AddToken(tl, CSTR, p, p + 3); vsb_printf(tl->sb, "Invalid hex char in %%xx escape\n"); vcc_ErrWhere(tl, tl->t); return(1); } u = (vcc_xdig(p[1]) * 16 + vcc_xdig(p[2])) & 0xff; if (!isgraph(u)) { vcc_AddToken(tl, CSTR, p, p + 3); vsb_printf(tl->sb, "Control character in %%xx escape\n"); vcc_ErrWhere(tl, tl->t); return(1); } *q++ = u; p += 3; } *q++ = '\0'; return (0); }
void vcc_ParseRoundRobinDirector(struct tokenlist *tl) { struct token *t_field, *t_be; int nelem; struct fld_spec *fs; const char *first; char *p; fs = vcc_FldSpec(tl, "!backend", NULL); Fc(tl, 0, "\nstatic const struct vrt_dir_round_robin_entry " "vdrre_%.*s[] = {\n", PF(tl->t_dir)); for (nelem = 0; tl->t->tok != '}'; nelem++) { /* List of members */ first = ""; t_be = tl->t; vcc_ResetFldSpec(fs); SkipToken(tl, '{'); Fc(tl, 0, "\t{"); while (tl->t->tok != '}') { /* Member fields */ vcc_IsField(tl, &t_field, fs); ERRCHK(tl); if (vcc_IdIs(t_field, "backend")) { vcc_ParseBackendHost(tl, nelem, &p); ERRCHK(tl); AN(p); Fc(tl, 0, "%s .host = VGC_backend_%s", first, p); } else { ErrInternal(tl); } first = ", "; } vcc_FieldsOk(tl, fs); if (tl->err) { vsb_printf(tl->sb, "\nIn member host specification starting at:\n"); vcc_ErrWhere(tl, t_be); return; } Fc(tl, 0, " },\n"); vcc_NextToken(tl); } Fc(tl, 0, "};\n"); Fc(tl, 0, "\nstatic const struct vrt_dir_round_robin vgc_dir_priv_%.*s = {\n", PF(tl->t_dir)); Fc(tl, 0, "\t.name = \"%.*s\",\n", PF(tl->t_dir)); Fc(tl, 0, "\t.nmember = %d,\n", nelem); Fc(tl, 0, "\t.members = vdrre_%.*s,\n", PF(tl->t_dir)); Fc(tl, 0, "};\n"); }
void vcc_NextToken(struct tokenlist *tl) { tl->t = VTAILQ_NEXT(tl->t, list); if (tl->t == NULL) { vsb_printf(tl->sb, "Ran out of input, something is missing or" " maybe unbalanced (...) or {...}\n"); tl->err = 1; return; } }
//lint -e{818} void vtc_dump(struct vtclog *vl, unsigned lvl, const char *pfx, const char *str) { int nl = 1; CHECK_OBJ_NOTNULL(vl, VTCLOG_MAGIC); assert(lvl < NLEAD); AZ(pthread_mutex_lock(&vl->mtx)); vsb_clear(vl->vsb); if (pfx == NULL) pfx = ""; if (str == NULL) vsb_printf(vl->vsb, "%s %-4s %s(null)\n", lead[lvl], vl->id, pfx); else for(; *str != '\0'; str++) { if (nl) { vsb_printf(vl->vsb, "%s %-4s %s| ", lead[lvl], vl->id, pfx); nl = 0; } if (*str == '\r') vsb_printf(vl->vsb, "\\r"); else if (*str == '\t') vsb_printf(vl->vsb, "\\t"); else if (*str == '\n') { vsb_printf(vl->vsb, "\\n\n"); nl = 1; } else if (*str < 0x20 || *str > 0x7e) vsb_printf(vl->vsb, "\\x%02x", *str); else vsb_printf(vl->vsb, "%c", *str); } if (!nl) vsb_printf(vl->vsb, "\n"); vsb_finish(vl->vsb); AZ(vsb_overflowed(vl->vsb)); vtc_log_emit(vl, lvl); vsb_clear(vl->vsb); AZ(pthread_mutex_unlock(&vl->mtx)); if (lvl == 0) { vtc_error = 1; if (pthread_self() != vtc_thread) pthread_exit(NULL); } }
static void cmd_http_chunked(CMD_ARGS) { struct http *hp; (void)cmd; (void)vl; CAST_OBJ_NOTNULL(hp, priv, HTTP_MAGIC); AN(av[1]); AZ(av[2]); vsb_clear(hp->vsb); vsb_printf(hp->vsb, "%x%s%s%s", strlen(av[1]), nl, av[1], nl); http_write(hp, 4, "chunked"); }
/* * Quote a string */ void vsb_quote(struct vsb *s, const char *p, int len, int how) { const char *q; int quote = 0; (void)how; /* For future enhancements */ if (len == -1) len = strlen(p); for (q = p; q < p + len; q++) { if (!isgraph(*q) || *q == '"' || *q == '\\') { quote++; break; } } if (!quote) { (void)vsb_bcat(s, p, len); return; } (void)vsb_putc(s, '"'); for (q = p; q < p + len; q++) { switch (*q) { case ' ': (void)vsb_putc(s, *q); break; case '\\': case '"': (void)vsb_putc(s, '\\'); (void)vsb_putc(s, *q); break; case '\n': (void)vsb_cat(s, "\\n"); break; case '\r': (void)vsb_cat(s, "\\r"); break; case '\t': (void)vsb_cat(s, "\\t"); break; default: if (isgraph(*q)) (void)vsb_putc(s, *q); else (void)vsb_printf(s, "\\%o", *q & 0xff); break; } } (void)vsb_putc(s, '"'); }
static void vcc_expr_not(struct vcc *tl, struct expr **e, enum var_type fmt) { struct expr *e2; struct token *tk; *e = NULL; if (fmt != BOOL || tl->t->tok != '!') { vcc_expr_cmp(tl, e, fmt); return; } vcc_NextToken(tl); tk = tl->t; vcc_expr_cmp(tl, &e2, fmt); ERRCHK(tl); if (e2->fmt == BOOL) { *e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL); return; } vsb_printf(tl->sb, "'!' must be followed by BOOL, found "); vsb_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt)); vcc_ErrWhere2(tl, tk, tl->t); }
void vcc_ErrWhere(struct tokenlist *tl, const struct token *t) { unsigned x, y; const char *p, *l, *e; vcc_icoord(tl->sb, t, &l); vsb_printf(tl->sb, "\n"); x = y = 0; e = t->src->e; for (p = l; p < e && *p != '\n'; p++) { if (*p == '\t') { y &= ~7; y += 8; while (x < y) { vsb_bcat(tl->sb, " ", 1); x++; } } else { x++; y++; vsb_bcat(tl->sb, p, 1); } } vsb_cat(tl->sb, "\n"); x = y = 0; for (p = l; p < e && *p != '\n'; p++) { if (p >= t->b && p < t->e) { vsb_bcat(tl->sb, "#", 1); x++; y++; continue; } if (*p == '\t') { y &= ~7; y += 8; } else y++; while (x < y) { vsb_bcat(tl->sb, "-", 1); x++; } } vsb_cat(tl->sb, "\n"); tl->err = 1; }
static void parse_restart(struct tokenlist *tl) { struct token *t1; t1 = VTAILQ_NEXT(tl->t, list); if (t1->tok == ID && vcc_IdIs(t1, "rollback")) { Fb(tl, 1, "VRT_Rollback(sp);\n"); vcc_NextToken(tl); } else if (t1->tok != ';') { vsb_printf(tl->sb, "Expected \"rollback\" or semicolon.\n"); vcc_ErrWhere(tl, t1); ERRCHK(tl); } Fb(tl, 1, "VRT_done(sp, VCL_RET_RESTART);\n"); vcc_ProcAction(tl->curproc, VCL_RET_RESTART, tl->t); vcc_NextToken(tl); }
static void parse_unset(struct tokenlist *tl) { struct var *vp; vcc_NextToken(tl); ExpectErr(tl, VAR); vp = vcc_FindVar(tl, tl->t, vcc_vars); ERRCHK(tl); assert(vp != NULL); if (vp->fmt != STRING || vp->hdr == NULL) { vsb_printf(tl->sb, "Only http header lines can be unset.\n"); vcc_ErrWhere(tl, tl->t); return; } check_writebit(tl, vp); ERRCHK(tl); Fb(tl, 1, "%s0);\n", vp->lname); vcc_NextToken(tl); }
static void vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt) { struct expr *e2; enum var_type f2, f3; struct token *tk; *e = NULL; vcc_expr4(tl, e, fmt); ERRCHK(tl); f3 = f2 = (*e)->fmt; switch(f2) { case INT: f2 = INT; break; case DURATION: f2 = REAL; break; case BYTES: f2 = REAL; break; default: if (tl->t->tok != '*' && tl->t->tok != '/') return; vsb_printf(tl->sb, "Operator %.*s not possible on type %s.\n", PF(tl->t), vcc_Type(f2)); vcc_ErrWhere(tl, tl->t); return; } while (tl->t->tok == '*' || tl->t->tok == '/') { tk = tl->t; vcc_NextToken(tl); vcc_expr4(tl, &e2, f2); ERRCHK(tl); assert(e2->fmt == f2); if (tk->tok == '*') *e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2); else *e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2); } }
static void parse_purge(struct tokenlist *tl) { const struct purge_var *pv; vcc_NextToken(tl); ExpectErr(tl, '('); vcc_NextToken(tl); if (tl->t->tok == VAR) { Fb(tl, 1, "VRT_ban(sp,\n"); tl->indent += INDENT; while (1) { ExpectErr(tl, VAR); /* Check valididity of purge variable */ for (pv = purge_var; pv->name != NULL; pv++) { if (!strncmp(pv->name, tl->t->b, strlen(pv->name))) break; } if (pv->name == NULL) { vsb_printf(tl->sb, "Unknown purge variable."); vcc_ErrWhere(tl, tl->t); return; } if ((pv->flag & PVAR_HTTP) && tl->t->b + strlen(pv->name) >= tl->t->e) { vsb_printf(tl->sb, "Missing header name."); vcc_ErrWhere(tl, tl->t); return; } Fb(tl, 1, " \"%.*s\",\n", PF(tl->t)); vcc_NextToken(tl); switch(tl->t->tok) { case '~': case T_NOMATCH: case T_EQ: case T_NEQ: Fb(tl, 1, " \"%.*s\",\n", PF(tl->t)); break; default: vsb_printf(tl->sb, "Expected ~, !~, == or !=.\n"); vcc_ErrWhere(tl, tl->t); return; } vcc_NextToken(tl); Fb(tl, 1, " "); if (!vcc_StringVal(tl)) { vcc_ExpectedStringval(tl); return; } Fb(tl, 0, ",\n"); if (tl->t->tok == ')') break; ExpectErr(tl, T_CAND); Fb(tl, 1, "\"%.*s\",\n", PF(tl->t)); vcc_NextToken(tl); } Fb(tl, 1, "0);\n"); tl->indent -= INDENT; } else { Fb(tl, 1, "VRT_ban_string(sp, "); if (!vcc_StringVal(tl)) { vcc_ExpectedStringval(tl); return; } do Fb(tl, 0, ", "); while (vcc_StringVal(tl)); Fb(tl, 0, "vrt_magic_string_end);\n"); } ExpectErr(tl, ')'); vcc_NextToken(tl); }
static void parse_set(struct tokenlist *tl) { struct var *vp; struct token *at, *vt; vcc_NextToken(tl); ExpectErr(tl, VAR); vt = tl->t; vp = vcc_FindVar(tl, tl->t, vcc_vars); ERRCHK(tl); assert(vp != NULL); check_writebit(tl, vp); ERRCHK(tl); Fb(tl, 1, "%s", vp->lname); vcc_NextToken(tl); switch (vp->fmt) { case INT: case SIZE: case TIME: case RTIME: case FLOAT: if (tl->t->tok != '=') Fb(tl, 0, "%s %c ", vp->rname, *tl->t->b); at = tl->t; vcc_NextToken(tl); switch (at->tok) { case T_MUL: case T_DIV: Fb(tl, 0, "%g", vcc_DoubleVal(tl)); break; case T_INCR: case T_DECR: case '=': vcc_VarVal(tl, vp, vt); ERRCHK(tl); break; default: vsb_printf(tl->sb, "Invalid assignment operator.\n"); vcc_ErrWhere(tl, at); return; } Fb(tl, 0, ");\n"); break; #if 0 /* XXX: enable if we find a legit use */ case IP: if (tl->t->tok != '=') { illegal_assignment(tl, "IP numbers"); return; } vcc_NextToken(tl); u = vcc_vcc_IpVal(tl); Fb(tl, 0, "= %uU; /* %u.%u.%u.%u */\n", u, (u >> 24) & 0xff, (u >> 16) & 0xff, (u >> 8) & 0xff, u & 0xff); break; #endif case BACKEND: if (tl->t->tok != '=') { illegal_assignment(tl, "backend"); return; } vcc_NextToken(tl); vcc_ExpectCid(tl); ERRCHK(tl); vcc_AddRef(tl, tl->t, R_BACKEND); Fb(tl, 0, "VGCDIR(_%.*s)", PF(tl->t)); vcc_NextToken(tl); Fb(tl, 0, ");\n"); break; case HASH: SkipToken(tl, T_INCR); if (!vcc_StringVal(tl)) { ERRCHK(tl); vcc_ExpectedStringval(tl); return; } Fb(tl, 0, ");\n"); /* * We count the number of operations on the req.hash * variable, so that varnishd can preallocate the worst case * number of slots for composing the hash string. */ break; case STRING: if (tl->t->tok != '=') { illegal_assignment(tl, "strings"); return; } vcc_NextToken(tl); if (!vcc_StringVal(tl)) { ERRCHK(tl); vcc_ExpectedStringval(tl); return; } do Fb(tl, 0, ", "); while (vcc_StringVal(tl)); if (tl->t->tok != ';') { ERRCHK(tl); vsb_printf(tl->sb, "Expected variable, string or semicolon\n"); vcc_ErrWhere(tl, tl->t); return; } Fb(tl, 0, "vrt_magic_string_end);\n"); break; case BOOL: if (tl->t->tok != '=') { illegal_assignment(tl, "boolean"); return; } vcc_NextToken(tl); ExpectErr(tl, ID); if (vcc_IdIs(tl->t, "true")) { Fb(tl, 0, " 1);\n", vp->lname); } else if (vcc_IdIs(tl->t, "false")) { Fb(tl, 0, " 0);\n", vp->lname); } else { vsb_printf(tl->sb, "Expected true or false\n"); vcc_ErrWhere(tl, tl->t); return; } vcc_NextToken(tl); break; default: vsb_printf(tl->sb, "Assignments not possible for type of '%s'\n", vp->name); vcc_ErrWhere(tl, tl->t); return; } }
void vcc_Lexer(struct tokenlist *tl, struct source *sp) { const char *p, *q; unsigned u; tl->src = sp; for (p = sp->b; p < sp->e; ) { /* Skip any whitespace */ if (isspace(*p)) { p++; continue; } /* Skip '#.*\n' comments */ if (*p == '#') { while (p < sp->e && *p != '\n') p++; continue; } /* Skip C-style comments */ if (*p == '/' && p[1] == '*') { for (q = p + 2; q < sp->e; q++) { if (*q == '/' && q[1] == '*') { vsb_printf(tl->sb, "/* ... */ comment contains /*\n"); vcc_AddToken(tl, EOI, p, p + 2); vcc_ErrWhere(tl, tl->t); vcc_AddToken(tl, EOI, q, q + 2); vcc_ErrWhere(tl, tl->t); return; } if (*q == '*' && q[1] == '/') { p = q + 2; break; } } if (q < sp->e) continue; vcc_AddToken(tl, EOI, p, p + 2); vsb_printf(tl->sb, "Unterminated /* ... */ comment, starting at\n"); vcc_ErrWhere(tl, tl->t); return; } /* Skip C++-style comments */ if (*p == '/' && p[1] == '/') { while (p < sp->e && *p != '\n') p++; continue; } /* Recognize inline C-code */ if (*p == 'C' && p[1] == '{') { for (q = p + 2; q < sp->e; q++) { if (*q == '}' && q[1] == 'C') { vcc_AddToken(tl, CSRC, p, q + 2); break; } } if (q < sp->e) { p = q + 2; continue; } vcc_AddToken(tl, EOI, p, p + 2); vsb_printf(tl->sb, "Unterminated inline C source, starting at\n"); vcc_ErrWhere(tl, tl->t); return; } /* Recognize long-strings */ if (*p == '{' && p[1] == '"') { for (q = p + 2; q < sp->e; q++) { if (*q == '"' && q[1] == '}') { vcc_AddToken(tl, CSTR, p, q + 2); break; } } if (q < sp->e) { p = q + 2; u = tl->t->e - tl->t->b; u -= 4; /* {" ... "} */ tl->t->dec = TlAlloc(tl, u + 1 ); AN(tl->t->dec); memcpy(tl->t->dec, tl->t->b + 2, u); tl->t->dec[u] = '\0'; continue; } vcc_AddToken(tl, EOI, p, p + 2); vsb_printf(tl->sb, "Unterminated long-string, starting at\n"); vcc_ErrWhere(tl, tl->t); return; } /* Match for the fixed tokens (see token.tcl) */ u = vcl_fixed_token(p, &q); if (u != 0) { vcc_AddToken(tl, u, p, q); p = q; continue; } /* Match strings, with \\ and \" escapes */ if (*p == '"') { for (q = p + 1; q < sp->e; q++) { if (*q == '"') { q++; break; } if (*q == '\r' || *q == '\n') { vcc_AddToken(tl, EOI, p, q); vsb_printf(tl->sb, "Unterminated string at\n"); vcc_ErrWhere(tl, tl->t); return; } } vcc_AddToken(tl, CSTR, p, q); if (vcc_decstr(tl)) return; p = q; continue; } /* Match Identifiers */ if (isident1(*p)) { for (q = p; q < sp->e; q++) if (!isident(*q)) break; if (isvar(*q)) { for (; q < sp->e; q++) if (!isvar(*q)) break; vcc_AddToken(tl, VAR, p, q); } else { vcc_AddToken(tl, ID, p, q); } p = q; continue; } /* Match numbers { [0-9]+ } */ if (isdigit(*p)) { for (q = p; q < sp->e; q++) if (!isdigit(*q)) break; vcc_AddToken(tl, CNUM, p, q); p = q; continue; } vcc_AddToken(tl, EOI, p, p + 1); vsb_printf(tl->sb, "Syntax error at\n"); vcc_ErrWhere(tl, tl->t); return; } }