Main Page | Modules | Data Structures | File List | Data Fields | Globals

bprintf.c

Go to the documentation of this file.
00001 /* BeeOS v0.1. Created: 2004/02/27 Modified: 2004/03/03
00002  * Copyright (C) 2004 Paul Harvey - ROMA, Australia.
00003  * csirac@users.sourceforge.net
00004  */
00005 
00006 /*   This program is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation; either verspion 2 of the License, or
00009  *   (at your option) any later version.
00010  * 
00011  *   This program is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  * 
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with this program; if not, write to the Free Software
00018  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  */
00023 #include "../include/beeos.h"
00024 #include "../include/bstring.h"
00025 /*#include "../include/bmalloc.h"*/
00026 #include <stdarg.h> /* va_start(), va_arg(), va_list, va_end() */
00027 #define IN_BPRINTF
00028 #include "../include/bprintf.h"
00029 #ifndef HOSTED_BUILD
00030 #   include "../include/arch/param.h"
00031 #   include "../include/asm/ports.h"
00032 #   include "../include/asm/ports_std.h"
00033 #   include "../include/sci.h"
00034 #else
00035 #   include <stdio.h>   /* HOSTED_BUILD putchar(). */
00036 #endif
00037 
00038 /* GLOBALS */
00039 bool lk_bputs;
00040 bool lk_putchar;
00041 /* END GLOBALS */
00042 
00048 #define digit2char(dst, num) do {\
00049     if ((char)10 > num) {\
00050         dst = num + '0';\
00051     } else {\
00052         dst = num + (char)'a' - (char)10;\
00053     }\
00054 } while(0);
00055 
00056 #ifndef HOSTED_BUILD
00057 
00061 void putchar(char c)
00062 {
00066 /*  while (lk_putchar);*/
00067     lk_putchar = true;
00068     sci_tx(((uchar *) (&SCI0BDH)), c);
00069     lk_putchar = false;
00070 }
00071 #endif
00072 
00077 /*@-redef@*/
00078 void bputs(char *pSrc)
00079 /*@=redef@*/
00080 {   
00081 /*@-nullderef@*/ /*@-retvalint@*/ /*@-internalglobs@*/ /*@-modfilesys@*/
00082     while (lk_bputs);
00083     lk_bputs = true;
00084     do {
00085         putchar(*pSrc);
00086     } while ('\0' != *pSrc++);
00087     lk_bputs = false;
00088 /*@=nullderef@*/ /*@=retvalint@*/ /*@=internalglobs@*/ /*@=modfilesys@*/
00089     
00090     return;
00091 }
00092 
00093 #ifdef INT2STRING
00094 
00101 void int2string(char **ppDst, sshort number, uchar intbase)
00102 {   
00119     ushort quotient, multiplier, i;
00120 
00121     switch (intbase) {  /* Should handle 16 bit ints. */
00122         case 10:    multiplier = 10000;     break;  /* For decimal numbers */
00123         case 0x10:  multiplier = 0x1000;    break;  /* For hex numbers */
00124         default:    multiplier = 0x8000;    break;  /* For oct+bin numbers */
00125     }
00126     if (0 == number) *(*ppDst)++ = '0'; /* Just print a '0' to the string... */
00127     else {  /* ...otherwise, deal with non-zero ints  */
00128         if (0 > number) {               /* Deal with negatives */
00129             *(*ppDst)++ = '-';
00130             number *= -1;
00131         }
00132         do {                            /* Deal with non-zero, positive int */
00133             if (number >= multiplier) { /* Find a base multiple for number */
00134                 quotient = number/multiplier;   /* quotient will be printed, */
00135                 number -= quotient*multiplier;  /* so update number accordingly */
00136                 digit2char(**ppDst, quotient);
00137                 (*ppDst)++;
00138                 if (multiplier/intbase > number)    /* Detect if zeroes need to be */
00139                     for (i = multiplier/intbase; i > number; i /= intbase) /* printed, */
00140                         *(*ppDst)++ = '0';  /* otherwise they will be skipped */
00141             }
00142             multiplier /= intbase;          /* Update multiplier for next digit print */
00143         } while (multiplier > 0);
00144     }
00145     
00146     return;
00147 }
00148 #endif
00149 
00150 #ifdef INT2STRINGPADDED
00151 
00160 /*@-redef@*/
00161 void int2stringpadded(char **ppDst, sshort number, uchar intbase, uchar padsize,
00162     bool numgroup, bool plussign)
00163 /*@-redef@*/
00164 /*@+charint@*/
00165 {   
00186     ushort multiplier, i;
00187     uchar quotient, groupsize;
00188     uchar ndigit = (uchar)0;    /* ndigit: counts digit no. for grouping */
00189 
00190     /* Calc. groupsize, "thousand" comma grouping. Should handle 16 bit ints. */
00191     switch (intbase) {
00192         case 10:    
00193             groupsize = 3;  
00194             multiplier = 10000;     /* For decimal numbers */
00195         break;
00196         case 0x10:
00197             groupsize = 4;
00198             multiplier = 0x1000;    /* For hex numbers */
00199         break;
00200         default:    
00201             groupsize = 4;
00202             multiplier = 0x8000;    /* To get full 16bit range for oct+bin */
00203         break;
00204     }
00205     if (!numgroup) {
00206         groupsize = 127;    /* Cheap way of saying "no grouping" */
00207     }
00208     /* Deal with +/- signs. */
00209     if (0 > number) {
00210 /*@-nullderef@*/
00211         *(*ppDst)++ = '-';
00212         number *= -1;               /* Int printing assumes positive numbers */
00213     } else if (0 == number) {
00214         if (0 != padsize) padsize--;
00215         *(*ppDst)++ = '0';
00216     } else if (plussign) {
00217         *(*ppDst)++ = '+';  /* Mandatory plussign if needed */
00218     }
00219     /* Calc. no. digits; necessary for "thousand" grouping commas. */
00220     for (i = number; 0 < i; i /= intbase) {
00221         ndigit++;
00222     }
00223     /* Do zero padding, with "thousand" grouping of those zeroes */
00224     for (i = padsize; i > ndigit; i--) {
00225             *(*ppDst)++ = '0';
00226         if ((0 == ((i - 1) % (groupsize))) && (1 != i)) {   /* != 1: no end comma */
00227             *(*ppDst)++ = ',';
00228         }
00229     }
00230     /* The main int printing loop.  */
00231     do {                            /* Deal with non-zero, positive int */
00232         if (number >= multiplier) { /* Find a base multiple for number */
00233             quotient = number/multiplier;   /* quotient will be printed, */
00234             number -= quotient*multiplier;  /* so update number accordingly */
00235             digit2char(**ppDst, quotient);  /* print the quotient to string */
00236             (*ppDst)++;
00237             ndigit--;
00238             if ((0 == (ndigit % groupsize)) && (0 != ndigit)) {
00239                 *(*ppDst)++ = ',';  /* "thousand" comma grouping */
00240             }
00241             if (multiplier/intbase > number) {  /* Detect zero printing */
00242                 for (i = multiplier/intbase; i > number; i /= intbase) {
00243                     *(*ppDst)++ = '0';  /* otherwise they will be skipped */
00244                     ndigit--;
00245                     if ((0 == (ndigit % groupsize)) && (0 != ndigit)) {
00246                         *(*ppDst)++ = ',';
00247                     }
00248 /*@=nullderef@*/
00249                 }
00250             }
00251         }
00252         multiplier /= intbase;      /* Update multiplier for next digit print */
00253     } while (multiplier > 0);
00254     
00255     return;
00256 }
00257 /*@=charint@*/
00258 #endif
00259 
00268 void bvsnprintf(char *pDst, ushort maxn, const char *pSrc, va_list ap)
00269 /*@+charint@*/
00270 {   
00279     char *pString = NULL;
00280     ushort ncopied = 0;
00281     sshort intvar = 0;
00282     uchar intbase = 0;
00283     uchar padzeroes = 0;
00284     bool plussign = false, numgroup = false;
00285     bool foundvar = false;
00286     
00287 #ifdef BPRINTF_DEBUG
00288     printf("bprintf(): pDst(%p), maxn(%i), pSrc = \"%s\"\n", pDst, maxn, pSrc);
00289 #endif
00290     do {
00291         if (*pSrc == '%') {
00292             foundvar = true;
00293         }
00294         if (foundvar) { /* If a '%' was hit, then interpret following chars. */
00295             switch (*(++pSrc)) {
00296                 case '%':   /* '%%' == '%' */
00297                     *pDst++ = *pSrc++;
00298                     ncopied++;
00299                     foundvar = false;
00300                 /*@switchbreak@*/break; 
00301                 case 'i':   /* decimal int */
00302                     intbase = 10;
00303                 /*@switchbreak@*/break;
00304                 case 'X':   /* hex int */
00305                 case 'x':
00306                 case 'p':
00307                     intbase = 0x10;
00308                 /*@switchbreak@*/break;
00309                 case 'o':   /* octal int */
00310                     intbase = 010;
00311                 /*@switchbreak@*/break;
00312                 case 'B':   /* binary int */
00313                     intbase = 2;
00314                 /*@switchbreak@*/break;
00315                 case 'c':   /* character char */
00316                     *pDst++ = (char) va_arg(ap, int);
00317                     ncopied++;      /*after here,finished with vartype*/
00318                 /*@switchbreak@*/break;
00319                 case 's':   /* a string var is to be printed */
00320                     pString = va_arg(ap, char *);
00321                     ncopied += bstrncpy(pDst, pString, maxn - ncopied);
00322                 /*@switchbreak@*/break;
00323                 case '0':   /* Zero padding */
00324                     padzeroes = *(pSrc + 1) - '0';
00325                 /*@switchbreak@*/break;
00326                 case '+':
00327                     plussign = true;
00328                 /*@switchbreak@*/break;
00329                 case '\'':
00330                     numgroup = true;
00331                 /*@switchbreak@*/break;
00332                 default:
00333                 /*@switchbreak@*/break;
00334             }
00335             if (0 < intbase) {
00336                 intvar = (sshort) (va_arg(ap, int));
00337                 pString = pDst;
00338 /*@-nullstate@*/
00339 #ifdef INT2STRINGPADDED
00340                 int2stringpadded(&pDst, intvar, intbase, padzeroes, numgroup, plussign);
00341 #else
00342 #ifdef INT2STRING
00343                 int2string(&pDst, intvar, intbase);
00344 #endif
00345 #endif
00346 /*@=nullstate@*/
00347                 pSrc++; /* Inc. past vartype char */
00348                 ncopied += pDst - pString;
00349                 intbase = 0;
00350                 foundvar = false;
00351             }
00352         } else {
00353             *(pDst++) = *pSrc;
00354             if ('\0' != *pSrc) pSrc++;
00355             ncopied++;
00356         }
00357     } while ( ((ushort)ncopied < maxn) && ('\0' != *(pSrc)) );
00358 /*@-nullderef@*/
00359     *pDst = '\0';
00360 /*@=nullderef@*/
00361     
00362     return;
00363 }
00364 /*@=charint@*/
00365 
00374 void bsnprintf(char *pDst, ushort maxn, const char *pSrc, ...)
00375 {   
00377     va_list ap;
00378     
00379     va_start(ap, pSrc);
00380     bvsnprintf(pDst, maxn, pSrc, ap);
00381     va_end(ap);
00382     
00383     return;
00384 }
00385 
00400 void bprintf(ushort extra, const char *pString, ...)
00401 {   
00408     char pWorking[80]; 
00409     va_list ap;
00410     
00411     va_start(ap, pString);
00412     bvsnprintf(pWorking, 80, pString, ap);
00413     va_end(ap);
00414     bputs(pWorking);
00415         
00416     return;
00417 }

Generated on Sat Apr 10 17:08:02 2004 for BeeOS by doxygen 1.3.6-20040222