Blame src/lib/libast/disc/sfkeyprintf.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1985-2012 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                 Glenn Fowler <gsf@research.att.com>                  *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                   Phong Vo <kpv@research.att.com>                    *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#pragma prototyped
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * Glenn Fowler
Packit Service a8c26c
 * AT&T Research
Packit Service a8c26c
 *
Packit Service a8c26c
 * keyword printf support
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#include <ast.h>
Packit Service a8c26c
#include <ccode.h>
Packit Service a8c26c
#include <ctype.h>
Packit Service a8c26c
#include <sfdisc.h>
Packit Service a8c26c
#include <regex.h>
Packit Service a8c26c
Packit Service a8c26c
#define FMT_case	1
Packit Service a8c26c
#define FMT_edit	2
Packit Service a8c26c
Packit Service a8c26c
typedef struct
Packit Service a8c26c
{
Packit Service a8c26c
	Sffmt_t			fmt;
Packit Service a8c26c
	void*			handle;
Packit Service a8c26c
	Sf_key_lookup_t		lookup;
Packit Service a8c26c
	Sf_key_convert_t	convert;
Packit Service a8c26c
	Sfio_t*			tmp[2];
Packit Service a8c26c
	regex_t			red[2];
Packit Service a8c26c
	regex_t*		re[2];
Packit Service a8c26c
	int			invisible;
Packit Service a8c26c
	int			level;
Packit Service a8c26c
	int			version;
Packit Service a8c26c
} Fmt_t;
Packit Service a8c26c
Packit Service a8c26c
typedef struct
Packit Service a8c26c
{
Packit Service a8c26c
	char*			next;
Packit Service a8c26c
	int			delimiter;
Packit Service a8c26c
	int			first;
Packit Service a8c26c
} Field_t;
Packit Service a8c26c
Packit Service a8c26c
typedef union
Packit Service a8c26c
{
Packit Service a8c26c
	char**			p;
Packit Service a8c26c
	char*			s;
Packit Service a8c26c
	Sflong_t		q;
Packit Service a8c26c
	long			l;
Packit Service a8c26c
	int			i;
Packit Service a8c26c
	short			h;
Packit Service a8c26c
	char			c;
Packit Service a8c26c
} Value_t;
Packit Service a8c26c
Packit Service a8c26c
#define initfield(f,s)	((f)->first = (f)->delimiter = *((f)->next = (s)))
Packit Service a8c26c
Packit Service a8c26c
static char*
Packit Service a8c26c
getfield(register Field_t* f, int restore)
Packit Service a8c26c
{
Packit Service a8c26c
	register char*	s;
Packit Service a8c26c
	register int	n;
Packit Service a8c26c
	register int	c;
Packit Service a8c26c
	register int	lp;
Packit Service a8c26c
	register int	rp;
Packit Service a8c26c
	char*		b;
Packit Service a8c26c
Packit Service a8c26c
	if (!f->delimiter)
Packit Service a8c26c
		return 0;
Packit Service a8c26c
	s = f->next;
Packit Service a8c26c
	if (f->first)
Packit Service a8c26c
		f->first = 0;
Packit Service a8c26c
	else if (restore)
Packit Service a8c26c
		*s = f->delimiter;
Packit Service a8c26c
	b = ++s;
Packit Service a8c26c
	lp = rp = n = 0;
Packit Service a8c26c
	for (;;)
Packit Service a8c26c
	{
Packit Service a8c26c
		if (!(c = *s++))
Packit Service a8c26c
		{
Packit Service a8c26c
			f->delimiter = 0;
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
		else if (c == CC_esc || c == '\\')
Packit Service a8c26c
		{
Packit Service a8c26c
			if (*s)
Packit Service a8c26c
				s++;
Packit Service a8c26c
		}
Packit Service a8c26c
		else if (c == lp)
Packit Service a8c26c
			n++;
Packit Service a8c26c
		else if (c == rp)
Packit Service a8c26c
			n--;
Packit Service a8c26c
		else if (n <= 0)
Packit Service a8c26c
		{
Packit Service a8c26c
			if (c == '(' && restore)
Packit Service a8c26c
			{
Packit Service a8c26c
				lp = '(';
Packit Service a8c26c
				rp = ')';
Packit Service a8c26c
				n = 1;
Packit Service a8c26c
			}
Packit Service a8c26c
			else if (c == '[' && restore)
Packit Service a8c26c
			{
Packit Service a8c26c
				lp = '[';
Packit Service a8c26c
				rp = ']';
Packit Service a8c26c
				n = 1;
Packit Service a8c26c
			}
Packit Service a8c26c
			else if (c == f->delimiter)
Packit Service a8c26c
			{
Packit Service a8c26c
				*(f->next = --s) = 0;
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	return b;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * sfio %! extension function
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
static int
Packit Service a8c26c
getfmt(Sfio_t* sp, void* vp, Sffmt_t* dp)
Packit Service a8c26c
{
Packit Service a8c26c
	register Fmt_t*	fp = (Fmt_t*)dp;
Packit Service a8c26c
	Value_t*	value = (Value_t*)vp;
Packit Service a8c26c
	register char*	v;
Packit Service a8c26c
	char*		t;
Packit Service a8c26c
	char*		b;
Packit Service a8c26c
	char*		a = 0;
Packit Service a8c26c
	char*		s = 0;
Packit Service a8c26c
	Sflong_t	n = 0;
Packit Service a8c26c
	int		h = 0;
Packit Service a8c26c
	int		i = 0;
Packit Service a8c26c
	int		x = 0;
Packit Service a8c26c
	int		d;
Packit Service a8c26c
	Field_t		f;
Packit Service a8c26c
	regmatch_t	match[10];
Packit Service a8c26c
Packit Service a8c26c
	fp->level++;
Packit Service a8c26c
	if (fp->fmt.t_str && fp->fmt.n_str > 0 && (v = fmtbuf(fp->fmt.n_str + 1)))
Packit Service a8c26c
	{
Packit Service a8c26c
		memcpy(v, fp->fmt.t_str, fp->fmt.n_str);
Packit Service a8c26c
		v[fp->fmt.n_str] = 0;
Packit Service a8c26c
		b = v;
Packit Service a8c26c
		for (;;)
Packit Service a8c26c
		{
Packit Service a8c26c
			switch (*v++)
Packit Service a8c26c
			{
Packit Service a8c26c
			case 0:
Packit Service a8c26c
				break;
Packit Service a8c26c
			case '(':
Packit Service a8c26c
				h++;
Packit Service a8c26c
				continue;
Packit Service a8c26c
			case ')':
Packit Service a8c26c
				h--;
Packit Service a8c26c
				continue;
Packit Service a8c26c
			case '=':
Packit Service a8c26c
			case ':':
Packit Service a8c26c
			case ',':
Packit Service a8c26c
				if (h <= 0)
Packit Service a8c26c
				{
Packit Service a8c26c
					a = v;
Packit Service a8c26c
					break;
Packit Service a8c26c
				}
Packit Service a8c26c
				continue;
Packit Service a8c26c
			default:
Packit Service a8c26c
				continue;
Packit Service a8c26c
			}
Packit Service a8c26c
			if (i = *--v)
Packit Service a8c26c
			{
Packit Service a8c26c
				*v = 0;
Packit Service a8c26c
				if (i == ':' && fp->fmt.fmt == 's' && strlen(a) > 4 && !isalnum(*(a + 4)))
Packit Service a8c26c
				{
Packit Service a8c26c
					d = *(a + 4);
Packit Service a8c26c
					*(a + 4) = 0;
Packit Service a8c26c
					if (streq(a, "case"))
Packit Service a8c26c
						x = FMT_case;
Packit Service a8c26c
					else if (streq(a, "edit"))
Packit Service a8c26c
						x = FMT_edit;
Packit Service a8c26c
					*(a + 4) = d;
Packit Service a8c26c
					if (x)
Packit Service a8c26c
						a = 0;
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
			break;
Packit Service a8c26c
		}
Packit Service a8c26c
		n = i;
Packit Service a8c26c
		t = fp->fmt.t_str;
Packit Service a8c26c
		fp->fmt.t_str = b;
Packit Service a8c26c
		h = (*fp->lookup)(fp->handle, &fp->fmt, a, &s, &n);
Packit Service a8c26c
		fp->fmt.t_str = t;
Packit Service a8c26c
		if (i)
Packit Service a8c26c
			*v++ = i;
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
	{
Packit Service a8c26c
		h = (*fp->lookup)(fp->handle, &fp->fmt, a, &s, &n);
Packit Service a8c26c
		v = 0;
Packit Service a8c26c
	}
Packit Service a8c26c
	fp->fmt.flags |= SFFMT_VALUE;
Packit Service a8c26c
	switch (fp->fmt.fmt)
Packit Service a8c26c
	{
Packit Service a8c26c
	case 'c':
Packit Service a8c26c
		value->c = s ? *s : n;
Packit Service a8c26c
		break;
Packit Service a8c26c
	case 'd':
Packit Service a8c26c
	case 'i':
Packit Service a8c26c
		fp->fmt.size = sizeof(Sflong_t);
Packit Service a8c26c
		value->q = (Sflong_t)(s ? strtoll(s, NiL, 0) : n);
Packit Service a8c26c
		break;
Packit Service a8c26c
	case 'o':
Packit Service a8c26c
	case 'u':
Packit Service a8c26c
	case 'x':
Packit Service a8c26c
		fp->fmt.size = sizeof(Sflong_t);
Packit Service a8c26c
		value->q = s ? (Sflong_t)strtoull(s, NiL, 0) : n;
Packit Service a8c26c
		break;
Packit Service a8c26c
	case 'p':
Packit Service a8c26c
		if (s)
Packit Service a8c26c
			n = strtoll(s, NiL, 0);
Packit Service a8c26c
		value->p = pointerof(n);
Packit Service a8c26c
		break;
Packit Service a8c26c
	case 'q':
Packit Service a8c26c
		if (s)
Packit Service a8c26c
		{
Packit Service a8c26c
			fp->fmt.fmt = 's';
Packit Service a8c26c
			value->s = fmtquote(s, "$'", "'", strlen(s), 0);
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
		{
Packit Service a8c26c
			fp->fmt.fmt = 'd';
Packit Service a8c26c
			value->q = n;
Packit Service a8c26c
		}
Packit Service a8c26c
		break;
Packit Service a8c26c
	case 's':
Packit Service a8c26c
		if (!s && (!h || !fp->tmp[1] && !(fp->tmp[1] = sfstropen()) || sfprintf(fp->tmp[1], "%I*d", sizeof(n), n) <= 0 || !(s = sfstruse(fp->tmp[1]))))
Packit Service a8c26c
			s = "";
Packit Service a8c26c
		if (x)
Packit Service a8c26c
		{
Packit Service a8c26c
			h = 0;
Packit Service a8c26c
			d = initfield(&f, v + 4);
Packit Service a8c26c
			switch (x)
Packit Service a8c26c
			{
Packit Service a8c26c
			case FMT_case:
Packit Service a8c26c
				while ((a = getfield(&f, 1)) && (v = getfield(&f, 0)))
Packit Service a8c26c
				{
Packit Service a8c26c
					if (strmatch(s, a))
Packit Service a8c26c
					{
Packit Service a8c26c
						Fmt_t	fmt;
Packit Service a8c26c
Packit Service a8c26c
						fmt = *fp;
Packit Service a8c26c
						fmt.fmt.form = v;
Packit Service a8c26c
						for (h = 0; h < elementsof(fmt.tmp); h++)
Packit Service a8c26c
							fmt.tmp[h] = 0;
Packit Service a8c26c
						if (!fp->tmp[0] && !(fp->tmp[0] = sfstropen()) || sfprintf(fp->tmp[0], "%!", &fmt) <= 0 || !(s = sfstruse(fp->tmp[0])))
Packit Service a8c26c
							s = "";
Packit Service a8c26c
						*(v - 1) = d;
Packit Service a8c26c
						if (f.delimiter)
Packit Service a8c26c
							*f.next = d;
Packit Service a8c26c
						for (h = 0; h < elementsof(fmt.tmp); h++)
Packit Service a8c26c
							if (fmt.tmp[h])
Packit Service a8c26c
								sfclose(fmt.tmp[h]);
Packit Service a8c26c
						h = 1;
Packit Service a8c26c
						break;
Packit Service a8c26c
					}
Packit Service a8c26c
					*(v - 1) = d;
Packit Service a8c26c
				}
Packit Service a8c26c
				break;
Packit Service a8c26c
			case FMT_edit:
Packit Service a8c26c
				for (x = 0; *f.next; x ^= 1)
Packit Service a8c26c
				{
Packit Service a8c26c
					if (fp->re[x])
Packit Service a8c26c
						regfree(fp->re[x]);
Packit Service a8c26c
					else
Packit Service a8c26c
						fp->re[x] = &fp->red[x];
Packit Service a8c26c
					if (regcomp(fp->re[x], f.next, REG_DELIMITED|REG_NULL))
Packit Service a8c26c
						break;
Packit Service a8c26c
					f.next += fp->re[x]->re_npat;
Packit Service a8c26c
					if (regsubcomp(fp->re[x], f.next, NiL, 0, 0))
Packit Service a8c26c
						break;
Packit Service a8c26c
					f.next += fp->re[x]->re_npat;
Packit Service a8c26c
					if (!regexec(fp->re[x], s, elementsof(match), match, 0) && !regsubexec(fp->re[x], s, elementsof(match), match))
Packit Service a8c26c
					{
Packit Service a8c26c
						s = fp->re[x]->re_sub->re_buf;
Packit Service a8c26c
						if (fp->re[x]->re_sub->re_flags & REG_SUB_STOP)
Packit Service a8c26c
							break;
Packit Service a8c26c
					}
Packit Service a8c26c
				}
Packit Service a8c26c
				h = 1;
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			if (!h)
Packit Service a8c26c
				s = "";
Packit Service a8c26c
		}
Packit Service a8c26c
		value->s = s;
Packit Service a8c26c
		if (fp->level == 1)
Packit Service a8c26c
			while ((s = strchr(s, CC_esc)) && *(s + 1) == '[')
Packit Service a8c26c
				do fp->invisible++; while (*s && !islower(*s++));
Packit Service a8c26c
		break;
Packit Service a8c26c
	case 'Z':
Packit Service a8c26c
		fp->fmt.fmt = 'c';
Packit Service a8c26c
		value->c = 0;
Packit Service a8c26c
		break;
Packit Service a8c26c
	case '\n':
Packit Service a8c26c
		value->s = "\n";
Packit Service a8c26c
		break;
Packit Service a8c26c
	case '.':
Packit Service a8c26c
		value->i = n;
Packit Service a8c26c
		break;
Packit Service a8c26c
	default:
Packit Service a8c26c
		if ((!fp->convert || !(value->s = (*fp->convert)(fp->handle, &fp->fmt, a, s, n))) && (!fp->tmp[0] && !(fp->tmp[0] = sfstropen()) || sfprintf(fp->tmp[0], "%%%c", fp->fmt.fmt) <= 0 || !(value->s = sfstruse(fp->tmp[0]))))
Packit Service a8c26c
			value->s = "";
Packit Service a8c26c
		break;
Packit Service a8c26c
	}
Packit Service a8c26c
	fp->level--;
Packit Service a8c26c
	return 0;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * this is the original interface
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#undef	sfkeyprintf
Packit Service a8c26c
Packit Service a8c26c
int
Packit Service a8c26c
sfkeyprintf(Sfio_t* sp, void* handle, const char* format, Sf_key_lookup_t lookup, Sf_key_convert_t convert)
Packit Service a8c26c
{
Packit Service a8c26c
	register int	i;
Packit Service a8c26c
	int		r;
Packit Service a8c26c
	Fmt_t		fmt;
Packit Service a8c26c
Packit Service a8c26c
	memset(&fmt, 0, sizeof(fmt));
Packit Service a8c26c
	fmt.fmt.version = SFIO_VERSION;
Packit Service a8c26c
	fmt.fmt.form = (char*)format;
Packit Service a8c26c
	fmt.fmt.extf = getfmt;
Packit Service a8c26c
	fmt.handle = handle;
Packit Service a8c26c
	fmt.lookup = lookup;
Packit Service a8c26c
	fmt.convert = convert;
Packit Service a8c26c
	r = sfprintf(sp, "%!", &fmt) - fmt.invisible;
Packit Service a8c26c
	for (i = 0; i < elementsof(fmt.tmp); i++)
Packit Service a8c26c
		if (fmt.tmp[i])
Packit Service a8c26c
			sfclose(fmt.tmp[i]);
Packit Service a8c26c
	for (i = 0; i < elementsof(fmt.re); i++)
Packit Service a8c26c
		if (fmt.re[i])
Packit Service a8c26c
			regfree(fmt.re[i]);
Packit Service a8c26c
	return r;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#undef	_AST_API_H
Packit Service a8c26c
Packit Service a8c26c
#include <ast_api.h>
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * Sffmt_t* callback args
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
int
Packit Service a8c26c
sfkeyprintf_20000308(Sfio_t* sp, void* handle, const char* format, Sf_key_lookup_t lookup, Sf_key_convert_t convert)
Packit Service a8c26c
{
Packit Service a8c26c
	register int	i;
Packit Service a8c26c
	int		r;
Packit Service a8c26c
	Fmt_t		fmt;
Packit Service a8c26c
Packit Service a8c26c
	memset(&fmt, 0, sizeof(fmt));
Packit Service a8c26c
	fmt.version = 20030909;
Packit Service a8c26c
	fmt.fmt.version = SFIO_VERSION;
Packit Service a8c26c
	fmt.fmt.form = (char*)format;
Packit Service a8c26c
	fmt.fmt.extf = getfmt;
Packit Service a8c26c
	fmt.handle = handle;
Packit Service a8c26c
	fmt.lookup = lookup;
Packit Service a8c26c
	fmt.convert = convert;
Packit Service a8c26c
	r = sfprintf(sp, "%!", &fmt) - fmt.invisible;
Packit Service a8c26c
	for (i = 0; i < elementsof(fmt.tmp); i++)
Packit Service a8c26c
		if (fmt.tmp[i])
Packit Service a8c26c
			sfclose(fmt.tmp[i]);
Packit Service a8c26c
	return r;
Packit Service a8c26c
}