V10/cmd/post/fmt.c

Compare this file to the similar file:
Show the results in this format:

#include <ctype.h>
#include <string.h>

#define	CAPS	(1<<0)
#define	ALLCAPS	(1<<1)
#define	RJUST	(1<<2)
#define	LDEL	(1<<3)
#define	RDEL	(1<<4)

#define	SUBST	1
#define	LMARK	2
#define	RMARK	3

#define	FLAGS	0
#define	WIDTH	1
#define	PREC	2
#define	VAR	3
#define	PSIZE	4

fmtcomp(prog, fmt, vars)
register char	*prog, *fmt;
char	*vars[];
{
	register char	c, b;
	register char	*p;
	int	nl = 1, curly, i;

	vars[0] = 0;
	while (c = *fmt++)
	top:	switch (c) {
		case '%':
			*prog++ = SUBST;
			prog[FLAGS] = prog[WIDTH] = prog[PREC] = 0;
			p = &prog[WIDTH];
			curly = 0;
			while (c = *fmt++)
				switch (c) {
				case '^':	prog[FLAGS] |= CAPS;	break;
				case '+':	prog[FLAGS] |= ALLCAPS;	break;
				case '-':	prog[FLAGS] |= RJUST;	break;
				case '<':	prog[FLAGS] |= LDEL;	break;
				case '>':	prog[FLAGS] |= RDEL;	break;
				case '.':	p = &prog[PREC];	break;
				case '{':
					curly++;
					c = *fmt++;
					/* fall thru */
				default:
					if (isdigit(c)) {
						*p = (*p * 10) + (c - '0');
						break;
					}
					p = --fmt;
					while (isalnum(c))
						c = *++fmt;
					if (p == fmt) {
						prog--;
						goto brake;
					}
					if (c)
						*fmt++ = 0;
					for (i = 0; vars[i] &&
						strcmp(vars[i], p); i++);
					prog[VAR] = i;
					prog += PSIZE;
					if (!vars[i]) {
						vars[i] = p;
						vars[++i] = 0;
					}
					if (c && !curly)
						goto top;
					goto brake;
				}
			prog--;
			fmt--;
		brake:	break;
		case '\\':
			switch (c = *fmt++) {
			case '<':	c = LMARK;	break;
			case '>':	c = RMARK;	break;
			case 'n':	c = '\n';	break;
			case 'r':	c = '\r';	break;
			case 't':	c = '\t';	break;
			case 'b':	c = '\b';	break;
			case 'f':	c = '\f';	break;
			case 'v':	c = '\v';	break;
			case 0:		c = '\\',fmt--;	break;
			case 'c':	nl = 0;		continue;
			default:
				for (i = b = 0; i < 3 && isdigit(c); i++) {
					b = (b * 010) + (c - '0');
					c = *fmt++;
				}
				if (i > 0) {
					c = b;
					fmt--;
				}
			}
			/* fall thru */
		default:
			*prog++ = c;
		}
	if (nl) {
		*prog++ = RMARK;
		*prog++ = '\n';
	}
	*prog = 0;
}

fmtexec(out, prog, vals)
register char	*out, *prog;
char	*vals[];
{
	register int	len, spaces;
	register char	c, prev;
	register char	*val;
	char	*mark = out;

	while (c = *prog++)
		switch (c) {
		case SUBST:
			c = prog[FLAGS];
			val = vals[prog[VAR]];
			if ((len = strlen(val)) == 0 && c & (LDEL|RDEL)) {
				prog += PSIZE;
				if (c & LDEL)
					out = mark;
				if (c & RDEL)
					while (*prog && *prog != RMARK)
						if (*prog++ == SUBST)
							prog += PSIZE;
				break;
			}
			if (prog[PREC] > 0 && prog[PREC] < len)
				len = prog[PREC];
			spaces = prog[WIDTH] - len;
			if (spaces > 0 && c & RJUST)
				while (spaces--)
					*out++ = ' ';
			prev = 0;
			while (len--)
				*out++ = prev = c & ALLCAPS ||
					       (c & CAPS && !isalnum(prev))
						? toupper(*val++) : *val++;
			if (spaces > 0 && !(c & RJUST))
				while (spaces--)
					*out++ = ' ';
			prog += PSIZE;
			break;
		case LMARK:
			mark = out;
			break;
		case RMARK:
			break;
		default:
			*out++ = c;
		}
	*out = 0;
}