Exemple #1
0
static int
validate_beg(Cx_t* cx, Cxexpr_t* expr, void* data, Cxdisc_t* disc)
{
	char**			argv = (char**)data;
	int			errors = error_info.errors;
	char*			s;
	State_t*		state;
	Cxvariable_t*		variable;
	register Field_t*	field;
	Field_t*		lastfield;
	Cxconstraint_t*		constraint;
	int			all;
	int			list;
	Vmalloc_t*		vm;

	if (!(vm = vmopen(Vmdcheap, Vmlast, 0)) || !(state = vmnewof(vm, 0, State_t, 1, 0)))
	{
		if (vm)
			vmclose(vm);
		if (disc->errorf)
			(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
		return -1;
	}
	state->vm = vm;
	list = 0;
	sfprintf(cx->buf, "%s%s", strchr(dss_lib_validate.description, '['), validate_usage);
	s = sfstruse(cx->buf);
	for (;;)
	{
		switch (optget(argv, s))
		{
		case 'd':
			state->discard = 1;
			continue;
		case 'l':
			list = 1;
			continue;
		case 'r':
			if (!(state->setf = cxcallout(cx, CX_SET, cx->state->type_void, cx->state->type_void, cx->disc)))
			{
				if (cx->disc->errorf)
					(*cx->disc->errorf)(NiL, cx->disc, 3, "reair requires CX_SET callout");
				return -1;
			}
			continue;
		case 's':
			state->summary = 1;
			continue;
		case 'v':
			state->summary = state->verbose = 1;
			continue;
		case '?':
			if (disc->errorf)
				(*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg);
			else
				return -1;
			continue;
		case ':':
			if (disc->errorf)
				(*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg);
			else
				return -1;
			continue;
		}
		break;
	}
	if (error_info.errors > errors)
		goto bad;
	argv += opt_info.index;
	if (all = !*argv)
		variable = 0;
	do
	{
		if (all)
		{
			if (!(variable = (Cxvariable_t*)(variable ? dtnext(cx->fields, variable) : dtfirst(cx->fields))))
				break;
		}
		else if (!(variable = cxvariable(cx, *argv, NiL, disc)))
			goto bad;
		if (variable->format.constraint || variable->format.map)
		{
			if (!(field = vmnewof(vm, 0, Field_t, 1, 0)))
			{
				if (disc->errorf)
					(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
				goto bad;
			}
			field->variable = variable;
			if (state->field)
				lastfield = lastfield->next = field;
			else
				lastfield = state->field = field;
		}
	} while (all || *++argv);
	if (!state->field && disc->errorf)
		(*disc->errorf)(NiL, disc, 1, "no field has constraints or maps");
	if (list)
	{
		for (field = state->field; field; field = field->next)
		{
			sfprintf(expr->op, "%16s", field->variable->name);
			if (field->variable->format.map)
				sfprintf(expr->op, " map");
			if (constraint = field->variable->format.constraint)
			{
				if (constraint->name)
					sfprintf(expr->op, " name=%s", constraint->name);
				if (constraint->constraintf)
					sfprintf(expr->op, " external");
				if (cxisnumber(field->variable->type))
				{
					if (constraint->def)
						number(expr->op, "default", constraint->def->number, &field->variable->format);
					if (constraint->min)
						number(expr->op, "min", constraint->min->number, &field->variable->format);
					if (constraint->max)
						number(expr->op, "max", constraint->max->number, &field->variable->format);
				}
				else if (cxisstring(field->variable->type) && constraint->def)
					sfprintf(expr->op, " default=\"%-.*s\"", constraint->def->string.size, constraint->def->string.data);
				if (constraint->expression)
					sfprintf(expr->op, " expression=\"%s\"", constraint->expression);
				if (constraint->pattern)
					sfprintf(expr->op, " pattern=\"%s\"", constraint->pattern);
			}
			sfprintf(expr->op, "\n");
		}
		goto bad;
	}
	if (!(state->getf = cxcallout(cx, CX_GET, cx->state->type_void, cx->state->type_void, cx->disc)))
	{
		if (cx->disc->errorf)
			(*cx->disc->errorf)(NiL, cx->disc, 3, "validation requires CX_GET callout");
		goto bad;
	}
	if (!state->verbose)
	{
		state->invaliddisc.comparf = invalidcmp;
		if (!(state->invalid = dtnew(vm, &state->invaliddisc, Dtoset)))
		{
			if (cx->disc->errorf)
				(*cx->disc->errorf)(NiL, cx->disc, 3, "validation requires CX_GET callout");
			goto bad;
		}
	}
	expr->data = state;
	return 0;
 bad:
	vmclose(vm);
	return -1;
}
Exemple #2
0
int
dssprintf(Dss_t* dss, Cx_t* cx, Sfio_t* sp, const char* format, Dssrecord_t* record)
{
	register char*	s;
	register char*	t;
	register char*	d;
	register char*	v;
	register int	n;
	register int	q;
	register Arg_t*	ap;
	int		l;
	int		x;
	char*		f;
	char*		o;
	char*		w;
	Format_t*	fp;
	Fmt_t		fmt;

	if (!cx)
		cx = dss->cx;
	for (fp = dss->print; fp && fp->oformat != (char*)format; fp = fp->next);
	if (!fp)
	{
		if (f = s = (char*)format)
		{
			char*	details['z' - 'a' + 1];

			memset(details, 0, sizeof(details));
			d = 0;
			l = 0;
			n = 0;
			q = 0;
			w = 0;
			for (;;)
			{
				switch (*s++)
				{
				case 0:
					if (q)
					{
						if (dss->disc->errorf)
							(*dss->disc->errorf)(NiL, dss->disc, 2, "%s: format character omitted", f);
						return -1;
					}
					break;
				case '%':
					if (*s != '%')
					{
						q = 1;
						n++;
						f = s - 1;
					}
					continue;
				case '(':
					if (q == 1)
					{
						q++;
						for (;;)
						{
							switch (*s++)
							{
							case 0:
								s--;
								break;
							case '(':
								q++;
								continue;
							case ')':
								if (--q == 1)
									break;
								continue;
							case ':':
								if (*s == ':')
									s++;
								else if (!d)
									d = s;
								continue;
							default:
								continue;
							}
							break;
						}
						if (d)
						{
							l += s - d + 1;
							d = 0;
						}
					}
					continue;
				case 'c':
				case 'd':
				case 'e':
				case 'f':
				case 'g':
				case 'o':
				case 's':
				case 'u':
				case 'x':
					if (q == 1)
						q = 0;
					continue;
				default:
					continue;
				}
				break;
			}
			if (!(fp = vmnewof(dss->vm, 0, Format_t, 1, (n - 1) * sizeof(Arg_t) + strlen(format) + 2 * n + l + 2)))
			{
				if (dss->disc->errorf)
					(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "out of space");
				return -1;
			}
			fp->oformat = (char*)format;
			fp->next = dss->print;
			dss->print = fp;
			ap = &fp->arg[0];
			s = t = fp->nformat = (char*)(&fp->arg[n]);
			strcpy(t, format);
			f = t + strlen(format) + 2 * n + 1;
			q = 0;
			d = 0;
			l = 0;
			for (;;)
			{
				switch (*t++ = *s++)
				{
				case 0:
					*(t - 1) = '\n';
					*t = 0;
					break;
				case '%':
					if (*s == '%')
						*t++ = *s++;
					else
						q = 1;
					continue;
				case '(':
					if (q == 1)
					{
						q++;
						t--;
						x = 0;
						v = s;
						for (;;)
						{
							switch (*s++)
							{
							case 0:
								if (dss->disc->errorf)
									(*dss->disc->errorf)(NiL, dss->disc, 2, "%s: %(...) imbalance", fp->oformat);
								return -1;
							case '(':
								if (!d)
									x = 1;
								q++;
								continue;
							case ')':
								if (--q == 1)
									break;
								continue;
							case ':':
								if (*s == ':')
									s++;
								else if (!d && q == 2)
									d = s;
								continue;
							case ',':
								if (!d)
									x = 1;
								continue;
							default:
								if (!d && cx->table->opcode[*(unsigned char*)(s - 1)])
									x = 1;
								continue;
							}
							break;
						}
						if (d)
							*(d - 1) = 0;
						*(s - 1) = 0;
						if (*v)
						{
							if (x)
							{
								void*	pop;
	
								if (!(pop = cxpush(cx, NiL, NiL, v, (d ? d : s) - v, 0)))
									return -1;
								ap->expr = cxcomp(cx);
								cxpop(cx, pop);
								if (!ap->expr)
									return -1;
							}
							else if (cx->referencef)
							{
								Cxoperand_t	a;
								Cxoperand_t	b;
								Cxoperand_t	r;
	
								a.type = cx->state->type_string;
								a.value.string.size = s - v - 1;
								a.value.string.data = v;
								b.type = a.type;
								if ((*cx->referencef)(cx, NiL, &r, &b, &a, NiL, cx->disc))
									return -1;
								ap->variable = r.value.variable;
							}
							else if (!(ap->variable = cxvariable(cx, v, NiL, cx->disc)))
								return -1;
						}
						else if (d)
						{
							w = d;
							d = 0;
						}
					}
					continue;
				case 'c':
					if (q == 1)
					{
						ap->type = DSS_FORMAT_char;
						ap->cast = cx->state->type_number;
						goto set;
					}
					continue;
				case 'd':
				case 'o':
				case 'u':
				case 'x':
					if (q == 1)
					{
						if (l > 1 || ap->variable && (ap->variable->format.width == 8 || ap->variable->type->format.width == 8))
						{
							n = *(t - 1);
							*(t - 1) = 'l';
							*t++ = 'l';
							*t++ = n;
							ap->type = DSS_FORMAT_long;
						}
						else
							ap->type = DSS_FORMAT_int;
						ap->cast = cx->state->type_number;
						goto set;
					}
					continue;
				case 'e':
				case 'f':
				case 'g':
					if (q == 1)
					{
						ap->type = DSS_FORMAT_float;
						ap->cast = cx->state->type_number;
						goto set;
					}
					continue;
				case 'h':
					if (q == 1)
						t--;
					continue;
				case 'l':
					if (q == 1)
					{
						t--;
						l++;
					}
					continue;
				case 's':
					if (q == 1)
					{
						ap->type = DSS_FORMAT_string;
						ap->cast = cx->state->type_string;
					set:
						if (w)
						{
							details[*(s-1) - 'a'] = w;
							w = 0;
							fp->nformat = t = s;
							continue;
						}
						if (!ap->variable && !ap->expr)
						{
							if (dss->disc->errorf)
							{
								*t = 0;
								(*dss->disc->errorf)(NiL, dss->disc, 2, "%s: (variable) omitted in format", fp->nformat);
							}
							return -1;
						}
						l = 0;
						q = 0;
						if (d || (d = details[*(s-1) - 'a']) || (d = cx->state->type_string->format.details))
						{
							ap->fmt = FMT_ALWAYS|FMT_ESCAPED;
							while (*d)
							{
								o = 0;
								v = d;
								while (*d)
									if (*d++ == ':')
									{
										*(o = d - 1) = 0;
										break;
									}
								if (strneq(v, "edit=", 5))
								{
									if (o)
										*o = ':';
									if (ap->edit = cxedit(cx, v + 5, dss->disc))
									{
										d = v + 5 + ap->edit->re.re_npat;
										if (d == o)
											d++;
									}
								}
								else if (strneq(v, "endquote=", 8))
								{
									ap->qe = v += 8;
									while (*f++ = *v++);
								}
								else if (streq(v, "expand"))
								{
									ap->fmt |= FMT_EXP_CHAR|FMT_EXP_LINE|FMT_EXP_WIDE;
									continue;
								}
								else if (strneq(v, "expand=", 7))
								{
									v += 7;
									while (*v)
									{
										if (*v == '|' || *v == ',')
										{
											v++;
											continue;
										}
										if (strneq(v, "all", 3))
										{
											ap->fmt |= FMT_EXP_CHAR|FMT_EXP_LINE|FMT_EXP_WIDE;
											break;
										}
										else if (strneq(v, "char", 4))
										{
											v += 4;
											ap->fmt |= FMT_EXP_CHAR;
										}
										else if (strneq(v, "line", 4))
										{
											v += 4;
											ap->fmt |= FMT_EXP_LINE;
										}
										else if (strneq(v, "nocr", 4))
										{
											v += 4;
											ap->fmt |= FMT_EXP_NOCR;
										}
										else if (strneq(v, "nonl", 4))
										{
											v += 4;
											ap->fmt |= FMT_EXP_NONL;
										}
										else if (strneq(v, "wide", 4))
										{
											v += 4;
											ap->fmt |= FMT_EXP_WIDE;
										}
										else
											while (*v && *v != '|' && *v != ',')
												v++;
									}
									continue;
								}
								else if (streq(v, "escape"))
									ap->fmt &= ~FMT_ESCAPED;
								else if (strneq(v, "opt", 3))
									ap->fmt &= ~FMT_ALWAYS;
								else if (streq(v, "quote") || strneq(v, "quote=", 6))
								{
									if (v[5])
									{
										ap->qb = v += 6;
										while (*f++ = *v++);
									}
									else
										ap->qb = "\"";
									if (!ap->qe)
										ap->qe = ap->qb;
								}
								else if (streq(v, "shell") || strneq(v, "shell=", 6))
								{
									ap->fmt |= FMT_SHELL;
									if (v[5])
									{
										ap->qb = v += 6;
										while (*f++ = *v++);
									}
									else
										ap->qb = "$'";
									if (!ap->qe)
										ap->qe = "'";
								}
								else if (streq(v, "wide"))
									ap->fmt |= FMT_WIDE;
								else
								{
									if (*d)
										*(d - 1) = ':';
									d = v;
									break;
								}
								ap->flags |= DSS_FORMAT_quote;
							}
							ap->details = f;
							while (*f++ = *d++);
							d = 0;
						}
						if (ap->variable && !ap->edit && cxisstring(ap->variable->type) && ap->variable->format.map && ap->variable->format.map->part && ap->variable->format.map->part->edit)
							ap->edit = ap->variable->format.map->part->edit;
						ap++;
					}
					continue;
				case 'L':
					if (q == 1)
					{
						t--;
						l += 2;
					}
					continue;
				default:
					continue;
				}
				break;
			}
		}
		else
		{
			Cxvariable_t*	vp;

			n = q = 0;
			if (dss->meth->cx->fields)
			{
				for (vp = (Cxvariable_t*)dtfirst(dss->meth->cx->fields); vp; vp = (Cxvariable_t*)dtnext(dss->meth->cx->fields, vp), n++)
					if (!(vp->header.flags & CX_DEPRECATED) && q < (l = strlen(vp->name)))
						q = l;
			}
			else if (dss->meth->data)
			{
				for (vp = (Cxvariable_t*)dss->meth->data; vp->name; vp++, n++)
					if (!(vp->header.flags & CX_DEPRECATED) && q < (l = strlen(vp->name)))
						q = l;
			}
			q += 2;
			if (!(fp = vmnewof(dss->vm, 0, Format_t, 1, n * sizeof(Arg_t) + n * (q + 3) + 2)))
			{
				if (dss->disc->errorf)
					(*dss->disc->errorf)(NiL, dss->disc, ERROR_SYSTEM|2, "out of space");
				return -1;
			}
			fp->oformat = 0;
			fp->next = dss->print;
			dss->print = fp;
			ap = &fp->arg[0];
			s = fp->nformat = (char*)(&fp->arg[n]);
			*s++ = '\n';
			vp = dss->meth->cx->fields ? (Cxvariable_t*)dtfirst(dss->meth->cx->fields) : dss->meth->data ? (Cxvariable_t*)dss->meth->data : 0;
			if (vp)
				for (;;)
				{
					if (dss->meth->cx->fields)
					{
						if (!vp)
							break;
					}
					else if (!vp->name)
						break;
					if (!(vp->header.flags & CX_DEPRECATED))
					{
						s += sfsprintf(s, q + 4, "%-*s%%s\n", q, vp->name);
						ap->variable = vp;
						ap->type = DSS_FORMAT_string;
						ap->cast = cx->state->type_string;
						if (cxisstring(vp->type) && vp->format.map && vp->format.map->part && vp->format.map->part->edit)
							ap->edit = vp->format.map->part->edit;
						ap++;
					}
					if (dss->meth->cx->fields)
						vp = (Cxvariable_t*)dtnext(dss->meth->cx->fields, vp);
					else
						vp++;
				}
			*s = 0;
		}
		if (!sp)
			return 0;
	}
	memset(&fmt, 0, sizeof(fmt));
	fmt.fmt.version = SFIO_VERSION;
	fmt.fmt.form = fp->nformat;
	fmt.fmt.extf = getfmt;
	fmt.cx = cx;
	fmt.data = record;
	fmt.ap = &fp->arg[0];
	n = sfprintf(sp, "%!", &fmt);
	return !sp ? 0 : (fmt.errors || n <= 0 && sp && sferror(sp)) ? -1 : n;
}
Exemple #3
0
static int
merge_beg(Cx_t* cx, Cxexpr_t* expr, void* data, Cxdisc_t* disc)
{
	register State_t*	state;
	register File_t*	file;
	char**			argv = (char**)data;
	char**			files = expr->files;
	Dss_t*			dss = DSS(cx);
	int			errors = error_info.errors;
	int			i;
	int			k;
	int			n;
	int			r;
	char*			path;
	char*			u;
	char**			v;
	Cxvariable_t*		variable;
	Cxoperand_t*		operands;
	Key_t*			key;
	Key_t*			lastkey;
	Key_t*			keys;
	Vmalloc_t*		vm;

	if (!(vm = vmopen(Vmdcheap, Vmbest, 0)))
	{
		if (disc->errorf)
			(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
		return -1;
	}
	r = -1;
	k = 0;
	keys = 0;
	sfprintf(cx->buf, "%s%s", strchr(dss_lib_merge.description, '['), merge_usage);
	u = sfstruse(cx->buf);
	for (;;)
	{
		switch (i = optget(argv, u))
		{
		case 'k':
		case 'r':
			if (!(variable = cxvariable(cx, opt_info.arg, NiL, disc)))
				goto bad;
			if (!(key = vmnewof(vm, 0, Key_t, 1, 0)))
			{
				if (disc->errorf)
					(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
				goto bad;
			}
			key->variable = variable;
			key->sense = (i == 'r') ? -1 : 1;
			if (keys)
				lastkey = lastkey->next = key;
			else
				lastkey = keys = key;
			k++;
			continue;
		case '?':
			if (disc->errorf)
				(*disc->errorf)(NiL, disc, ERROR_USAGE|4, "%s", opt_info.arg);
			else
				return -1;
			continue;
		case ':':
			if (disc->errorf)
				(*disc->errorf)(NiL, disc, 2, "%s", opt_info.arg);
			else
				return -1;
			continue;
		}
		break;
	}
	if (error_info.errors > errors)
		goto bad;
	argv += opt_info.index;
	for (v = argv; *v; v++);
	n = v - argv;
	if (files)
	{
		for (v = files; *v; v++);
		n += v - files;
	}
	if (!n)
		n = 1;
	if (!(state = vmnewof(vm, 0, State_t, 1, (n - 1) * sizeof(File_t))) || !(operands = vmnewof(vm, 0, Cxoperand_t, n * k, 0)))
	{
		if (cx->disc->errorf)
			(*cx->disc->errorf)(NiL, cx->disc, ERROR_SYSTEM|2, "out of space");
		goto bad;
	}
	state->cx = cx;
	if (!(state->getf = cxcallout(cx, CX_GET, cx->state->type_void, cx->state->type_void, cx->disc)))
	{
		if (cx->disc->errorf)
			(*cx->disc->errorf)(NiL, cx->disc, 2, "CX_GET callout required");
		goto bad;
	}
	state->nfiles = n;
	state->nkeys = k;
	state->keys = keys;
	for (n = 0; n < state->nfiles; n++)
	{
		state->files[n].data = operands;
		operands += k;
	}
	state->orderdisc.comparf = ordercmp;
	if (!(state->order = dtnew(vm, &state->orderdisc, Dtoset)))
	{
		if (cx->disc->errorf)
			(*cx->disc->errorf)(NiL, cx->disc, ERROR_SYSTEM|2, "out of space");
		goto bad;
	}
	n = 0;
	if (path = *argv)
		argv++;
	else if (files)
	{
		argv = files;
		files = 0;
		if (path = *argv)
			argv++;
	}
	for (;;)
	{
		if (!(state->files[n].file = dssfopen(dss, path, NiL, DSS_FILE_READ, NiL)))
			goto drop;
		enter(dss, state, &state->files[n]);
		n++;
		if (!(path = *argv++))
		{
			if (!files)
				break;
			argv = files;
			files = 0;
			if (!(path = *argv++))
				break;
		}
	}
	expr = expr->pass;
	if (dssbeg(dss, expr))
		goto drop;
	while (file = (File_t*)dtfirst(state->order))
	{
		if (dsseval(dss, expr, file->record) < 0)
			goto drop;
		enter(dss, state, file);
	}
	if (error_info.errors == errors)
		r = 0;
 drop:
	for (n = 0; n < state->nfiles; n++)
		if (state->files[n].file)
			dssfclose(state->files[n].file);
 bad:
	vmclose(vm);
	return r;
}