gonzui


Format: Advanced Search

tkernel_2/lib/libtm/src/tm_printf.cbare sourcepermlink (0.02 seconds)

Search this content:

    1: /*
    2:  *----------------------------------------------------------------------
    3:  *    T-Kernel 2.0 Software Package
    4:  *
    5:  *    Copyright 2011 by Ken Sakamura.
    6:  *    This software is distributed under the latest version of T-License 2.x.
    7:  *----------------------------------------------------------------------
    8:  *
    9:  *    Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17.
   10:  *    Added by T-Engine Forum at 2012/11/27.
   11:  *    Modified by T-Engine Forum at 2013/02/28.
   12:  *    Modified by TRON Forum(http://www.tron.org/) at 2015/06/01.
   13:  *
   14:  *----------------------------------------------------------------------
   15:  */
   16: 
   17: /*
   18:  *      @(#)tm_printf.c (libtm)
   19:  *
   20:  *      printf() / sprintf() routine using t-monitor function.
   21:  *
   22:  *      - Unsupported specifiers: floating point, long long and others.
   23:  *              Coversion:   a, A, e, E, f, F, g, G, n
   24:  *              Size qualifier:  hh, ll, j, z, t, L
   25:  *      - No limitation of output string length.
   26:  *      - Minimize stack usage.
   27:  *              Depending on available stack size, define OUTBUF_SZ by
   28:  *              appropriate value.
   29:  */
   30: #include <stdarg.h>
   31: #include <basic.h>
   32: 
   33: /* Output Buffer size in stack */
   34: #define OUTBUF_SZ       0
   35: 
   36: typedef unsigned char   uchar;
   37: 
   38: extern  int      tm_putchar(int c);
   39: extern  int      tm_putstring(uchar *s);
   40: 
   41: /* Output function */
   42: typedef struct {
   43:         short  len;             /* Total output length */
   44:         short  cnt;             /* Buffer counts */
   45:         uchar  *bufp;           /* Buffer pointer for tm_sprintf */
   46: } OutPar;
   47: typedef void    (*OutFn)(uchar *str, int len, OutPar *par);
   48: 
   49: /*
   50:  *      Output integer value
   51:  */
   52: static  uchar    *outint(uchar *ep, unsigned long val, uchar base)
   53: {
   54: static const uchar  digits[] = "0123456789abcdef0123456789ABCDEF";
   55:         uchar  caps;
   56: 
   57:         caps = (base & 0x40) >> 2;             /* 'a' or 'A' */
   58:         for (base &= 0x3F; val >= base; val /= base) {
   59:                 *--ep = digits[(val % base) + caps];
   60:         }
   61:         *--ep = digits[val + caps];
   62:         return ep;                             /* buffer top pointer */
   63: }
   64: 
   65: /*
   66:  *      Output with format (limitted version)
   67:  */
   68: static  void     _vsprintf(OutFn ostr, OutPar *par,
   69:                                         const uchar *fmt, va_list ap)
   70: {
   71: #define MAX_DIGITS      14
   72:         unsigned long  v;
   73:         short  wid, prec, n;
   74:         uchar  *fms, *cbs, *cbe, cbuf[MAX_DIGITS];
   75:         uchar  c, base, flg, sign, qual;
   76: 
   77: /* flg */
   78: #define F_LEFT          0x01
   79: #define F_PLUS          0x02
   80: #define F_SPACE         0x04
   81: #define F_PREFIX        0x08
   82: #define F_ZERO          0x10
   83: 
   84:         for (fms = NULL; (c = *fmt++) != '\0'; ) {
   85: 
   86:                 if (c != '%') {       /* Fixed string */
   87:                         if (fms == NULL) fms = (uchar*)fmt - 1;
   88:                         continue;
   89:                 }
   90: 
   91:                 /* Output fix string */
   92:                 if (fms != NULL) {
   93:                         (*ostr)(fms, fmt - fms - 1, par);
   94:                         fms = NULL;
   95:                 }
   96: 
   97:                 /* Get flags */
   98:                 for (flg = 0; ; ) {
   99:                         switch (c = *fmt++) {
  100:                         case '-': flg |= F_LEFT;     continue;
  101:                         case '+': flg |= F_PLUS;     continue;
  102:                         case ' ': flg |= F_SPACE;    continue;
  103:                         case '#': flg |= F_PREFIX;   continue;
  104:                         case '0': flg |= F_ZERO;     continue;
  105:                         }
  106:                         break;
  107:                 }
  108: 
  109:                 /* Get field width */
  110:                 if (c == '*') {
  111:                         wid = va_arg(ap, int);
  112:                         if (wid < 0) {
  113:                                 wid = -wid;
  114:                                 flg |= F_LEFT;
  115:                         }
  116:                         c = *fmt++;
  117:                 } else {
  118:                         for (wid = 0; c >= '0' && c <= '9'; c = *fmt++)
  119:                                 wid = wid * 10 + c - '0';
  120:                 }
  121: 
  122:                 /* Get precision */
  123:                 prec = -1;
  124:                 if (c == '.') {
  125:                         c = *fmt++;
  126:                         if (c == '*') {
  127:                                 prec = va_arg(ap, int);
  128:                                 if (prec < 0) prec = 0;
  129:                                 c = *fmt++;
  130:                         } else {
  131:                                 for (prec = 0;c >= '0' && c <= '9';c = *fmt++)
  132:                                         prec = prec * 10 + c - '0';
  133:                         }
  134:                         flg &= ~F_ZERO;              /* No ZERO padding */
  135:                 }
  136: 
  137:                 /* Get qualifier */
  138:                 qual = 0;
  139:                 if (c == 'h' || c == 'l') {
  140:                         qual = c;
  141:                         c = *fmt++;
  142:                 }
  143: 
  144:                 /* Format items */
  145:                 base = 10;
  146:                 sign = 0;
  147:                 cbe = &cbuf[MAX_DIGITS];      /* buffer end pointer */
  148: 
  149:                 switch (c) {
  150:                 case 'i':
  151:                 case 'd':
  152:                 case 'u':
  153:                 case 'X':
  154:                 case 'x':
  155:                 case 'o':
  156:                         if (qual == 'l') {
  157:                                 v = va_arg(ap, unsigned long);
  158:                         } else {
  159:                                 v = va_arg(ap, unsigned int);
  160:                                 if (qual == 'h') {
  161:                                         v = (c == 'i' || c == 'd') ?
  162:                                                 (short)v :(unsigned short)v;
  163:                                 }
  164:                         }
  165:                         switch (c) {
  166:                         case 'i':
  167:                         case 'd':
  168:                                 if ((long)v < 0) {
  169:                                         v = - (long)v;
  170:                                         sign = '-';
  171:                                 } else if ((flg & F_PLUS) != 0) {
  172:                                         sign = '+';
  173:                                 } else if ((flg & F_SPACE) != 0) {
  174:                                         sign = ' ';
  175:                                 } else {
  176:                                         break;
  177:                                 }
  178:                                 wid--;              /* for sign */
  179:                         case 'u':
  180:                                 break;
  181:                         case 'X':
  182:                                 base += 0x40;       /* base = 16 + 0x40 */
  183:                         case 'x':
  184:                                 base += 8;  /* base = 16 */
  185:                         case 'o':
  186:                                 base -= 2;  /* base = 8 */
  187:                                 if ((flg & F_PREFIX) != 0 && v != 0) {
  188:                                         wid -= (base == 8) ? 1 : 2;
  189:                                         base |= 0x80;
  190:                                 }
  191:                                 break;
  192:                         }
  193:                         /* Note: None outputs when v == 0 && prec == 0 */
  194:                         cbs = (v == 0 && prec == 0) ?
  195:                                                 cbe : outint(cbe, v, base);
  196:                         break;
  197:                 case 'p':
  198:                         v = (unsigned long)va_arg(ap, void *);
  199:                         if (v != 0) {
  200:                                 base = 16 | 0x80;
  201:                                 wid -= 2;
  202:                         }
  203:                         cbs = outint(cbe, v, base);
  204:                         break;
  205:                 case 's':
  206:                         cbe = cbs = va_arg(ap, uchar *);
  207:                         if (prec < 0) {
  208:                                 while (*cbe != '\0') cbe++;
  209:                         } else {
  210:                                 while (--prec >= 0 && *cbe != '\0') cbe++;
  211:                         }
  212:                         break;
  213:                 case 'c':
  214:                         cbs = cbe;
  215:                         *--cbs = (uchar)va_arg(ap, int);
  216:                         prec = 0;
  217:                         break;
  218:                 case '\0':
  219:                         fmt--;
  220:                         continue;
  221:                 default:
  222:                         /* Output as fixed string */
  223:                         fms = (uchar*)fmt - 1;
  224:                         continue;
  225:                 }
  226: 
  227:                 n = cbe - cbs;                                /* item length */
  228:                 if ((prec -= n) > 0) n += prec;
  229:                 wid -= n;                             /* pad length */
  230: 
  231:                 /* Output preceding spaces */
  232:                 if ((flg & (F_LEFT | F_ZERO)) == 0 ) {
  233:                         while (--wid >= 0) (*ostr)((uchar*)" ", 1, par);
  234:                 }
  235: 
  236:                 /* Output sign */
  237:                 if (sign != 0) {
  238:                         (*ostr)(&sign, 1, par);
  239:                 }
  240: 
  241:                 /* Output prefix "0x", "0X" or "0" */
  242:                 if ((base & 0x80) != 0) {
  243:                         (*ostr)((uchar*)"0", 1, par);
  244:                         if ((base & 0x10) != 0) {
  245:                                 (*ostr)((base & 0x40) ?
  246:                                         (uchar*)"X" : (uchar*)"x", 1, par);
  247:                         }
  248:                 }
  249: 
  250:                 /* Output preceding zeros for precision or padding */
  251:                 if ((n = prec) <= 0) {
  252:                         if ((flg & (F_LEFT | F_ZERO)) == F_ZERO ) {
  253:                                 n = wid;
  254:                                 wid = 0;
  255:                         }
  256:                 }
  257:                 while (--n >= 0) (*ostr)((uchar*)"0", 1, par);
  258: 
  259:                 /* Output item string */
  260:                 (*ostr)(cbs, cbe - cbs, par);
  261: 
  262:                 /* Output tailing spaces */
  263:                 while (--wid >= 0) (*ostr)((uchar*)" ", 1, par);
  264:         }
  265: 
  266:         /* Output last fix string */
  267:         if (fms != NULL) {
  268:                 (*ostr)(fms, fmt - fms - 1, par);
  269:         }
  270: #if     OUTBUF_SZ > 0
  271:         /* Flush output */
  272:         (*ostr)(NULL, 0, par);
  273: #endif
  274: }
  275: 
  276: /*
  277:  *      Output to console
  278:  */
  279: static  void     out_cons(uchar *str, int len,  OutPar *par)
  280: {
  281: #if     OUTBUF_SZ == 0
  282:         /* Direct output to console */
  283:         par->len += len;
  284:         while (--len >= 0) tm_putchar(*str++);
  285: #else
  286:         /* Buffered output to console */
  287:         if (str == NULL) {     /* Flush */
  288:                 if (par->cnt > 0) {
  289:                         par->bufp[par->cnt] = '\0';
  290:                         tm_putstring(par->bufp);
  291:                         par->cnt = 0;
  292:                 }
  293:         } else {
  294:                 par->len += len;
  295:                 while (--len >= 0) {
  296:                         if (par->cnt >= OUTBUF_SZ - 1) {
  297:                                 par->bufp[par->cnt] = '\0';
  298:                                 tm_putstring(par->bufp);
  299:                                 par->cnt = 0;
  300:                         }
  301:                         par->bufp[par->cnt++] = *str++;
  302:                 }
  303:         }
  304: #endif
  305: }
  306: 
  307: int     tm_vprintf(const char *format, va_list ap)
  308: {
  309: #if     OUTBUF_SZ == 0
  310:         short  len = 0;
  311:         _vsprintf(out_cons, (OutPar*)&len, (const uchar *)format, ap);
  312:         return len;
  313: #else
  314:         char   obuf[OUTBUF_SZ];
  315:         OutPar par;
  316: 
  317:         par.len = par.cnt = 0;
  318:         par.bufp = obuf;
  319:         _vsprintf(out_cons, (OutPar*)&par, (const uchar *)format, ap);
  320:         va_end(ap);
  321:         return par.len;
  322: #endif  
  323: }
  324: 
  325: int     tm_printf(const char *format, ...)
  326: {
  327:         va_list        ap;
  328:         int    len;
  329: 
  330:         va_start(ap, format);
  331:         len = tm_vprintf(format, ap);
  332:         va_end(ap);
  333: 
  334:         return len;
  335: }
  336: 
  337: /*
  338:  *      Output to buffer
  339:  */
  340: static  void     out_buf(uchar *str, int len, OutPar *par)
  341: {
  342:         par->len += len;
  343:         while (--len >= 0) *(par->bufp)++ = *str++;
  344: }
  345: 
  346: int     tm_vsprintf(char *str, const char *format, va_list ap)
  347: {
  348:         OutPar par;
  349: 
  350:         par.len = 0;
  351:         par.bufp = (uchar*)str;
  352:         _vsprintf(out_buf, &par, (const uchar *)format, ap);
  353:         str[par.len] = '\0';
  354:         return par.len;
  355: }
  356: 
  357: int     tm_sprintf(char *str, const char *format, ...)
  358: {
  359:         va_list        ap;
  360:         int    len;
  361: 
  362:         va_start(ap, format);
  363:         len = tm_vsprintf(str, format, ap);
  364:         va_end(ap);
  365: 
  366:         return len;
  367: }
  368: