forked from Imagelibrary/rtems
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:
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
46
cpukit/score/include/rtems/score/io.h
Normal file
46
cpukit/score/include/rtems/score/io.h
Normal 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 */
|
||||
@@ -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
|
||||
|
||||
31
cpukit/score/src/ioprintf.c
Normal file
31
cpukit/score/src/ioprintf.c
Normal 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;
|
||||
}
|
||||
365
cpukit/score/src/iovprintf.c
Normal file
365
cpukit/score/src/iovprintf.c
Normal 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
|
||||
}
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 ***
|
||||
|
||||
Reference in New Issue
Block a user