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.
This commit is contained in:
Sebastian Huber
2017-10-23 13:30:44 +02:00
parent a54d10d177
commit 10827984c2
8 changed files with 613 additions and 298 deletions

View File

@@ -6,224 +6,32 @@
*/
/*
* (C) Copyright 1997 -
* - NavIST Group - Real-Time Distributed Systems and Industrial Automation
* Copyright (c) 2017 embedded brains GmbH. All rights reserved.
*
* http://pandora.ist.utl.pt
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* Instituto Superior Tecnico * Lisboa * PORTUGAL
*
* Disclaimer:
*
* This file is provided "AS IS" without warranty of any kind, either
* expressed or implied.
*
* This code is based on code by: Jose Rufino - IST
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdbool.h>
#include <rtems/bspIo.h>
#include <rtems/score/io.h>
static int printNum(
long long num,
unsigned base,
bool sign,
unsigned maxwidth,
char lead
);
/**
* A simplified version of printf intended for use when the
* console is not yet initialized or in ISR's.
*
* Arguments:
* as in printf: fmt - format string, ... - unnamed arguments.
*/
int vprintk(
const char *fmt,
va_list ap
)
static void vprintk_putchar( int c, void *arg )
{
int len_out = 0;
for (; *fmt != '\0'; fmt++) {
unsigned base = 0;
unsigned width = 0;
enum {
LFLAG_INT,
LFLAG_LONG,
LFLAG_LONG_LONG
} lflag = LFLAG_INT;
bool minus = false;
bool sign = false;
char lead = ' ';
char c = *fmt;
long long num;
if (c != '%') {
rtems_putc(c);
++len_out;
continue;
}
++fmt; c = *fmt;
if (c == '0') {
lead = '0';
++fmt; c = *fmt;
}
if (c == '-') {
minus = true;
++fmt; c = *fmt;
}
while (c >= '0' && c <= '9' ) {
width *= 10;
width += ((unsigned) c - '0');
++fmt; c = *fmt;
}
if (c == 'l') {
lflag = LFLAG_LONG;
++fmt; c = *fmt;
if (c == 'l') {
lflag = LFLAG_LONG_LONG;
++fmt; c = *fmt;
}
}
if ( c == 'c' ) {
/* need a cast here since va_arg() only takes fully promoted types */
char chr = (char) va_arg(ap, int);
rtems_putc(chr);
++len_out;
continue;
}
if ( c == 's' ) {
unsigned i, len;
char *s, *str;
str = va_arg(ap, char *);
if ( str == NULL ) {
str = "";
}
/* calculate length of string */
for ( len=0, s=str ; *s ; len++, s++ )
;
/* leading spaces */
if ( !minus )
for ( i=len ; i<width ; i++, len_out++ )
rtems_putc(' ');
/* no width option */
if (width == 0) {
width = len;
}
/* output the string */
for ( i=0 ; i<width && *str ; str++, len_out++ )
rtems_putc(*str);
/* trailing spaces */
if ( minus )
for ( i=len ; i<width ; i++, len_out++ )
rtems_putc(' ');
continue;
}
/* must be a numeric format or something unsupported */
if ( c == 'o' || c == 'O' ) {
base = 8; sign = false;
} else if ( c == 'i' || c == 'I' ||
c == 'd' || c == 'D' ) {
base = 10; sign = true;
} else if ( c == 'u' || c == 'U' ) {
base = 10; sign = false;
} else if ( c == 'x' || c == 'X' ) {
base = 16; sign = false;
} else if ( c == 'p' ) {
base = 16; sign = false; lflag = LFLAG_LONG;
} else {
rtems_putc(c);
++len_out;
continue;
}
switch (lflag) {
case LFLAG_LONG:
num = sign ? (long long) va_arg(ap, long)
: (long long) va_arg(ap, unsigned long);
break;
case LFLAG_LONG_LONG:
num = va_arg(ap, long long);
break;
case LFLAG_INT:
default:
num = sign ? (long long) va_arg(ap, int)
: (long long) va_arg(ap, unsigned int);
break;
}
len_out += printNum(num, base, sign, width, lead);
}
return len_out;
rtems_putc((char) c);
}
/**
* @brief Print Number in a Given Base
* @param[in] num is the number to print
* @param[in] base is the base used to print the number
*/
static int printNum(
long long num,
unsigned base,
bool sign,
unsigned maxwidth,
char lead
)
int vprintk( const char *fmt, va_list ap )
{
unsigned long long unsigned_num;
unsigned long long n;
unsigned count;
#define UINT64_MAX_IN_OCTAL_FORMAT "1777777777777777777777"
char toPrint[sizeof(UINT64_MAX_IN_OCTAL_FORMAT)];
int len_out = 0;
if ( sign && (num < 0) ) {
rtems_putc('-');
++len_out;
unsigned_num = (unsigned long long) -num;
if (maxwidth) maxwidth--;
} else {
unsigned_num = (unsigned long long) num;
}
count = 0;
while ((n = unsigned_num / base) > 0) {
toPrint[count++] = (char) (unsigned_num - (n * base));
unsigned_num = n;
}
toPrint[count++] = (char) unsigned_num;
for (n=maxwidth ; n > count; n--, len_out++ )
rtems_putc(lead);
for (n = 0; n < count; n++, len_out++) {
rtems_putc("0123456789ABCDEF"[(int)(toPrint[count-(n+1)])]);
}
return len_out;
return _IO_Vprintf( vprintk_putchar, NULL, fmt, ap );
}

