(Linux-3.2.2)arch/x86/boot/printf.c

/* -*- linux-c -*-------------------------------------------------------- *

 *

 *  Copyright (C) 1991, 1992 Linus Torvalds

 *  Copyright 2007 rPath, Inc. - All Rights Reserved

 *

 *   Thisfile is part of the Linux kernel, and is made available under

 *   theterms of the GNU General Public License version 2.

 *

 *----------------------------------------------------------------------- */

 

/*

 *Oh, it's a waste of space, but oh-so-yummy for debugging.  This

 *version of printf() does not include 64-bit support.  "Live with

 *it."

 *

 */

 

#include "boot.h"

 

static int skip_atoi(const char **s)

{

         inti = 0;

 

         while(isdigit(**s))

                   i= i * 10 + *((*s)++) - '0';

         returni;

}

 

#define ZEROPAD    1                /* pad withzero */

#define SIGN    2                /*unsigned/signed long */

#define PLUS    4                /* showplus */

#define SPACE 8                /* space ifplus */

#define LEFT    16              /* leftjustified */

#define SMALL          32              /*Must be 32 == 0x20 */

#define SPECIAL       64              /* 0x */

 

#define __do_div(n, base) ({ \

int __res; \

__res = ((unsigned long) n) % (unsigned)base; \

n = ((unsigned long) n) / (unsigned) base;\

__res; })

 

static char *number(char *str, long num,int base, int size, int precision,

                       int type)

{

         /*we are called with base 8, 10 or 16, only, thus don't need"G..."  */

         staticconst char digits[16] = "0123456789ABCDEF"; /*"GHIJKLMNOPQRSTUVWXYZ"; */

 

         chartmp[66];

         charc, sign, locase;

         inti;

 

         /*locase = 0 or 0x20. ORing digits or letters with 'locase'

          * produces same digits or (maybe lowercased)letters */

         locase= (type & SMALL);

         if(type & LEFT)

                   type&= ~ZEROPAD;

         if(base < 2 || base > 36)

                   returnNULL;

         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;

                   elseif (base == 8)

                            size--;

         }

         i= 0;

         if(num == 0)

                   tmp[i++]= '0';

         else

                   while(num != 0)

                            tmp[i++]= (digits[__do_div(num, base)] | locase);

         if(i > precision)

                   precision= i;

         size-= precision;

         if(!(type & (ZEROPAD + LEFT)))

                   while(size-- > 0)

                            *str++= ' ';

         if(sign)

                   *str++= sign;

         if(type & SPECIAL) {

                   if(base == 8)

                            *str++= '0';

                   elseif (base == 16) {

                            *str++= '0';

                            *str++= ('X' | locase);

                   }

         }

         if(!(type & LEFT))

                   while(size-- > 0)

                            *str++= c;

         while(i < precision--)

                   *str++= '0';

         while(i-- > 0)

                   *str++= tmp[i];

         while(size-- > 0)

                   *str++= ' ';

         returnstr;

}

 

int vsprintf(char *buf, const char *fmt,va_list args)

{

         intlen;

         unsignedlong num;

         inti, base;

         char*str;

         constchar *s;

 

         intflags;            /* flags to number() */

 

         intfield_width;         /* width of outputfield */

         intprecision;             /* min. # of digitsfor integers; max

                                        number of chars for from string */

         intqualifier;               /* 'h', 'l', or'L' for integer fields */

 

         for(str = buf; *fmt; ++fmt) {

                   if(*fmt != '%') {

                            *str++= *fmt;

                            continue;

                   }

 

                   /*process flags */

                   flags= 0;

               repeat:

                   ++fmt;               /* this also skips first '%' */

                   switch(*fmt) {

                   case'-':

                            flags|= LEFT;

                            gotorepeat;

                   case'+':

                            flags|= PLUS;

                            gotorepeat;

                   case' ':

                            flags|= SPACE;

                            gotorepeat;

                   case'#':

                            flags|= SPECIAL;

                            gotorepeat;

                   case'0':

                            flags|= ZEROPAD;

                            gotorepeat;

                   }

 

                   /*get field width */

                   field_width= -1;

                   if(isdigit(*fmt))

                            field_width= skip_atoi(&fmt);

                   elseif (*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);

                            elseif (*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') {

                            qualifier= *fmt;

                            ++fmt;

                   }

 

                   /*default base */

                   base= 10;

 

                   switch(*fmt) {

                   case'c':

                            if(!(flags & LEFT))

                                     while(--field_width > 0)

                                               *str++= ' ';

                            *str++= (unsigned char)va_arg(args, int);

                            while(--field_width > 0)

                                     *str++= ' ';

                            continue;

 

                   case's':

                            s= va_arg(args, char *);

                            len= strnlen(s, precision);

 

                            if(!(flags & LEFT))

                                     while(len < field_width--)

                                               *str++= ' ';

                            for(i = 0; i < len; ++i)

                                     *str++= *s++;

                            while(len < field_width--)

                                     *str++= ' ';

                            continue;

 

                   case'p':

                            if(field_width == -1) {

                                     field_width= 2 * sizeof(void *);

                                     flags|= ZEROPAD;

                            }

                            str= number(str,

                                          (unsigned long)va_arg(args, void *), 16,

                                          field_width, precision, flags);

                            continue;

 

                   case'n':

                            if(qualifier == 'l') {

                                     long*ip = va_arg(args, long *);

                                     *ip= (str - buf);

                            }else {

                                     int*ip = va_arg(args, int *);

                                     *ip= (str - buf);

                            }

                            continue;

 

                   case'%':

                            *str++= '%';

                            continue;

 

                            /*integer number formats - set up the flags and "break" */

                   case'o':

                            base= 8;

                            break;

 

                   case'x':

                            flags|= SMALL;

                   case'X':

                            base= 16;

                            break;

 

                   case'd':

                   case'i':

                            flags|= SIGN;

                   case'u':

                            break;

 

                   default:

                            *str++= '%';

                            if(*fmt)

                                     *str++= *fmt;

                            else

                                     --fmt;

                            continue;

                   }

                   if(qualifier == 'l')

                            num= va_arg(args, unsigned long);

                   elseif (qualifier == 'h') {

                            num= (unsigned short)va_arg(args, int);

                            if(flags & SIGN)

                                     num= (short)num;

                   }else if (flags & SIGN)

                            num= va_arg(args, int);

                   else

                            num= va_arg(args, unsigned int);

                   str= number(str, num, base, field_width, precision, flags);

         }

         *str= '\0';

         returnstr - buf;

}

 

int sprintf(char *buf, const char *fmt,...)

{

         va_listargs;

         inti;

 

         va_start(args,fmt);

         i= vsprintf(buf, fmt, args);

         va_end(args);

         returni;

}

 

int printf(const char *fmt, ...)

{

         charprintf_buf[1024];

         va_listargs;

         intprinted;

 

         va_start(args,fmt);

         printed= vsprintf(printf_buf, fmt, args);

         va_end(args);

 

         puts(printf_buf);

 

         returnprinted;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值