PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PokittoPrintf.cpp Source File

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