View File

@@ -46,6 +46,7 @@ include_rtems_score_HEADERS += include/rtems/score/heap.h
include_rtems_score_HEADERS += include/rtems/score/heapimpl.h
include_rtems_score_HEADERS += include/rtems/score/protectedheap.h
include_rtems_score_HEADERS += include/rtems/score/interr.h
include_rtems_score_HEADERS += include/rtems/score/io.h
include_rtems_score_HEADERS += include/rtems/score/isr.h
include_rtems_score_HEADERS += include/rtems/score/isrlevel.h
include_rtems_score_HEADERS += include/rtems/score/isrlock.h
@@ -333,6 +334,8 @@ libscore_a_SOURCES += src/chain.c \
src/chainnodecount.c \
src/debugisthreaddispatchingallowed.c \
src/interr.c src/isr.c src/wkspace.c src/wkstringduplicate.c
libscore_a_SOURCES += src/ioprintf.c
libscore_a_SOURCES += src/iovprintf.c
libscore_a_SOURCES += src/isrisinprogress.c
libscore_a_SOURCES += src/condition.c
libscore_a_SOURCES += src/debugisownerofallocator.c

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2017 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifndef _RTEMS_SCORE_IO_H
#define _RTEMS_SCORE_IO_H
#include <rtems/score/basedefs.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef void ( *IO_Put_char )(int c, void *arg);
int _IO_Printf(
IO_Put_char put_char,
void *arg,
char const *fmt,
...
) RTEMS_PRINTFLIKE( 3, 4 );
int _IO_Vprintf(
IO_Put_char put_char,
void *arg,
char const *fmt,
va_list ap
);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _RTEMS_SCORE_IO_H */

View File

