PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Dependents: YATTT sd_map_test cPong SnowDemo ... more
PokittoPrintf.cpp
00001 /* 00002 Copyright 2001 Georges Menie 00003 https://www.menie.org/georges/embedded/small_printf_source_code.html 00004 00005 This program is free software; you can redistribute it and/or modify 00006 it under the terms of the GNU Lesser General Public License as published by 00007 the Free Software Foundation; either version 2 of the License, or 00008 (at your option) any later version. 00009 00010 This program is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public License 00016 along with this program; if not, write to the Free Software 00017 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 */ 00019 00020 /* 00021 putchar is the only external dependency for this file, 00022 if you have a working putchar, just remove the following 00023 define. If the function should be called something else, 00024 replace outbyte(c) by your own function call. 00025 */ 00026 00027 #include "PokittoDisplay.h " 00028 00029 //#define putchar(c) outbyte(c) 00030 00031 static void printchar(char **str, int c) 00032 { 00033 //extern int putchar(int c); 00034 00035 if (str) { 00036 **str = c; 00037 ++(*str); 00038 } 00039 //else (void)putchar(c); 00040 else Pokitto::Display::print((const char*)&c); 00041 } 00042 00043 #define PAD_RIGHT 1 00044 #define PAD_ZERO 2 00045 00046 static int prints(char **out, const char *string, int width, int pad) 00047 { 00048 register int pc = 0, padchar = ' '; 00049 00050 if (width > 0) { 00051 register int len = 0; 00052 register const char *ptr; 00053 for (ptr = string; *ptr; ++ptr) ++len; 00054 if (len >= width) width = 0; 00055 else width -= len; 00056 if (pad & PAD_ZERO) padchar = '0'; 00057 } 00058 if (!(pad & PAD_RIGHT)) { 00059 for ( ; width > 0; --width) { 00060 printchar (out, padchar); 00061 ++pc; 00062 } 00063 } 00064 for ( ; *string ; ++string) { 00065 printchar (out, *string); 00066 ++pc; 00067 } 00068 for ( ; width > 0; --width) { 00069 printchar (out, padchar); 00070 ++pc; 00071 } 00072 00073 return pc; 00074 } 00075 00076 /* the following should be enough for 32 bit int */ 00077 #define PRINT_BUF_LEN 12 00078 00079 static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase) 00080 { 00081 char print_buf[PRINT_BUF_LEN]; 00082 register char *s; 00083 register int t, neg = 0, pc = 0; 00084 register unsigned int u = i; 00085 00086 if (i == 0) { 00087 print_buf[0] = '0'; 00088 print_buf[1] = '\0'; 00089 return prints (out, print_buf, width, pad); 00090 } 00091 00092 if (sg && b == 10 && i < 0) { 00093 neg = 1; 00094 u = -i; 00095 } 00096 00097 s = print_buf + PRINT_BUF_LEN-1; 00098 *s = '\0'; 00099 00100 while (u) { 00101 t = u % b; 00102 if( t >= 10 ) 00103 t += letbase - '0' - 10; 00104 *--s = t + '0'; 00105 u /= b; 00106 } 00107 00108 if (neg) { 00109 if( width && (pad & PAD_ZERO) ) { 00110 printchar (out, '-'); 00111 ++pc; 00112 --width; 00113 } 00114 else { 00115 *--s = '-'; 00116 } 00117 } 00118 00119 return pc + prints (out, s, width, pad); 00120 } 00121 00122 static int _ext_print(char **out, int *varg) 00123 { 00124 register int width, pad; 00125 register int pc = 0; 00126 register char *format = (char *)(*varg++); 00127 char scr[2]; 00128 00129 for (; *format != 0; ++format) { 00130 if (*format == '%') { 00131 ++format; 00132 width = pad = 0; 00133 if (*format == '\0') break; 00134 if (*format == '%') goto out; 00135 if (*format == '-') { 00136 ++format; 00137 pad = PAD_RIGHT; 00138 } 00139 while (*format == '0') { 00140 ++format; 00141 pad |= PAD_ZERO; 00142 } 00143 for ( ; *format >= '0' && *format <= '9'; ++format) { 00144 width *= 10; 00145 width += *format - '0'; 00146 } 00147 if( *format == 's' ) { 00148 register char *s = *((char **)varg++); 00149 pc += prints (out, s?s:"(null)", width, pad); 00150 continue; 00151 } 00152 if( *format == 'd' ) { 00153 pc += printi (out, *varg++, 10, 1, width, pad, 'a'); 00154 continue; 00155 } 00156 if( *format == 'x' ) { 00157 pc += printi (out, *varg++, 16, 0, width, pad, 'a'); 00158 continue; 00159 } 00160 if( *format == 'X' ) { 00161 pc += printi (out, *varg++, 16, 0, width, pad, 'A'); 00162 continue; 00163 } 00164 if( *format == 'u' ) { 00165 pc += printi (out, *varg++, 10, 0, width, pad, 'a'); 00166 continue; 00167 } 00168 if( *format == 'c' ) { 00169 /* char are converted to int then pushed on the stack */ 00170 scr[0] = *varg++; 00171 scr[1] = '\0'; 00172 pc += prints (out, scr, width, pad); 00173 continue; 00174 } 00175 } 00176 else { 00177 out: 00178 printchar (out, *format); 00179 ++pc; 00180 } 00181 } 00182 if (out) **out = '\0'; 00183 return pc; 00184 } 00185 00186 /* assuming sizeof(void *) == sizeof(int) */ 00187 00188 int _ext_printf(const char *format, ...) 00189 { 00190 register int *varg = (int *)(&format); 00191 return _ext_print(0, varg); 00192 } 00193 00194 int _ext_sprintf(char *out, const char *format, ...) 00195 { 00196 register int *varg = (int *)(&format); 00197 return _ext_print(&out, varg); 00198 } 00199 00200 /** 00201 * Use an external (PokittoPrintf.cpp) small implementation of printf 00202 * to simplify printing formatted strings 00203 * @param pointer to const formatted string 00204 */ 00205 00206 int Pokitto::Display::printf(const char *format, ...) { 00207 register int *varg = (int *)(&format); 00208 return _ext_print(0, varg); 00209 }; 00210 00211 // The following is from the original source and is left here for reference and LGPL 00212 // source: https://www.menie.org/georges/embedded/small_printf_source_code.html 00213 00214 #ifdef TEST_PRINTF 00215 int main(void) 00216 { 00217 char *ptr = "Hello world!"; 00218 char *np = 0; 00219 int i = 5; 00220 unsigned int bs = sizeof(int)*8; 00221 int mi; 00222 char buf[80]; 00223 00224 mi = (1 << (bs-1)) + 1; 00225 printf("%s\n", ptr); 00226 printf("printf test\n"); 00227 printf("%s is null pointer\n", np); 00228 printf("%d = 5\n", i); 00229 printf("%d = - max int\n", mi); 00230 printf("char %c = 'a'\n", 'a'); 00231 printf("hex %x = ff\n", 0xff); 00232 printf("hex %02x = 00\n", 0); 00233 printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3); 00234 printf("%d %s(s)%", 0, "message"); 00235 printf("\n"); 00236 printf("%d %s(s) with %%\n", 0, "message"); 00237 sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf); 00238 sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf); 00239 sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf); 00240 sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf); 00241 sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf); 00242 sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf); 00243 sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf); 00244 sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf); 00245 00246 return 0; 00247 } 00248 00249 /* 00250 * if you compile this file with 00251 * gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c 00252 * you will get a normal warning: 00253 * printf.c:214: warning: spurious trailing `%' in format 00254 * this line is testing an invalid % at the end of the format string. 00255 * 00256 * this should display (on 32bit int machine) : 00257 * 00258 * Hello world! 00259 * printf test 00260 * (null) is null pointer 00261 * 5 = 5 00262 * -2147483647 = - max int 00263 * char a = 'a' 00264 * hex ff = ff 00265 * hex 00 = 00 00266 * signed -3 = unsigned 4294967293 = hex fffffffd 00267 * 0 message(s) 00268 * 0 message(s) with % 00269 * justif: "left " 00270 * justif: " right" 00271 * 3: 0003 zero padded 00272 * 3: 3 left justif. 00273 * 3: 3 right justif. 00274 * -3: -003 zero padded 00275 * -3: -3 left justif. 00276 * -3: -3 right justif. 00277 */ 00278 00279 #endif 00280
Generated on Tue Jul 12 2022 11:20:38 by 1.7.2