/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */

/* $Header:printf.c 12.0$ */
/* $ACIS:printf.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/pc_code/RCS/printf.c,v $ */

#ifndef lint
static char *rcsid = "$Header:printf.c 12.0$";
#endif


#include <sys/types.h>
#include "pcparam.h"
#include "rb.h"
#include "vars.h"

/*
 * Get rid of stdio's definition of getchar and putchar
 * so we call our on version (defined in as.asm)
 */

#define printf rbprintf		/* We get libary problems otherwise */
#define getchar rbgetchar
#define putchar rbputchar




int             linecnt = 0;	/* rb's notion of what line the cursor in on */


/*
 * put the character to screen or printer
 * depending on the option flags
 */
rbputchar(c)
	char c;
{
	if(option_flag & OPTION_PRINT) {
		rblpchar(c);
	} else {
		rbputc(c);
	}
}

/*
 * Scaled down version of C Library printf.
 * Used to print diagnostic information directly on console tty.
 * Since it is not interrupt driven, all system activities are
 * suspended.  Printf should not be used for chit-chat.
 *
 * One additional format: %b is supported to decode error registers.
 * Usage is:
 *      printf("reg=%b\n", regval, "<base><arg>*");
 * Where <base> is the output base expressed as a control character,
 * e.g. \10 gives octal; \20 gives hex.  Each arg is a sequence of
 * characters, the first of which gives the bit number to be inspected
 * (origin 1), and the next characters (up to a control character, i.e.
 * a character <= 32), give the name of the register.  Thus
 *      printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
 * would produce output:
 *      reg=2<BITTWO,BITONE>
 */
/*VARARGS1*/
printf(fmt, x1)
	char           *fmt;
	u_short         x1;
{

	prf(fmt, (u_short far *) &x1);
}


prf(fmt, adx)
	char           *fmt;
	u_short far    *adx;
{
	register int    b, c;
	char           *s;
	u_long          longval;
	u_short         i, j;
#ifdef LARGEMODEL
	u_short         seg, off;
#endif /* LARGEMODEL */

loop:
	while ((c = *fmt++) != '%')
	{
		if (c == '\0')
		{
			return;
		}
		switch (c)

		{
		case ('\n'):	/* Map NL to CR LF */
			putchar('\r');
			putchar('\n');
			break;


		case ('\t'):	/* Map TAB to 4 blanks */
			for (i = 0; i < 4; i++)
				putchar(' ');
			break;
		default:
			putchar(c);
		}

	}
again:
	c = *fmt++;
	/* THIS CODE IS VAX DEPENDENT IN HANDLING %l? AND %c */
	/* they lied ... it works fine on a 370             */

	switch (c)
	{

	case '0':		/* we ignore all of these */
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	case 'b':
	case '.':
	case '-':
		goto again;

	case ('#'):
		putchar('0');
		putchar('x');
		goto again;

	case 'l':
		b = 10;
		i = *adx;	/* First get the lower half */
		adx++;		/* Now get the upper half        */
		j = *adx;
		longval = j;
		longval = (longval << 16) | i;
		c = *fmt++;
		switch (c)
		{
		case 'x':
		case 'X':
			b = 16;
			break;

		case 'd':
		case 'D':
		case 'u':	/* what a joke */
			b = 10;
			break;

		case 'o':
		case 'O':
			b = 8;
			break;

	defalut:
			break;
		}
		printn((long) longval, b);
		break;

	case 'x':
	case 'X':
		b = 16;
		goto number;
	case 'd':
	case 'D':
	case 'u':		/* what a joke */
		b = 10;
		goto number;
	case 'o':
	case 'O':
		b = 8;
number:
		printn((long) *adx, b);
		break;
	case 'c':
		b = *adx;


		for (i = 24; i >= 0; i -= 8)
			if (c = (b >> i) & 0x7f)
				putchar(c);
		break;

	case 's':
#ifdef LARGEMODEL
		off = *adx;
		adx++;
		seg = *adx;
		adx++;
		s = (char far *) MAKESADDR(seg, off);
#else
		s = (char *) *adx;
#endif
		while (c = *s++)
			putchar(c);
		break;
	}
	adx++;
	goto loop;
}


/*
 * Printn prints a number n in base b.
 * We don't use recursion to avoid deep kernel stacks.
 */
printn(n, b)
	long            n;
	int             b;
{
	register char  *cptr, c;
	char            cbuf[35];


	ltoa(n, cbuf, b);
	cptr = cbuf;
	while ((c = *cptr++) != 0)
		putchar(c);


}


char           *
rbgets(buf)
	char           *buf;
{
	register char  *lp;
	register        c;

	lp = buf;
	for (;;)
	{
		c = getchar() & 0177;
store:
		switch (c)
		{
		case '\n':
		case '\r':
			c = '\n';	/* treat both as newline */
			*lp++ = '\0';
			return (buf);
		case '\b':
			putchar(' ');
			putchar('\b');
			break;
		default:
			*lp++ = c;
			putchar(c);
		}
	}

}
