Metropoli BBS
VIEWER: prf.c MODE: TEXT (ASCII)
/****************************************************************/
/*								*/
/*			      prf.c				*/
/*								*/
/*		    Abbreviated printf Function			*/
/*		       DOS-C kernel version			*/
/*								*/
/*			 January 10, 1993			*/
/*								*/
/*			Copyright (c) 1995			*/
/*			Pasquale J. Villani			*/
/*			All Rights Reserved			*/
/*								*/
/* This file is part of DOS-C.					*/
/*								*/
/* DOS-C is free software; you can redistribute it and/or	*/
/* modify it under the terms of the GNU General Public License	*/
/* as published by the Free Software Foundation; either version	*/
/* 2, or (at your option) any later version.			*/
/*								*/
/* DOS-C is distributed in the hope that it will be useful, but	*/
/* WITHOUT ANY WARRANTY; without even the implied warranty of	*/
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	*/
/* the GNU General Public License for more details.		*/
/*								*/
/* You should have received a copy of the GNU General Public	*/
/* License along with DOS-C; see the file COPYING.  If not,	*/
/* write to the Free Software Foundation, 675 Mass Ave,		*/
/* Cambridge, MA 02139, USA.					*/
/****************************************************************/

#include "../../hdr/portab.h"

/* $Logfile:   C:/dos-c/src/misc/prf.c_v  $ */
static BYTE *prfRcsId = "$Header:   C:/dos-c/src/misc/prf.c_v   1.1   01 Sep 1995 18:11:02   patv  $";

/*
 * $Log:   C:/dos-c/src/misc/prf.c_v  $
 *	
 *	   Rev 1.1   01 Sep 1995 18:11:02   patv
 *	First GPL release.
 *	
 *	   Rev 1.0   02 Jul 1995 11:04:50   patv
 *	Initial revision.
 */

static BYTE *charp;

#ifdef PROTO
VOID handle_char(COUNT);
VOID put_console(COUNT);
BYTE *ltob(LONG, BYTE *, COUNT);
static BYTE *itob(COUNT, BYTE *, COUNT);
COUNT do_printf(CONST BYTE *, REG BYTE **);
#else
VOID handle_char();
VOID put_console();
BYTE *ltob();
static BYTE *itob();
COUNT do_printf();
#endif

/* The following is user supplied and must match the following prototype */
#ifdef PROTO
VOID sto (COUNT);
#else
VOID sto ();
#endif

/* special console output routine */
VOID put_console(c)
COUNT c;
{
	if(c == '\n')
		sto('\r');
	sto(c);
}


/* special handler to switch between sprintf and printf */
static VOID handle_char(c)
COUNT c;
{
	if(charp == 0)
		put_console(c);
	else
		*charp++ = c;
}


/* ltob -- convert an long integer to a string in any base (2-16) */
static BYTE *ltob(n, s, base)
LONG n;
BYTE *s;
COUNT base;
{
	ULONG u;
	REG BYTE *p, *q;
	REG negative, c;

	if (n < 0 && base == -10)
	{
		negative = 1;
		u = -n;
	}
	else
	{
		negative = 0;
		u = n;
	}
	if (base == -10)		/* signals signed conversion */
		base = 10;
	p = q = s;
	do
	{				/* generate digits in reverse order */
		*p++ = "0123456789abcdef"[u % base];
	} while ((u /= base) > 0);
	if (negative)
		*p++ = '-';
	*p = '\0';			/* terminate the string */
	while (q < --p)
	{				/* reverse the digits */
		c = *q;
		*q++ = *p;
		*p = c;
	}
	return s;
}

/* itob -- convert an long integer to a string in any base (2-16) */
static BYTE *itob(n, s, base)
COUNT n;
BYTE *s;
COUNT base;
{
	UWORD u;
	REG BYTE *p, *q;
	REG negative, c;

	if (n < 0 && base == -10)
	{
		negative = 1;
		u = -n;
	}
	else
	{
		negative = 0;
		u = n;
	}
	if (base == -10)		/* signals signed conversion */
		base = 10;
	p = q = s;
	do
	{				/* generate digits in reverse order */
		*p++ = "0123456789abcdef"[u % base];
	} while ((u /= base) > 0);
	if (negative)
		*p++ = '-';
	*p = '\0';			/* terminate the string */
	while (q < --p)
	{				/* reverse the digits */
		c = *q;
		*q++ = *p;
		*p = c;
	}
	return s;
}

