jnand_printf.c

来自「QUALCOMM JNAND DRIVER」· C语言 代码 · 共 803 行 · 第 1/2 页

C
803
字号
#ifdef COMPILE_PRINTF

#define DISABLE_TERM
/* 
 * Mach Operating System
 * Copyright (c) 1993 Carnegie Mellon University
 * All Rights Reserved.
 * 
 * Permission to use, copy, modify and distribute this software and its
 * documentation is hereby granted, provided that both the copyright
 * notice and this permission notice appear in all copies of the
 * software, derivative works or modified versions, and any portions
 * thereof, and that both notices appear in supporting documentation.
 * 
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 * 
 * Carnegie Mellon requests users of this software to return to
 * 
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 *  School of Computer Science
 *  Carnegie Mellon University
 *  Pittsburgh PA 15213-3890
 * 
 * any improvements or extensions that they make and grant Carnegie Mellon
 * the rights to redistribute these changes.
 */
/*
 * HISTORY
 *
 * 02/06/03   pg      Moved from ASWP402 server to ASWP401 server.
 *                    Added #ifdef COMPILE_PRINTF around it.
 *
 * $Log: printf.c,v $
 * Revision 1.1  1999/01/20 18:32:11  qcdb
 * Initial checkin.
 *
 * Revision 1.1  1995/06/07 20:42:08  dbrown
 * MK83 distribution from CMU
 *
 * Revision 2.15  93/03/09  10:55:12  danner
 * 	Lint to quiet GCC.
 * 	[93/03/07  13:25:20  af]
 * 
 * 	A better, MP-safe sprintf.
 * 	[93/03/05            af]
 * 
 * Revision 2.14  93/01/27  09:34:37  danner
 * 	printf_init(), sprintf() are void.
 * 	[93/01/25            jfriedl]
 * 
 * 	Updated copyright.
 * 	[93/01/12            berman]
 * 	Wrote a version of sprintf() for general use.
 * 	[92/03/18            berman]
 * 
 * Revision 2.13  93/01/14  17:35:37  danner
 * 	64bit cleanup.  Tuned up doprnt slightly.
 * 	[92/12/01            af]
 * 
 * Revision 2.12  92/08/03  17:38:32  jfriedl
 * 	removed silly prototypes
 * 	[92/08/02            jfriedl]
 * 
 * Revision 2.11  92/05/21  17:14:57  jfriedl
 * 	Cleanup to quiet gcc warnings.
 * 	Changed PUTC arg of _doprnt, etc. to be VOID (which it is)
 * 	[92/05/16            jfriedl]
 * 
 * Revision 2.10  92/04/01  19:33:21  rpd
 * 	Renamed gets to safe_gets.
 * 	[92/03/31            rpd]
 * 
 * Revision 2.9  91/06/06  17:07:22  jsb
 * 	Added gets (derived from boot_gets).
 * 	[91/05/14  09:18:50  jsb]
 * 
 * Revision 2.8  91/05/14  16:44:59  mrt
 * 	Correcting copyright
 * 
 * Revision 2.7  91/02/05  17:28:14  mrt
 * 	Changed to new Mach copyright
 * 	[91/02/01  16:15:41  mrt]
 * 
 * Revision 2.6  90/10/25  14:45:18  rwd
 * 	Purged uprintf.
 * 	[90/10/21            rpd]
 * 
 * Revision 2.5  90/08/27  22:03:08  dbg
 * 	Add extra formats to printf: '#- ' prefixes, %z (signed hex),
 * 	%r and %n (signed and unsigned, current radix).
 * 	[90/08/20            dbg]
 * 
 * Revision 2.4  90/01/11  11:43:44  dbg
 * 	De-linted.
 * 	[90/01/03            dbg]
 * 
 * Revision 2.3  89/11/29  14:09:06  af
 * 	Ooops, a typo.
 * 	[89/10/29  09:34:26  af]
 * 
 * 	Changed the case for %c to load ints and not chars. Or
 * 	else it is byte-order dependent since C passes char as ints.
 * 	[89/10/13            af]
 * 
 * 	Turned the unused 'file descriptor' field for _doprnt and putchar
 * 	into a more useful pointer to an (optional) specialized putchar
 * 	routine.  This can be used, for instance, to divert debugging
 * 	printouts to some specialized interface or IOP.
 * 	[89/10/09            af]
 * 
 * Revision 2.2  89/09/25  11:00:58  rwd
 * 	Added case 'X' same as 'x' for now.
 * 	[89/09/20            rwd]
 * 
 * Revision 2.1  89/08/03  15:51:14  rwd
 * Created.
 * 
 *  8-Aug-88  David Golub (dbg) at Carnegie-Mellon University
 *	Converted for MACH kernel use.  Removed %r, %R, %b; added %b
 *	from Berkeley's kernel to print bit fields in device registers;
 *	changed to use varargs.
 *
 */

