Changeset 1082798 in rtems


Ignore:
Timestamp:
Oct 23, 2017, 11:30:44 AM (18 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
ac28f15
Parents:
a54d10d
git-author:
Sebastian Huber <sebastian.huber@…> (10/23/17 11:30:44)
git-committer:
Sebastian Huber <sebastian.huber@…> (11/06/17 06:25:51)
Message:

score: Add _IO_Printf() and _IO_Vprintf()

The previous vprintk() implementation had a questionable licence header,
lacks support for the 'z' and 'j' format specifiers, is not robust
against invalid format specifiers, uses a global variable for output.
Replace it with a stripped down version of the FreeBSD kernel kvprintf()
function.

The new implementation allows a low overhead rtems_snprintf() if
necessary.

Update #3199.
Close #3216.

Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libcsupport/src/vprintk.c

    ra54d10d r1082798  
    77
    88/*
    9  * (C) Copyright 1997 -
    10  * - NavIST Group - Real-Time Distributed Systems and Industrial Automation
     9 * Copyright (c) 2017 embedded brains GmbH.  All rights reserved.
    1110 *
    12  * http://pandora.ist.utl.pt
     11 *  embedded brains GmbH
     12 *  Dornierstr. 4
     13 *  82178 Puchheim
     14 *  Germany
     15 *  <rtems@embedded-brains.de>
    1316 *
    14  * Instituto Superior Tecnico * Lisboa * PORTUGAL
    15  *
    16  * Disclaimer:
    17  *
    18  * This file is provided "AS IS" without warranty of any kind, either
    19  * expressed or implied.
    20  *
    21  * This code is based on code by: Jose Rufino - IST
     17 * The license and distribution terms for this file may be
     18 * found in the file LICENSE in this distribution or at
     19 * http://www.rtems.org/license/LICENSE.
    2220 */
    2321
     
    2624#endif
    2725
    28 #include <stdarg.h>
    29 #include <stdio.h>
    30 #include <stdbool.h>
    3126#include <rtems/bspIo.h>
     27#include <rtems/score/io.h>
    3228
    33 static int printNum(
    34   long long num,
    35   unsigned base,
    36   bool sign,
    37   unsigned maxwidth,
    38   char lead
    39 );
    40 
    41 /**
    42  *  A simplified version of printf intended for use when the
    43  *  console is not yet initialized or in ISR's.
    44  *
    45  * Arguments:
    46  *    as in printf: fmt - format string, ... - unnamed arguments.
    47  */
    48 int vprintk(
    49   const char *fmt,
    50   va_list     ap
    51 )
     29static void vprintk_putchar( int c, void *arg )
    5230{
    53   int len_out = 0;
    54   for (; *fmt != '\0'; fmt++) {
    55     unsigned base = 0;
    56     unsigned width = 0;
    57     enum {
    58       LFLAG_INT,
    59       LFLAG_LONG,
    60       LFLAG_LONG_LONG
    61     } lflag = LFLAG_INT;
    62     bool minus = false;
    63     bool sign = false;
    64     char lead = ' ';
    65     char c = *fmt;
    66     long long num;
    67 
    68     if (c != '%') {
    69       rtems_putc(c);
    70       ++len_out;
    71       continue;
    72     }
    73 
    74     ++fmt; c = *fmt;
    75 
    76     if (c == '0') {
    77       lead = '0';
    78       ++fmt; c = *fmt;
    79     }
    80 
    81     if (c == '-') {
    82       minus = true;
    83       ++fmt; c = *fmt;
    84     }
    85 
    86     while (c >= '0' && c <= '9' ) {
    87       width *= 10;
    88       width += ((unsigned) c - '0');
    89       ++fmt; c = *fmt;
    90     }
    91 
    92     if (c == 'l') {
    93       lflag = LFLAG_LONG;
    94       ++fmt; c = *fmt;
    95 
    96       if (c == 'l') {
    97         lflag = LFLAG_LONG_LONG;
    98         ++fmt; c = *fmt;
    99       }
    100     }
    101 
    102     if ( c == 'c' ) {
    103       /* need a cast here since va_arg() only takes fully promoted types */
    104       char chr = (char) va_arg(ap, int);
    105       rtems_putc(chr);
    106       ++len_out;
    107       continue;
    108     }
    109 
    110     if ( c == 's' ) {
    111       unsigned i, len;
    112       char *s, *str;
    113 
    114       str = va_arg(ap, char *);
    115 
    116       if ( str == NULL ) {
    117         str = "";
    118       }
    119 
    120       /* calculate length of string */
    121       for ( len=0, s=str ; *s ; len++, s++ )
    122         ;
    123 
    124       /* leading spaces */
    125       if ( !minus )
    126         for ( i=len ; i<width ; i++, len_out++ )
    127           rtems_putc(' ');
    128 
    129       /* no width option */
    130       if (width == 0) {
    131           width = len;
    132       }
    133 
    134       /* output the string */
    135       for ( i=0 ; i<width && *str ; str++, len_out++ )
    136         rtems_putc(*str);
    137 
    138       /* trailing spaces */
    139       if ( minus )
    140         for ( i=len ; i<width ; i++, len_out++ )
    141           rtems_putc(' ');
    142 
    143       continue;
    144     }
    145 
    146     /* must be a numeric format or something unsupported */
    147     if ( c == 'o' || c == 'O' ) {
    148       base = 8; sign = false;
    149     } else if ( c == 'i' || c == 'I' ||
    150                 c == 'd' || c == 'D' ) {
    151       base = 10; sign = true;
    152     } else if ( c == 'u' || c == 'U' ) {
    153       base = 10; sign = false;
    154     } else if ( c == 'x' || c == 'X' ) {
    155       base = 16; sign = false;
    156     } else if ( c == 'p' ) {
    157       base = 16; sign = false; lflag = LFLAG_LONG;
    158     } else {
    159       rtems_putc(c);
    160       ++len_out;
    161       continue;
    162     }
    163 
    164     switch (lflag) {
    165       case LFLAG_LONG:
    166         num = sign ? (long long) va_arg(ap, long)
    167           : (long long) va_arg(ap, unsigned long);
    168         break;
    169       case LFLAG_LONG_LONG:
    170         num = va_arg(ap, long long);
    171         break;
    172       case LFLAG_INT:
    173       default:
    174         num = sign ? (long long) va_arg(ap, int)
    175           : (long long) va_arg(ap, unsigned int);
    176         break;
    177     }
    178 
    179     len_out += printNum(num, base, sign, width, lead);
    180   }
    181 
    182   return len_out;
     31  rtems_putc((char) c);
    18332}
    18433
    185 /**
    186  *  @brief Print Number in a Given Base
    187  *  @param[in] num is the number to print
    188  *  @param[in] base is the base used to print the number
    189  */
    190 static int printNum(
    191   long long num,
    192   unsigned base,
    193   bool sign,
    194   unsigned maxwidth,
    195   char lead
    196 )
     34int vprintk( const char *fmt, va_list ap )
    19735{
    198   unsigned long long unsigned_num;
    199   unsigned long long n;
    200   unsigned count;
    201   #define UINT64_MAX_IN_OCTAL_FORMAT "1777777777777777777777"
    202   char toPrint[sizeof(UINT64_MAX_IN_OCTAL_FORMAT)];
    203   int len_out = 0;
    204 
    205   if ( sign && (num <  0) ) {
    206     rtems_putc('-');
    207     ++len_out;
    208     unsigned_num = (unsigned long long) -num;
    209     if (maxwidth) maxwidth--;
    210   } else {
    211     unsigned_num = (unsigned long long) num;
    212   }
    213 
    214   count = 0;
    215   while ((n = unsigned_num / base) > 0) {
    216     toPrint[count++] = (char) (unsigned_num - (n * base));
    217     unsigned_num = n;
    218   }
    219   toPrint[count++] = (char) unsigned_num;
    220 
    221   for (n=maxwidth ; n > count; n--, len_out++ )
    222     rtems_putc(lead);
    223 
    224   for (n = 0; n < count; n++, len_out++) {
    225     rtems_putc("0123456789ABCDEF"[(int)(toPrint[count-(n+1)])]);
    226   }
    227 
    228   return len_out;
     36  return _IO_Vprintf( vprintk_putchar, NULL, fmt, ap );
    22937}
  • cpukit/score/Makefile.am

    ra54d10d r1082798  
    4747include_rtems_score_HEADERS += include/rtems/score/protectedheap.h
    4848include_rtems_score_HEADERS += include/rtems/score/interr.h
     49include_rtems_score_HEADERS += include/rtems/score/io.h
    4950include_rtems_score_HEADERS += include/rtems/score/isr.h
    5051include_rtems_score_HEADERS += include/rtems/score/isrlevel.h
     
    334335    src/debugisthreaddispatchingallowed.c \
    335336    src/interr.c src/isr.c src/wkspace.c src/wkstringduplicate.c
     337libscore_a_SOURCES += src/ioprintf.c
     338libscore_a_SOURCES += src/iovprintf.c
    336339libscore_a_SOURCES += src/isrisinprogress.c
    337340libscore_a_SOURCES += src/condition.c
  • cpukit/score/preinstall.am

    ra54d10d r1082798  
    152152        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/interr.h
    153153PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/interr.h
     154
     155$(PROJECT_INCLUDE)/rtems/score/io.h: include/rtems/score/io.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
     156        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/io.h
     157PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/io.h
    154158
    155159$(PROJECT_INCLUDE)/rtems/score/isr.h: include/rtems/score/isr.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
  • testsuites/sptests/spprintk/init.c

    ra54d10d r1082798  
    1414#endif
    1515
    16 #include <rtems/score/basedefs.h>
     16#include <rtems/score/io.h>
    1717
    1818/*
     
    2828const char rtems_test_name[] = "SPPRINTK";
    2929
    30 /* forward declarations to avoid warnings */
    31 rtems_task Init(rtems_task_argument argument);
    32 int test_getchar(void);
    33 void do_getchark(void);
    34 void do_putk(void);
    35 void do_printk(void);
    36 
    37 int test_getchar(void)
     30static int test_getchar(void)
    3831{
    3932  return 0x35;
    4033}
    4134
    42 void do_getchark(void)
     35static void do_getchark(void)
    4336{
    4437  int                                sc;
     
    6154}
    6255
    63 void do_putk(void)
     56static void do_putk(void)
    6457{
    6558  putk( "This is a test of putk" );
    6659}
    6760
    68 void do_printk(void)
     61static void do_printk(void)
    6962{
    7063  long lm = 2147483647L;
     
    7366  long long ullm = 18446744073709551615ULL;
    7467
    75   printk( "bad format -- %%q in parentheses (%q)\n" );
    76 
    77   printk( "bad format -- %%lq in parentheses (%lq)\n", 0x1234 );
    78 
    79   printk( "%%O octal upper case 16 -- %O\n", 16 );
    80   printk( "%%o octal lower case of 16 -- %O\n", 16 );
    81   printk( "%%I of 16 -- %I\n", 16 );
    82   printk( "%%i of 16 -- %i\n", 16 );
    83   printk( "%%D of 16 -- %D\n", 16 );
    84   printk( "%%d of 16 -- %d\n", 16 );
    85   printk( "%%-3d of 16 -- %-3d\n", 16 );
    86   printk( "%%U of 16 -- %U\n", 16 );
    87   printk( "%%u of 16 -- %u\n", 16 );
    88   printk( "%%X of 16 -- %X\n", 16 );
    89   printk( "%%x of 16 -- %x\n", 16 );
    90   printk( "%%p of 0x1234 -- %p\n", (void *)0x1234 );
     68  printk( "bad format                   -- %%q in parentheses (%q)\n" );
     69
     70  printk( "bad format                   -- %%lq in parentheses (%lq)\n" );
     71
     72  printk( "%%o of 16                     -- %o\n", 16 );
     73  printk( "%%i of 16                     -- %i\n", 16 );
     74  printk( "%%d of 16                     -- %d\n", 16 );
     75  printk( "'%%-3d' of 16                 -- '%-3d'\n", 16 );
     76  printk( "'%%3d' of 16                  -- '%3d'\n", 16 );
     77  printk( "%%u of 16                     -- %u\n", 16 );
     78  printk( "%%X of 16                     -- %X\n", 16 );
     79  printk( "%%x of 16                     -- %x\n", 16 );
     80  printk( "%%p of 0x1234                 -- %p\n", (void *)0x1234 );
    9181
    9282  /* long */
    93   printk( "%%lo of 2147483647 -- %lo\n", lm );
    94   printk( "%%li of 2147483647 -- %li\n", lm );
    95   printk( "%%lu of 2147483647 -- %lu\n", lm );
    96   printk( "%%lx of 2147483647 -- %lx\n", lm );
    97   printk( "%%lo of -2147483648 -- %lo\n", -lm - 1L );
    98   printk( "%%li of -2147483648 -- %li\n", -lm - 1L );
    99   printk( "%%lx of -2147483648 -- %lx\n", -lm - 1L );
    100   printk( "%%lo of 4294967295 -- %lo\n", ulm );
    101   printk( "%%lu of 4294967295 -- %lu\n", ulm );
    102   printk( "%%lx of 4294967295 -- %lx\n", ulm );
     83  printk( "%%lo of 2147483647            -- %lo\n", lm );
     84  printk( "%%li of 2147483647            -- %li\n", lm );
     85  printk( "%%lu of 2147483647            -- %lu\n", lm );
     86  printk( "%%lx of 2147483647            -- %lx\n", lm );
     87  printk( "%%lo of -2147483648           -- %lo\n", -lm - 1L );
     88  printk( "%%li of -2147483648           -- %li\n", -lm - 1L );
     89  printk( "%%lx of -2147483648           -- %lx\n", -lm - 1L );
     90  printk( "%%lo of 4294967295            -- %lo\n", ulm );
     91  printk( "%%lu of 4294967295            -- %lu\n", ulm );
     92  printk( "%%lx of 4294967295            -- %lx\n", ulm );
    10393
    10494  /* long long */
    105   printk( "%%llo of 9223372036854775807 -- %llo\n", llm );
    106   printk( "%%lli of 9223372036854775807 -- %lli\n", llm );
    107   printk( "%%llu of 9223372036854775807 -- %llu\n", llm );
    108   printk( "%%llx of 9223372036854775807 -- %llx\n", llm );
     95  printk( "%%llo of 9223372036854775807  -- %llo\n", llm );
     96  printk( "%%lli of 9223372036854775807  -- %lli\n", llm );
     97  printk( "%%llu of 9223372036854775807  -- %llu\n", llm );
     98  printk( "%%llx of 9223372036854775807  -- %llx\n", llm );
    10999  printk( "%%llo of -9223372036854775808 -- %llo\n", -llm - 1LL );
    110100  printk( "%%lli of -9223372036854775808 -- %lli\n", -llm - 1LL );
     
    115105
    116106  /* negative numbers */
    117   printk( "%%d of -16 -- %d\n", -16 );
    118   printk( "%%d of -16 -- %-3d\n", -16 );
    119   printk( "%%u of -16 -- %u\n", -16 );
     107  printk( "%%d of -16                    -- %d\n", -16 );
     108  printk( "%%d of -16                    -- %-3d\n", -16 );
     109  printk( "%%u of -16                    -- %u\n", -16 );
    120110
    121111  /* string formats */
    122   printk( "%%s of Mary Had a Little Lamb -- (%s)\n",
     112  printk( "%%s of Mary Had a Little Lamb -- '%s'\n",
    123113          "Mary Had a Little Lamb" );
    124   printk( "%%s of NULL -- (%s)\n", NULL );
    125   printk( "%%12s of joel -- (%20s)\n", "joel" );
    126   printk( "%%4s of joel -- (%4s)\n", "joel" );
    127   printk( "%%-12s of joel -- (%-20s)\n", "joel" );
    128   printk( "%%-4s of joel -- (%-4s)\n", "joel" );
    129   printk( "%%c of X -- (%c)\n", 'X' );
    130 }
    131 
    132 rtems_task Init(
     114  printk( "%%s of NULL                   -- '%s'\n", NULL );
     115  printk( "%%12s of joel                 -- '%20s'\n", "joel" );
     116  printk( "%%4s of joel                  -- '%4s'\n", "joel" );
     117  printk( "%%-12s of joel                -- '%-20s'\n", "joel" );
     118  printk( "%%-4s of joel                 -- '%-4s'\n", "joel" );
     119  printk( "%%c of X                      -- '%c'\n", 'X' );
     120  printk( "%%hhu of X                    -- %hhu\n", 'X' );
     121}
     122
     123typedef struct {
     124  char buf[128];
     125  size_t i;
     126} test_context;
     127
     128static test_context test_instance;
     129
     130static void clear( test_context *ctx )
     131{
     132  ctx->i = 0;
     133  memset( ctx->buf, 0, sizeof( ctx->buf ) );
     134}
     135
     136static void put_char( int c, void *arg )
     137{
     138  test_context *ctx;
     139
     140  ctx = arg;
     141
     142  if ( ctx->i < sizeof( ctx->buf ) ) {
     143    ctx->buf[ ctx->i ] = (char) c;
     144    ++ctx->i;
     145  }
     146}
     147
     148static test_context test_instance;
     149
     150static void test_io_printf( test_context *ctx )
     151{
     152  int i;
     153  intmax_t j;
     154  long long ll;
     155  long l;
     156  size_t z;
     157  ptrdiff_t t;
     158
     159  clear( ctx );
     160  i = 123;
     161  _IO_Printf( put_char, ctx, "%i", i );
     162  rtems_test_assert( strcmp( ctx->buf, "123" ) == 0 );
     163
     164  clear( ctx );
     165  j = 456;
     166  _IO_Printf( put_char, ctx, "%ji", j );
     167  rtems_test_assert( strcmp( ctx->buf, "456" ) == 0 );
     168
     169  clear( ctx );
     170  ll = 789;
     171  _IO_Printf( put_char, ctx, "%lli", ll );
     172  rtems_test_assert( strcmp( ctx->buf, "789" ) == 0 );
     173
     174  clear( ctx );
     175  l = 101112;
     176  _IO_Printf( put_char, ctx, "%li", l );
     177  rtems_test_assert( strcmp( ctx->buf, "101112" ) == 0 );
     178
     179  clear( ctx );
     180  z = 131415;
     181  _IO_Printf( put_char, ctx, "%zi", z );
     182  rtems_test_assert( strcmp( ctx->buf, "131415" ) == 0 );
     183
     184  clear( ctx );
     185  t = 161718;
     186  _IO_Printf( put_char, ctx, "%ti", t );
     187  rtems_test_assert( strcmp( ctx->buf, "161718" ) == 0 );
     188}
     189
     190static rtems_task Init(
    133191  rtems_task_argument argument
    134192)
     
    143201
    144202  do_getchark();
     203  test_io_printf(&test_instance);
    145204
    146205  TEST_END();
  • testsuites/sptests/spprintk/spprintk.scn

    ra54d10d r1082798  
    1 *** TEST PRINTK ***
     1*** BEGIN OF TEST SPPRINTK ***
    22This is a test of putk
    33
    4 bad format -- %q in parentheses (q)
    5 bad format -- %lq in parentheses (q)
    6 %O octal upper case 16 -- 20
    7 %o octal lower case of 16 -- 20
    8 %I of 16 -- 16
    9 %i of 16 -- 16
    10 %D of 16 -- 16
    11 %d of 16 -- 16
    12 %-3d of 16 --  16
    13 %U of 16 -- 16
    14 %u of 16 -- 16
    15 %X of 16 -- 10
    16 %x of 16 -- 10
    17 %p of 0x1234 -- 1234
    18 %lo of 2147483647 -- 17777777777
    19 %li of 2147483647 -- 2147483647
    20 %lu of 2147483647 -- 2147483647
    21 %lx of 2147483647 -- 7FFFFFFF
    22 %lo of -2147483648 -- 20000000000
    23 %li of -2147483648 -- -2147483648
    24 %lx of -2147483648 -- 80000000
    25 %lo of 4294967295 -- 37777777777
    26 %lu of 4294967295 -- 4294967295
    27 %lx of 4294967295 -- FFFFFFFF
    28 %llo of 9223372036854775807 -- 777777777777777777777
    29 %lli of 9223372036854775807 -- 9223372036854775807
    30 %llu of 9223372036854775807 -- 9223372036854775807
    31 %llx of 9223372036854775807 -- 7FFFFFFFFFFFFFFF
     4bad format                   -- %q in parentheses (%q)
     5bad format                   -- %lq in parentheses (%lq)
     6%o of 16                     -- 20
     7%i of 16                     -- 16
     8%d of 16                     -- 16
     9'%-3d' of 16                 -- '16 '
     10'%3d' of 16                  -- ' 16'
     11%u of 16                     -- 16
     12%X of 16                     -- 10
     13%x of 16                     -- 10
     14%p of 0x1234                 -- 0x1234
     15%lo of 2147483647            -- 17777777777
     16%li of 2147483647            -- 2147483647
     17%lu of 2147483647            -- 2147483647
     18%lx of 2147483647            -- 7fffffff
     19%lo of -2147483648           -- 20000000000
     20%li of -2147483648           -- -2147483648
     21%lx of -2147483648           -- 80000000
     22%lo of 4294967295            -- 37777777777
     23%lu of 4294967295            -- 4294967295
     24%lx of 4294967295            -- ffffffff
     25%llo of 9223372036854775807  -- 777777777777777777777
     26%lli of 9223372036854775807  -- 9223372036854775807
     27%llu of 9223372036854775807  -- 9223372036854775807
     28%llx of 9223372036854775807  -- 7fffffffffffffff
    3229%llo of -9223372036854775808 -- 1000000000000000000000
    3330%lli of -9223372036854775808 -- -9223372036854775808
     
    3532%llo of 18446744073709551615 -- 1777777777777777777777
    3633%llu of 18446744073709551615 -- 18446744073709551615
    37 %llx of 18446744073709551615 -- FFFFFFFFFFFFFFFF
    38 %d of -16 -- -16
    39 %d of -16 -- -16
    40 %u of -16 -- 4294967280
    41 %s of Mary Had a Little Lamb -- (Mary Had a Little Lamb)
    42 %s of NULL -- ()
    43 %12s of joel -- (                joel)
    44 %4s of joel -- (joel)
    45 %-12s of joel -- (joel                )
    46 %-4s of joel -- (joel)
    47 %c of X -- (X)
     34%llx of 18446744073709551615 -- ffffffffffffffff
     35%d of -16                    -- -16
     36%d of -16                    -- -16
     37%u of -16                    -- 4294967280
     38%s of Mary Had a Little Lamb -- 'Mary Had a Little Lamb'
     39%s of NULL                   -- '(null)'
     40%12s of joel                 -- '                joel'
     41%4s of joel                  -- 'joel'
     42%-12s of joel                -- 'joel                '
     43%-4s of joel                 -- 'joel'
     44%c of X                      -- 'X'
     45%hhu of X                    -- 88
    4846
    4947getchark - NULL getchar method - return -1
    5048getchark - test getchar method - returns 0x35
    51 *** END OF TEST PRINTK ***
     49
     50*** END OF TEST SPPRINTK ***
Note: See TracChangeset for help on using the changeset viewer.