2005-01-18 Joerg Wunsch Implement savannah patch #3516: %S format for printf(). * AUTHORS: Mention Helmut Wallner for his contribution. * include/stdio.h: Document the new %S format. * include/avr/pgmspace.h: Prototype for new strnlen_P() function. * libc/pmstring/Makefile.am: Include strnlen_P.S. * libc/stdio/vfprintf.c: Add implementation for %S. Index: AUTHORS =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/AUTHORS,v retrieving revision 1.6 diff -u -u -r1.6 AUTHORS --- AUTHORS 31 Dec 2004 15:43:48 -0000 1.6 +++ AUTHORS 18 Jan 2005 16:18:47 -0000 @@ -27,6 +27,7 @@ Philip Soeberg Nils Kristian Strom Michael Stumpf +Helmut Wallner Eric B. Weddington Joerg Wunsch University of California Index: NEWS =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/NEWS,v retrieving revision 1.42 diff -u -u -r1.42 NEWS --- NEWS 16 Jan 2005 18:26:01 -0000 1.42 +++ NEWS 18 Jan 2005 16:18:47 -0000 @@ -11,6 +11,18 @@ [#11510] Abstract the change enable bit in wdt.h for mega32. [#11522] Rewrite wdt_disable() to match datasheet algorithm. +* Extend stdio and pmstring APIs: + +Implement patch #3516: printf: Handling of argument strings from +program memory + +The %S format can now be used to print strings that are located in +program-space memory (aka. ROM). + +As a prerequisite for this, the function strnlen_P() has been added +which is similar to strnlen() except that it takes a pointer to a +program-space string. + *** Changes in avr-libc-1.2: * Bugs fixed: Index: include/stdio.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/stdio.h,v retrieving revision 1.16 diff -u -u -r1.16 stdio.h --- include/stdio.h 29 Oct 2004 16:26:47 -0000 1.16 +++ include/stdio.h 18 Jan 2005 16:18:49 -0000 @@ -1,4 +1,4 @@ -/* Copyright (c) 2002 Joerg Wunsch +/* Copyright (c) 2002, 2005, Joerg Wunsch All rights reserved. Portions of documentation Copyright (c) 1990, 1991, 1993 @@ -337,6 +337,8 @@ than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit. + - \c S Similar to the \c s format, except the pointer is expected to + point to a program-memory (ROM) string instead of a RAM string. In no case does a non-existent or small field width cause truncation of a numeric field; if the result of a conversion is wider than the field Index: include/avr/pgmspace.h =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/include/avr/pgmspace.h,v retrieving revision 1.22 diff -u -u -r1.22 pgmspace.h --- include/avr/pgmspace.h 19 Sep 2004 19:11:06 -0000 1.22 +++ include/avr/pgmspace.h 18 Jan 2005 16:18:51 -0000 @@ -495,6 +495,7 @@ extern size_t strlcat_P (char *, PGM_P, size_t ); extern size_t strlcpy_P (char *, PGM_P, size_t ); extern size_t strlen_P(PGM_P) __ATTR_CONST__; /* program memory can't change */ +extern size_t strnlen_P(PGM_P, size_t) __ATTR_CONST__; /* program memory can't change */ extern int strncmp_P(const char *, PGM_P, size_t) __ATTR_PURE__; extern int strncasecmp_P(const char *, PGM_P, size_t) __ATTR_PURE__; extern char *strncat_P(char *, PGM_P, size_t); Index: libc/pmstring/Makefile.am =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/libc/pmstring/Makefile.am,v retrieving revision 1.2 diff -u -u -r1.2 Makefile.am --- libc/pmstring/Makefile.am 19 Jun 2003 20:11:29 -0000 1.2 +++ libc/pmstring/Makefile.am 18 Jan 2005 16:18:51 -0000 @@ -42,7 +42,8 @@ strncasecmp_P.S \ strncat_P.S \ strncmp_P.S \ - strncpy_P.S + strncpy_P.S \ + strnlen_P.S lib_a_SOURCES = $(lib_a_asm_sources) Index: libc/stdio/vfprintf.c =================================================================== RCS file: /cvsroot/avr-libc/avr-libc/libc/stdio/vfprintf.c,v retrieving revision 1.11 diff -u -u -r1.11 vfprintf.c --- libc/stdio/vfprintf.c 28 Dec 2004 19:26:41 -0000 1.11 +++ libc/stdio/vfprintf.c 18 Jan 2005 16:18:56 -0000 @@ -1,5 +1,6 @@ /* Copyright (c) 2002, Alexander Popov (address@hidden) Copyright (c) 2002,2004 Joerg Wunsch + Copyright (c) 2005, Helmut Wallner All rights reserved. Redistribution and use in source and binary forms, with or without @@ -349,6 +350,18 @@ base = strlen(a.pc); #endif goto nextitem; + case 'S': + a.pc = va_arg(ap, char *); +#if PRINTF_LEVEL > PRINTF_MIN + if (flags & FLPREC) + base = strnlen_P(a.pc, prec); + else + base = strlen_P(a.pc); + width -= base; +#else + base = strlen_P(a.pc); +#endif + goto nextitem; case 'd': case 'i': a.l = flags & FLLONG ? @@ -470,6 +483,11 @@ else if (c == 's') while (base--) putc(*a.pc++, stream); + else if (c == 'S') + while (base--) { + putc(pgm_read_byte(a.pc), stream); + a.pc++; + } #if PRINTF_LEVEL >= PRINTF_FLT else if (flags & FLFLOAT) { if (flags & FLFCVT) { --- /dev/null Tue Jan 18 17:17:31 2005 +++ libc/pmstring/strnlen_P.S Mon Jan 17 23:23:53 2005 @@ -0,0 +1,76 @@ +/* Copyright (c) 2005, Helmut Wallner + + based on libc/string/strnlen.S which is + Copyright (c) 2002, Marek Michalkiewicz + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of the copyright holders nor the names of + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. */ + +/* $Id$ */ + +#include "macros.inc" + +#define src_hi r25 +#define src_lo r24 +#define len_hi r23 +#define len_lo r22 + +/** \ingroup avr_pgmspace + \fn size_t strnlen_P(PGM_P src, size_t len) + \brief Determine the length of a fixed-size string. + + The strnlen_P() function is similar to strnlen(), except that \c src is a + pointer to a string in program space. + + \returns The strnlen_P function returns strlen_P(src), if that is less than + \c len, or \c len if there is no '\\0' character among the first \c len + characters pointed to by \c src. */ + +#if !defined(DOXYGEN) + + .text + .global _U(strnlen_P) + .type _U(strnlen_P), @function +_U(strnlen_P): + LOAD_Z(src_lo, src_hi) +1: + subi len_lo, lo8(1) + sbci len_hi, hi8(1) + LPM_R0_ZP + cpse r0, __zero_reg__ + brcc 1b +; Z points one character past the terminating NUL +; return Z - 1 - src = (-1 - src) + Z = ~src + Z + com src_lo + com src_hi + add src_lo, ZL + adc src_hi, ZH + ret +.Lstrnlen_P_end: + .size _U(strnlen_P), .Lstrnlen_P_end - _U(strnlen_P) + +#endif /* not DOXYGEN */