Changeset e499a30 in mainline


Ignore:
Timestamp:
2006-05-02T11:25:22Z (19 years ago)
Author:
Josef Cejka <malyzelenyhnus@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6445baf
Parents:
7dd1787
Message:

All the *printf functions ported to kernel.
Comments updated.
Printf1 test uses snprintf to test printing to a string.

Files:
7 added
3 edited
1 moved

Legend:

Unmodified
Added
Removed
  • Makefile

    r7dd1787 re499a30  
    134134        generic/src/lib/sort.c \
    135135        generic/src/lib/elf.c \
    136         generic/src/debug/print.c \
     136        generic/src/debug/printf_core.c \
     137        generic/src/debug/printf.c \
     138        generic/src/debug/sprintf.c \
     139        generic/src/debug/snprintf.c \
     140        generic/src/debug/vprintf.c \
     141        generic/src/debug/vsprintf.c \
     142        generic/src/debug/vsnprintf.c \
    137143        generic/src/debug/symtab.c \
    138144        generic/src/time/clock.c \
  • generic/include/print.h

    r7dd1787 re499a30  
    3232#include <arch/types.h>
    3333#include <synch/spinlock.h>
    34 
    35 #define INT8    1
    36 #define INT16   2
    37 #define INT32   4
    38 #define INT64   8
    39 
    40 extern int printf(const char *fmt, ...);
     34#include <arch/arg.h>
    4135
    4236/* We need this address in spinlock to avoid deadlock in deadlock detection */
     
    4539#define EOF (-1)
    4640
     41extern int puts(const char * str);
     42
     43extern int printf(const char *fmt, ...);
     44extern int sprintf(char *str, const char *fmt, ...);
     45extern int snprintf(char *str, size_t size, const char *fmt, ...);
     46
     47extern int vprintf(const char *fmt, va_list ap);
     48extern int vsprintf(char *str, const char *fmt, va_list ap);
     49extern int vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
     50
    4751#endif
  • generic/src/debug/printf_core.c

    r7dd1787 re499a30  
    3333 */
    3434
     35#include <printf/printf_core.h>
    3536#include <putchar.h>
    3637#include <print.h>
     
    4344SPINLOCK_INITIALIZE(printflock);                        /**< printf spinlock */
    4445
    45 #define __PRINTF_FLAG_PREFIX            0x00000001      /* show prefixes 0x or 0 */
    46 #define __PRINTF_FLAG_SIGNED            0x00000002      /* signed / unsigned number */
    47 #define __PRINTF_FLAG_ZEROPADDED        0x00000004      /* print leading zeroes */
    48 #define __PRINTF_FLAG_LEFTALIGNED       0x00000010      /* align to left */
    49 #define __PRINTF_FLAG_SHOWPLUS          0x00000020      /* always show + sign */
    50 #define __PRINTF_FLAG_SPACESIGN         0x00000040      /* print space instead of plus */
    51 #define __PRINTF_FLAG_BIGCHARS          0x00000080      /* show big characters */
    52 #define __PRINTF_FLAG_NEGATIVE          0x00000100      /* number has - sign */
    53 
    54 #define PRINT_NUMBER_BUFFER_SIZE        (64+5)          /* Buffer big enought for 64 bit number
     46#define __PRINTF_FLAG_PREFIX            0x00000001      /**< show prefixes 0x or 0*/
     47#define __PRINTF_FLAG_SIGNED            0x00000002      /**< signed / unsigned number */
     48#define __PRINTF_FLAG_ZEROPADDED        0x00000004      /**< print leading zeroes */
     49#define __PRINTF_FLAG_LEFTALIGNED       0x00000010      /**< align to left */
     50#define __PRINTF_FLAG_SHOWPLUS          0x00000020      /**< always show + sign */
     51#define __PRINTF_FLAG_SPACESIGN         0x00000040      /**< print space instead of plus */
     52#define __PRINTF_FLAG_BIGCHARS          0x00000080      /**< show big characters */
     53#define __PRINTF_FLAG_NEGATIVE          0x00000100      /**< number has - sign */
     54
     55#define PRINT_NUMBER_BUFFER_SIZE        (64+5)          /**< Buffer big enought for 64 bit number
    5556                                                         * printed in base 2, sign, prefix and
    5657                                                         * 0 to terminate string.. (last one is only for better testing
    57                                                          * end of buffer by zero-filling subroutine)
    58                                                          */
     58                                                         * end of buffer by zero-filling subroutine)*/
     59
     60/** Enumeration of possible arguments types.
     61 */
    5962typedef enum {
    6063        PrintfQualifierByte = 0,
     
    6770} qualifier_t;
    6871
    69 static char digits_small[] = "0123456789abcdef";        /* Small hexadecimal characters */
    70 static char digits_big[] = "0123456789ABCDEF";          /* Big hexadecimal characters */
    71 
     72static char digits_small[] = "0123456789abcdef";        /**< Small hexadecimal characters */
     73static char digits_big[] = "0123456789ABCDEF";  /**< Big hexadecimal characters */
     74
     75/** Checks c for a digit.
     76 * @param c One character.
     77 * @return nonzero if c is from interval '0 to '9'.
     78 */
    7279static inline int isdigit(int c)
    7380{
     
    7582}
    7683
     84/** Compute length of given zero terminated string.
     85 * @param str Pointer to valid string.
     86 * @return string length without trailing zero.
     87 */
    7788static __native strlen(const char *str)
    7889{
     
    8697}
    8798
    88 /** Print one string without appending newline to the end.
    89  *
    90  * Do not use this function directly - printflock is not locked here.
    91  *
    92  */
    93 static int putstr(const char *str)
    94 {
    95         int count;
     99/** Print count chars from buffer without adding newline
     100 * @param buf Buffer with size at least count bytes - NULL pointer NOT allowed!
     101 * @param count
     102 * @param ps output method and its data
     103 * @return 0 on success, EOF on fail
     104 */
     105static int printf_putnchars(const char * buf, size_t count, struct printf_spec *ps)
     106{
     107        if (ps->write((void *)buf, count, ps->data) == count) {
     108                return 0;
     109        }
     110       
     111        return EOF;
     112}
     113
     114/** Print string without added newline
     115 * @param str string to print
     116 * @param ps write function specification and support data
     117 * @return 0 on success or EOF on fail
     118 */
     119static int printf_putstr(const char * str, struct printf_spec *ps)
     120{
     121        size_t count;
     122       
    96123        if (str == NULL) {
    97                 str = "(NULL)";
    98         }
    99        
    100         for (count = 0; str[count] != 0; count++) {
    101                 putchar(str[count]);
    102         }
    103         return count;
    104 }
    105 
    106 /** Print count characters from buffer to output.
    107  *
    108  * @param buffer Address of the buffer with charaters to be printed.
    109  * @param count Number of characters to be printed.
    110  *
    111  * @return Number of characters printed.
    112  */
    113 static int putnchars(const char *buffer, __native count)
    114 {
    115         int i;
    116         if (buffer == NULL) {
    117                 buffer = "(NULL)";
    118                 count = 6;
    119         }
    120 
    121         for (i = 0; i < count; i++) {
    122                 putchar(buffer[i]);
    123         }
    124        
    125         return count;
     124                return printf_putnchars("(NULL)", 6, ps);
     125        }
     126
     127        count = strlen(str);
     128
     129        if (ps->write((void *) str, count, ps->data) == count) {
     130                return 0;
     131        }
     132       
     133        return EOF;
     134}
     135
     136/** Print one character to output
     137 * @param c one character
     138 * @param ps output method
     139 * @return printed character or EOF
     140 */
     141static int printf_putchar(int c, struct printf_spec *ps)
     142{
     143        unsigned char ch = c;
     144       
     145        if (ps->write((void *) &ch, 1, ps->data) == 1) {
     146                return c;
     147        }
     148       
     149        return EOF;
    126150}
    127151
    128152/** Print one formatted character
    129  *
    130  * @param c Character to print.
     153 * @param c character to print
    131154 * @param width
    132155 * @param flags
    133  * @return Number of printed characters or EOF.
    134  */
    135 static int print_char(char c, int width, __u64 flags)
     156 * @return number of printed characters or EOF
     157 */
     158static int print_char(char c, int width, __u64 flags, struct printf_spec *ps)
    136159{
    137160        int counter = 0;
    138161       
    139162        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    140                 while (--width > 0) {   /* one space is consumed by character itself hence the predecrement */
    141                         /* FIXME: painfully slow */
    142                         putchar(' ');   
     163                while (--width > 0) {   /* one space is consumed by character itself hence predecrement */
     164                        /* FIXME: painful slow */
     165                        printf_putchar(' ', ps);       
    143166                        ++counter;
    144167                }
    145168        }
    146169       
    147         putchar(c);
    148         ++counter;
    149 
    150         while (--width > 0) { /* one space is consumed by character itself hence the predecrement */
    151                 putchar(' ');
     170        if (printf_putchar(c, ps) == EOF) {
     171                return EOF;
     172        }
     173
     174        while (--width > 0) { /* one space is consumed by character itself hence predecrement */
     175                printf_putchar(' ', ps);
    152176                ++counter;
    153177        }
    154178       
    155         return counter;
     179        return ++counter;
    156180}
    157181
     
    163187 * @return number of printed characters or EOF
    164188 */
    165 static int print_string(char *s, int width, int precision, __u64 flags)
     189                                               
     190static int print_string(char *s, int width, int precision, __u64 flags, struct printf_spec *ps)
    166191{
    167192        int counter = 0;
    168         __native size;
     193        size_t size;
    169194
    170195        if (s == NULL) {
    171                 return putstr("(NULL)");
     196                return printf_putstr("(NULL)", ps);
    172197        }
    173198       
     
    183208        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    184209                while (width-- > 0) {   
    185                         putchar(' ');   
     210                        printf_putchar(' ', ps);       
    186211                        counter++;
    187212                }
     
    190215        while (precision > size) {
    191216                precision--;
    192                 putchar(' ');   
     217                printf_putchar(' ', ps);       
    193218                ++counter;
    194219        }
    195220       
    196         if (putnchars(s, precision) == EOF) {
     221        if (printf_putnchars(s, precision, ps) == EOF) {
    197222                return EOF;
    198223        }
     
    201226
    202227        while (width-- > 0) {
    203                 putchar(' ');   
     228                printf_putchar(' ', ps);       
    204229                ++counter;
    205230        }
     
    220245 *             be in range 2 .. 16).
    221246 * @param flags output modifiers
    222  * @return number of written characters or EOF.
    223  */
    224 static int print_number(__u64 num, int width, int precision, int base , __u64 flags)
     247 * @return number of written characters or EOF
     248 *
     249 */
     250static int print_number(__u64 num, int width, int precision, int base , __u64 flags, struct printf_spec *ps)
    225251{
    226252        char *digits = digits_small;
    227253        char d[PRINT_NUMBER_BUFFER_SIZE];       /* this is good enough even for base == 2, prefix and sign */
    228254        char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1];
    229         int size = 0;
     255        int size = 0; /* size of number with all prefixes and signs */
    230256        int number_size; /* size of plain number */
    231257        int written = 0;
     
    246272                } while (num /= base);
    247273        }
    248 
     274       
    249275        number_size = size;
    250        
     276
    251277        /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */
    252278        if (flags & __PRINTF_FLAG_PREFIX) {
     
    297323        if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) {
    298324                while (width-- > 0) {   
    299                         putchar(' ');   
     325                        printf_putchar(' ', ps);       
    300326                        written++;
    301327                }
     
    304330        /* print sign */
    305331        if (sgn) {
    306                 putchar(sgn);
     332                printf_putchar(sgn, ps);
    307333                written++;
    308334        }
     
    313339                switch(base) {
    314340                        case 2: /* Binary formating is not standard, but usefull */
    315                                 putchar('0');
     341                                printf_putchar('0', ps);
    316342                                if (flags & __PRINTF_FLAG_BIGCHARS) {
    317                                         putchar('B');
     343                                        printf_putchar('B', ps);
    318344                                } else {
    319                                         putchar('b');
     345                                        printf_putchar('b', ps);
    320346                                }
    321347                                written += 2;
    322348                                break;
    323349                        case 8:
    324                                 putchar('o');
     350                                printf_putchar('o', ps);
    325351                                written++;
    326352                                break;
    327353                        case 16:
    328                                 putchar('0');
     354                                printf_putchar('0', ps);
    329355                                if (flags & __PRINTF_FLAG_BIGCHARS) {
    330                                         putchar('X');
     356                                        printf_putchar('X', ps);
    331357                                } else {
    332                                         putchar('x');
     358                                        printf_putchar('x', ps);
    333359                                }
    334360                                written += 2;
     
    340366        precision -= number_size;
    341367        while (precision-- > 0) {       
    342                 putchar('0');   
     368                printf_putchar('0', ps);       
    343369                written++;
    344370        }
     
    347373        /* print number itself */
    348374
    349         written += putstr(++ptr);
     375        written += printf_putstr(++ptr, ps);
    350376       
    351377        /* print ending spaces */
    352378       
    353379        while (width-- > 0) {   
    354                 putchar(' ');   
     380                printf_putchar(' ', ps);       
    355381                written++;
    356382        }
     
    358384        return written;
    359385}
     386
    360387
    361388/** Print formatted string.
     
    368395 *
    369396 * FLAGS:@n
    370  * "#"  Force to print prefix.
     397 *      - "#" Force to print prefix.
    371398 *      For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and 0X
    372399 *      and for conversion \%b the prefix is 0b.
    373400 *
    374  * "-"  Align to left.
    375  *
    376  * "+"  Print positive sign just as negative.
    377  *
    378  * " "  If the printed number is positive and "+" flag is not set, print space in
     401 *      - "-"   Align to left.
     402 *
     403 *      - "+"   Print positive sign just as negative.
     404 *
     405 *      - " "   If the printed number is positive and "+" flag is not set, print space in
    379406 *      place of sign.
    380407 *
    381  * "0"  Print 0 as padding instead of spaces. Zeroes are placed between sign and the
     408 *      - "0"   Print 0 as padding instead of spaces. Zeroes are placed between sign and the
    382409 *      rest of the number. This flag is ignored if "-" flag is specified.
    383410 *
    384411 * WIDTH:@n
    385  * Specify minimal width of printed argument. If it is bigger, width is ignored.
     412 *      - Specify minimal width of printed argument. If it is bigger, width is ignored.
    386413 * If width is specified with a "*" character instead of number, width is taken from
    387414 * parameter list. And integer parameter is expected before parameter for processed
     
    390417 *
    391418 * PRECISION:@n
    392  * Value precision. For numbers it specifies minimum valid numbers.
     419 *      - Value precision. For numbers it specifies minimum valid numbers.
    393420 * Smaller numbers are printed with leading zeroes. Bigger numbers are not affected.
    394421 * Strings with more than precision characters are cut off.
     
    399426 *
    400427 * TYPE:@n
    401  * "hh" Signed or unsigned char.@n
    402  * "h"  Signed or usigned short.@n
    403  * ""   Signed or usigned int (default value).@n
    404  * "l"  Signed or usigned long int.@n
    405  * "ll" Signed or usigned long long int.@n
    406  * "z"  __native (non-standard extension).@n
     428 *      - "hh"  Signed or unsigned char.@n
     429 *      - "h"   Signed or usigned short.@n
     430 *      - ""    Signed or usigned int (default value).@n
     431 *      - "l"   Signed or usigned long int.@n
     432 *      - "ll"  Signed or usigned long long int.@n
     433 *      - "z"   __native (non-standard extension).@n
    407434 *
    408435 *
    409436 * CONVERSION:@n
    410  * %    Print percentile character itself.
    411  *
    412  * c    Print single character.
    413  *
    414  * s    Print zero terminated string. If a NULL value is passed as value, "(NULL)" is printed instead.
     437 *      - %     Print percentile character itself.
     438 *
     439 *      - c     Print single character.
     440 *
     441 *      - s     Print zero terminated string. If a NULL value is passed as value, "(NULL)" is printed instead.
    415442 *
    416  * P, p Print value of a pointer. Void * value is expected and it is printed in hexadecimal notation with prefix
     443 *      - P, p  Print value of a pointer. Void * value is expected and it is printed in hexadecimal notation with prefix
    417444 *      (as with \%#X or \%#x for 32bit or \%#X / \%#x for 64bit long pointers).
    418445 *
    419  * b    Print value as unsigned binary number. Prefix is not printed by default. (Nonstandard extension.)
     446 *      - b     Print value as unsigned binary number. Prefix is not printed by default. (Nonstandard extension.)
    420447 *
    421  * o    Print value as unsigned octal number. Prefix is not printed by default.
    422  *
    423  * d,i  Print signed decimal number. There is no difference between d and i conversion.
    424  *
    425  * u    Print unsigned decimal number.
    426  *
    427  * X, x Print hexadecimal number with upper- or lower-case. Prefix is not printed by default.
     448 *      - o     Print value as unsigned octal number. Prefix is not printed by default.
     449 *
     450 *      - d,i   Print signed decimal number. There is no difference between d and i conversion.
     451 *
     452 *      - u     Print unsigned decimal number.
     453 *
     454 *      - X, x  Print hexadecimal number with upper- or lower-case. Prefix is not printed by default.
    428455 *
    429456 * All other characters from fmt except the formatting directives
     
    433460 * @return Number of printed characters or negative value on failure.
    434461 */
    435 int printf(const char *fmt, ...)
     462int printf_core(const char *fmt, struct printf_spec *ps, va_list ap)
    436463{
    437464        int irqpri;
     
    440467        int counter; /* counter of printed characters */
    441468        int retval; /* used to store return values from called functions */
    442         va_list ap;
    443469        char c;
    444470        qualifier_t qualifier;  /* type of argument */
    445471        int base;       /* base in which will be parameter (numbers only) printed */
    446472        __u64 number; /* argument value */
    447         __native size; /* byte size of integer parameter */
     473        size_t  size; /* byte size of integer parameter */
    448474        int width, precision;
    449475        __u64 flags;
     
    451477        counter = 0;
    452478       
    453         va_start(ap, fmt);
    454        
    455479        irqpri = interrupts_disable();
    456480        spinlock_lock(&printflock);
    457481
    458        
    459482        while ((c = fmt[i])) {
    460483                /* control character */
     
    462485                        /* print common characters if any processed */ 
    463486                        if (i > j) {
    464                                 if ((retval = putnchars(&fmt[j], (__native)(i - j))) == EOF) { /* error */
     487                                if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) == EOF) { /* error */
    465488                                        counter = -counter;
    466489                                        goto out;
     
    559582                                */
    560583                                case 's':
    561                                         if ((retval = print_string(va_arg(ap, char*), width, precision, flags)) == EOF) {
     584                                        if ((retval = print_string(va_arg(ap, char*), width, precision, flags, ps)) == EOF) {
    562585                                                counter = -counter;
    563586                                                goto out;
     
    569592                                case 'c':
    570593                                        c = va_arg(ap, unsigned int);
    571                                         if ((retval = print_char(c, width, flags )) == EOF) {
     594                                        if ((retval = print_char(c, width, flags, ps)) == EOF) {
    572595                                                counter = -counter;
    573596                                                goto out;
     
    654677                                        counter = -counter;
    655678                                        goto out;
    656                                        
    657679                        }
    658680                       
     
    671693                        }
    672694
    673                         if ((retval = print_number(number, width, precision, base, flags)) == EOF ) {
     695                        if ((retval = print_number(number, width, precision, base, flags, ps)) == EOF ) {
    674696                                counter = -counter;
    675697                                goto out;
     
    685707       
    686708        if (i > j) {
    687                 if ((retval = putnchars(&fmt[j], (__native)(i - j))) == EOF) { /* error */
     709                if ((retval = printf_putnchars(&fmt[j], (__native)(i - j), ps)) == EOF) { /* error */
    688710                        counter = -counter;
    689711                        goto out;
     712                       
    690713                }
    691714                counter += retval;
    692715        }
     716
    693717out:
    694718        spinlock_unlock(&printflock);
    695719        interrupts_restore(irqpri);
    696720       
    697         va_end(ap);
    698721        return counter;
    699722}
     723
  • test/print/print1/test.c

    r7dd1787 re499a30  
    2929#include <test.h>
    3030
     31#define BUFFER_SIZE 32
     32
    3133void test(void)
    3234{
    3335        __native nat = 0x12345678u;
     36       
     37        unsigned char buffer[BUFFER_SIZE];
     38       
    3439        printf(" Printf test \n");
    3540       
     
    4752       
    4853        printf(" Print to NULL '%s'\n",NULL);
     54
     55        printf("Print short text to %d char long buffer via snprintf.\n", BUFFER_SIZE);
     56        snprintf(buffer, BUFFER_SIZE, "Short %s", "text");
     57        printf("Result is: '%s'\n", buffer);
     58       
     59        printf("Print long text to %d char long buffer via snprintf.\n", BUFFER_SIZE);
     60        snprintf(buffer, BUFFER_SIZE, "Very long %s. This text`s length is more than %d. We are interested in the result.", "text" , BUFFER_SIZE);
     61        printf("Result is: '%s'\n", buffer);
     62       
    4963        return;
    5064}
Note: See TracChangeset for help on using the changeset viewer.