⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printfmt.c~

📁 jos lab3代码
💻 C~
字号:
// Stripped-down primitive printf-style formatting routines,// used in common by printf, sprintf, fprintf, etc.// This code is also used by both the kernel and user programs.#include <inc/types.h>#include <inc/stdio.h>#include <inc/string.h>#include <inc/stdarg.h>#include <inc/error.h>/* * Space or zero padding and a field width are supported for the numeric * formats only.  *  * The special format %e takes an integer error code * and prints a string describing the error. * The integer may be positive or negative, * so that -E_NO_MEM and E_NO_MEM are equivalent. */static const char * const error_string[MAXERROR + 1] ={	NULL,	"unspecified error",	"bad environment",	"invalid parameter",	"out of memory",	"out of environments",	"segmentation fault",};/* * Print a number (base <= 16) in reverse order, * using specified putch function and associated pointer putdat. */static voidprintnum(void (*putch)(int, void*), void *putdat,	 unsigned long long num, unsigned base, int width, int padc){	// first recursively print all preceding (more significant) digits	if (num >= base) {		printnum(putch, putdat, num / base, base, width - 1, padc);	} else {		// print any needed pad characters before first digit		while (--width > 0)			putch(padc, putdat);	}	// then print this (the least significant) digit	putch("0123456789abcdef"[num % base], putdat);}// Get an unsigned int of various possible sizes from a varargs list,// depending on the lflag parameter.static unsigned long longgetuint(va_list *ap, int lflag){	if (lflag >= 2)		return va_arg(*ap, unsigned long long);	else if (lflag)		return va_arg(*ap, unsigned long);	else		return va_arg(*ap, unsigned int);}// Same as getuint but signed - can't use getuint// because of sign extensionstatic long longgetint(va_list *ap, int lflag){	if (lflag >= 2)		return va_arg(*ap, long long);	else if (lflag)		return va_arg(*ap, long);	else		return va_arg(*ap, int);}// Main function to format and print a string.void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...);voidvprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap){	register const char *p;	register int ch, err;	unsigned long long num;	int base, lflag, width, precision, altflag;	char padc;	while (1) {		while ((ch = *(unsigned char *) fmt++) != '%') {			if (ch == '\0')				return;			putch(ch, putdat);		}		// Process a %-escape sequence		padc = ' ';		width = -1;		precision = -1;		lflag = 0;		altflag = 0;	reswitch:		switch (ch = *(unsigned char *) fmt++) {		// flag to pad on the right		case '-':			padc = '-';			goto reswitch;					// flag to pad with 0's instead of spaces		case '0':			padc = '0';			goto reswitch;		// width field		case '1':		case '2':		case '3':		case '4':		case '5':		case '6':		case '7':		case '8':		case '9':			for (precision = 0; ; ++fmt) {				precision = precision * 10 + ch - '0';				ch = *fmt;				if (ch < '0' || ch > '9')					break;			}			goto process_precision;		case '*':			precision = va_arg(ap, int);			goto process_precision;		case '.':			if (width < 0)				width = 0;			goto reswitch;		case '#':			altflag = 1;			goto reswitch;		process_precision:			if (width < 0)				width = precision, precision = -1;			goto reswitch;		// long flag (doubled for long long)		case 'l':			lflag++;			goto reswitch;		// character		case 'c':			putch(va_arg(ap, int), putdat);			break;		// error message		case 'e':			err = va_arg(ap, int);			if (err < 0)				err = -err;			if (err > MAXERROR || (p = error_string[err]) == NULL)				printfmt(putch, putdat, "error %d", err);			else				printfmt(putch, putdat, "%s", p);			break;		// string		case 's':			if ((p = va_arg(ap, char *)) == NULL)				p = "(null)";			if (width > 0 && padc != '-')				for (width -= strnlen(p, precision); width > 0; width--)					putch(padc, putdat);			for (; (ch = *p++) != '\0' && (precision < 0 || --precision >= 0); width--)				if (altflag && (ch < ' ' || ch > '~'))					putch('?', putdat);				else					putch(ch, putdat);			for (; width > 0; width--)				putch(' ', putdat);			break;		// (signed) decimal		case 'd':			num = getint(&ap, lflag);			if ((long long) num < 0) {				putch('-', putdat);				num = -(long long) num;			}			base = 10;			goto number;		// unsigned decimal		case 'u':			num = getuint(&ap, lflag);			base = 10;			goto number;		// (unsigned) octal		case 'o':			// Replace this with your code.			putch('X', putdat);			putch('X', putdat);			putch('X', putdat);			break;		// pointer		case 'p':			putch('0', putdat);			putch('x', putdat);			num = (unsigned long long)				(uintptr_t) va_arg(ap, void *);			base = 16;			goto number;		// (unsigned) hexadecimal		case 'x':			num = getuint(&ap, lflag);			base = 16;		number:			printnum(putch, putdat, num, base, width, padc);			break;		// escaped '%' character		case '%':			putch(ch, putdat);			break;					// unrecognized escape sequence - just print it literally		default:			putch('%', putdat);			for (fmt--; fmt[-1] != '%'; fmt--)				/* do nothing */;			break;		}	}}voidprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...){	va_list ap;	va_start(ap, fmt);	vprintfmt(putch, putdat, fmt, ap);	va_end(ap);}struct sprintbuf {	char *buf;	char *ebuf;	int cnt;};static voidsprintputch(int ch, struct sprintbuf *b){	b->cnt++;	if (b->buf < b->ebuf)		*b->buf++ = ch;}intvsnprintf(char *buf, int n, const char *fmt, va_list ap){	struct sprintbuf b = {buf, buf+n-1, 0};	if (buf == NULL || n < 1)		return -E_INVAL;	// print the string to the buffer	vprintfmt((void*)sprintputch, &b, fmt, ap);	// null terminate the buffer	*b.buf = '\0';	return b.cnt;}intsnprintf(char *buf, int n, const char *fmt, ...){	va_list ap;	int rc;	va_start(ap, fmt);	rc = vsnprintf(buf, n, fmt, ap);	va_end(ap);	return rc;}

⌨️ 快捷键说明

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