/*		Q/C V3.2 Utility Library		*/
/*     Copyright (c) 1984 Quality Computer Systems	*/
/*			11/25/84			*/

#include "stdio.h"

/* Internal routine for printf/fprintf/sprintf

	Full K&R 7.3 except for long and float

	Original from the C Users Group, Volume III
	Modified for Q/C by Lyle P. Bickley, Phila., PA
	Further modifications by Jim Colvin
*/

#define MAXFLD 128

_fmt(func,dest,pargs)
register (*func)(),dest;
char *pargs;
{
	static char *format, *sptr;
	register char *wptr;
	register c, *args;
	static base, pf, ljf, padchr, width, precision;
	char wbuf[MAXFLD], *itob();

	args = pargs;
	format = *args--;

	while (c = *format++) {
	    if (c == '%') {
		wptr = wbuf;
		precision = 6;
		ljf = pf = FALSE;

		if (*format == '-') {
			++format;
			ljf = TRUE;
			}
		padchr = (*format == '0') ? '0': ' ';
		width = (isdigit(*format)) ? _atoi(&format) : 0;
		if ((c = *format++) == '.') {
			precision = _atoi(&format);
			pf = TRUE;
			c = *format++;
			}
		switch(chupper(c)) {

		case 'D':
			base = -10; goto val;
		case 'U':
			base = 10; goto val;
		case 'X':
			base = 16; goto val;
		case 'O':
			base = 8;
		val:	itob(*args--, wptr, base);
			width -= strlen(wptr);
			goto pad2;
		case 'C':
			*wptr++ = *args--;
			--width;
			goto pad;
		case 'S':
			if (!pf) precision = MAXFLD;
			sptr = *args--;
			while (*sptr && precision) {
				*wptr++ = *sptr++;
				--precision;
				--width;
			}
		pad:	*wptr = '\0';
		pad2:	wptr = wbuf;
			if (!ljf)
				while (--width >= 0)
					(*func)(padchr,dest);
			while (*wptr)
				(*func)(*wptr++,dest);
			if (ljf)
				while (--width >= 0)
					(*func)(padchr,dest);
			break;

		default:
			(*func)(c,dest);
		}
	    }
	    else (*func)(c,dest);
	}
}
