/*-----------------------------------------------------------------
- printfl.c - source file for reduced version of printf
-
+ printfl.c - source file for reduced version of printf
+
Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
-
- This program is distributed in the hope that it will be useful,
+
+ This library 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
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
+
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
+ what you give them. Help stamp out software-hoarding!
+
+ 2001060401: Improved by was@icb.snz.chel.su
-------------------------------------------------------------------------*/
+
/* following formats are supported :-
format output type argument-type
%d decimal int
- %ld decimal long
- %hd decimal short/char
+ %ld decimal long
+ %hd decimal char
%x hexadecimal int
- %lx hexadecimal long
- %hx hexadecimal short/char
+ %lx hexadecimal long
+ %hx hexadecimal char
%o octal int
- %lo octal long
- %ho octal short/char
- %c character char/short
- %s character _generic pointer
+ %lo octal long
+ %ho octal char
+ %c character char
+ %s character generic pointer
*/
#include <stdarg.h>
-#include <reg51.h>
-extern void putchar(char );
-
-static data volatile char ch;
-static data char radix ;
-static bit long_flag = 0;
-static bit string_flag =0;
-static bit short_flag = 0;
-static bit sign;
-static char * data str ;
-static data long val;
-
-static void pvalhex( long val)
-{
- volatile char sp = SP;
- unsigned long lval = val;
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __ds390
+/* just for the SP */
+#include <8051.h>
+#endif
- if (!long_flag)
- lval &= 0x0000ffff;
+static __data char radix ;
+static __bit long_flag = 0;
+static __bit string_flag =0;
+static __bit char_flag = 0;
+static char * __data str ;
+static __data long val;
- if (short_flag)
- lval &= 0x000000ff;
+/* This great loop fails with the ds390 port (2003-01-13).
- while (lval) {
- ch = "0123456789ABCDEF"[(unsigned short)lval & 0x0f];
- _asm push _ch _endasm;
- lval /= 16;
- }
+ At the beginning resp. end of the loop the compiler inserts a "push ar2"
+ resp. "pop ar2", which badly interfers with the push/pop in the source.
- while (sp != SP) {
- _asm pop _ch _endasm;
- putchar(ch);
- }
-
-}
+ Library functions should be rock solid and portable. There's an _ltoa in
+ the library, so let's use it and don't reinvent the wheel.
+
+ Bernhard
+*/
-static void pvaloct(long val)
+#if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
+static __data volatile char ch;
+static __bit sign;
+
+static void pval(void)
{
- char sp ;
- unsigned long lval;
- sp = SP;
- if (val < 0) {
- lval = -val;
- sign = 1;
- } else {
- lval = val;
- sign = 0;
+ volatile char sp;
+ unsigned long lval;
+ sp = SP;
+
+ if (val < 0 && radix != 16)
+ {
+ lval = -val;
+ sign = 1;
+ }
+ else { sign = 0; lval = val;}
+
+ if (!long_flag) {
+ lval &= 0x0000ffff;
}
-
- if (!long_flag)
- lval &= 0x0000ffff;
- if (short_flag)
- lval &= 0x000000ff;
-
- while (lval) {
- ch = (lval % 8) + '0';
- _asm push _ch _endasm;
- lval = lval / 8;
+ if (char_flag) {
+ lval &= 0x000000ff;
}
- if (sign) {
- ch = '-';
- _asm push _ch _endasm;
- }
-
-
- while (sp != SP) {
- _asm pop _ch _endasm;
- putchar(ch);
+ do
+ {
+
+# if 1
+ if(radix != 16) ch = (lval % radix) + '0';
+ else ch = "0123456789ABCDEF"[(unsigned char)lval & 0x0f];
+ __asm push _ch __endasm;
+ lval /= radix;
+# else
+ // This only looks more efficient, but isn't. see the .map
+ ch = (lval % radix) + '0';
+ if (ch>'9') ch+=7;
+ __asm push _ch __endasm;
+ lval /= radix;
+# endif
}
-}
+ while (lval);
-static void pvaldec(long val )
-{
- char sp ;
- unsigned long lval;
- sp = SP;
- if (val < 0) {
- lval = -val;
- sign = 1;
- } else {
- lval = val;
- sign = 0;
- }
-
- while (lval) {
- ch = (lval % 10) + '0';
- _asm push _ch _endasm;
- lval = lval / 10;
- }
+ if (sign) {
+ ch = '-';
+ __asm push _ch __endasm;
+ }
- if (sign) {
- ch = '-';
- _asm push _ch _endasm;
- }
-
-
- while (sp != SP) {
- _asm pop _ch _endasm;
- putchar(ch);
+ while (sp != SP) {
+ __asm pop _ch __endasm;
+ putchar(ch);
}
}
+#endif
-void printf_small (char * fmt, ... ) reentrant
+void printf_small (char * fmt, ... ) __reentrant
{
va_list ap ;
-
+
va_start(ap,fmt);
-
+
for (; *fmt ; fmt++ ) {
- if (*fmt == '%') {
- long_flag = string_flag = short_flag = 0;
- fmt++ ;
- switch (*fmt) {
- case 'l':
- long_flag = 1;
- fmt++;
- break;
- case 'h':
- short_flag = 1;
- fmt++;
- }
-
- switch (*fmt) {
- case 's':
- string_flag = 1;
- break;
- case 'd':
- radix = 10;
- break;
- case 'x':
- radix = 16;
- break;
- case 'c':
- radix = 0;
- break;
- case 'o':
- radix = 8;
- break;
- }
-
- if (string_flag) {
- str = va_arg(ap,char _generic *);
- while (*str) putchar(*str++);
- continue ;
- }
-
- if (long_flag)
- val = va_arg(ap,long);
- else
- if (short_flag)
- val = va_arg(ap,short);
- else
- val = va_arg(ap,int);
-
- switch (radix) {
- case 10:
- pvaldec(val) ;
- break;
- case 16:
- pvalhex (val);
- break;
- case 0:
- putchar((char)val);
- break;
- case 8:
- pvaloct(val) ;
- break;
- }
-
- } else
- putchar(*fmt);
- }
+ if (*fmt == '%') {
+ long_flag = string_flag = char_flag = 0;
+ fmt++ ;
+ switch (*fmt) {
+ case 'l':
+ long_flag = 1;
+ fmt++;
+ break;
+ case 'h':
+ char_flag = 1;
+ fmt++;
+ }
+
+ switch (*fmt) {
+ case 's':
+ string_flag = 1;
+ break;
+ case 'd':
+ radix = 10;
+ break;
+ case 'x':
+ radix = 16;
+ break;
+ case 'c':
+ radix = 0;
+ break;
+ case 'o':
+ radix = 8;
+ break;
+ }
+
+ if (string_flag) {
+ str = va_arg(ap, char *);
+ while (*str) putchar(*str++);
+ continue ;
+ }
+
+ if (long_flag)
+ val = va_arg(ap,long);
+ else
+ if (char_flag)
+ val = va_arg(ap,char);
+ else
+ val = va_arg(ap,int);
+
+#if NICE_LIFO_IMPLEMENTATION_BUT_NOT_PORTABLE
+ if (radix) pval();
+#else
+ if (radix)
+ {
+ static char __idata buffer[12]; /* 37777777777(oct) */
+ char __idata * stri;
+
+ _ltoa (val, buffer, radix);
+ stri = buffer;
+ while (*stri)
+ {
+ putchar (*stri);
+ stri++;
+ }
+ }
+#endif
+ else
+ putchar((char)val);
+
+ } else
+ putchar(*fmt);
+ }
}