예제 #1
0
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;
}
예제 #2
0
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");
}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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);
}
예제 #7
0
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));
}
예제 #8
0
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);
}
예제 #9
0
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);
}
예제 #10
0
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);
}
예제 #11
0
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);
}
예제 #12
0
//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));
}
예제 #14
0
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);
}
예제 #15
0
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;
}
예제 #16
0
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);
}
예제 #17
0
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");
}
예제 #19
0
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;
	}
}
예제 #20
0
//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);
	}
}
예제 #21
0
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");
}
예제 #22
0
/*
 * 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, '"');
}
예제 #23
0
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);
}
예제 #24
0
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;
}
예제 #25
0
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);
}
예제 #26
0
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);
}
예제 #27
0
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);
	}
}
예제 #28
0
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);
}
예제 #29
0
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;
	}
}
예제 #30
0
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;
	}
}