vsprintf.c

Go to the documentation of this file.
00001 /*****************************************************************************************
00002  Copyright (c) 2002 The UbixOS Project
00003  All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are
00006 permitted provided that the following conditions are met:
00007 
00008 Redistributions of source code must retain the above copyright notice, this list of
00009 conditions, the following disclaimer and the list of authors.  Redistributions in binary
00010 form must reproduce the above copyright notice, this list of conditions, the following
00011 disclaimer and the list of authors in the documentation and/or other materials provided
00012 with the distribution. Neither the name of the UbixOS Project nor the names of its
00013 contributors may be used to endorse or promote products derived from this software
00014 without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00017 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00019 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00021 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00023 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 
00026  $Log: vsprintf_8c-source.html,v $
00026  Revision 1.7  2006/12/15 17:47:08  reddawg
00026  Updates
00026 
00027  Revision 1.1.1.1  2006/06/01 12:46:16  reddawg
00028  ubix2
00029 
00030  Revision 1.2  2005/10/12 00:13:37  reddawg
00031  Removed
00032 
00033  Revision 1.1.1.1  2005/09/26 17:24:14  reddawg
00034  no message
00035 
00036  Revision 1.2  2004/06/28 23:12:58  reddawg
00037  file format now container:/path/to/file
00038 
00039  Revision 1.1.1.1  2004/04/15 12:07:11  reddawg
00040  UbixOS v1.0
00041 
00042  Revision 1.3  2004/04/13 16:36:33  reddawg
00043  Changed our copyright, it is all now under a BSD-Style license
00044 
00045 
00046 
00047  $Id: vsprintf_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
00048 
00049 *****************************************************************************************/
00050 
00051 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
00052 /*
00053  * Wirzenius wrote this portably, Torvalds fucked it up :-)
00054  */
00055 
00056 #include <stdarg.h>
00057 #include <lib/string.h>
00058 
00059 /* we use this so that we can do without the ctype library */
00060 #define is_digit(c)     ((c) >= '0' && (c) <= '9')
00061 
00062 static int skip_atoi(const char **s)
00063 {
00064         int i=0;
00065 
00066         while (is_digit(**s))
00067                 i = i*10 + *((*s)++) - '0';
00068         return i;
00069 }
00070 
00071 #define ZEROPAD 1               /* pad with zero */
00072 #define SIGN    2               /* unsigned/signed long */
00073 #define PLUS    4               /* show plus */
00074 #define SPACE   8               /* space if plus */
00075 #define LEFT    16              /* left justified */
00076 #define SPECIAL 32              /* 0x */
00077 #define SMALL   64              /* use 'abcdef' instead of 'ABCDEF' */
00078 
00079 #define do_div(n,base) ({ \
00080 int __res; \
00081 __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
00082 __res; })
00083 
00084 static char * number(char * str, int num, int base, int size, int precision
00085         ,int type)
00086 {
00087         char c,sign,tmp[36];
00088         const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
00089         int i;
00090 
00091         if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
00092         if (type&LEFT) type &= ~ZEROPAD;
00093         if (base<2 || base>36)
00094                 return 0;
00095         c = (type & ZEROPAD) ? '0' : ' ' ;
00096         if (type&SIGN && num<0) {
00097                 sign='-';
00098                 num = -num;
00099         } else
00100                 sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
00101         if (sign) size--;
00102         if (type&SPECIAL) {
00103           if (base==16) { size -= 2; }
00104                 else if (base==8) { size--; }
00105           }
00106         i=0;
00107         if (num==0)
00108                 tmp[i++]='0';
00109         else while (num!=0)
00110                 tmp[i++]=digits[do_div(num,base)];
00111         if (i>precision) precision=i;
00112         size -= precision;
00113         if (!(type&(ZEROPAD+LEFT)))
00114                 while(size-->0)
00115                         *str++ = ' ';
00116         if (sign)
00117                 *str++ = sign;
00118         if (type&SPECIAL) {
00119           if (base==8) {
00120             *str++ = '0';
00121             }
00122           else if (base==16) {
00123                 *str++ = '0';
00124                 *str++ = digits[33];
00125                 }
00126           }
00127         if (!(type&LEFT))
00128                 while(size-->0)
00129                         *str++ = c;
00130         while(i<precision--)
00131                 *str++ = '0';
00132         while(i-->0)
00133                 *str++ = tmp[i];
00134         while(size-->0)
00135                 *str++ = ' ';
00136         return str;
00137 }
00138 
00139 int vsprintf(char *buf, const char *fmt, vaList args)
00140 {
00141         int len;
00142         int i;
00143         char * str;
00144         char *s;
00145         int *ip;
00146 
00147         int flags;              /* flags to number() */
00148 
00149         int field_width;        /* width of output field */
00150         int precision;          /* min. # of digits for integers; max
00151                                    number of chars for from string */
00152         int qualifier;          /* 'h', 'l', or 'L' for integer fields */
00153 
00154         for (str=buf ; *fmt ; ++fmt) {
00155                 if (*fmt != '%') {
00156                         *str++ = *fmt;
00157                         continue;
00158                 }
00159                         
00160                 /* process flags */
00161                 flags = 0;
00162                 repeat:
00163                         ++fmt;          /* this also skips first '%' */
00164                         switch (*fmt) {
00165                                 case '-': flags |= LEFT; goto repeat;
00166                                 case '+': flags |= PLUS; goto repeat;
00167                                 case ' ': flags |= SPACE; goto repeat;
00168                                 case '#': flags |= SPECIAL; goto repeat;
00169                                 case '0': flags |= ZEROPAD; goto repeat;
00170                                 }
00171                 
00172                 /* get field width */
00173                 field_width = -1;
00174                 if (is_digit(*fmt))
00175                         field_width = skip_atoi(&fmt);
00176                 else if (*fmt == '*') {
00177                         /* it's the next argument */
00178                         field_width = vaArg(args, int);
00179                         if (field_width < 0) {
00180                                 field_width = -field_width;
00181                                 flags |= LEFT;
00182                         }
00183                 }
00184 
00185                 /* get the precision */
00186                 precision = -1;
00187                 if (*fmt == '.') {
00188                         ++fmt;  
00189                         if (is_digit(*fmt))
00190                                 precision = skip_atoi(&fmt);
00191                         else if (*fmt == '*') {
00192                                 /* it's the next argument */
00193                                 precision = vaArg(args, int);
00194                         }
00195                         if (precision < 0)
00196                                 precision = 0;
00197                 }
00198 
00199                 /* get the conversion qualifier */
00200                 qualifier = -1;
00201                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
00202                         qualifier = *fmt;
00203                         ++fmt;
00204                 }
00205 
00206                 switch (*fmt) {
00207                 case 'c':
00208                         if (!(flags & LEFT))
00209                                 while (--field_width > 0)
00210                                         *str++ = ' ';
00211                         *str++ = (unsigned char) vaArg(args, int);
00212                         while (--field_width > 0)
00213                                 *str++ = ' ';
00214                         break;
00215 
00216                 case 's':
00217                         s = vaArg(args, char *);
00218                         len = strlen(s);
00219                         if (precision < 0)
00220                                 precision = len;
00221                         else if (len > precision)
00222                                 len = precision;
00223 
00224                         if (!(flags & LEFT))
00225                                 while (len < field_width--)
00226                                         *str++ = ' ';
00227                         for (i = 0; i < len; ++i)
00228                                 *str++ = *s++;
00229                         while (len < field_width--)
00230                                 *str++ = ' ';
00231                         break;
00232 
00233                 case 'o':
00234                         str = number(str, vaArg(args, unsigned long), 8,
00235                                 field_width, precision, flags);
00236                         break;
00237 
00238                 case 'p':
00239                         if (field_width == -1) {
00240                                 field_width = 8;
00241                                 flags |= ZEROPAD;
00242                         }
00243                         str = number(str,
00244                                 (unsigned long) vaArg(args, void *), 16,
00245                                 field_width, precision, flags);
00246                         break;
00247 
00248                 case 'x':
00249                         flags |= SMALL;
00250                 case 'X':
00251                         str = number(str, vaArg(args, unsigned long), 16,
00252                                 field_width, precision, flags);
00253                         break;
00254 
00255                 case 'd':
00256                 case 'i':
00257                         flags |= SIGN;
00258                 case 'u':
00259                         str = number(str, vaArg(args, unsigned long), 10,
00260                                 field_width, precision, flags);
00261                         break;
00262 
00263                 case 'n':
00264                         ip = vaArg(args, int *);
00265                         *ip = (str - buf);
00266                         break;
00267 
00268                 default:
00269                         if (*fmt != '%')
00270                                 *str++ = '%';
00271                         if (*fmt)
00272                                 *str++ = *fmt;
00273                         else
00274                                 --fmt;
00275                         break;
00276                 }
00277         }
00278         *str = '\0';
00279         return str-buf;
00280 }
00281 
00282 /***
00283  END
00284  ***/
00285 

Generated on Fri Dec 15 11:18:55 2006 for UbixOS V2 by  doxygen 1.4.7