/*
 *  Common code for printf et al.
 *
 *  The calling routine typically takes a variable number of arguments,
 *  and passes the address of the first one.  This implementation
 *  assumes a straightforward, stack implementation, aligned to the
 *  machine's wordsize.  Increasing addresses are assumed to point to
 *  successive arguments (left-to-right), as is the case for a machine
 *  with a downward-growing stack with arguments pushed right-to-left.
 *
 *  To write, for example, fprintf() using this routine, the code
 *
 *	fprintf(fd, format, args)
 *	FILE *fd;
 *	char *format;
 *	{
 *	_doprnt(format, &args, fd);
 *	}
 *
 *  would suffice.  (This example does not handle the fprintf's "return
 *  value" correctly, but who looks at the return value of fprintf
 *  anyway?)
 *
 *  This version implements the following printf features:
 *
 *	%d	decimal conversion
 *	%u	unsigned conversion
 *	%x	hexadecimal conversion
 *	%X	hexadecimal conversion with capital letters
 *	%o	octal conversion
 *	%c	character
 *	%s	string
 *	%m.n	field width, precision
 *	%-m.n	left adjustment
 *	%0m.n	zero-padding
 *	%*.*	width and precision taken from arguments
 *
 *  This version does not implement %f, %e, or %g.  It accepts, but
 *  ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
 *  work correctly on machines for which sizeof(long) != sizeof(int).
 *  It does not even parse %D, %O, or %U; you should be using %ld, %o and
 *  %lu if you mean long conversion.
 *
 *  As mentioned, this version does not return any reasonable value.
 *
 *  Permission is granted to use, modify, or propagate this code as
 *  long as this notice is incorporated.
 *
 *  Steve Summit 3/25/87
 */

/*
 * Added formats for decoding device registers:
 *
 * printf("reg = %b", regval, "<base><arg>*")
 *
 * where <base> is the output base expressed as a control character:
 * i.e. '\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 rest (up to a control character (<= 32)) give the
 * name of the register.  Thus
 *	printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
 * would produce
 *	reg = 3<BITTWO,BITONE>
 *
 * If the second character in <arg> is also a control character, it
 * indicates the last bit of a bit field.  In this case, printf will extract
 * bits <1> to <2> and print it.  Characters following the second control
 * character are printed before the bit field.
 *	printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
 * would produce
 *	reg = b<FIELD1=2,BITONE>
 */
/*
 * Added for general use:
 *	#	prefix for alternate format:
 *		0x (0X) for hex
 *		leading 0 for octal
 *	+	print '+' if positive
 *	blank	print ' ' if positive
 *
 *	z	signed hexadecimal
 *	r	signed, 'radix'
 *	n	unsigned, 'radix'
 *
 *	D,U,O,Z	same as corresponding lower-case versions
 *		(compatibility)
 */

#include "string.h"
//#include "varargs.h"
#include "stdarg.h"

extern void term_put(char);

/* Needed CMU junk. */
typedef unsigned long vm_offset_t;
typedef int boolean_t;
#define FALSE 0
#define TRUE  1

