Example #1
0
static void
vcc_suckaddr(struct vcc *tl, const char *host, const struct suckaddr *vsa,
    const char **ip, const char **ip_ascii, const char **p_ascii)
{
	char a[VTCP_ADDRBUFSIZE];
	char p[VTCP_PORTBUFSIZE];
	const int sz = sizeof(unsigned long long);
	const unsigned n = (vsa_suckaddr_len + sz - 1) / sz;
	unsigned long long b[n];
	int len;
	char *q;

	VTCP_name(vsa, a, sizeof a, p, sizeof p);
	Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, a);
	if (ip_ascii != NULL)
		*ip_ascii = TlDup(tl, a);
	if (p_ascii != NULL && *p_ascii == NULL)
		*p_ascii = TlDup(tl, p);

	Fh(tl, 0, "static const unsigned long long");
	Fh(tl, 0, " suckaddr_%u[%d] = {\n", tl->unique, n);
	memcpy(b, vsa, vsa_suckaddr_len);
	for (len = 0; len < n; len++)
		Fh(tl, 0, "%s    0x%0*llxULL",
		    len ? ",\n" : "", sz * 2, b[len]);
	Fh(tl, 0, "\n};\n");

	q = TlAlloc(tl, 40);
	AN(q);
	assert(snprintf(q, 40, "(const void*)suckaddr_%u", tl->unique) < 40);
	*ip = q;
	tl->unique++;
}
Example #2
0
void
VCC_Stevedore(struct vcc *vcc, const char *stv_name)
{
	struct symbol *sym;
	struct stvars *sv;
	char buf[1024];

	CHECK_OBJ_NOTNULL(vcc, VCC_MAGIC);
	bprintf(buf, "storage.%s", stv_name);
	sym = VCC_Symbol(vcc, NULL, buf, NULL, SYM_VAR, 1);
	AN(sym);
	sym->fmt = STEVEDORE;
	sym->eval = vcc_Eval_Var;
	bprintf(buf, "VRT_stevedore(\"%s\")", stv_name);
	sym->rname = TlDup(vcc, buf);
	sym->r_methods = ~0;

	for(sv = stvars; sv->name != NULL; sv++) {
		bprintf(buf, "storage.%s.%s", stv_name, sv->name);
		sym = VCC_Symbol(vcc, NULL, buf, NULL, SYM_VAR, 1);
		AN(sym);
		sym->fmt = sv->fmt;
		sym->eval = vcc_Eval_Var;
		bprintf(buf, "VRT_Stv_%s(\"%s\")", sv->name, stv_name);
		sym->rname = TlDup(vcc, buf);
		sym->r_methods = ~0;
	}
}
Example #3
0
struct symbol *
vcc_Stv_Wildcard(struct vcc *tl, const struct token *t,
    const struct symbol *wcsym)
{
	const char *p, *q;
	struct var *v = NULL;
	struct symbol *sym;
	struct stvars *sv;
	char stv[1024];
	char buf[1024];

	(void)wcsym;
	assert((t->e - t->b) > strlen(PFX));
	AZ(memcmp(t->b, PFX, strlen(PFX)));

	p = t->b + strlen(PFX);
	for (q = p; q < t->e && *q != '.'; q++)
		continue;
	bprintf(stv, "%.*s", (int)(q - p), p);

	if (q == t->e) {
		v = vcc_Stv_mkvar(tl, t, BOOL);
		bprintf(buf, "VRT_Stv(\"%s\")", stv);
		v->rname = TlDup(tl, buf);
	} else {
		assert(*q  == '.');
		q++;
		for(sv = stvars; sv->name != NULL; sv++) {
			if (strncmp(q, sv->name, t->e - q))
				continue;
			if (sv->name[t->e - q] != '\0')
				continue;
			v = vcc_Stv_mkvar(tl, t, sv->fmt);
			bprintf(buf, "VRT_Stv_%s(\"%s\")", sv->name, stv);
			v->rname = TlDup(tl, buf);
			break;
		}
	}

	if (v == NULL)
		return (NULL);

	sym = VCC_AddSymbolTok(tl, t, SYM_VAR);
	AN(sym);
	sym->var = v;
	sym->fmt = v->fmt;
	sym->eval = vcc_Eval_Var;
	sym->r_methods = v->r_methods;

	return (sym);
}
Example #4
0
struct symbol *
vcc_Var_Wildcard(struct vcc *tl, const struct token *t, const struct symbol *wc)
{
	struct symbol *sym;
	struct var *v;
	const struct var *vh;
	int l;
	char buf[258];

	vh = wc->var;

	v = TlAlloc(tl, sizeof *v);
	AN(v);

	v->name = TlDupTok(tl, t);
	v->r_methods = vh->r_methods;
	v->w_methods = vh->w_methods;
	v->fmt = STRING;
	v->http = vh->http;
	l = strlen(v->name + vh->len) + 1;

	bprintf(buf, "\\%03o%s:", (unsigned)l, v->name + vh->len);
	v->hdr = TlDup(tl, buf);
	bprintf(buf, "VRT_GetHdr(sp, %s, \"%s\")", v->http, v->hdr);
	v->rname = TlDup(tl, buf);

	bprintf(buf, "VRT_SetHdr(sp, %s, \"%s\", ", v->http, v->hdr);
	v->lname = TlDup(tl, buf);

	sym = VCC_AddSymbolTok(tl, t, SYM_VAR);
	AN(sym);
	sym->var = v;
	sym->fmt = v->fmt;
	sym->eval = vcc_Eval_Var;
	sym->r_methods = v->r_methods;
	return (sym);
}
Example #5
0
void
vcc_ParseImport(struct vcc *tl)
{
	void *hdl;
	char fn[1024], *fnp, *fnpx;
	char buf[256];
	struct token *mod, *t1;
	struct inifin *ifp;
	const char * const *spec;
	struct symbol *sym;
	struct symbol *msym;
	const struct symbol *osym;
	const char *p;
	// int *modlen;
	const struct vmod_data *vmd;

	t1 = tl->t;
	SkipToken(tl, ID);		/* "import" */

	ExpectErr(tl, ID);
	mod = tl->t;
	vcc_NextToken(tl);

	osym = VCC_SymbolTok(tl, NULL, mod, SYM_NONE, 0);
	if (osym != NULL && osym->kind != SYM_VMOD) {
		VSB_printf(tl->sb, "Module %.*s conflicts with other symbol.\n",
		    PF(mod));
		vcc_ErrWhere2(tl, t1, tl->t);
		return;
	}
	if (osym != NULL) {
		VSB_printf(tl->sb, "Module %.*s already imported.\n",
		    PF(mod));
		vcc_ErrWhere2(tl, t1, tl->t);
		VSB_printf(tl->sb, "Previous import was here:\n");
		vcc_ErrWhere2(tl, osym->def_b, osym->def_e);
		return;
	}

	bprintf(fn, "%.*s", PF(mod));
	msym = VCC_Symbol(tl, NULL, fn, NULL, SYM_VMOD, 1);
	ERRCHK(tl);
	AN(msym);
	msym->def_b = t1;
	msym->def_e = tl->t;

	if (tl->t->tok == ID) {
		if (!vcc_IdIs(tl->t, "from")) {
			VSB_printf(tl->sb, "Expected 'from path ...'\n");
			vcc_ErrWhere(tl, tl->t);
			return;
		}
		vcc_NextToken(tl);
		if (!tl->unsafe_path && strchr(tl->t->dec, '/')) {
			VSB_printf(tl->sb,
			    "'import ... from path ...' is unsafe.\nAt:");
			vcc_ErrToken(tl, tl->t);
			vcc_ErrWhere(tl, tl->t);
			return;
		}
		ExpectErr(tl, CSTR);
		p = strrchr(tl->t->dec, '/');
		if (p != NULL && p[1] == '\0')
			bprintf(fn, "%slibvmod_%.*s.so", tl->t->dec, PF(mod));
		else
			bprintf(fn, "%s", tl->t->dec);
		vcc_NextToken(tl);
	} else {
		bprintf(fn, "libvmod_%.*s.so", PF(mod));
	}

	SkipToken(tl, ';');

	if (VFIL_searchpath(tl->vmod_path,
	    vcc_path_dlopen, &hdl, fn, &fnpx)) {
		VSB_printf(tl->sb, "Could not load VMOD %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n",
		    fnpx != NULL ? fnpx : fn);
		VSB_printf(tl->sb, "\tdlerror: %s\n", dlerror());
		vcc_ErrWhere(tl, mod);
		free(fnpx);
		return;
	}

	AN(fnpx);
	fnp = TlDup(tl, fnpx);
	free(fnpx);

	bprintf(buf, "Vmod_%.*s_Data", PF(mod));
	vmd = dlsym(hdl, buf);
	if (vmd == NULL) {
		VSB_printf(tl->sb, "Malformed VMOD %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
		VSB_printf(tl->sb, "\t(no Vmod_Data symbol)\n");
		vcc_ErrWhere(tl, mod);
		return;
	}
	if (strcmp(VCS_Branch, "master") == 0 &&
	    strcmp(vmd->abi, VMOD_ABI_Version) != 0) {
		VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
		VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
			   VMOD_ABI_Version, vmd->abi);
		vcc_ErrWhere(tl, mod);
		return;
	}
	if (vmd->vrt_major != VRT_MAJOR_VERSION ||
	    vmd->vrt_minor > VRT_MINOR_VERSION) {
		VSB_printf(tl->sb, "Incompatible VMOD %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
		VSB_printf(tl->sb, "\tVMOD version %u.%u\n",
		    vmd->vrt_major, vmd->vrt_minor);
		VSB_printf(tl->sb, "\tvarnishd version %u.%u\n",
		    VRT_MAJOR_VERSION, VRT_MINOR_VERSION);
		vcc_ErrWhere(tl, mod);
		return;
	}
	if (vmd->name == NULL ||
	    vmd->func == NULL ||
	    vmd->func_len <= 0 ||
	    vmd->proto == NULL ||
	    vmd->abi == NULL) {
		VSB_printf(tl->sb, "Mangled VMOD %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
		VSB_printf(tl->sb, "\tInconsistent metadata\n");
		vcc_ErrWhere(tl, mod);
		return;
	}

	if (!vcc_IdIs(mod, vmd->name)) {
		VSB_printf(tl->sb, "Wrong VMOD file %.*s\n", PF(mod));
		VSB_printf(tl->sb, "\tFile name: %s\n", fnp);
		VSB_printf(tl->sb, "\tContains vmod \"%s\"\n", vmd->name);
		vcc_ErrWhere(tl, mod);
		return;
	}

	ifp = New_IniFin(tl);

	VSB_printf(ifp->ini, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod));
	VSB_printf(ifp->ini, "\t    &Vmod_%.*s_Func,\n", PF(mod));
	VSB_printf(ifp->ini, "\t    sizeof(Vmod_%.*s_Func),\n", PF(mod));
	VSB_printf(ifp->ini, "\t    \"%.*s\",\n", PF(mod));
	VSB_printf(ifp->ini, "\t    ");
	VSB_quote(ifp->ini, fnp, -1, VSB_QUOTE_CSTR);
	VSB_printf(ifp->ini, ",\n");
	AN(vmd);
	AN(vmd->file_id);
	VSB_printf(ifp->ini, "\t    \"%s\",\n", vmd->file_id);
	VSB_printf(ifp->ini, "\t    ctx))\n");
	VSB_printf(ifp->ini, "\t\treturn(1);");

	/* XXX: zero the function pointer structure ?*/
	VSB_printf(ifp->fin, "\t\tVRT_priv_fini(&vmod_priv_%.*s);", PF(mod));
	VSB_printf(ifp->fin, "\n\t\tVRT_Vmod_Fini(&VGC_vmod_%.*s);", PF(mod));

	ifp = NULL;

	spec = vmd->spec;
	for (; *spec != NULL; spec++) {
		p = *spec;
		if (!strcmp(p, "$OBJ")) {
			p += strlen(p) + 1;
			sym = VCC_Symbol(tl, NULL, p, NULL, SYM_OBJECT, 1);
			XXXAN(sym);
			sym->extra = p;
			sym->vmod = msym->name;
		} else if (!strcmp(p, "$EVENT")) {
			p += strlen(p) + 1;
			if (ifp == NULL)
				ifp = New_IniFin(tl);
			VSB_printf(ifp->ini,
			    "\tif (%s(ctx, &vmod_priv_%.*s, VCL_EVENT_LOAD))\n"
			    "\t\treturn(1);",
			    p, PF(mod));
			VSB_printf(ifp->fin,
			    "\t\t(void)%s(ctx, &vmod_priv_%.*s,\n"
			    "\t\t    VCL_EVENT_DISCARD);\n", p, PF(mod));
			VSB_printf(ifp->event, "\t%s(ctx, &vmod_priv_%.*s, ev)",
			    p, PF(mod));
		} else if (!strcmp(p, "$FUNC")) {
			p += strlen(p) + 1;
			sym = VCC_Symbol(tl, NULL, p, NULL, SYM_FUNC, 1);
			ERRCHK(tl);
			AN(sym);
			sym->vmod = msym->name;
			sym->eval = vcc_Eval_SymFunc;
			p += strlen(p) + 1;
			sym->eval_priv = p;
			sym->fmt = VCC_Type(p);
			AN(sym->fmt);
		} else {
			VSB_printf(tl->sb, "Internal spec error (%s)\n", p);
			vcc_ErrWhere(tl, mod);
			return;
		}
	}

	Fh(tl, 0, "\n/* --- BEGIN VMOD %.*s --- */\n\n", PF(mod));
	Fh(tl, 0, "static struct vmod *VGC_vmod_%.*s;\n", PF(mod));
	Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
	Fh(tl, 0, "\n%s\n", vmd->proto);
	Fh(tl, 0, "\n/* --- END VMOD %.*s --- */\n\n", PF(mod));
}
Example #6
0
void
vcc_ParseNew(struct vcc *tl)
{
	struct symbol *sy1, *sy2, *sy3;
	struct inifin *ifp;
	const char *p, *s_obj;
	char buf1[128];
	char buf2[128];

	vcc_NextToken(tl);
	ExpectErr(tl, ID);
	vcc_ExpectCid(tl, "VCL object");
	ERRCHK(tl);
	sy1 = VCC_HandleSymbol(tl, tl->t, INSTANCE, "XXX");
	ERRCHK(tl);

	/* We allow implicit use of VMOD objects:  Pretend it's ref'ed */
	sy1->nref++;

	vcc_NextToken(tl);

	ExpectErr(tl, '=');
	vcc_NextToken(tl);

	ExpectErr(tl, ID);
	sy2 = VCC_SymbolTok(tl, NULL, tl->t, SYM_OBJECT, 0);
	if (sy2 == NULL) {
		VSB_printf(tl->sb, "Symbol not found: ");
		vcc_ErrToken(tl, tl->t);
		VSB_printf(tl->sb, " at ");
		vcc_ErrWhere(tl, tl->t);
		return;
	}
	vcc_NextToken(tl);

	p = sy2->extra;

	s_obj = p;
	p += strlen(p) + 1;

	Fh(tl, 0, "static %s *vo_%s;\n\n", p, sy1->name);
	p += strlen(p) + 1;

	bprintf(buf1, ", &vo_%s, \"%s\"", sy1->name, sy1->name);
	vcc_Eval_Func(tl, p, buf1, sy2);
	ExpectErr(tl, ';');

	while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0')
		p++;
	p += 3;

	ifp = New_IniFin(tl);
	p += strlen(p) + 1;
	VSB_printf(ifp->fin, "\t\t%s(&vo_%s);", p, sy1->name);

	while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0')
		p++;
	p += 3;

	/* Instantiate symbols for the methods */
	bprintf(buf1, ", vo_%s", sy1->name);
	while (*p != '\0') {
		p += strlen(s_obj);
		bprintf(buf2, "%s%s", sy1->name, p);
		sy3 = VCC_Symbol(tl, NULL, buf2, NULL, SYM_FUNC, 1);
		AN(sy3);
		sy3->eval = vcc_Eval_SymFunc;
		p += strlen(p) + 1;
		sy3->eval_priv = p;
		sy3->fmt = VCC_Type(p);
		sy3->extra = TlDup(tl, buf1);
		while (p[0] != '\0' || p[1] != '\0' || p[2] != '\0')
			p++;
		p += 3;
	}
	sy1->def_e = tl->t;
}
Example #7
0
static void
parse_new(struct vcc *tl)
{
	struct symbol *sy1, *sy2, *sy3;
	struct inifin *ifp;
	const char *p, *s_obj, *s_init, *s_struct, *s_fini;
	char buf1[128];
	char buf2[128];

	vcc_NextToken(tl);
	ExpectErr(tl, ID);
	if (!vcc_isCid(tl->t)) {
		VSB_printf(tl->sb,
		    "Names of VCL objects cannot contain '-'\n");
		vcc_ErrWhere(tl, tl->t);
		return;
	}
	sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE);
	if (sy1 != NULL) {
		VSB_printf(tl->sb, "Object name '%.*s' already used.\n",
		    PF(tl->t));

		VSB_printf(tl->sb, "First usage:\n");
		AN(sy1->def_b);
		if (sy1->def_e != NULL)
			vcc_ErrWhere2(tl, sy1->def_b, sy1->def_e);
		else
			vcc_ErrWhere(tl, sy1->def_b);
		VSB_printf(tl->sb, "Redefinition:\n");
		vcc_ErrWhere(tl, tl->t);
		return;
	}

	sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE);	// XXX: NONE ?
	XXXAN(sy1);
	sy1->def_b = tl->t;
	vcc_NextToken(tl);

	ExpectErr(tl, '=');
	vcc_NextToken(tl);

	ExpectErr(tl, ID);
	sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT);
	if (sy2 == NULL) {
		VSB_printf(tl->sb, "Symbol not found: ");
		vcc_ErrToken(tl, tl->t);
		VSB_printf(tl->sb, " at ");
		vcc_ErrWhere(tl, tl->t);
		return;
	}
	XXXAN(sy2);

	/*lint -save -e448 */
	/* Split the first three args */
	p = sy2->args;
	s_obj = p;
	p += strlen(p) + 1;
	s_init = p;
	while (p[0] != '\0' || p[1] != '\0')
		p++;
	p += 2;
	s_struct = p;
	p += strlen(p) + 1;
	s_fini = p + strlen(p) + 1;
	while (p[0] != '\0' || p[1] != '\0')
		p++;
	p += 2;

	Fh(tl, 0, "static %s *vo_%s;\n\n", s_struct, sy1->name);

	vcc_NextToken(tl);

	bprintf(buf1, ", &vo_%s, \"%s\"", sy1->name, sy1->name);
	vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1);
	ifp = New_IniFin(tl);
	VSB_printf(ifp->fin, "\t%s(&vo_%s);", s_fini, sy1->name);
	ExpectErr(tl, ';');

	bprintf(buf1, ", vo_%s", sy1->name);
	/* Split the methods from the args */
	while (*p != '\0') {
		p += strlen(s_obj);
		bprintf(buf2, "%s%s", sy1->name, p);
		sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC);
		AN(sy3);
		sy3->eval = vcc_Eval_SymFunc;
		p += strlen(p) + 1;
		sy3->cfunc = p;
		p += strlen(p) + 1;

		/* Functions which return VOID are procedures */
		if (!memcmp(p, "VOID\0", 5))
			sy3->kind = SYM_PROC;

		sy3->args = p;
		sy3->extra = TlDup(tl, buf1);
		while (p[0] != '\0' || p[1] != '\0') {
			if (!memcmp(p, "ENUM\0", 5)) {
				/* XXX: Special case for ENUM that has
				   it's own \0\0 end marker. Not exactly
				   elegant, we should consider
				   alternatives here. Maybe runlength
				   encode the entire block? */
				p += strlen(p) + 1;
				while (p[0] != '\0' || p[1] != '\0')
					p++;
			}
			p++;
		}
		p += 2;
	}
	sy1->def_e = tl->t;
	/*lint -restore */
}
Example #8
0
static void
vcc_ParseProbeSpec(struct vcc *tl, const struct symbol *sym, char **name)
{
	struct fld_spec *fs;
	struct token *t_field;
	struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL;
	struct token *t_initial = NULL;
	struct vsb *vsb;
	char *retval;
	unsigned window, threshold, initial, status;
	double t;

	fs = vcc_FldSpec(tl,
	    "?url",
	    "?request",
	    "?expected_response",
	    "?timeout",
	    "?interval",
	    "?window",
	    "?threshold",
	    "?initial",
	    NULL);

	SkipToken(tl, '{');

	vsb = VSB_new_auto();
	AN(vsb);
	if (sym != NULL)
		VSB_cat(vsb, sym->rname);
	else
		VSB_printf(vsb, "vgc_probe__%d", tl->nprobe++);
	AZ(VSB_finish(vsb));
	retval = TlDup(tl, VSB_data(vsb));
	AN(retval);
	VSB_destroy(&vsb);
	if (name != NULL)
		*name = retval;

	window = 0;
	threshold = 0;
	initial = 0;
	status = 0;
	Fh(tl, 0, "static const struct vrt_backend_probe %s[] = {{\n", retval);
	Fh(tl, 0, "\t.magic = VRT_BACKEND_PROBE_MAGIC,\n");
	while (tl->t->tok != '}') {

		vcc_IsField(tl, &t_field, fs);
		ERRCHK(tl);
		if (vcc_IdIs(t_field, "url")) {
			vcc_Redef(tl, "Probe request", &t_did, t_field);
			ERRCHK(tl);
			ExpectErr(tl, CSTR);
			Fh(tl, 0, "\t.url = ");
			EncToken(tl->fh, tl->t);
			Fh(tl, 0, ",\n");
			vcc_NextToken(tl);
		} else if (vcc_IdIs(t_field, "request")) {
			vcc_Redef(tl, "Probe request", &t_did, t_field);
			ERRCHK(tl);
			ExpectErr(tl, CSTR);
			Fh(tl, 0, "\t.request =\n");
			while (tl->t->tok == CSTR) {
				Fh(tl, 0, "\t\t");
				EncToken(tl->fh, tl->t);
				Fh(tl, 0, " \"\\r\\n\"\n");
				vcc_NextToken(tl);
			}
			Fh(tl, 0, "\t\t\"\\r\\n\",\n");
		} else if (vcc_IdIs(t_field, "timeout")) {
			Fh(tl, 0, "\t.timeout = ");
			vcc_Duration(tl, &t);
			ERRCHK(tl);
			Fh(tl, 0, "%g,\n", t);
		} else if (vcc_IdIs(t_field, "interval")) {
			Fh(tl, 0, "\t.interval = ");
			vcc_Duration(tl, &t);
			ERRCHK(tl);
			Fh(tl, 0, "%g,\n", t);
		} else if (vcc_IdIs(t_field, "window")) {
			t_window = tl->t;
			window = vcc_UintVal(tl);
			ERRCHK(tl);
		} else if (vcc_IdIs(t_field, "initial")) {
			t_initial = tl->t;
			initial = vcc_UintVal(tl);
			ERRCHK(tl);
		} else if (vcc_IdIs(t_field, "expected_response")) {
			status = vcc_UintVal(tl);
			if (status < 100 || status > 999) {
				VSB_printf(tl->sb,
				    "Must specify .expected_response with "
				    "exactly three digits "
				    "(100 <= x <= 999)\n");
				vcc_ErrWhere(tl, tl->t);
				return;
			}
			ERRCHK(tl);
		} else if (vcc_IdIs(t_field, "threshold")) {
			t_threshold = tl->t;
			threshold = vcc_UintVal(tl);
			ERRCHK(tl);
		} else {
			vcc_ErrToken(tl, t_field);
			vcc_ErrWhere(tl, t_field);
			ErrInternal(tl);
			return;
		}

		SkipToken(tl, ';');
	}

	if (t_threshold != NULL || t_window != NULL) {
		if (t_threshold == NULL && t_window != NULL) {
			VSB_printf(tl->sb,
			    "Must specify .threshold with .window\n");
			vcc_ErrWhere(tl, t_window);
			return;
		} else if (t_threshold != NULL && t_window == NULL) {
			if (threshold > 64) {
				VSB_printf(tl->sb,
				    "Threshold must be 64 or less.\n");
				vcc_ErrWhere(tl, t_threshold);
				return;
			}
			window = threshold + 1;
		} else if (window > 64) {
			AN(t_window);
			VSB_printf(tl->sb, "Window must be 64 or less.\n");
			vcc_ErrWhere(tl, t_window);
			return;
		}
		if (threshold > window ) {
			VSB_printf(tl->sb,
			    "Threshold can not be greater than window.\n");
			AN(t_threshold);
			vcc_ErrWhere(tl, t_threshold);
			AN(t_window);
			vcc_ErrWhere(tl, t_window);
		}
		Fh(tl, 0, "\t.window = %u,\n", window);
		Fh(tl, 0, "\t.threshold = %u,\n", threshold);
	}
	if (t_initial != NULL)
		Fh(tl, 0, "\t.initial = %u,\n", initial);
	else
		Fh(tl, 0, "\t.initial = ~0U,\n");
	if (status > 0)
		Fh(tl, 0, "\t.exp_status = %u,\n", status);
	Fh(tl, 0, "}};\n");
	SkipToken(tl, '}');
}
Example #9
0
static void
parse_new(struct vcc *tl)
{
	struct symbol *sy1, *sy2, *sy3;
	const char *p, *s_obj, *s_init, *s_struct, *s_fini;
	char buf1[128];
	char buf2[128];

	vcc_NextToken(tl);
	ExpectErr(tl, ID);
	sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE);
	XXXAZ(sy1);

	sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE);	// XXX: NONE ?
	XXXAN(sy1);
	vcc_NextToken(tl);

	ExpectErr(tl, '=');
	vcc_NextToken(tl);

	ExpectErr(tl, ID);
	sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT);
	XXXAN(sy2);

	/*lint -save -e448 */
	/* Split the first three args */
	p = sy2->args;
	s_obj = p;
	p += strlen(p) + 1;
	s_init = p;
	while (p[0] != '\0' || p[1] != '\0')
		p++;
	p += 2;
	s_struct = p;
	p += strlen(p) + 1;
	s_fini = p + strlen(p) + 1;
	while (p[0] != '\0' || p[1] != '\0')
		p++;
	p += 2;

	Fh(tl, 0, "static %s *%s;\n\n", s_struct, sy1->name);

	vcc_NextToken(tl);

	bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name);
	vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1);
	Fd(tl, 0, "\t%s(&%s);\n", s_fini, sy1->name);
	ExpectErr(tl, ';');

	bprintf(buf1, ", %s", sy1->name);
	/* Split the methods from the args */
	while (*p != '\0') {
		p += strlen(s_obj);
		bprintf(buf2, "%s%s", sy1->name, p);
		sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC);
		AN(sy3);
		sy3->eval = vcc_Eval_SymFunc;
		p += strlen(p) + 1;
		sy3->cfunc = p;
		p += strlen(p) + 1;

		/* Functions which return VOID are procedures */
		if (!memcmp(p, "VOID\0", 5))
			sy3->kind = SYM_PROC;

		sy3->args = p;
		sy3->extra = TlDup(tl, buf1);
		while (p[0] != '\0' || p[1] != '\0')
			p++;
		p += 2;
	}
	/*lint -restore */
}