Ignore:
Timestamp:
2007-10-04T15:00:19Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f7fad5a
Parents:
18525c5
Message:

Fix a bug in interpretation of precision when printing strings. Fix cstyle.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/io/printf_core.c

    r18525c5 r1c38445  
    7777 * @return number of printed characters
    7878 */
    79 static int printf_putnchars(const char * buf, size_t count, struct printf_spec *ps)
     79static int printf_putnchars(const char * buf, size_t count,
     80    struct printf_spec *ps)
    8081{
    8182        return ps->write((void *)buf, count, ps->data);
     
    125126       
    126127        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    127                 while (--width > 0) {   /* one space is consumed by character itself hence predecrement */
     128                /*
     129                 * One space is consumed by the character itself, hence the
     130                 * predecrement.
     131                 */
     132                while (--width > 0) {
    128133                        if (printf_putchar(' ', ps) > 0)       
    129134                                ++counter;
     
    133138        if (printf_putchar(c, ps) > 0)
    134139                counter++;
    135        
    136         while (--width > 0) { /* one space is consumed by character itself hence predecrement */
     140        /*
     141         * One space is consumed by the character itself, hence the
     142         * predecrement.
     143         */
     144        while (--width > 0) {
    137145                if (printf_putchar(' ', ps) > 0)
    138146                        ++counter;
     
    149157 * @return number of printed characters
    150158 */
    151                                                
    152 static int print_string(char *s, int width, int precision, uint64_t flags, struct printf_spec *ps)
     159static int print_string(char *s, int width, int precision, uint64_t flags,
     160    struct printf_spec *ps)
    153161{
    154162        int counter = 0;
     
    176184        }
    177185
    178         while (precision > size) {
    179                 precision--;
    180                 if (printf_putchar(' ', ps) == 1)       
    181                         ++counter;
    182         }
    183        
    184         if ((retval = printf_putnchars(s, precision, ps)) < 0) {
     186        if ((retval = printf_putnchars(s, size < precision ? size : precision,
     187            ps)) < 0) {
    185188                return -counter;
    186189        }
     
    211214 *
    212215 */
    213 static int print_number(uint64_t num, int width, int precision, int base , uint64_t flags, struct printf_spec *ps)
     216static int print_number(uint64_t num, int width, int precision, int base,
     217    uint64_t flags, struct printf_spec *ps)
    214218{
    215219        char *digits = digits_small;
    216         char d[PRINT_NUMBER_BUFFER_SIZE];       /* this is good enough even for base == 2, prefix and sign */
     220        char d[PRINT_NUMBER_BUFFER_SIZE];       /* this is good enough even for
     221                                                 * base == 2, prefix and sign */
    217222        char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
    218223        int size = 0; /* size of number with all prefixes and signs */
     
    239244        number_size = size;
    240245
    241         /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */
     246        /*
     247         * Collect sum of all prefixes/signs/... to calculate padding and
     248         * leading zeroes
     249         */
    242250        if (flags & __PRINTF_FLAG_PREFIX) {
    243251                switch(base) {
     
    260268                        size++;
    261269                } else if (flags & __PRINTF_FLAG_SHOWPLUS) {
    262                                 sgn = '+';
    263                                 size++;
    264                         } else if (flags & __PRINTF_FLAG_SPACESIGN) {
    265                                         sgn = ' ';
    266                                         size++;
    267                                 }
     270                        sgn = '+';
     271                        size++;
     272                } else if (flags & __PRINTF_FLAG_SPACESIGN) {
     273                        sgn = ' ';
     274                        size++;
     275                }
    268276        }
    269277
     
    272280        }
    273281
    274         /* if number is leftaligned or precision is specified then zeropadding is ignored */
     282        /*
     283         * If number is leftaligned or precision is specified then zeropadding
     284         * is ignored.
     285         */
    275286        if (flags & __PRINTF_FLAG_ZEROPADDED) {
    276287                if ((precision == 0) && (width > size)) {
     
    280291
    281292        /* print leading spaces */
    282         if (number_size > precision) /* We must print whole number not only a part */
     293
     294        /* We must print whole number not only a part. */
     295        if (number_size > precision)
    283296                precision = number_size;
    284297
     
    358371/** Print formatted string.
    359372 *
    360  * Print string formatted according to the fmt parameter
    361  * and variadic arguments. Each formatting directive
    362  * must have the following form:
     373 * Print string formatted according to the fmt parameter and variadic arguments.
     374 * Each formatting directive must have the following form:
    363375 *
    364376 *      \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION
     
    366378 * FLAGS:@n
    367379 *      - "#" Force to print prefix.
    368  *      For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and 0X
    369  *      and for conversion \%b the prefix is 0b.
     380 *      For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and
     381 *      0X and for conversion \%b the prefix is 0b.
    370382 *
    371383 *      - "-"   Align to left.
     
    373385 *      - "+"   Print positive sign just as negative.
    374386 *
    375  *      - " "   If the printed number is positive and "+" flag is not set, print space in
    376  *      place of sign.
    377  *
    378  *      - "0"   Print 0 as padding instead of spaces. Zeroes are placed between sign and the
    379  *      rest of the number. This flag is ignored if "-" flag is specified.
     387 *      - " "   If the printed number is positive and "+" flag is not set,
     388 *              print space in place of sign.
     389 *
     390 *      - "0"   Print 0 as padding instead of spaces. Zeroes are placed between
     391 *              sign and the rest of the number. This flag is ignored if "-"
     392 *              flag is specified.
    380393 *
    381394 * WIDTH:@n
    382  *      - Specify minimal width of printed argument. If it is bigger, width is ignored.
    383  * If width is specified with a "*" character instead of number, width is taken from
    384  * parameter list. And integer parameter is expected before parameter for processed
    385  * conversion specification. If this value is negative its absolute value is taken
    386  * and the "-" flag is set.
     395 *      - Specify minimal width of printed argument. If it is bigger, width is
     396 *        ignored. If width is specified with a "*" character instead of number,
     397 *        width is taken from parameter list. And integer parameter is expected
     398 *        before parameter for processed conversion specification. If this value
     399 *        is negative its absolute value is taken and the "-" flag is set.
    387400 *
    388401 * PRECISION:@n
    389402 *      - Value precision. For numbers it specifies minimum valid numbers.
    390  * Smaller numbers are printed with leading zeroes. Bigger numbers are not affected.
    391  * Strings with more than precision characters are cut off.
    392  * Just as with width, an "*" can be used used instead of a number.
    393  * An integer value is then expected in parameters. When both width and precision
    394  * are specified using "*", the first parameter is used for width and the second one
    395  * for precision.
     403 *        Smaller numbers are printed with leading zeroes. Bigger numbers are
     404 *        not affected. Strings with more than precision characters are cut off.
     405 *        Just as with width, an "*" can be used used instead of a number. An
     406 *        integer value is then expected in parameters. When both width and
     407 *        precision are specified using "*", the first parameter is used for
     408 *        width and the second one for precision.
    396409 *
    397410 * TYPE:@n
     
    409422 *      - c     Print single character.
    410423 *
    411  *      - s     Print zero terminated string. If a NULL value is passed as value, "(NULL)" is printed instead.
     424 *      - s     Print zero terminated string. If a NULL value is passed as
     425 *              value, "(NULL)" is printed instead.
    412426 *
    413  *      - P, p  Print value of a pointer. Void * value is expected and it is printed in hexadecimal notation with prefix
    414  *      (as with '\%#X' or '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers).
    415  *
    416  *      - b     Print value as unsigned binary number. Prefix is not printed by default. (Nonstandard extension.)
     427 *      - P, p  Print value of a pointer. Void * value is expected and it is
     428 *              printed in hexadecimal notation with prefix (as with '\%#X' or
     429 *              '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers).
     430 *
     431 *      - b     Print value as unsigned binary number. Prefix is not printed by
     432 *              default. (Nonstandard extension.)
    417433 *
    418  *      - o     Print value as unsigned octal number. Prefix is not printed by default.
    419  *
    420  *      - d,i   Print signed decimal number. There is no difference between d and i conversion.
     434 *      - o     Print value as unsigned octal number. Prefix is not printed by
     435 *              default.
     436 *
     437 *      - d, i  Print signed decimal number. There is no difference between d
     438 *              and i conversion.
    421439 *
    422440 *      - u     Print unsigned decimal number.
    423441 *
    424  *      - X, x  Print hexadecimal number with upper- or lower-case. Prefix is not printed by default.
     442 *      - X, x  Print hexadecimal number with upper- or lower-case. Prefix is
     443 *              not printed by default.
    425444 *
    426  * All other characters from fmt except the formatting directives
    427  * are printed in verbatim.
     445 * All other characters from fmt except the formatting directives are printed in
     446 * verbatim.
    428447 *
    429448 * @param fmt Formatting NULL terminated string.
     
    432451int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
    433452{
    434         int i = 0, j = 0; /* i is index of currently processed char from fmt, j is index to the first not printed nonformating character */
     453        /* i is the index of the currently processed char from fmt */
     454        int i = 0;
     455        /* j is the index to the first not printed nonformating character */
     456        int j = 0;
     457
    435458        int end;
    436         int counter; /* counter of printed characters */
    437         int retval; /* used to store return values from called functions */
     459        int counter;    /* counter of printed characters */
     460        int retval;     /* used to store return values from called functions */
    438461        char c;
    439462        qualifier_t qualifier;  /* type of argument */
    440         int base;       /* base in which will be parameter (numbers only) printed */
     463        int base;       /* base in which will be a numeric parameter printed */
    441464        uint64_t number; /* argument value */
    442         size_t  size; /* byte size of integer parameter */
     465        size_t  size;   /* byte size of integer parameter */
    443466        int width, precision;
    444467        uint64_t flags;
     
    451474                        /* print common characters if any processed */ 
    452475                        if (i > j) {
    453                                 if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) < 0) { /* error */
     476                                if ((retval = printf_putnchars(&fmt[j],
     477                                    (size_t)(i - j), ps)) < 0) { /* error */
    454478                                        goto minus_out;
    455479                                }
     
    465489                                ++i;
    466490                                switch (c = fmt[i]) {
    467                                 case '#': flags |= __PRINTF_FLAG_PREFIX; break;
    468                                 case '-': flags |= __PRINTF_FLAG_LEFTALIGNED; break;
    469                                 case '+': flags |= __PRINTF_FLAG_SHOWPLUS; break;
    470                                 case ' ': flags |= __PRINTF_FLAG_SPACESIGN; break;
    471                                 case '0': flags |= __PRINTF_FLAG_ZEROPADDED; break;
    472                                 default: end = 1;
     491                                case '#':
     492                                        flags |= __PRINTF_FLAG_PREFIX;
     493                                        break;
     494                                case '-':
     495                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     496                                        break;
     497                                case '+':
     498                                        flags |= __PRINTF_FLAG_SHOWPLUS;
     499                                        break;
     500                                case ' ':
     501                                        flags |= __PRINTF_FLAG_SPACESIGN;
     502                                        break;
     503                                case '0':
     504                                        flags |= __PRINTF_FLAG_ZEROPADDED;
     505                                        break;
     506                                default:
     507                                        end = 1;
    473508                                };     
    474509                               
     
    487522                                width = (int)va_arg(ap, int);
    488523                                if (width < 0) {
    489                                         /* negative width means to set '-' flag */
     524                                        /* negative width sets '-' flag */
    490525                                        width *= -1;
    491526                                        flags |= __PRINTF_FLAG_LEFTALIGNED;
     
    503538                                        }
    504539                                } else if (fmt[i] == '*') {
    505                                         /* get precision value from argument list*/
     540                                        /* get precision value from argument */
    506541                                        i++;
    507542                                        precision = (int)va_arg(ap, int);
    508543                                        if (precision < 0) {
    509                                                 /* negative precision means to ignore it */
     544                                                /* negative precision ignored */
    510545                                                precision = 0;
    511546                                        }
     
    514549
    515550                        switch (fmt[i++]) {
    516                         /** TODO: unimplemented qualifiers:
     551                        /** @todo unimplemented qualifiers:
    517552                         * t ptrdiff_t - ISO C 99
    518553                         */
     
    535570                                break;
    536571                        default:
    537                                 qualifier = PrintfQualifierInt; /* default type */
     572                                /* set default type */
     573                                qualifier = PrintfQualifierInt;
    538574                                --i;
    539575                        }       
     
    543579                        switch (c = fmt[i]) {
    544580
    545                                 /*
    546                                 * String and character conversions.
    547                                 */
     581                        /*
     582                         * String and character conversions.
     583                         */
    548584                        case 's':
    549                                 if ((retval = print_string(va_arg(ap, char*), width, precision, flags, ps)) < 0) {
     585                                if ((retval = print_string(va_arg(ap, char*),
     586                                    width, precision, flags, ps)) < 0) {
    550587                                        goto minus_out;
    551588                                }
     
    556593                        case 'c':
    557594                                c = va_arg(ap, unsigned int);
    558                                 if ((retval = print_char(c, width, flags, ps)) < 0) {
     595                                retval = print_char(c, width, flags, ps);
     596                                if (retval < 0) {
    559597                                        goto minus_out;
    560598                                }
     
    566604                        /*
    567605                         * Integer values
    568                         */
     606                         */
    569607                        case 'P': /* pointer */
    570608                                flags |= __PRINTF_FLAG_BIGCHARS;
     
    595633                                goto next_char;
    596634                        /*
    597                         * Bad formatting.
    598                         */
     635                         * Bad formatting.
     636                         */
    599637                        default:
    600                                 /* Unknown format
    601                                  *  now, the j is index of '%' so we will
    602                                  * print whole bad format sequence
     638                                /*
     639                                 * Unknown format. Now, j is the index of '%',
     640                                 * so we will print the whole bad format
     641                                 * sequence.
    603642                                 */
    604643                                goto next_char;         
     
    606645               
    607646               
    608                 /* Print integers */
    609                         /* print number */
     647                        /* Print integers */
    610648                        switch (qualifier) {
    611649                        case PrintfQualifierByte:
     
    627665                        case PrintfQualifierLongLong:
    628666                                size = sizeof(unsigned long long);
    629                                 number = (uint64_t)va_arg(ap, unsigned long long);
     667                                number = (uint64_t)va_arg(ap,
     668                                    unsigned long long);
    630669                                break;
    631670                        case PrintfQualifierPointer:
    632671                                size = sizeof(void *);
    633                                 number = (uint64_t)(unsigned long)va_arg(ap, void *);
     672                                number = (uint64_t)(unsigned long)va_arg(ap,
     673                                    void *);
    634674                                break;
    635675                        case PrintfQualifierSizeT:
     
    643683                       
    644684                        if (flags & __PRINTF_FLAG_SIGNED) {
    645                                 if (number & (0x1 << (size*8 - 1))) {
     685                                if (number & (0x1 << (size * 8 - 1))) {
    646686                                        flags |= __PRINTF_FLAG_NEGATIVE;
    647687                               
     
    650690                                        } else {
    651691                                                number = ~number;
    652                                                 number &= (~((0xFFFFFFFFFFFFFFFFll) <<  (size * 8)));
     692                                                number &=
     693                                                    ~(0xFFFFFFFFFFFFFFFFll <<
     694                                                    (size * 8));
    653695                                                number++;
    654696                                        }
     
    656698                        }
    657699
    658                         if ((retval = print_number(number, width, precision, base, flags, ps)) < 0 ) {
     700                        if ((retval = print_number(number, width, precision,
     701                            base, flags, ps)) < 0 ) {
    659702                                goto minus_out;
    660                         };
     703                        }
    661704
    662705                        counter += retval;
     
    669712       
    670713        if (i > j) {
    671                 if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) < 0) { /* error */
     714                retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps);
     715                if (retval < 0) { /* error */
    672716                        goto minus_out;
    673717                }
Note: See TracChangeset for help on using the changeset viewer.