From 10827984c2cf54188a9af71b94a7e83197812bb5 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Oct 2017 13:30:44 +0200 Subject: 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. --- cpukit/libcsupport/src/vprintk.c | 220 ++----------------- cpukit/score/Makefile.am | 3 + cpukit/score/include/rtems/score/io.h | 46 ++++ cpukit/score/preinstall.am | 4 + cpukit/score/src/ioprintf.c | 31 +++ cpukit/score/src/iovprintf.c | 365 +++++++++++++++++++++++++++++++ testsuites/sptests/spprintk/init.c | 161 +++++++++----- testsuites/sptests/spprintk/spprintk.scn | 81 ++++--- 8 files changed, 613 insertions(+), 298 deletions(-) create mode 100644 cpukit/score/include/rtems/score/io.h create mode 100644 cpukit/score/src/ioprintf.c create mode 100644 cpukit/score/src/iovprintf.c diff --git a/cpukit/libcsupport/src/vprintk.c b/cpukit/libcsupport/src/vprintk.c index a254934a0d..09b6f0f006 100644 --- a/cpukit/libcsupport/src/vprintk.c +++ b/cpukit/libcsupport/src/vprintk.c @@ -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 + * * - * 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 -#include -#include #include +#include -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 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 ); } diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index 7ff1f41684..11bf59cca8 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -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 diff --git a/cpukit/score/include/rtems/score/io.h b/cpukit/score/include/rtems/score/io.h new file mode 100644 index 0000000000..ae3c57f031 --- /dev/null +++ b/cpukit/score/include/rtems/score/io.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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 + +#include + +#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 */ diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index 0329b9ce92..3d70ec311f 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -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 diff --git a/cpukit/score/src/ioprintf.c b/cpukit/score/src/ioprintf.c new file mode 100644 index 0000000000..05e31566e7 --- /dev/null +++ b/cpukit/score/src/ioprintf.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * 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 + +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; +} diff --git a/cpukit/score/src/iovprintf.c b/cpukit/score/src/iovprintf.c new file mode 100644 index 0000000000..cf54ecbbc7 --- /dev/null +++ b/cpukit/score/src/iovprintf.c @@ -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 + +#include +__FBSDID("$FreeBSD: head/sys/kern/subr_prf.c 320908 2017-07-12 07:30:14Z rlibby $"); + +#include +#include + +/* 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 +} diff --git a/testsuites/sptests/spprintk/init.c b/testsuites/sptests/spprintk/init.c index e956c76ff3..4ef28daf5d 100644 --- a/testsuites/sptests/spprintk/init.c +++ b/testsuites/sptests/spprintk/init.c @@ -13,7 +13,7 @@ #include "config.h" #endif -#include +#include /* * 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' ); +} + +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 ); } -rtems_task Init( +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 ); diff --git a/testsuites/sptests/spprintk/spprintk.scn b/testsuites/sptests/spprintk/spprintk.scn index 4b8130b75c..d537750472 100644 --- a/testsuites/sptests/spprintk/spprintk.scn +++ b/testsuites/sptests/spprintk/spprintk.scn @@ -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 *** -- cgit v1.2.3