@@ -152,6 +152,10 @@ $(PROJECT_INCLUDE)/rtems/score/interr.h: include/rtems/score/interr.h $(PROJECT_
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/interr.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/interr.h
$(PROJECT_INCLUDE)/rtems/score/io.h: include/rtems/score/io.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/io.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/io.h
$(PROJECT_INCLUDE)/rtems/score/isr.h: include/rtems/score/isr.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/isr.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/isr.h

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2017 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/score/io.h>
int _IO_Printf( IO_Put_char put_char, void *arg, char const *fmt, ... )
{
va_list ap;
int len;
va_start( ap, fmt );
len = _IO_Vprintf( put_char, arg, fmt, ap );
va_end( ap );
return len;
}

View File

@@ -0,0 +1,365 @@
/*-
* Copyright (c) 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
*/
#include <rtems/score/io.h>
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 320908 2017-07-12 07:30:14Z rlibby $");
#include <sys/param.h>
#include <string.h>
/* Max number conversion buffer length: a intmax_t in base 8, plus NUL byte. */
#define MAXNBUF (howmany(sizeof(intmax_t) * NBBY, 3) + 1)
static inline int imax(int a, int b) { return (a > b ? a : b); }
static char const hex2ascii_data[2][16] = {
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' },
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' }
};
static inline char
hex2ascii(int hex)
{
return (hex2ascii_data[0][hex]);
}
/*
* Put a NUL-terminated ASCII number (base <= 16) in a buffer in reverse
* order; return an optional length and a pointer to the last character
* written in the buffer (i.e., the first character of the string).
* The buffer pointed to by `nbuf' must have length >= MAXNBUF.
*/
static char *
ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
{
char *p;
p = nbuf;
*p = '\0';
do {
*++p = hex2ascii_data[upper][num % base];
} while (num /= base);
if (lenp)
*lenp = p - nbuf;
return (p);
}
int
_IO_Vprintf(IO_Put_char put_char, void *arg, char const *fmt, va_list ap)
{
#define PCHAR(c) {int cc=(c); (*put_char)(cc, arg); retval++; }
char nbuf[MAXNBUF];
const char *p, *percent, *q;
u_char *up;
int ch, n;
uintmax_t num;
int base, lflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
int cflag, hflag, jflag;
RTEMS_STATIC_ASSERT(sizeof(intmax_t) == sizeof(long long), _IO_Vprintf_j);
#if __SIZEOF_PTRDIFF_T__ == __SIZEOF_LONG__
#define tflag lflag
#else
int tflag;
#endif
#if __SIZEOF_SIZE_T__ == __SIZEOF_LONG__
#define zflag lflag
#else
int zflag;
#endif
int dwidth, upper;
char padc;
int stop = 0, retval = 0;
num = 0;
if (fmt == NULL)
fmt = "(fmt null)\n";
for (;;) {
padc = ' ';
width = 0;
while ((ch = (u_char)*fmt++) != '%' || stop) {
if (ch == '\0')
return (retval);
PCHAR(ch);
}
percent = fmt - 1;
lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
reswitch: switch (ch = (u_char)*fmt++) {
case '.':
dot = 1;
goto reswitch;
case '#':
sharpflag = 1;
goto reswitch;
case '+':
sign = 1;
goto reswitch;
case '-':
ladjust = 1;
goto reswitch;
case '%':
PCHAR(ch);
break;
case '*':
if (!dot) {
width = va_arg(ap, int);
if (width < 0) {
ladjust = !ladjust;
width = -width;
}
} else {
dwidth = va_arg(ap, int);
}
goto reswitch;
case '0':
if (!dot) {
padc = '0';
goto reswitch;
}
case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
for (n = 0;; ++fmt) {
n = n * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
if (dot)
dwidth = n;
else
width = n;
goto reswitch;
case 'c':
width -= 1;
if (!ladjust && width > 0)
while (width--)
PCHAR(padc);
PCHAR(va_arg(ap, int));
if (ladjust && width > 0)
while (width--)
PCHAR(padc);
break;
case 'D':
up = va_arg(ap, u_char *);
p = va_arg(ap, char *);
if (!width)
width = 16;
while(width--) {
PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f));
up++;
if (width)
for (q=p;*q;q++)
PCHAR(*q);
}
break;
case 'd':
case 'i':
base = 10;
sign = 1;
goto handle_sign;
case 'h':
if (hflag) {
hflag = 0;
cflag = 1;
} else
hflag = 1;
goto reswitch;
case 'j':
jflag = 1;
goto reswitch;
case 'l':
if (lflag) {
jflag = 1;
} else
lflag = 1;
goto reswitch;
case 'o':
base = 8;
goto handle_nosign;
case 'p':
base = 16;
sharpflag = (width == 0);
sign = 0;
num = (uintptr_t)va_arg(ap, void *);
goto number;
case 's':
p = va_arg(ap, char *);
if (p == NULL)
p = "(null)";
if (!dot)
n = strlen (p);
else
for (n = 0; n < dwidth && p[n]; n++)
continue;
width -= n;
if (!ladjust && width > 0)
while (width--)
PCHAR(padc);
while (n--)
PCHAR(*p++);
if (ladjust && width > 0)
while (width--)
PCHAR(padc);
break;
case 't':
tflag = 1;
goto reswitch;
case 'u':
base = 10;
goto handle_nosign;
case 'X':
upper = 1;
case 'x':
base = 16;
goto handle_nosign;
case 'y':
base = 16;
sign = 1;
goto handle_sign;
case 'z':
zflag = 1;
goto reswitch;
handle_nosign:
sign = 0;
if (jflag)
num = va_arg(ap, uintmax_t);
#if __SIZEOF_PTRDIFF_T__ != __SIZEOF_LONG__
else if (tflag)
num = va_arg(ap, ptrdiff_t);
#endif
else if (lflag)
num = va_arg(ap, u_long);
#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG__
else if (zflag)
num = va_arg(ap, size_t);
#endif
else if (hflag)
num = (u_short)va_arg(ap, int);
else if (cflag)
num = (u_char)va_arg(ap, int);
else
num = va_arg(ap, u_int);
goto number;
handle_sign:
if (jflag)
num = va_arg(ap, intmax_t);
#if __SIZEOF_PTRDIFF_T__ == __SIZEOF_LONG__
else if (tflag)
num = va_arg(ap, ptrdiff_t);
#endif
else if (lflag)
num = va_arg(ap, long);
#if __SIZEOF_SIZE_T__ == __SIZEOF_LONG__
else if (zflag)
num = va_arg(ap, ssize_t);
#endif
else if (hflag)
num = (short)va_arg(ap, int);
else if (cflag)
num = (char)va_arg(ap, int);
else
num = va_arg(ap, int);
number:
if (sign && (intmax_t)num < 0) {
neg = 1;
num = -(intmax_t)num;
}
p = ksprintn(nbuf, num, base, &n, upper);
tmp = 0;
if (sharpflag && num != 0) {
if (base == 8)
tmp++;
else if (base == 16)
tmp += 2;
}
if (neg)
tmp++;
if (!ladjust && padc == '0')
dwidth = width - tmp;
width -= tmp + imax(dwidth, n);
dwidth -= n;
if (!ladjust)
while (width-- > 0)
PCHAR(' ');
if (neg)
PCHAR('-');
if (sharpflag && num != 0) {
if (base == 8) {
PCHAR('0');
} else if (base == 16) {
PCHAR('0');
PCHAR('x');
}
}
while (dwidth-- > 0)
PCHAR('0');
while (*p)
PCHAR(*p--);
if (ladjust)
while (width-- > 0)
PCHAR(' ');
break;
default:
while (percent < fmt)
PCHAR(*percent++);
/*
* Since we ignore a formatting argument it is no
* longer safe to obey the remaining formatting
* arguments as the arguments will no longer match
* the format specs.
*/
stop = 1;
break;
}
}
#undef PCHAR
}

