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

📄 vprintf.c

📁 eCos1.31版
💻 C
字号:
//==========================================================================////      vprintf.c////      Stripped down (no floating point) for debugging printf in ROMable BSP.////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    // Contributors: gthomas// Date:         1999-10-20// Purpose:      // Description:  //               ////####DESCRIPTIONEND####////=========================================================================/* * Copyright (c) 1990, 1999 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * Stripped down (no floating point) for debugging printf in ROMable BSP. */#include <string.h>#include <stdarg.h>#define	BUF		40#ifndef NULL#define NULL ((void *)0)#endif/* * Macros for converting digits to letters and vice versa */#define	to_digit(c)	((c) - '0')#define is_digit(c)	((unsigned)to_digit(c) <= 9)#define	to_char(n)	((n) + '0')/* * Flags used during conversion. */#define	ALT		0x001		/* alternate form */#define	HEXPREFIX	0x002		/* add 0x or 0X prefix */#define	LADJUST		0x004		/* left adjustment */#define	LONGDBL		0x008		/* long double; unimplemented */#define	LONGINT		0x010		/* long integer */#define	QUADINT		0x020		/* quad integer */#define	SHORTINT	0x040		/* short integer */#define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */#define FPT		0x100		/* Floating point number */void__vprintf(void (*putc_func)(char c), const char *fmt0, va_list ap){    char *fmt;		/* format string */    int ch;		/* character from fmt */    int n, m;		/* handy integers (short term usage) */    char *cp;		/* handy char pointer (short term usage) */    int flags;		/* flags as above */    int width;			/* width from format (%8d), or 0 */    int prec;			/* precision from format (%.3d), or -1 */    char sign;			/* sign prefix (' ', '+', '-', or \0) */    unsigned long _uquad;    enum {OCT, DEC, HEX} base;  /* base for [diouxX] conversion */    int dprec;			/* a copy of prec if [diouxX], 0 otherwise */    int realsz;			/* field size expanded by dprec */    int size;			/* size of converted field or string */    char *xdigs = NULL;		/* digits for [xX] conversion */    char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */    char ox[2];			/* space for 0x hex-prefix */#define	PRINT(ptr, len) {         \        for(n=0;n<(len);n++) {    \	  if((ptr)[n] == '\n')    \            (*putc_func)('\r');   \	  (*putc_func)((ptr)[n]); \	} \}#define	PAD(howmany, with) {        \	if ((n = (howmany)) > 0) {  \	    while (n--)             \		(*putc_func)(with); \	} \}    /*     * To extend shorts properly, we need both signed and unsigned     * argument extraction methods.     */#define	SARG() \        (flags&LONGINT ? va_arg(ap, long) : \	    flags&SHORTINT ? (long)(short)va_arg(ap, int) : \	    (long)va_arg(ap, int))#define	UARG() \	(flags&LONGINT ? va_arg(ap, unsigned long) : \	    flags&SHORTINT ? (unsigned long)(unsigned short)va_arg(ap, int) : \	    (unsigned long)va_arg(ap, unsigned int))    fmt = (char *)fmt0;    /*     * Scan the format for conversions (`%' character).     */    for (;;) {	cp = fmt;	while (*fmt && *fmt != '%')	    fmt++;	if ((m = fmt - cp) != 0) {	    PRINT(cp, m);	}	if (*fmt)	    fmt++;		/* skip over '%' */	else	    goto done;	flags = 0;	dprec = 0;	width = 0;	prec = -1;	sign = '\0';    rflag:	ch = *fmt++;    reswitch:	switch (ch) {	  case ' ':	    /*	     * ``If the space and + flags both appear, the space	     * flag will be ignored.''	     *	-- ANSI X3J11	     */	    if (!sign)		sign = ' ';	    goto rflag;	  case '#':	    flags |= ALT;	    goto rflag;	  case '*':	    /*	     * ``A negative field width argument is taken as a	     * - flag followed by a positive field width.''	     *	-- ANSI X3J11	     * They don't exclude field widths read from args.	     */	    if ((width = va_arg(ap, int)) >= 0)		goto rflag;	    width = -width;	    /* FALLTHROUGH */	  case '-':	    flags |= LADJUST;	    goto rflag;	  case '+':	    sign = '+';	    goto rflag;	  case '.':	    if ((ch = *fmt++) == '*') {		n = va_arg(ap, int);		prec = n < 0 ? -1 : n;		goto rflag;	    }	    n = 0;	    while (is_digit(ch)) {		n = 10 * n + to_digit(ch);		ch = *fmt++;	    }	    prec = n < 0 ? -1 : n;	    goto reswitch;	  case '0':	    /*	     * ``Note that 0 is taken as a flag, not as the	     * beginning of a field width.''	     *	-- ANSI X3J11	     */	    flags |= ZEROPAD;	    goto rflag;	  case '1': case '2': case '3': case '4':	  case '5': case '6': case '7': case '8': case '9':	    n = 0;	    do {		n = 10 * n + to_digit(ch);		ch = *fmt++;	    } while (is_digit(ch));	    width = n;	    goto reswitch;	  case 'h':	    flags |= SHORTINT;	    goto rflag;	  case 'l':	    if (*fmt == 'l') {		fmt++;		flags |= QUADINT;	    } else {		flags |= LONGINT;	    }	    goto rflag;	  case 'c':	    *(cp = buf) = va_arg(ap, int);	    size = 1;	    sign = '\0';	    break;	  case 'd':	  case 'i':	    _uquad = SARG();	    if ((long) _uquad < 0)		{		    _uquad = -_uquad;		    sign = '-';		}	    base = DEC;	    goto number;	  case 'o':	    _uquad = UARG();	    base = OCT;	    goto nosign;	  case 's':	    if ((cp = va_arg(ap, char *)) == NULL)		cp = "(null)";	    if (prec >= 0) {		/*		 * can't use strlen; can only look for the		 * NUL in the first `prec' characters, and		 * strlen() will go further.		 */		char *p = memchr(cp, 0, prec);		if (p != NULL) {		    size = p - cp;		    if (size > prec)			size = prec;		} else		    size = prec;	    } else		size = strlen(cp);	    sign = '\0';	    break;	  case 'u':	    _uquad = UARG();	    base = DEC;	    goto nosign;	  case 'X':	    xdigs = "0123456789ABCDEF";	    goto hex;	  case 'x':	    xdigs = "0123456789abcdef";	hex:			_uquad = UARG();	    base = HEX;	    /* leading 0x/X only if non-zero */	    if (flags & ALT && _uquad != 0)		flags |= HEXPREFIX;	    /* unsigned conversions */	nosign:			sign = '\0';	    /*	     * ``... diouXx conversions ... if a precision is	     * specified, the 0 flag will be ignored.''	     *	-- ANSI X3J11	     */	number:			if ((dprec = prec) >= 0)	    flags &= ~ZEROPAD;	    /*	     * ``The result of converting a zero value with an	     * explicit precision of zero is no characters.''	     *	-- ANSI X3J11	     */	    cp = buf + BUF;	    if (_uquad != 0 || prec != 0) {		/*		 * Unsigned mod is hard, and unsigned mod		 * by a constant is easier than that by		 * a variable; hence this switch.		  */		switch (base) {		  case OCT:		    do {			*--cp = to_char(_uquad & 7);			_uquad >>= 3;		    } while (_uquad);		    /* handle octal leading 0 */		    if (flags & ALT && *cp != '0')			*--cp = '0';		    break;		  case DEC:		    /* many numbers are 1 digit */		    while (_uquad >= 10) {			*--cp = to_char(_uquad % 10);			_uquad /= 10;		    }		    *--cp = to_char(_uquad);		    break;		  case HEX:		    do {			*--cp = xdigs[_uquad & 15];			_uquad >>= 4;		    } while (_uquad);		    break;		  default:		    cp = "bug in vfprintf: bad base";		    size = strlen(cp);		    goto skipsize;		}	    }	    size = buf + BUF - cp;	skipsize:	    break;	  default:	/* "%?" prints ?, unless ? is NUL */	    if (ch == '\0')		goto done;	    /* pretend it was %c with argument ch */	    cp = buf;	    *cp = ch;	    size = 1;	    sign = '\0';	    break;	}	/*	 * All reasonable formats wind up here.  At this point, `cp'	 * points to a string which (if not flags&LADJUST) should be	 * padded out to `width' places.  If flags&ZEROPAD, it should	 * first be prefixed by any sign or other prefix; otherwise,	 * it should be blank padded before the prefix is emitted.	 * After any left-hand padding and prefixing, emit zeroes	 * required by a decimal [diouxX] precision, then print the	 * string proper, then emit zeroes required by any leftover	 * floating precision; finally, if LADJUST, pad with blanks.	 *	 * Compute actual size, so we know how much to pad.	 * size excludes decimal prec; realsz includes it.	 */	realsz = dprec > size ? dprec : size;	if (sign)	    realsz++;	else if (flags & HEXPREFIX)	    realsz+= 2;	/* right-adjusting blank padding */	if ((flags & (LADJUST|ZEROPAD)) == 0)	    PAD(width - realsz, ' ');	/* prefix */	if (sign) {	    PRINT(&sign, 1);	} else if (flags & HEXPREFIX) {	    ox[0] = '0';	    ox[1] = ch;	    PRINT(ox, 2);	}	/* right-adjusting zero padding */	if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)	    PAD(width - realsz, '0');	/* leading zeroes from decimal precision */	PAD(dprec - size, '0');	/* the string or number proper */	PRINT(cp, size);	/* left-adjusting padding (always blank) */	if (flags & LADJUST)	    PAD(width - realsz, ' ');    } done:}

⌨️ 快捷键说明

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