Changeset c9857c6 in mainline


Ignore:
Timestamp:
2006-04-12T10:21:01Z (19 years ago)
Author:
Josef Cejka <malyzelenyhnus@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f30e6a0b
Parents:
fcd10af
Message:

Printf support for width and precision modifiers.
Several necessary helping functions added.

Location:
libc
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • libc/generic/io/io.c

    rfcd10af rc9857c6  
    3838        size_t count;
    3939       
     40        if (str == NULL) {
     41                return putnchars("(NULL)",6 );
     42        }
     43       
    4044        for (count = 0; str[count] != 0; count++);
    4145        if (write(1, (void * ) str, count) == count) {
     
    4852
    4953/** Put count chars from buffer to stdout without adding newline
    50  * @param buf Buffer with size at least count bytes
     54 * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
    5155 * @param count
    5256 * @return 0 on succes, EOF on fail
     
    8084}
    8185
     86int putchar(int c)
     87{
     88        unsigned char ch = c;
     89        if (write(1, (void *)&ch , 1) == 1) {
     90                        return c;
     91        }
     92       
     93        return EOF;
     94}
     95
    8296ssize_t write(int fd, const void * buf, size_t count)
    8397{
  • libc/generic/io/print.c

    rfcd10af rc9857c6  
    3232#include <io/io.h>
    3333#include <stdarg.h>
     34#include <ctype.h>
     35#include <string.h>
    3436
    3537#define __PRINTF_FLAG_PREFIX            0x00000001      /* show prefixes 0x or 0*/
     
    6062static char digits_big[] = "0123456789ABCDEF";  /* Big hexadecimal characters */
    6163
     64
     65/** Print one formatted character
     66 * @param c character to print
     67 * @param width
     68 * @param flags
     69 * @return number of printed characters or EOF
     70 */
     71                                               
     72static int print_char(char c, int width, uint64_t flags)
     73{
     74        int counter = 0;
     75        char space = ' ';
     76       
     77        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     78                while (--width > 0) {   /* one space is consumed by character itself hence predecrement */
     79                        /* FIXME: painful slow */
     80                        putchar(' ');   
     81                        ++counter;
     82                }
     83        }
     84       
     85        if (putchar(c) == EOF) {
     86                return EOF;
     87        }
     88
     89        while (--width > 0) { /* one space is consumed by character itself hence predecrement */
     90                putchar(' ');
     91                ++counter;
     92        }
     93       
     94        return ++counter;
     95}
     96
     97/** Print one string
     98 * @param s string
     99 * @param width
     100 * @param precision
     101 * @param flags
     102 * @return number of printed characters or EOF
     103 */
     104                                               
     105static int print_string(char *s, int width, int precision, uint64_t flags)
     106{
     107        int counter = 0;
     108        size_t size;
     109
     110        if (s == NULL) {
     111                return putstr("(NULL)");
     112        }
     113       
     114        size = strlen(s);
     115
     116        /* print leading spaces */
     117
     118        if (precision == 0)
     119                precision = size;
     120
     121        width -= precision;
     122       
     123        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     124                while (width-- > 0) {   
     125                        putchar(' ');   
     126                        counter++;
     127                }
     128        }
     129
     130        while (precision > size) {
     131                precision--;
     132                putchar(' ');   
     133                ++counter;
     134        }
     135       
     136        if (putnchars(s, precision) == EOF) {
     137                return EOF;
     138        }
     139
     140        counter += precision;
     141
     142        while (width-- > 0) {
     143                putchar(' ');   
     144                ++counter;
     145        }
     146       
     147        return ++counter;
     148}
     149
     150
    62151/** Print number in given base
    63152 *
     
    66155 *
    67156 * @param num  Number to print.
    68  * @param size not used, in future releases will be replaced with precision and width params
     157 * @param width
     158 * @param precision
    69159 * @param base Base to print the number in (should
    70160 *             be in range 2 .. 16).
     
    73163 *
    74164 */
    75 static int print_number(uint64_t num, size_t size, int base , uint64_t flags)
     165static int print_number(uint64_t num, int width, int precision, int base , uint64_t flags)
    76166{
    77         /* FIXME: This is only first version.
    78          * Printf does not have support for specification of size
    79          * and precision, so this function writes with parameters defined by
    80          * their type size.
    81          */
    82167        char *digits = digits_small;
    83168        char d[PRINT_NUMBER_BUFFER_SIZE];       /* this is good enough even for base == 2, prefix and sign */
    84169        char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
     170        int size = 0;
     171        int written = 0;
     172        char sgn;
    85173       
    86174        if (flags & __PRINTF_FLAG_BIGCHARS)
     
    91179        if (num == 0) {
    92180                *ptr-- = '0';
     181                size++;
    93182        } else {
    94183                do {
    95184                        *ptr-- = digits[num % base];
     185                        size++;
    96186                } while (num /= base);
    97187        }
    98         if (flags & __PRINTF_FLAG_PREFIX) { /*FIXME*/
     188
     189        /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */
     190        if (flags & __PRINTF_FLAG_PREFIX) {
    99191                switch(base) {
    100192                        case 2: /* Binary formating is not standard, but usefull */
    101                                 *ptr = 'b';
    102                                 if (flags & __PRINTF_FLAG_BIGCHARS) *ptr = 'B';
    103                                 ptr--;
    104                                 *ptr-- = '0';
     193                                size += 2;
    105194                                break;
    106195                        case 8:
    107                                 *ptr-- = 'o';
     196                                size++;
    108197                                break;
    109198                        case 16:
    110                                 *ptr = 'x';
    111                                 if (flags & __PRINTF_FLAG_BIGCHARS) *ptr = 'X';
    112                                 ptr--;
    113                                 *ptr-- = '0';
     199                                size += 2;
    114200                                break;
    115201                }
    116202        }
    117        
     203
     204        sgn = 0;
    118205        if (flags & __PRINTF_FLAG_SIGNED) {
    119206                if (flags & __PRINTF_FLAG_NEGATIVE) {
    120                         *ptr-- = '-';
     207                        sgn = '-';
     208                        size++;
    121209                } else if (flags & __PRINTF_FLAG_SHOWPLUS) {
    122                                 *ptr-- = '+';
     210                                sgn = '+';
     211                                size++;
    123212                        } else if (flags & __PRINTF_FLAG_SPACESIGN) {
    124                                         *ptr-- = ' ';
    125                                 }
    126         }
    127 
    128         /* Print leading zeroes */
     213                                        sgn = ' ';
     214                                        size++;
     215                                }
     216        }
    129217
    130218        if (flags & __PRINTF_FLAG_LEFTALIGNED) {
    131219                flags &= ~__PRINTF_FLAG_ZEROPADDED;
    132220        }
     221
     222        /* if number is leftaligned or precision is specified then zeropadding is ignored */
    133223        if (flags & __PRINTF_FLAG_ZEROPADDED) {
    134                 while (ptr != d ) {
    135                         *ptr-- = '0';
     224                if ((precision == 0) && (width > size)) {
     225                        precision = width - size;
    136226                }
    137227        }
    138        
    139         return putstr(++ptr);
     228
     229        /* print leading spaces */
     230        if (size > precision) /* We must print whole number not only a part */
     231                precision = size;
     232
     233        width -= precision;
     234       
     235        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
     236                while (width-- > 0) {   
     237                        putchar(' ');   
     238                        written++;
     239                }
     240        }
     241       
     242        /* print sign */
     243        if (sgn) {
     244                putchar(sgn);
     245                written++;
     246        }
     247       
     248        /* print prefix */
     249       
     250        if (flags & __PRINTF_FLAG_PREFIX) {
     251                switch(base) {
     252                        case 2: /* Binary formating is not standard, but usefull */
     253                                putchar('0');
     254                                if (flags & __PRINTF_FLAG_BIGCHARS) {
     255                                        putchar('B');
     256                                } else {
     257                                        putchar('b');
     258                                }
     259                                written == 2;
     260                                break;
     261                        case 8:
     262                                putchar('o');
     263                                written++;
     264                                break;
     265                        case 16:
     266                                putchar('0');
     267                                if (flags & __PRINTF_FLAG_BIGCHARS) {
     268                                        putchar('X');
     269                                } else {
     270                                        putchar('x');
     271                                }
     272                                written += 2;
     273                                break;
     274                }
     275        }
     276
     277        /* print leading zeroes */
     278        precision -= size;
     279        while (precision-- > 0) {       
     280                putchar('0');   
     281                written++;
     282        }
     283
     284       
     285        /* print number itself */
     286
     287        written += putstr(++ptr);
     288       
     289        /* print ending spaces */
     290       
     291        while (width-- > 0) {   
     292                putchar(' ');   
     293                written++;
     294        }
     295
     296        return written;
    140297}
    141298
     
    209366        uint64_t number; /* argument value */
    210367        size_t  size; /* byte size of integer parameter */
     368        int width, precision;
    211369        uint64_t flags;
    212370       
    213371        counter = 0;
    214372        va_start(ap, fmt);
    215 
     373       
    216374        while ((c = fmt[i])) {
    217375                /* control character */
     
    242400                               
    243401                        } while (end == 0);     
    244                         /* TODO: width & '*' operator */
    245                         /* TODO: precision and '*' operator */ 
     402                       
     403                        /* width & '*' operator */
     404                        width = 0;
     405                        if (isdigit(fmt[i])) {
     406                                while (isdigit(fmt[i])) {
     407                                        width *= 10;
     408                                        width += fmt[i++] - '0';
     409                                }
     410                        } else if (fmt[i] == '*') {
     411                                /* get width value from argument list*/
     412                                i++;
     413                                width = (int)va_arg(ap, int);
     414                                if (width < 0) {
     415                                        /* negative width means to set '-' flag */
     416                                        width *= -1;
     417                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     418                                }
     419                        }
     420                       
     421                        /* precision and '*' operator */       
     422                        precision = 0;
     423                        if (fmt[i] == '.') {
     424                                ++i;
     425                                if (isdigit(fmt[i])) {
     426                                        while (isdigit(fmt[i])) {
     427                                                precision *= 10;
     428                                                precision += fmt[i++] - '0';
     429                                        }
     430                                } else if (fmt[i] == '*') {
     431                                        /* get precision value from argument list*/
     432                                        i++;
     433                                        precision = (int)va_arg(ap, int);
     434                                        if (precision < 0) {
     435                                                /* negative precision means to ignore it */
     436                                                precision = 0;
     437                                        }
     438                                }
     439                        }
    246440
    247441                        switch (fmt[i++]) {
     442                                /** TODO: unimplemented qualifiers:
     443                                 * t ptrdiff_t - ISO C 99
     444                                 */
    248445                                case 'h':       /* char or short */
    249446                                        qualifier = PrintfQualifierShort;
     
    276473                                */
    277474                                case 's':
    278                                         if ((retval = putstr(va_arg(ap, char*))) == EOF) {
     475                                        if ((retval = print_string(va_arg(ap, char*), width, precision, flags)) == EOF) {
    279476                                                return -counter;
    280477                                        };
     
    284481                                        goto next_char;
    285482                                case 'c':
    286                                         c = va_arg(ap, unsigned long);
    287                                         if ((retval = putnchars(&c, sizeof(char))) == EOF) {
     483                                        c = va_arg(ap, unsigned int);
     484                                        if ((retval = print_char(c, width, flags )) == EOF) {
    288485                                                return -counter;
    289486                                        };
     
    385582                        }
    386583
    387                         if ((retval = print_number(number, size, base, flags)) == EOF ) {
     584                        if ((retval = print_number(number, width, precision, base, flags)) == EOF ) {
    388585                                return -counter;
    389586                        };
  • libc/generic/string.c

    rfcd10af rc9857c6  
    2727 */
    2828
    29 #include <types.h>
    3029#include <string.h>
    3130
     
    4847        return dest;
    4948}
     49
     50size_t strlen(const char *str)
     51{
     52        int counter = 0;
     53
     54        while (str[counter] != 0) {
     55                counter++;
     56        }
     57
     58        return counter;
     59}
  • libc/include/io/io.h

    rfcd10af rc9857c6  
    3434int putnchars(const char * buf, size_t count);
    3535int putstr(const char * str);
     36int putchar(int c);
    3637
    3738#endif
  • libc/include/string.h

    rfcd10af rc9857c6  
    3131#define __LIBC__STRING_H__
    3232
     33#include <types.h>
     34
    3335void * memset(void *s, int c, size_t n);
    3436void * memcpy(void *dest, void *src, size_t n);
    3537
     38size_t strlen(const char *str);
     39
    3640#endif
Note: See TracChangeset for help on using the changeset viewer.