printf.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 794 行 · 第 1/2 页

C
794
字号
/*  **************************************************************************** * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge **************************************************************************** * *        File: printf.c *      Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) *     Changes: Grzegorz Milos (gm281@cam.ac.uk)  *               *        Date: Aug 2003, Aug 2005 *  * Environment: Xen Minimal OS * Description: Library functions for printing *              (freebsd port, mainly sys/subr_prf.c) * **************************************************************************** * *- * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This software was developed by the Computer Systems Engineering group * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and * contributed to Berkeley. * * 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. * * $FreeBSD: src/sys/libkern/divdi3.c,v 1.6 1999/08/28 00:46:31 peter Exp $ */#if !defined HAVE_LIBC#include <os.h>#include <types.h>#include <hypervisor.h>#include <lib.h>#include <mm.h>#include <ctype.h>#include <limits.h>/** * simple_strtoul - convert a string to an unsigned long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base){    unsigned long result = 0,value;    if (!base) {        base = 10;        if (*cp == '0') {            base = 8;            cp++;            if ((*cp == 'x') && isxdigit(cp[1])) {                cp++;                base = 16;            }        }    }    while (isxdigit(*cp) &&           (value = isdigit(*cp) ? *cp-'0' : toupper(*cp)-'A'+10) < base) {        result = result*base + value;        cp++;    }    if (endp)        *endp = (char *)cp;    return result;}/** * simple_strtol - convert a string to a signed long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */long simple_strtol(const char *cp,char **endp,unsigned int base){    if(*cp=='-')        return -simple_strtoul(cp+1,endp,base);    return simple_strtoul(cp,endp,base);}/** * simple_strtoull - convert a string to an unsigned long long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */unsigned long long simple_strtoull(const char *cp,char **endp,unsigned int base){    unsigned long long result = 0,value;    if (!base) {        base = 10;        if (*cp == '0') {            base = 8;            cp++;            if ((*cp == 'x') && isxdigit(cp[1])) {                cp++;                base = 16;            }        }    }    while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)                                                               ? toupper(*cp) : *cp)-'A'+10) < base) {        result = result*base + value;        cp++;    }    if (endp)        *endp = (char *)cp;    return result;}/** * simple_strtoll - convert a string to a signed long long * @cp: The start of the string * @endp: A pointer to the end of the parsed string will be placed here * @base: The number base to use */long long simple_strtoll(const char *cp,char **endp,unsigned int base){    if(*cp=='-')        return -simple_strtoull(cp+1,endp,base);    return simple_strtoull(cp,endp,base);}static int skip_atoi(const char **s){    int i=0;    while (isdigit(**s))        i = i*10 + *((*s)++) - '0';    return i;}#define ZEROPAD 1               /* pad with zero */#define SIGN    2               /* unsigned/signed long */#define PLUS    4               /* show plus */#define SPACE   8               /* space if plus */#define LEFT    16              /* left justified */#define SPECIAL 32              /* 0x */#define LARGE   64              /* use 'ABCDEF' instead of 'abcdef' */static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type){    char c,sign,tmp[66];    const char *digits;    const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";    const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";    int i;    digits = (type & LARGE) ? large_digits : small_digits;    if (type & LEFT)        type &= ~ZEROPAD;    if (base < 2 || base > 36)        return buf;    c = (type & ZEROPAD) ? '0' : ' ';    sign = 0;    if (type & SIGN) {        if (num < 0) {            sign = '-';            num = -num;            size--;        } else if (type & PLUS) {            sign = '+';            size--;        } else if (type & SPACE) {            sign = ' ';            size--;        }    }    if (type & SPECIAL) {        if (base == 16)            size -= 2;        else if (base == 8)            size--;    }    i = 0;    if (num == 0)        tmp[i++]='0';    else     {        /* XXX KAF: force unsigned mod and div. */        unsigned long long num2=(unsigned long long)num;        unsigned int base2=(unsigned int)base;        while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; }    }    if (i > precision)        precision = i;    size -= precision;    if (!(type&(ZEROPAD+LEFT))) {        while(size-->0) {            if (buf <= end)                *buf = ' ';            ++buf;        }    }    if (sign) {        if (buf <= end)            *buf = sign;        ++buf;    }    if (type & SPECIAL) {        if (base==8) {            if (buf <= end)                *buf = '0';            ++buf;        } else if (base==16) {            if (buf <= end)                *buf = '0';            ++buf;            if (buf <= end)                *buf = digits[33];            ++buf;        }    }    if (!(type & LEFT)) {        while (size-- > 0) {            if (buf <= end)                *buf = c;            ++buf;        }    }    while (i < precision--) {        if (buf <= end)            *buf = '0';        ++buf;    }    while (i-- > 0) {        if (buf <= end)            *buf = tmp[i];        ++buf;    }    while (size-- > 0) {        if (buf <= end)            *buf = ' ';        ++buf;    }    return buf;}/*** vsnprintf - Format a string and place it in a buffer* @buf: The buffer to place the result into* @size: The size of the buffer, including the trailing null space* @fmt: The format string to use* @args: Arguments for the format string** Call this function if you are already dealing with a va_list.* You probably want snprintf instead. */int vsnprintf(char *buf, size_t size, const char *fmt, va_list args){    int len;    unsigned long long num;    int i, base;    char *str, *end, c;    const char *s;    int flags;          /* flags to number() */    int field_width;    /* width of output field */    int precision;              /* min. # of digits for integers; max                                   number of chars for from string */    int qualifier;              /* 'h', 'l', or 'L' for integer fields */                                /* 'z' support added 23/7/1999 S.H.    */                                /* 'z' changed to 'Z' --davidm 1/25/99 */    str = buf;    end = buf + size - 1;    if (end < buf - 1) {        end = ((void *) -1);        size = end - buf + 1;    }    for (; *fmt ; ++fmt) {        if (*fmt != '%') {            if (str <= end)                *str = *fmt;            ++str;            continue;        }        /* process flags */        flags = 0;    repeat:        ++fmt;          /* this also skips first '%' */        switch (*fmt) {        case '-': flags |= LEFT; goto repeat;        case '+': flags |= PLUS; goto repeat;        case ' ': flags |= SPACE; goto repeat;        case '#': flags |= SPECIAL; goto repeat;        case '0': flags |= ZEROPAD; goto repeat;        }        /* get field width */        field_width = -1;        if (isdigit(*fmt))            field_width = skip_atoi(&fmt);        else if (*fmt == '*') {            ++fmt;            /* it's the next argument */            field_width = va_arg(args, int);            if (field_width < 0) {                field_width = -field_width;                flags |= LEFT;            }        }        /* get the precision */        precision = -1;        if (*fmt == '.') {            ++fmt;            if (isdigit(*fmt))                precision = skip_atoi(&fmt);            else if (*fmt == '*') {                ++fmt;                          /* it's the next argument */                precision = va_arg(args, int);            }            if (precision < 0)                precision = 0;        }        /* get the conversion qualifier */        qualifier = -1;        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {            qualifier = *fmt;            ++fmt;            if (qualifier == 'l' && *fmt == 'l') {                qualifier = 'L';                ++fmt;            }        }        if (*fmt == 'q') {            qualifier = 'L';            ++fmt;        }        /* default base */        base = 10;        switch (*fmt) {        case 'c':            if (!(flags & LEFT)) {                while (--field_width > 0) {                    if (str <= end)                        *str = ' ';                    ++str;                }            }            c = (unsigned char) va_arg(args, int);            if (str <= end)                *str = c;            ++str;            while (--field_width > 0) {                if (str <= end)                    *str = ' ';                ++str;            }            continue;        case 's':            s = va_arg(args, char *);            if (!s)                s = "<NULL>";            len = strnlen(s, precision);

⌨️ 快捷键说明

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