Show
Ignore:
Timestamp:
10/03/08 12:25:17 (3 months ago)
Author:
mwhitworth
Message:

Add vasprintf function, rework vsprintf into vsnprintf. remove the unsafe sprintf function.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • Whitix/branches/keobject/lib/vsprintf.c

    r973 r1066  
    2222#include <string.h> 
    2323#include <typedefs.h> 
     24#include <types.h> 
    2425 
    2526#define SIGN 1 
     
    3233 
    3334#define is_digit(c) ((c) >= '0' && (c) <= '9') 
     35 
    3436#define do_div(n,base) ({ \ 
    35 int __res; \ 
    36 __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \ 
    37 __res; }) 
     37        unsigned long __upper, __low, __high, __mod, __base; \ 
     38        __base = (base); \ 
     39        asm("":"=a" (__low), "=d" (__high):"A" (n)); \ 
     40        __upper = __high; \ 
     41        if (__high) { \ 
     42                __upper = __high % (__base); \ 
     43                __high = __high / (__base); \ 
     44        } \ 
     45        asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \ 
     46        asm("":"=A" (n):"a" (__low),"d" (__high)); \ 
     47        __mod; \ 
     48}) 
    3849 
    3950int skip_atoi(const char** s) 
     
    4556} 
    4657 
    47 char* number(char* str,int num,int base,int size,int precision,int type) 
     58char* number(char* str, char* end, unsigned long long num,int base,int size,int precision,int type) 
    4859{ 
    4960        char c,sign,tmp[36]; 
     
    5364        if (type & SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz"; 
    5465        if (type & LEFT) type &= ~ZEROPAD; 
     66         
    5567        if (base < 2 || base > 36) 
    5668                return NULL; 
     69                 
    5770        c=(type & ZEROPAD) ? '0' : ' '; 
    58         if (type & SIGN && num < 0) 
     71         
     72        if (type & SIGN && (signed long long)num < 0) 
    5973        { 
    6074                sign='-'; 
    61                 num=-num; 
     75                num=- (signed long long)num; 
    6276        }else 
    6377                sign=(type & PLUS) ? '+' : ((type & SPACE) ? ' ' : 0); 
    64         if (sign) size--; 
     78                 
     79        if (sign) 
     80                size--; 
     81         
    6582        if (type & SPECIAL) 
    6683        { 
     
    7693        } 
    7794 
    78         if (i>precision) precision=i; 
     95        if (i>precision) 
     96                precision=i; 
     97                 
    7998        size-=precision; 
     99         
    80100        if (!(type & (ZEROPAD+LEFT))) 
    81101                while (size-- > 0) 
    82                         *str++=' '; 
     102                { 
     103                        if (str < end) 
     104                                *str = ' '; 
     105                        str++; 
     106                } 
    83107                         
    84108        if (sign) 
    85                 *str++=sign; 
    86          
    87         if (type & SPECIAL) 
     109        { 
     110                if (str < end) 
     111                        *str = sign; 
     112                 
     113                str++; 
     114        } 
     115         
     116        if (type & SPECIAL && str < end) 
    88117        { 
    89118                if (base == 8) 
    90                         *str++='0'; 
    91                 else if (base == 16) 
    92                 { 
    93                         *str++='0'; 
    94                         *str++=digits[33]; 
     119                { 
     120                        if (str < end) 
     121                                *str = '0'; 
     122                        str++; 
     123                }else if (base == 16) 
     124                { 
     125                        if (str < end) 
     126                                *str='0'; 
     127                        str++; 
     128                         
     129                        if (str < end) 
     130                                *str = digits[33]; 
     131                                 
     132                        str++; 
    95133                } 
    96134        } 
     
    98136        if (!(type & LEFT)) 
    99137                while (size-- > 0) 
    100                         *str++=c; 
     138                { 
     139                        if (str < end) 
     140                                *str = c; 
     141                        str++; 
     142                } 
    101143                         
    102144        while (i < precision--) 
    103                 *str++='0'; 
     145        { 
     146                if (str < end) 
     147                        *str='0'; 
     148                         
     149                str++; 
     150        } 
     151         
    104152        while (i-- > 0) 
    105                 *str++=tmp[i]; 
     153        { 
     154                if (str < end) 
     155                        *str = tmp[i]; 
     156                 
     157                str++; 
     158        } 
     159         
    106160        while (size-- > 0) 
    107                 *str++=' '; 
     161        { 
     162                if (str < end) 
     163                        *str = ' '; 
     164                         
     165                str++; 
     166        } 
     167                 
    108168        return str; 
    109169} 
    110170 
    111 int vsprintf(char* buf,const char* fmt,va_list args) 
     171int vsnprintf(char* buf, int size, const char* fmt, VaList args) 
    112172{ 
    113173        char* str=buf; 
     174        char* end; 
    114175        int fieldWidth,precision,qualifier,flags; 
     176 
     177        end = buf+size; 
     178         
     179        if (end < buf) 
     180        { 
     181                end = ((void*)-1); 
     182                size = end - buf; 
     183        } 
    115184 
    116185        for (; *fmt; fmt++) 
     
    121190                if (LIKELY(*fmt != '%')) 
    122191                { 
    123                         *str++=*fmt; 
     192                        if (str < end) 
     193                                *str = *fmt; 
     194                                 
     195                        str++; 
    124196                        continue; 
    125197                } 
     
    141213                else if (*fmt == '*') 
    142214                { 
    143                         fieldWidth=va_arg(args,int); 
     215                        fieldWidth=VaArg(args, int); 
    144216                        if (fieldWidth < 0) 
    145217                        { 
     
    156228                        else if (*fmt == '*') 
    157229                        { 
    158                                 precision=va_arg(args,int); 
     230                                precision=VaArg(args,int); 
    159231                        } 
    160232                        if (precision < 0) 
     
    174246                        if (!(flags & LEFT)) 
    175247                                while (--fieldWidth > 0) 
    176                                         *str++=' '; 
    177                         *str++=(unsigned char)va_arg(args,int); 
     248                                { 
     249                                        if (str < end) 
     250                                                *str=' '; 
     251                                                 
     252                                        ++str; 
     253                                } 
     254                                 
     255                        if (str < end) 
     256                                *str=(unsigned char)VaArg(args,int); 
     257                                 
     258                        str++; 
     259                                 
    178260                        while (--fieldWidth > 0) 
    179                                 *str++=' ';                      
     261                        { 
     262                                if (str < end) 
     263                                        *str=' '; 
     264                                         
     265                                str++; 
     266                        }                
    180267                        break; 
    181268 
    182269                case 's': 
    183270                { 
    184                         char* s=va_arg(args,char*); 
     271                        char* s=VaArg(args,char*); 
    185272                        if (!s) 
    186273                                s="<NULL>"; 
     
    193280                        if (!(flags & LEFT)) 
    194281                                while (len < fieldWidth--) 
    195                                         *str++=' '; 
     282                                { 
     283                                        if (str < end) 
     284                                                *str=' '; 
     285                                                 
     286                                        str++; 
     287                                } 
    196288                        int i; 
    197289                        for (i=0; i<len; i++) 
    198                                 *str++=*s++; 
     290                        { 
     291                                if (str < end) 
     292                                        *str=*s; 
     293                                         
     294                                str++; 
     295                                s++; 
     296                        } 
    199297                                 
    200298                        while (len < fieldWidth--) 
    201                                 *str++=' '; 
     299                        { 
     300                                if (str < end)                   
     301                                        *str++=' '; 
     302                        } 
    202303                        break; 
    203304                } 
    204305                 
    205306                case 'o': 
    206                         str=number(str,va_arg(args,unsigned long),8,fieldWidth, 
     307                        str=number(str, end, VaArg(args,unsigned long),8,fieldWidth, 
    207308                                precision,flags); 
    208309                        break; 
     
    214315                                flags |= ZEROPAD; 
    215316                        } 
    216                         str=number(str,(unsigned long)va_arg(args,void*),16,fieldWidth, 
     317                        str=number(str, end, (unsigned long)VaArg(args,void*),16,fieldWidth, 
    217318                                precision,flags); 
    218319                        break; 
     
    221322                        flags |= SMALL; 
    222323                case 'X': 
    223                         str=number(str,va_arg(args,unsigned long),16,fieldWidth, 
     324                        str=number(str, end, VaArg(args,unsigned long),16,fieldWidth, 
    224325                                precision,flags); 
    225326                        break; 
     
    228329                        flags |= SIGN; 
    229330                case 'u': 
    230                         str=number(str,va_arg(args,unsigned long),10,fieldWidth, 
     331                        str=number(str, end, VaArg(args,unsigned long),10,fieldWidth, 
    231332                                precision,flags); 
    232333                        break; 
    233334                default: 
    234                         if (*fmt != '%') 
    235                                 *str++ = '%'; 
     335                        if (str < end) 
     336                                *str = '%'; 
     337                         
    236338                        if (*fmt) 
    237                                 *str++ = *fmt; 
    238                         else 
     339                        { 
     340                                if (str < end) 
     341                                        *str = *fmt; 
     342                                ++str; 
     343                        }else 
    239344                                --fmt; 
    240345                        break; 
    241346                } 
    242347        } 
    243         *str='\0'; 
     348         
     349        if (size > 0) 
     350        { 
     351                if (str < end) 
     352                        *str = '\0'; 
     353                else 
     354                        end[-1] = '\0'; 
     355        } 
     356         
    244357        return (str-buf); 
    245358} 
    246359 
     360SYMBOL_EXPORT(vsnprintf); 
     361 
     362int vsprintf(char* buf,const char* fmt, VaList args) 
     363{ 
     364        return vsnprintf(buf, INT_MAX, fmt, args); 
     365} 
     366 
    247367SYMBOL_EXPORT(vsprintf); 
    248368 
    249 int sprintf(char* buf,const char* fmt,...) 
    250 { 
    251         int i; 
    252         va_list args; 
    253  
    254         va_start(args,fmt); 
    255         i=vsprintf(buf,fmt,args); 
    256         va_end(args); 
    257         return i; 
    258 } 
    259  
    260 SYMBOL_EXPORT(sprintf); 
     369char* vasprintf(const char* fmt, VaList args) 
     370{ 
     371        int length; 
     372        char* ret; 
     373        VaList temp; 
     374         
     375        VaCopy(temp, args); 
     376         
     377        length = vsnprintf(NULL, 0, fmt, temp); 
     378         
     379        VaEnd(temp); 
     380         
     381        ret = (char*)MemAlloc(length + 1); 
     382         
     383        if (!ret) 
     384                return NULL; 
     385         
     386        vsnprintf(ret, length+1, fmt, args); 
     387 
     388        return ret; 
     389} 
     390 
     391SYMBOL_EXPORT(vasprintf);