/* This file is part of MutekP. MutekP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. MutekP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with MutekP; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA UPMC / LIP6 / SOC (c) 2007 */ /* revision 1.2.2 2011/07/12 11:08:34 Ghassan - Split main loop into 3 noinline functions: compute_dec32, compute_dec64, compute_hex - Use bigger buffer size - Reuse buffer treatment - Add 64 bits support - Add char count; revision 1.2.1 2007/11/11 18:54:23 Ghassan rename iprintf to __iprintk, it's a copy of iprintf called on system level. stdio of the ghost of libc Developped by Denis Hommais and Frédéric Pétrot $Log: iprintf.c,v $ Revision 1.2 2003/07/01 13:40:46 fred Supports the %u and doesnt core anymore on an unrecognized char following a % Revision 1.1.1.1 2002/02/28 12:58:56 disydent Creation of Disydent CVS Tree Revision 1.1 2001/11/22 15:07:36 fred Adding the iprintf function that does the formatting, and removes all the old stuff hanging around. $Id: iprintf.c,v 1.2 2003/07/01 13:40:46 fred Exp $ Made up this file to centralize the printf behavior */ #include #include #include /* Handling of the printf internals * Addr is either the buffer or the tty addrs * inc is 0 for a tty and 1 for a buffer * Other arguments are self explanatory */ #define SIZE_OF_BUF 20 static char* __attribute__((noinline)) compute_dec64(char **addr, char *buf, int inc, uint64_t val, bool_t isSigned) { register int64_t sval; register uint32_t uval; register char *tmp; register uint_t count; register uint_t i; if(isSigned == true) { sval = val; if(sval < 0) { sval = -sval; val = sval; **addr = '-'; (*addr) += inc; } } count = 0; i = 0; tmp = buf + SIZE_OF_BUF; *--tmp = '\0'; while(val >= 1000000000UL) { val -= 1000000000UL; count ++; } uval = (uint32_t) val; do { *--tmp = (uval % 10) + '0'; uval /= 10; i++; }while((uval) || (i < 9)); uval = count; do { *--tmp = (uval % 10) + '0'; uval /= 10; }while(uval); return tmp; } static char* __attribute__((noinline)) compute_dec(char **addr, char *buf, int inc, uint_t val, bool_t isSigned) { register sint_t sval; register char *tmp; if(isSigned == true) { sval = val; if(sval < 0) { sval = -sval; val = sval; **addr = '-'; (*addr) += inc; } } tmp = buf + SIZE_OF_BUF; *--tmp = '\0'; do { *--tmp = (val % 10) + '0'; val /= 10; }while (val); return tmp; } static char* __attribute__((noinline)) compute_hex(char **addr, char *buf, uint_t val, bool_t isPointer) { register char *tmp; register char *xdigit; register uint_t i; i = 0; xdigit = "0123456789abcdef"; tmp = buf + SIZE_OF_BUF; *--tmp = '\0'; do { *--tmp = xdigit[val & 15]; val = val >> 4; i++; }while (val); if(isPointer) { while (i < 8) { *--tmp = xdigit[0]; i++; } } return tmp; } int iprintk (char *addr, int inc, const char *fmt, va_list ap) { char *tmp; sint_t val; uint_t uval; uint_t count = 0; char buf[SIZE_OF_BUF]; while (*fmt) { while ((*fmt != '%') && (*fmt)) { *addr = *fmt++; addr += inc; count++; } if (*fmt) { fmt++; switch (*fmt) { case '%': *addr = '%'; addr += inc; count++; goto next; case 'c': *addr = va_arg (ap, uint_t); addr += inc; count++; goto next; case 'd': count ++; val = va_arg (ap, sint_t); tmp = compute_dec(&addr, &buf[0], inc, val, true); break; case 'u': uval = va_arg (ap, uint_t); tmp = compute_dec(&addr, &buf[0], inc, uval, false); break; case 'D': count ++; val = va_arg (ap, int64_t); tmp = compute_dec64(&addr, &buf[0], inc, val, true); break; case 'U': uval = va_arg (ap, uint64_t); tmp = compute_dec64(&addr, &buf[0], inc, uval, false); break; case 's': tmp = va_arg (ap, char *); if (!tmp) tmp = "empty str"; break; case 'p': case 'x': uval = va_arg (ap, uint_t); tmp = compute_hex(&addr, &buf[0], uval, (*fmt == 'p') ? true : false); break; default: *addr = *fmt; count++; goto next; } while (*tmp) { *addr = *tmp++; addr += inc; count++; } next: fmt++; } } va_end (ap); return count; }