View File

@@ -13,7 +13,7 @@
#include "config.h"
#endif
#include <rtems/score/basedefs.h>
#include <rtems/score/io.h>
/*
* Undefined the RTEMS_PRINTFLIKE and make it nothing. The test code
@@ -27,19 +27,12 @@
const char rtems_test_name[] = "SPPRINTK";
/* forward declarations to avoid warnings */
rtems_task Init(rtems_task_argument argument);
int test_getchar(void);
void do_getchark(void);
void do_putk(void);
void do_printk(void);
int test_getchar(void)
static int test_getchar(void)
{
return 0x35;
}
void do_getchark(void)
static void do_getchark(void)
{
int sc;
BSP_polling_getchar_function_type poll_char;
@@ -60,52 +53,49 @@ void do_getchark(void)
BSP_poll_char = poll_char;
}
void do_putk(void)
static void do_putk(void)
{
putk( "This is a test of putk" );
}
void do_printk(void)
static void do_printk(void)
{
long lm = 2147483647L;
unsigned long ulm = 4294967295UL;
long long llm = 9223372036854775807LL;
long long ullm = 18446744073709551615ULL;
printk( "bad format -- %%q in parentheses (%q)\n" );
printk( "bad format -- %%q in parentheses (%q)\n" );
printk( "bad format -- %%lq in parentheses (%lq)\n", 0x1234 );
printk( "bad format -- %%lq in parentheses (%lq)\n" );
printk( "%%O octal upper case 16 -- %O\n", 16 );
printk( "%%o octal lower case of 16 -- %O\n", 16 );
printk( "%%I of 16 -- %I\n", 16 );
printk( "%%i of 16 -- %i\n", 16 );
printk( "%%D of 16 -- %D\n", 16 );
printk( "%%d of 16 -- %d\n", 16 );
printk( "%%-3d of 16 -- %-3d\n", 16 );
printk( "%%U of 16 -- %U\n", 16 );
printk( "%%u of 16 -- %u\n", 16 );
printk( "%%X of 16 -- %X\n", 16 );
printk( "%%x of 16 -- %x\n", 16 );
printk( "%%p of 0x1234 -- %p\n", (void *)0x1234 );
printk( "%%o of 16 -- %o\n", 16 );
printk( "%%i of 16 -- %i\n", 16 );
printk( "%%d of 16 -- %d\n", 16 );
printk( "'%%-3d' of 16 -- '%-3d'\n", 16 );
printk( "'%%3d' of 16 -- '%3d'\n", 16 );
printk( "%%u of 16 -- %u\n", 16 );
printk( "%%X of 16 -- %X\n", 16 );
printk( "%%x of 16 -- %x\n", 16 );
printk( "%%p of 0x1234 -- %p\n", (void *)0x1234 );
/* long */
printk( "%%lo of 2147483647 -- %lo\n", lm );
printk( "%%li of 2147483647 -- %li\n", lm );
printk( "%%lu of 2147483647 -- %lu\n", lm );
printk( "%%lx of 2147483647 -- %lx\n", lm );
printk( "%%lo of -2147483648 -- %lo\n", -lm - 1L );
printk( "%%li of -2147483648 -- %li\n", -lm - 1L );
printk( "%%lx of -2147483648 -- %lx\n", -lm - 1L );
printk( "%%lo of 4294967295 -- %lo\n", ulm );
printk( "%%lu of 4294967295 -- %lu\n", ulm );
printk( "%%lx of 4294967295 -- %lx\n", ulm );
printk( "%%lo of 2147483647 -- %lo\n", lm );
printk( "%%li of 2147483647 -- %li\n", lm );
printk( "%%lu of 2147483647 -- %lu\n", lm );
printk( "%%lx of 2147483647 -- %lx\n", lm );
printk( "%%lo of -2147483648 -- %lo\n", -lm - 1L );
printk( "%%li of -2147483648 -- %li\n", -lm - 1L );
printk( "%%lx of -2147483648 -- %lx\n", -lm - 1L );
printk( "%%lo of 4294967295 -- %lo\n", ulm );
printk( "%%lu of 4294967295 -- %lu\n", ulm );
printk( "%%lx of 4294967295 -- %lx\n", ulm );
/* long long */
printk( "%%llo of 9223372036854775807 -- %llo\n", llm );
printk( "%%lli of 9223372036854775807 -- %lli\n", llm );
printk( "%%llu of 9223372036854775807 -- %llu\n", llm );
printk( "%%llx of 9223372036854775807 -- %llx\n", llm );
printk( "%%llo of 9223372036854775807 -- %llo\n", llm );
printk( "%%lli of 9223372036854775807 -- %lli\n", llm );
printk( "%%llu of 9223372036854775807 -- %llu\n", llm );
printk( "%%llx of 9223372036854775807 -- %llx\n", llm );
printk( "%%llo of -9223372036854775808 -- %llo\n", -llm - 1LL );
printk( "%%lli of -9223372036854775808 -- %lli\n", -llm - 1LL );
printk( "%%llx of -9223372036854775808 -- %llx\n", -llm - 1LL );
@@ -114,22 +104,90 @@ void do_printk(void)
printk( "%%llx of 18446744073709551615 -- %llx\n", ullm );
/* negative numbers */
printk( "%%d of -16 -- %d\n", -16 );
printk( "%%d of -16 -- %-3d\n", -16 );
printk( "%%u of -16 -- %u\n", -16 );
printk( "%%d of -16 -- %d\n", -16 );
printk( "%%d of -16 -- %-3d\n", -16 );
printk( "%%u of -16 -- %u\n", -16 );
/* string formats */
printk( "%%s of Mary Had a Little Lamb -- (%s)\n",
printk( "%%s of Mary Had a Little Lamb -- '%s'\n",
"Mary Had a Little Lamb" );
printk( "%%s of NULL -- (%s)\n", NULL );
printk( "%%12s of joel -- (%20s)\n", "joel" );
printk( "%%4s of joel -- (%4s)\n", "joel" );
printk( "%%-12s of joel -- (%-20s)\n", "joel" );
printk( "%%-4s of joel -- (%-4s)\n", "joel" );
printk( "%%c of X -- (%c)\n", 'X' );
printk( "%%s of NULL -- '%s'\n", NULL );
printk( "%%12s of joel -- '%20s'\n", "joel" );
printk( "%%4s of joel -- '%4s'\n", "joel" );
printk( "%%-12s of joel -- '%-20s'\n", "joel" );
printk( "%%-4s of joel -- '%-4s'\n", "joel" );
printk( "%%c of X -- '%c'\n", 'X' );
printk( "%%hhu of X -- %hhu\n", 'X' );
}
rtems_task Init(
typedef struct {
char buf[128];
size_t i;
} test_context;
static test_context test_instance;
static void clear( test_context *ctx )
{
ctx->i = 0;
memset( ctx->buf, 0, sizeof( ctx->buf ) );
}
static void put_char( int c, void *arg )
{
test_context *ctx;
ctx = arg;
if ( ctx->i < sizeof( ctx->buf ) ) {
ctx->buf[ ctx->i ] = (char) c;
++ctx->i;
}
}
static test_context test_instance;
static void test_io_printf( test_context *ctx )
{
int i;
intmax_t j;
long long ll;
long l;
size_t z;
ptrdiff_t t;
clear( ctx );
i = 123;
_IO_Printf( put_char, ctx, "%i", i );
rtems_test_assert( strcmp( ctx->buf, "123" ) == 0 );
clear( ctx );
j = 456;
_IO_Printf( put_char, ctx, "%ji", j );
rtems_test_assert( strcmp( ctx->buf, "456" ) == 0 );
clear( ctx );
ll = 789;
_IO_Printf( put_char, ctx, "%lli", ll );
rtems_test_assert( strcmp( ctx->buf, "789" ) == 0 );
clear( ctx );
l = 101112;
_IO_Printf( put_char, ctx, "%li", l );
rtems_test_assert( strcmp( ctx->buf, "101112" ) == 0 );
clear( ctx );
z = 131415;
_IO_Printf( put_char, ctx, "%zi", z );
rtems_test_assert( strcmp( ctx->buf, "131415" ) == 0 );
clear( ctx );
t = 161718;
_IO_Printf( put_char, ctx, "%ti", t );
rtems_test_assert( strcmp( ctx->buf, "161718" ) == 0 );
}
static rtems_task Init(
rtems_task_argument argument
)
{
@@ -142,6 +200,7 @@ rtems_task Init(
putk("");
do_getchark();
test_io_printf(&test_instance);
TEST_END();
rtems_test_exit( 0 );

View File

@@ -1,51 +1,50 @@
*** TEST PRINTK ***
*** BEGIN OF TEST SPPRINTK ***
This is a test of putk
bad format -- %q in parentheses (q)
bad format -- %lq in parentheses (q)
%O octal upper case 16 -- 20
%o octal lower case of 16 -- 20
%I of 16 -- 16
%i of 16 -- 16
%D of 16 -- 16
%d of 16 -- 16
%-3d of 16 -- 16
%U of 16 -- 16
%u of 16 -- 16
%X of 16 -- 10
%x of 16 -- 10
%p of 0x1234 -- 1234
%lo of 2147483647 -- 17777777777
%li of 2147483647 -- 2147483647
%lu of 2147483647 -- 2147483647
%lx of 2147483647 -- 7FFFFFFF
%lo of -2147483648 -- 20000000000
%li of -2147483648 -- -2147483648
%lx of -2147483648 -- 80000000
%lo of 4294967295 -- 37777777777
%lu of 4294967295 -- 4294967295
%lx of 4294967295 -- FFFFFFFF
%llo of 9223372036854775807 -- 777777777777777777777
%lli of 9223372036854775807 -- 9223372036854775807
%llu of 9223372036854775807 -- 9223372036854775807
%llx of 9223372036854775807 -- 7FFFFFFFFFFFFFFF
bad format -- %q in parentheses (%q)
bad format -- %lq in parentheses (%lq)
%o of 16 -- 20
%i of 16 -- 16
%d of 16 -- 16
'%-3d' of 16 -- '16 '
'%3d' of 16 -- ' 16'
%u of 16 -- 16
%X of 16 -- 10
%x of 16 -- 10
%p of 0x1234 -- 0x1234
%lo of 2147483647 -- 17777777777
%li of 2147483647 -- 2147483647
%lu of 2147483647 -- 2147483647
%lx of 2147483647 -- 7fffffff
%lo of -2147483648 -- 20000000000
%li of -2147483648 -- -2147483648
%lx of -2147483648 -- 80000000
%lo of 4294967295 -- 37777777777
%lu of 4294967295 -- 4294967295
%lx of 4294967295 -- ffffffff
%llo of 9223372036854775807 -- 777777777777777777777
%lli of 9223372036854775807 -- 9223372036854775807
%llu of 9223372036854775807 -- 9223372036854775807
%llx of 9223372036854775807 -- 7fffffffffffffff
%llo of -9223372036854775808 -- 1000000000000000000000
%lli of -9223372036854775808 -- -9223372036854775808
%llx of -9223372036854775808 -- 8000000000000000
%llo of 18446744073709551615 -- 1777777777777777777777
%llu of 18446744073709551615 -- 18446744073709551615
%llx of 18446744073709551615 -- FFFFFFFFFFFFFFFF
%d of -16 -- -16
%d of -16 -- -16
%u of -16 -- 4294967280
%s of Mary Had a Little Lamb -- (Mary Had a Little Lamb)
%s of NULL -- ()
%12s of joel -- ( joel)
%4s of joel -- (joel)
%-12s of joel -- (joel )
%-4s of joel -- (joel)
%c of X -- (X)
%llx of 18446744073709551615 -- ffffffffffffffff
%d of -16 -- -16
%d of -16 -- -16
%u of -16 -- 4294967280
%s of Mary Had a Little Lamb -- 'Mary Had a Little Lamb'
%s of NULL -- '(null)'
%12s of joel -- ' joel'
%4s of joel -- 'joel'
%-12s of joel -- 'joel '
%-4s of joel -- 'joel'
%c of X -- 'X'
%hhu of X -- 88
getchark - NULL getchar method - return -1
getchark - test getchar method - returns 0x35
*** END OF TEST PRINTK ***
*** END OF TEST SPPRINTK ***