#define isdigit(d) ((d) >= '0' && (d) <= '9')
#define Ctod(c) ((c) - '0')

#define MAXBUF (sizeof(long int) * 8)		 /* enough for binary */


void printnum(
	register unsigned long	u,
	register int		base,
	void			(*putc)( char ch, vm_offset_t fake),
	vm_offset_t		putc_arg)
{
	char	buf[MAXBUF];	/* build number here */
	register char *	p = &buf[MAXBUF-1];
	static char digs[] = "0123456789abcdef";

	do {
	    *p-- = digs[u % base];
	    u /= base;
	} while (u != 0);

	while (++p != &buf[MAXBUF])
	    (*putc)(*p, putc_arg);

}

boolean_t	_doprnt_truncates = FALSE;
#if 0
decl_simple_lock_data(,_doprnt_lock)
#endif

#if 0
void printf_init()
{
	simple_lock_init(&_doprnt_lock);
}
#endif

void _doprnt(
	register char	*fmt,
	va_list		*argp,
					/* character output routine */
 	void		(*putc)( char, vm_offset_t),
	int		radix,		/* default radix - for '%r' */
	vm_offset_t	putc_arg)
{
	int		length;
	int		prec;
	boolean_t	ladjust;
	char		padc;
	long		n;
	unsigned long	u;
	int		plus_sign;
	int		sign_char;
	boolean_t	altfmt, truncate;
	int		base;
	register char	c;

#if 0
#if 0
	/* Make sure that we get *some* printout, no matter what */
	simple_lock(&_doprnt_lock);
#else
	{
		register int i = 0;
		while (i < 1*1024*1024) {
			if (simple_lock_try(&_doprnt_lock))
				break;
			i++;
		}
	}
#endif
#endif

	while ((c = *fmt) != '\0') {
	    if (c != '%') {
		(*putc)(c, putc_arg);
		fmt++;
		continue;
	    }

	    fmt++;

	    length = 0;
	    prec = -1;
	    ladjust = FALSE;
	    padc = ' ';
	    plus_sign = 0;
	    sign_char = 0;
	    altfmt = FALSE;

	    while (TRUE) {
		c = *fmt;
		if (c == '#') {
		    altfmt = TRUE;
		}
		else if (c == '-') {
		    ladjust = TRUE;
		}
		else if (c == '+') {
		    plus_sign = '+';
		}
		else if (c == ' ') {
		    if (plus_sign == 0)
			plus_sign = ' ';
		}
		else
		    break;
		fmt++;
	    }

	    if (c == '0') {
		padc = '0';
		c = *++fmt;
	    }

	    if (isdigit(c)) {
		while(isdigit(c)) {
		    length = 10 * length + Ctod(c);
		    c = *++fmt;
		}
	    }
	    else if (c == '*') {
		length = va_arg(*argp, int);
		c = *++fmt;
		if (length < 0) {
		    ladjust = !ladjust;
		    length = -length;
		}
	    }

	    if (c == '.') {
		c = *++fmt;
		if (isdigit(c)) {
		    prec = 0;
		    while(isdigit(c)) {
			prec = 10 * prec + Ctod(c);
			c = *++fmt;
		    }
		}
		else if (c == '*') {
		    prec = va_arg(*argp, int);
		    c = *++fmt;
		}
	    }

	    if (c == 'l')
		c = *++fmt;	/* need it if sizeof(int) < sizeof(long) */

	    truncate = FALSE;

	    switch(c) {
		case 'b':
		case 'B':
		{
		    register char *p;
		    boolean_t	  any;
		    register int  i;

		    u = va_arg(*argp, unsigned long);
		    p = va_arg(*argp, char *);
		    base = *p++;
		    printnum(u, base, putc, putc_arg);

		    if (u == 0)
			break;

		    any = FALSE;
		    while ((i = *p++) != 0) {
			/* NOTE: The '32' here is because ascii space */
			if (*p <= 32) {
			    /*
			     * Bit field
			     */
			    register int j;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?