X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=mware%2Fformatwr.c;h=f8df352ee8523394bffa2cdf87b9a55069b7f42f;hb=5f3952176a4e9a00ca8dd5ec4a6b994958f89e0a;hp=fd40deef20896889a705a1ad66b0a84298141be5;hpb=277b540c0764dd376dcf583acdc97a2b2fd3d8e6;p=bertos.git diff --git a/mware/formatwr.c b/mware/formatwr.c old mode 100755 new mode 100644 index fd40deef..f8df352e --- a/mware/formatwr.c +++ b/mware/formatwr.c @@ -1,8 +1,8 @@ -/*! +/** * \file * * * \version $Id$ @@ -53,69 +53,82 @@ /*#* *#* $Log$ - *#* Revision 1.8 2004/08/25 14:12:09 rasky - *#* Aggiornato il comment block dei log RCS + *#* Revision 1.19 2006/09/20 13:58:17 marco + *#* Added z modifier in string format. + *#* + *#* Revision 1.18 2006/07/19 12:56:27 bernie + *#* Convert to new Doxygen style. + *#* + *#* Revision 1.17 2005/11/04 17:43:27 bernie + *#* Fix for LP64 architectures; Add some more tests. *#* - *#* Revision 1.7 2004/08/04 15:53:47 rasky - *#* Nuove opzioni di configurazione per formatted_write e ridotto maggiormente l'utilizzo dellos tack + *#* Revision 1.16 2005/07/19 07:25:46 bernie + *#* Use appconfig.h instead of cfg/config.h. *#* - *#* Revision 1.6 2004/07/30 14:34:10 rasky - *#* Vari fix per documentazione e commenti - *#* Aggiunte PP_CATn e STATIC_ASSERT + *#* Revision 1.15 2005/04/11 19:10:28 bernie + *#* Include top-level headers from cfg/ subdir. *#* - *#* Revision 1.5 2004/07/29 22:57:09 bernie - *#* Switch to new-style config handling. + *#* Revision 1.14 2005/03/01 23:26:22 bernie + *#* Use shared hextab. *#* - *#* Revision 1.4 2004/07/21 00:20:20 bernie - *#* Allow completely disabling printf()-like formatter. + *#* Revision 1.13 2005/02/18 12:33:25 bernie + *#* Avoid strlen(). *#* - *#* Revision 1.3 2004/07/18 22:00:15 bernie - *#* Reorganize configuration parameters to match DevLib's convention. + *#* Revision 1.12 2005/02/16 20:28:03 bernie + *#* Add %S formatter. *#* - *#* Revision 1.2 2004/06/03 11:27:09 bernie - *#* Add dual-license information. + *#* Revision 1.11 2005/02/16 16:51:29 bernie + *#* Simplify float code. *#* - *#* Revision 1.1 2004/05/23 15:43:16 bernie - *#* Import mware modules. + *#* Revision 1.10 2004/10/26 09:01:35 bernie + *#* Fix spacing. *#* + *#* Revision 1.9 2004/09/14 21:06:23 bernie + *#* Spelling fix. + *#* + *#* Revision 1.8 2004/08/25 14:12:09 rasky + *#* Aggiornato il comment block dei log RCS *#*/ #include "formatwr.h" -#include /* progmem macros */ -#include /* CONFIG_ macros */ -#include /* ASSERT */ +#include +#include +#include /* ASSERT */ +#include /* CONFIG_ macros */ #ifndef CONFIG_PRINTF_N_FORMATTER - /*! Enable arcane %n formatter */ + /** Disable the arcane %n formatter. */ #define CONFIG_PRINTF_N_FORMATTER 0 #endif #ifndef CONFIG_PRINTF_OCTAL_FORMATTER - /*! Enable %o formatter */ + /** Disable the %o formatter. */ #define CONFIG_PRINTF_OCTAL_FORMATTER 0 #endif -// True if we must keep a count of the number of characters we print +/* True if we must keep a count of the number of characters we print. */ #define CONFIG_PRINTF_COUNT_CHARS (CONFIG_PRINTF_RETURN_COUNT || CONFIG_PRINTF_N_FORMATTER) #if CONFIG_PRINTF #if CONFIG_PRINTF > PRINTF_NOFLOAT -#include -#endif /* CONFIG_PRINTF > PRINTF_NOFLOAT */ + #include -#if CONFIG_PRINTF > PRINTF_NOFLOAT -/*bernie: save some memory, who cares about floats with lots of decimals? */ -/*#define FRMWRI_BUFSIZE 134*/ - #error 134 is too much, the code must be fixed to have a lower precision limit + /* Maximum precision for floating point values */ + typedef long double max_float_t; + + /*bernie: save some memory, who cares about floats with lots of decimals? */ + #define FRMWRI_BUFSIZE 134 + #warning 134 is too much, the code must be fixed to have a lower precision limit #else /* * Conservative estimate. Should be (probably) 12 (which is the size necessary - * to represent (2^32-1) in octal plus the sign bit + * to represent (2^32-1) in octal plus the sign bit. */ #define FRMWRI_BUFSIZE 16 #endif +/* Probably useful for fancy microcontrollers such as the PIC, nobody knows. */ #ifndef MEM_ATTRIBUTE #define MEM_ATTRIBUTE #endif @@ -129,7 +142,7 @@ #if CONFIG_PRINTF > PRINTF_NOFLOAT -static char *float_conversion(MEM_ATTRIBUTE long double value, +static char *float_conversion(MEM_ATTRIBUTE max_float_t value, MEM_ATTRIBUTE short nr_of_digits, MEM_ATTRIBUTE char *buf, MEM_ATTRIBUTE char format_flag, @@ -218,7 +231,7 @@ static char *float_conversion(MEM_ATTRIBUTE long double value, i = dec_point_pos; while (i <= nr_of_digits ) { - value -= (long double)(n = (short)value); /* n=Digit value=Remainder */ + value -= (max_float_t)(n = (short)value); /* n=Digit value=Remainder */ value *= 10; /* Prepare for next shot */ *buf_pointer++ = n + '0'; if ( ! i++ && (nr_of_digits || alternate_flag)) @@ -313,7 +326,7 @@ CLEAN_UP: #endif /* CONFIG_PRINTF > PRINTF_NOFLOAT */ -/*! +/** * This routine forms the core and entry of the formatter. * * The conversion performed conforms to the ANSI specification for "printf". @@ -344,24 +357,27 @@ PGM_FUNC(_formatted_write)(const char * PGM_ATTR format, DIV_OCT, #endif }; - struct { - MEM_ATTRIBUTE enum PLUS_SPACE_FLAGS plus_space_flag : 2; + MEM_ATTRIBUTE struct { + enum PLUS_SPACE_FLAGS plus_space_flag : 2; #if CONFIG_PRINTF_OCTAL_FORMATTER - MEM_ATTRIBUTE enum DIV_FACTOR div_factor : 2; + enum DIV_FACTOR div_factor : 2; #else - MEM_ATTRIBUTE enum DIV_FACTOR div_factor : 1; + enum DIV_FACTOR div_factor : 1; +#endif + bool left_adjust : 1; + bool l_L_modifier : 1; + bool h_modifier : 1; + bool alternate_flag : 1; + bool nonzero_value : 1; + bool zeropad : 1; +#if CPU_HARVARD + bool progmem : 1; #endif - MEM_ATTRIBUTE bool left_adjust : 1; - MEM_ATTRIBUTE bool l_L_modifier : 1; - MEM_ATTRIBUTE bool h_modifier : 1; - MEM_ATTRIBUTE bool alternate_flag : 1; - MEM_ATTRIBUTE bool nonzero_value : 1; - MEM_ATTRIBUTE bool zeropad : 1; } flags; MEM_ATTRIBUTE unsigned long ulong; #if CONFIG_PRINTF > PRINTF_NOFLOAT - MEM_ATTRIBUTE long double fvalue; + MEM_ATTRIBUTE max_float_t fvalue; #endif MEM_ATTRIBUTE char *buf_pointer; @@ -401,8 +417,11 @@ PGM_FUNC(_formatted_write)(const char * PGM_ATTR format, flags.alternate_flag = false; flags.plus_space_flag = PSF_NONE; flags.zeropad = false; +#if CPU_HARVARD + flags.progmem = false; +#endif ptr = buf_pointer = &buf[0]; - hex = "0123456789ABCDEF"; + hex = HEX_tab; /* check for leading '-', '+', ' ','#' or '0' flags */ for (;;) @@ -482,11 +501,12 @@ NEXT_FLAG: flags.l_L_modifier = false; flags.h_modifier = false; - /* Optional 'l','L' r 'h' modifier? */ + /* Optional 'l','L','z' or 'h' modifier? */ switch (PGM_READ_CHAR(format)) { case 'l': case 'L': + case 'z': flags.l_L_modifier = true; format++; break; @@ -538,15 +558,34 @@ NEXT_FLAG: ptr++; break; + /* Custom formatter for strings in program memory. */ + case 'S': +#if CPU_HARVARD + flags.progmem = true; +#endif + /* Fall trough */ + case 's': if ( !(buf_pointer = va_arg(ap, char *)) ) buf_pointer = null_pointer; if (precision < 0) precision = 10000; - for (n=0; *buf_pointer++ && n < precision; n++) - ; - ptr = --buf_pointer; - buf_pointer -= n; + + /* + * Move `ptr' to the last character of the + * string that will be actually printed. + */ + ptr = buf_pointer; +#if CPU_HARVARD + if (flags.progmem) + { + for (n=0; pgm_read_char(ptr) && n < precision; n++) + ++ptr; + } + else +#endif + for (n=0; *ptr && n < precision; n++) + ++ptr; break; #if CONFIG_PRINTF_OCTAL_FORMATTER @@ -555,7 +594,7 @@ NEXT_FLAG: precision++; #endif case 'x': - hex = "0123456789abcdef"; + hex = hex_tab; case 'u': case 'p': case 'X': @@ -563,18 +602,18 @@ NEXT_FLAG: #if defined(__AVR__) || defined(__I196__) /* 16bit pointers */ ulong = (unsigned long)(unsigned short)va_arg(ap, char *); #else /* 32bit pointers */ - ulong = (unsigned long)va_arg(ap, char *); + ulong = (unsigned long)va_arg(ap, char *); #endif /* 32bit pointers */ - else if (sizeof(short) == sizeof(int)) - ulong = flags.l_L_modifier ? - va_arg(ap, unsigned long) : (unsigned long)va_arg(ap, unsigned int); + else if (flags.l_L_modifier) + ulong = va_arg(ap, unsigned long); + else if (flags.h_modifier) + ulong = (unsigned long)(unsigned short)va_arg(ap, unsigned int); else - ulong = flags.h_modifier ? - (unsigned long)(unsigned short) va_arg(ap, int) - : (unsigned long)va_arg(ap, int); - flags.div_factor = + ulong = va_arg(ap, unsigned int); + + flags.div_factor = #if CONFIG_PRINTF_OCTAL_FORMATTER - (format_flag == 'o') ? DIV_OCT : + (format_flag == 'o') ? DIV_OCT : #endif (format_flag == 'u') ? DIV_DEC : DIV_HEX; flags.plus_space_flag = PSF_NONE; @@ -582,32 +621,18 @@ NEXT_FLAG: case 'd': case 'i': - if (sizeof(short) == sizeof(long)) - { - if ( (long)(ulong = va_arg(ap, unsigned long)) < 0) - { - flags.plus_space_flag = PSF_MINUS; - ulong = (unsigned long)(-((signed long)ulong)); - } - } - else if (sizeof(short) == sizeof(int)) - { - if ( (long)(ulong = flags.l_L_modifier ? - va_arg(ap,unsigned long) : (unsigned long)va_arg(ap,int)) < 0) - { - flags.plus_space_flag = PSF_MINUS; - ulong = (unsigned long)(-((signed long)ulong)); - } - } + if (flags.l_L_modifier) + ulong = (unsigned long)(long)va_arg(ap, long); else + ulong = (unsigned long)(long)va_arg(ap, int); + + /* Extract sign */ + if ((signed long)ulong < 0) { - if ( (signed long)(ulong = (unsigned long) (flags.h_modifier ? - (short) va_arg(ap, int) : va_arg(ap,int))) < 0) - { - flags.plus_space_flag = PSF_MINUS; - ulong = (unsigned long)(-((signed long)ulong)); - } + flags.plus_space_flag = PSF_MINUS; + ulong = (unsigned long)(-((signed long)ulong)); } + flags.div_factor = DIV_DEC; /* Now convert to digits */ @@ -685,16 +710,16 @@ FLOATING_CONVERSION: { precision = 6; } - if (sizeof(double) != sizeof(long double)) + + if (sizeof(double) != sizeof(max_float_t)) { - if ( (fvalue = flags.l_L_modifier ? - va_arg(ap,long double) : va_arg(ap,double)) < 0) - { - flags.plus_space_flag = PSF_MINUS; - fvalue = -fvalue; - } + fvalue = flags.l_L_modifier ? + va_arg(ap,max_float_t) : va_arg(ap,double); } - else if ( (fvalue = va_arg(ap,long double)) < 0) + else + fvalue = va_arg(ap,max_float_t); + + if (fvalue < 0) { flags.plus_space_flag = PSF_MINUS; fvalue = -fvalue; @@ -713,16 +738,6 @@ FLOATING_CONVERSION: } break; -#else /* CONFIG_PRINTF <= PRINTF_NOFLOAT */ - case 'g': - case 'G': - case 'f': - case 'e': - case 'E': - ptr = buf_pointer = bad_conversion; - while (*ptr) - ptr++; - break; #endif /* CONFIG_PRINTF <= PRINTF_NOFLOAT */ case '\0': /* Really bad place to find NUL in */ @@ -731,7 +746,7 @@ FLOATING_CONVERSION: default: /* Undefined conversion! */ ptr = buf_pointer = bad_conversion; - ptr += 3; + ptr += sizeof(bad_conversion) - 1; break; } @@ -771,13 +786,28 @@ FLOATING_CONVERSION: #endif } - /* emit the string itself */ - while (--precision >= 0) +#if CPU_HARVARD + if (flags.progmem) { - put_one_char(*buf_pointer++, secret_pointer); + while (--precision >= 0) + { + put_one_char(pgm_read_char(buf_pointer++), secret_pointer); #if CONFIG_PRINTF_COUNT_CHARS - nr_of_chars++; + nr_of_chars++; +#endif + } + } + else +#endif /* CPU_HARVARD */ + { + /* emit the string itself */ + while (--precision >= 0) + { + put_one_char(*buf_pointer++, secret_pointer); +#if CONFIG_PRINTF_COUNT_CHARS + nr_of_chars++; #endif + } } /* emit trailing space characters */ @@ -794,7 +824,7 @@ FLOATING_CONVERSION: #else /* PRINTF_REDUCED starts here */ #if CONFIG_PRINTF > PRINTF_NOMODIFIERS - char l_modifier, h_modifier; + bool l_modifier, h_modifier; unsigned long u_val, div_val; #else unsigned int u_val, div_val; @@ -820,16 +850,16 @@ FLOATING_CONVERSION: /*=================================*/ /* Optional 'l' or 'h' modifiers ? */ /*=================================*/ - l_modifier = h_modifier = 0; + l_modifier = h_modifier = false; switch (PGM_READ_CHAR(format)) { case 'l': - l_modifier = 1; + l_modifier = true; format++; break; case 'h': - h_modifier = 1; + h_modifier = true; format++; break; }