summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-10-23 13:30:44 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-11-06 07:25:51 +0100
commit10827984c2cf54188a9af71b94a7e83197812bb5 (patch)
treed0faa328fff4ed71c72993675a231a1b6a0d710c
parenta54d10d17724ffe780e998acd0b7f3d673b2ff67 (diff)
downloadrtems-10827984c2cf54188a9af71b94a7e83197812bb5.tar.bz2
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.
-rw-r--r--cpukit/libcsupport/src/vprintk.c220
-rw-r--r--cpukit/score/Makefile.am3
-rw-r--r--cpukit/score/include/rtems/score/io.h46
-rw-r--r--cpukit/score/preinstall.am4
-rw-r--r--cpukit/score/src/ioprintf.c31
-rw-r--r--cpukit/score/src/iovprintf.c365
-rw-r--r--testsuites/sptests/spprintk/init.c161
-rw-r--r--testsuites/sptests/spprintk/spprintk.scn81
8 files changed, 613 insertions, 298 deletions
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
+ * <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 );
}
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
+ * <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 */
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
+ * <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;
+}
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 <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
+}
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 <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' );
+}
+
+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 ***