root/lib/libsa/printf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. printf
  2. vprintf
  3. kdoprnt
  4. kprintn
  5. kprintn64
  6. twiddle

    1 /*      $OpenBSD: printf.c,v 1.24 2006/09/18 21:11:50 mpf Exp $ */
    2 /*      $NetBSD: printf.c,v 1.10 1996/11/30 04:19:21 gwr Exp $  */
    3 
    4 /*-
    5  * Copyright (c) 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the University nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  *      @(#)printf.c    8.1 (Berkeley) 6/11/93
   33  */
   34 
   35 /*
   36  * Scaled down version of printf(3).
   37  *
   38  * One additional format:
   39  *
   40  * The format %b is supported to decode error registers.
   41  * Its usage is:
   42  *
   43  *      printf("reg=%b\n", regval, "<base><arg>*");
   44  *
   45  * where <base> is the output base expressed as a control character, e.g.
   46  * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
   47  * the first of which gives the bit number to be inspected (origin 1), and
   48  * the next characters (up to a control character, i.e. a character <= 32),
   49  * give the name of the register.  Thus:
   50  *
   51  *      printf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
   52  *
   53  * would produce output:
   54  *
   55  *      reg=3<BITTWO,BITONE>
   56  */
   57 
   58 #include <sys/cdefs.h>
   59 #include <sys/types.h>
   60 #include <sys/stdarg.h>
   61 
   62 #include "stand.h"
   63 
   64 void kprintn(void (*)(int), u_long, int);
   65 #ifdef LIBSA_LONGLONG_PRINTF
   66 void kprintn64(void (*)(int), u_int64_t, int);
   67 #endif
   68 void kdoprnt(void (*)(int), const char *, va_list);
   69 
   70 const char hexdig[] = "0123456789abcdef";
   71 
   72 void
   73 printf(const char *fmt, ...)
   74 {
   75         va_list ap;
   76 
   77         va_start(ap, fmt);
   78         kdoprnt(putchar, fmt, ap);
   79         va_end(ap);
   80 }
   81 
   82 void
   83 vprintf(const char *fmt, va_list ap)
   84 {
   85         kdoprnt(putchar, fmt, ap);
   86 }
   87 
   88 void
   89 kdoprnt(void (*put)(int), const char *fmt, va_list ap)
   90 {
   91 #ifdef LIBSA_LONGLONG_PRINTF
   92         u_int64_t ull;
   93 #endif
   94         unsigned long ul;
   95         int ch, lflag;
   96         char *p;
   97 
   98         for (;;) {
   99                 while ((ch = *fmt++) != '%') {
  100                         if (ch == '\0')
  101                                 return;
  102                         put(ch);
  103                 }
  104                 lflag = 0;
  105 reswitch:       switch (ch = *fmt++) {
  106                 case 'l':
  107                         lflag++;
  108                         goto reswitch;
  109 #ifndef STRIPPED
  110                 case 'b':
  111                 {
  112                         int set, n;
  113 
  114                         ul = va_arg(ap, int);
  115                         p = va_arg(ap, char *);
  116                         kprintn(put, ul, *p++);
  117 
  118                         if (!ul)
  119                                 break;
  120 
  121                         for (set = 0; (n = *p++);) {
  122                                 if (ul & (1 << (n - 1))) {
  123                                         put(set ? ',' : '<');
  124                                         for (; (n = *p) > ' '; ++p)
  125                                                 put(n);
  126                                         set = 1;
  127                                 } else
  128                                         for (; *p > ' '; ++p)
  129                                                 ;
  130                         }
  131                         if (set)
  132                                 put('>');
  133                 }
  134                         break;
  135 #endif
  136                 case 'c':
  137                         ch = va_arg(ap, int);
  138                         put(ch & 0x7f);
  139                         break;
  140                 case 's':
  141                         p = va_arg(ap, char *);
  142                         while ((ch = *p++))
  143                                 put(ch);
  144                         break;
  145                 case 'd':
  146 #ifdef LIBSA_LONGLONG_PRINTF
  147                         if (lflag > 1) {
  148                                 ull = va_arg(ap, int64_t);
  149                                 if ((int64_t)ull < 0) {
  150                                         put('-');
  151                                         ull = -(int64_t)ull;
  152                                 }
  153                                 kprintn64(put, ull, 10);
  154                                 break;
  155                         } 
  156 #endif
  157                         ul = lflag ?
  158                             va_arg(ap, long) : va_arg(ap, int);
  159                         if ((long)ul < 0) {
  160                                 put('-');
  161                                 ul = -(long)ul;
  162                         }
  163                         kprintn(put, ul, 10);
  164                         break;
  165                 case 'o':
  166 #ifdef LIBSA_LONGLONG_PRINTF
  167                         if (lflag > 1) {
  168                                 ull = va_arg(ap, u_int64_t);
  169                                 kprintn64(put, ull, 8);
  170                                 break;
  171                         } 
  172 #endif
  173                         ul = lflag ?
  174                             va_arg(ap, u_long) : va_arg(ap, u_int);
  175                         kprintn(put, ul, 8);
  176                         break;
  177                 case 'u':
  178 #ifdef LIBSA_LONGLONG_PRINTF
  179                         if (lflag > 1) {
  180                                 ull = va_arg(ap, u_int64_t);
  181                                 kprintn64(put, ull, 10);
  182                                 break;
  183                         } 
  184 #endif
  185                         ul = lflag ?
  186                             va_arg(ap, u_long) : va_arg(ap, u_int);
  187                         kprintn(put, ul, 10);
  188                         break;
  189                 case 'p':
  190                         put('0');
  191                         put('x');
  192                         lflag += sizeof(void *)==sizeof(u_long)? 1 : 0;
  193                 case 'x':
  194 #ifdef LIBSA_LONGLONG_PRINTF
  195                         if (lflag > 1) {
  196                                 ull = va_arg(ap, u_int64_t);
  197                                 kprintn64(put, ull, 16);
  198                                 break;
  199                         }
  200 #else
  201                         if (lflag > 1) {
  202                                 /* hold an int64_t in base 16 */
  203                                 char *p, buf[(sizeof(u_int64_t) * NBBY / 4) + 1];
  204                                 u_int64_t ull;
  205 
  206                                 ull = va_arg(ap, u_int64_t);
  207                                 p = buf;
  208                                 do {
  209                                         *p++ = hexdig[ull & 15];
  210                                 } while (ull >>= 4);
  211                                 do {
  212                                         put(*--p);
  213                                 } while (p > buf);
  214                                 break;
  215                         }
  216 #endif
  217                         ul = lflag ?
  218                             va_arg(ap, u_long) : va_arg(ap, u_int);
  219                         kprintn(put, ul, 16);
  220                         break;
  221                 default:
  222                         put('%');
  223 #ifdef LIBSA_LONGLONG_PRINTF
  224                         while (--lflag)
  225 #else
  226                         if (lflag)
  227 #endif
  228                                 put('l');
  229                         put(ch);
  230                 }
  231         }
  232         va_end(ap);
  233 }
  234 
  235 void
  236 kprintn(void (*put)(int), unsigned long ul, int base)
  237 {
  238         /* hold a long in base 8 */
  239         char *p, buf[(sizeof(long) * NBBY / 3) + 1];
  240 
  241         p = buf;
  242         do {
  243                 *p++ = hexdig[ul % base];
  244         } while (ul /= base);
  245         do {
  246                 put(*--p);
  247         } while (p > buf);
  248 }
  249 
  250 #ifdef LIBSA_LONGLONG_PRINTF
  251 void
  252 kprintn64(void (*put)(int), u_int64_t ull, int base)
  253 {
  254         /* hold an int64_t in base 8 */
  255         char *p, buf[(sizeof(u_int64_t) * NBBY / 3) + 1];
  256 
  257         p = buf;
  258         do {
  259                 *p++ = hexdig[ull % base];
  260         } while (ull /= base);
  261         do {
  262                 put(*--p);
  263         } while (p > buf);
  264 }
  265 #endif
  266 
  267 int donottwiddle = 0;
  268 
  269 void
  270 twiddle(void)
  271 {
  272         static int pos;
  273 
  274         if (!donottwiddle) {
  275                 putchar("|/-\\"[pos++ & 3]);
  276                 putchar('\b');
  277         }
  278 }

/* [<][>][^][v][top][bottom][index][help] */