#define	NONE	0
#define	LEFT	1
#define	RIGHT	2

/* printf -- short version of printf to conserve space */
WORD printf(fmt, args)
CONST BYTE *fmt;
BYTE *args;
{
	charp = 0;
	return do_printf(fmt, &args);
}

WORD sprintf(buff, fmt, args)
BYTE *buff;
CONST BYTE *fmt;
BYTE *args;
{
	WORD ret;

	charp = buff;
	ret = do_printf(fmt, &args);
	handle_char(NULL);
	return ret;
}


static COUNT do_printf(fmt, arg)
CONST BYTE *fmt;
REG BYTE **arg;
{
	REG base;
	BYTE s[11], *p, *ltob();
	BYTE c, slen, flag, size, fill;

	flag = NONE;
	size = 0;
	while ((c = *fmt++) != '\0')
	{
		if (size == 0 && flag == NONE && c != '%')
		{
			handle_char(c);
			continue;
		}
		if(flag == NONE && *fmt == '0')
		{
			flag = RIGHT;
			fill = '0';
		}
		switch(*fmt)
		{
		case '-':
			flag = RIGHT;
			fill = *(fmt + 1) == '0' ? '0' : ' ';
			continue;

		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			if(flag == NONE)
				flag = LEFT;
			size = *fmt++ - '0';
			while((c = *fmt++) != '\0')
			{
				switch(c)
				{
				case '0':
				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					size = size * 10 + (c - '0');
					continue;

				default:
					--fmt;
					break;
				}
				break;
			}
			break;
		}
		switch (c = *fmt++)
		{
		case 'c':
			handle_char(*(COUNT *)arg++);
			continue;

		case 'd':
			base = -10;
			goto prt;

		case 'o':
			base = 8;
			goto prt;

		case 'u':
			base = 10;
			goto prt;

		case 'x':
			base = 16;

		prt:
			itob(*((COUNT *)arg)++, s, base);
			if(flag == RIGHT || flag == LEFT)
			{
				for(slen = 0, p = s; *p != '\0'; p++)
					++slen;
			}
			if(flag == RIGHT && slen < size)
			{
				WORD i;

				for(i = size - slen; i > 0; i--)
					handle_char(fill);
			}
			for(p = s; *p != '\0'; p++)
				handle_char(*p);
			if(flag == LEFT)
			{
				WORD i;
				BYTE sp = ' ';

				for(i = size - slen; i > 0; i--)
					handle_char(sp);
			}
			size = 0;
			flag = NONE;
			continue;

		case 'l':
			switch(c = *fmt++)
			{
			case 'd':
				base = -10;
				goto lprt;

			case 'o':
				base = 8;
				goto lprt;

			case 'u':
				base = 10;
				goto lprt;

			case 'x':
				base = 16;

			lprt:
				ltob(*((LONG *)arg)++, s, base);
				if(flag == RIGHT || flag == LEFT)
				{
					for(slen = 0, p = s; *p != '\0'; p++)
						++slen;
				}
				if(flag == RIGHT && slen < size)
				{
					WORD i;

					for(i = size - slen; i > 0; i--)
						handle_char(fill);
				}
				for(p = s; *p != '\0'; p++)
					handle_char(*p);
				if(flag == LEFT)
				{
					WORD i;
					BYTE sp = ' ';

					for(i = size - slen; i > 0; i--)
						handle_char(sp);
				}
				size = 0;
				flag = NONE;
				continue;

			default:
				handle_char(c);
			}

		case 's':
			for(p = *arg; *p != '\0'; p++)
			{
				--size;
				handle_char(*p);
			}
			for( ; size > 0; size--)
				handle_char(' ');
			++arg;
			size = 0;
			flag = NONE;
			continue;

		default:
			handle_char(c);
			continue;
		}
	}
	return 0;
}


[ RETURN TO DIRECTORY ]