Home | History | Annotate | Line # | Download | only in libsa
subr_prf.c revision 1.17.4.1
      1  1.17.4.1     rmind /*	$NetBSD: subr_prf.c,v 1.17.4.1 2011/03/05 20:55:29 rmind Exp $	*/
      2       1.1        pk 
      3       1.1        pk /*-
      4       1.1        pk  * Copyright (c) 1993
      5       1.1        pk  *	The Regents of the University of California.  All rights reserved.
      6       1.1        pk  *
      7       1.1        pk  * Redistribution and use in source and binary forms, with or without
      8       1.1        pk  * modification, are permitted provided that the following conditions
      9       1.1        pk  * are met:
     10       1.1        pk  * 1. Redistributions of source code must retain the above copyright
     11       1.1        pk  *    notice, this list of conditions and the following disclaimer.
     12       1.1        pk  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1        pk  *    notice, this list of conditions and the following disclaimer in the
     14       1.1        pk  *    documentation and/or other materials provided with the distribution.
     15      1.10       agc  * 3. Neither the name of the University nor the names of its contributors
     16       1.1        pk  *    may be used to endorse or promote products derived from this software
     17       1.1        pk  *    without specific prior written permission.
     18       1.1        pk  *
     19       1.1        pk  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20       1.1        pk  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21       1.1        pk  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22       1.1        pk  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23       1.1        pk  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1        pk  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25       1.1        pk  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1        pk  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1        pk  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1        pk  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1        pk  * SUCH DAMAGE.
     30       1.1        pk  *
     31       1.1        pk  *	@(#)printf.c	8.1 (Berkeley) 6/11/93
     32       1.1        pk  */
     33       1.1        pk 
     34       1.1        pk /*
     35       1.1        pk  * Scaled down version of printf(3).
     36       1.1        pk  */
     37       1.1        pk 
     38       1.1        pk #include <sys/cdefs.h>
     39       1.1        pk #include <sys/types.h>
     40      1.14       uwe #include <sys/stdint.h>		/* XXX: for intptr_t */
     41       1.1        pk #include <machine/stdarg.h>
     42       1.1        pk 
     43       1.1        pk #include "stand.h"
     44       1.1        pk 
     45      1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
     46      1.17   tsutsui #define INTMAX_T	longlong_t
     47      1.17   tsutsui #define UINTMAX_T	u_longlong_t
     48      1.17   tsutsui #else
     49      1.17   tsutsui #define INTMAX_T	long
     50      1.17   tsutsui #define UINTMAX_T	u_long
     51      1.17   tsutsui #endif
     52      1.17   tsutsui 
     53      1.17   tsutsui #if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
     54      1.17   tsutsui #define PTRDIFF_T	ptrdiff_t
     55      1.17   tsutsui #else
     56      1.17   tsutsui #define PTRDIFF_T	intptr_t
     57      1.17   tsutsui #endif
     58      1.17   tsutsui 
     59      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
     60      1.17   tsutsui static void kprintn(void (*)(int), UINTMAX_T, int, int, int);
     61      1.17   tsutsui #else
     62      1.17   tsutsui static void kprintn(void (*)(int), UINTMAX_T, int);
     63      1.17   tsutsui #endif
     64       1.6     bjh21 static void sputchar(int);
     65       1.6     bjh21 static void kdoprnt(void (*)(int), const char *, va_list);
     66       1.1        pk 
     67       1.1        pk static char *sbuf, *ebuf;
     68       1.1        pk 
     69  1.17.4.1     rmind const char hexdigits[16] = "0123456789abcdef";
     70      1.11  christos 
     71      1.17   tsutsui #define LONG		0x01
     72      1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
     73      1.17   tsutsui #define LLONG		0x02
     74      1.17   tsutsui #endif
     75      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
     76      1.17   tsutsui #define ALT		0x04
     77      1.17   tsutsui #define SPACE		0x08
     78      1.17   tsutsui #define LADJUST		0x10
     79      1.17   tsutsui #define SIGN		0x20
     80      1.17   tsutsui #define ZEROPAD		0x40
     81      1.17   tsutsui #define NEGATIVE	0x80
     82      1.17   tsutsui #define KPRINTN(base)	kprintn(put, ul, base, lflag, width)
     83      1.17   tsutsui #define RZERO()							\
     84      1.17   tsutsui do {								\
     85      1.17   tsutsui 	if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) {		\
     86      1.17   tsutsui 		while (width-- > 0)				\
     87      1.17   tsutsui 			put('0');				\
     88      1.17   tsutsui 	}							\
     89      1.17   tsutsui } while (/*CONSTCOND*/0)
     90      1.17   tsutsui #define RPAD()							\
     91      1.17   tsutsui do {								\
     92      1.17   tsutsui 	if (lflag & LADJUST) {					\
     93      1.17   tsutsui 		while (width-- > 0)				\
     94      1.17   tsutsui 			put(' ');				\
     95      1.17   tsutsui 	}							\
     96      1.17   tsutsui } while (/*CONSTCOND*/0)
     97      1.17   tsutsui #define LPAD()							\
     98      1.17   tsutsui do {								\
     99      1.17   tsutsui 	if ((lflag & (ZEROPAD|LADJUST)) == 0) {			\
    100      1.17   tsutsui 		while (width-- > 0)				\
    101      1.17   tsutsui 			put(' ');				\
    102      1.17   tsutsui 	}							\
    103      1.17   tsutsui } while (/*CONSTCOND*/0)
    104      1.17   tsutsui #else	/* LIBSA_PRINTF_WIDTH_SUPPORT */
    105      1.17   tsutsui #define KPRINTN(base)	kprintn(put, ul, base)
    106      1.17   tsutsui #define RZERO()		/**/
    107      1.17   tsutsui #define RPAD()		/**/
    108      1.17   tsutsui #define LPAD()		/**/
    109      1.17   tsutsui #endif	/* LIBSA_PRINTF_WIDTH_SUPPORT */
    110      1.17   tsutsui 
    111      1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    112      1.17   tsutsui #define KPRINT(base)						\
    113      1.17   tsutsui do {								\
    114      1.17   tsutsui 	ul = (lflag & LLONG)					\
    115      1.17   tsutsui 	    ? va_arg(ap, u_longlong_t)				\
    116      1.17   tsutsui 	    : (lflag & LONG)					\
    117      1.17   tsutsui 		? va_arg(ap, u_long)				\
    118      1.17   tsutsui 		: va_arg(ap, u_int);				\
    119      1.17   tsutsui 	KPRINTN(base);						\
    120      1.17   tsutsui } while (/*CONSTCOND*/0)
    121      1.17   tsutsui #else	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
    122      1.17   tsutsui #define KPRINT(base)						\
    123      1.17   tsutsui do {								\
    124      1.17   tsutsui 	ul = (lflag & LONG)					\
    125      1.17   tsutsui 	    ? va_arg(ap, u_long) : va_arg(ap, u_int);		\
    126      1.17   tsutsui 	KPRINTN(base);						\
    127      1.17   tsutsui } while (/*CONSTCOND*/0)
    128      1.17   tsutsui #endif	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
    129      1.17   tsutsui 
    130       1.1        pk static void
    131       1.6     bjh21 sputchar(int c)
    132       1.1        pk {
    133       1.6     bjh21 
    134       1.1        pk 	if (sbuf < ebuf)
    135       1.1        pk 		*sbuf++ = c;
    136       1.1        pk }
    137       1.1        pk 
    138       1.1        pk void
    139       1.1        pk vprintf(const char *fmt, va_list ap)
    140       1.1        pk {
    141       1.1        pk 
    142       1.1        pk 	kdoprnt(putchar, fmt, ap);
    143       1.1        pk }
    144       1.1        pk 
    145       1.1        pk int
    146       1.1        pk vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
    147       1.1        pk {
    148       1.1        pk 
    149       1.1        pk 	sbuf = buf;
    150       1.1        pk 	ebuf = buf + size - 1;
    151       1.1        pk 	kdoprnt(sputchar, fmt, ap);
    152       1.1        pk 	*sbuf = '\0';
    153      1.16     isaki 	return sbuf - buf;
    154       1.1        pk }
    155       1.1        pk 
    156       1.5   thorpej static void
    157       1.6     bjh21 kdoprnt(void (*put)(int), const char *fmt, va_list ap)
    158       1.1        pk {
    159       1.3  augustss 	char *p;
    160       1.9      tron 	int ch;
    161      1.17   tsutsui 	UINTMAX_T ul;
    162       1.9      tron 	int lflag;
    163      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    164      1.17   tsutsui 	int width;
    165      1.17   tsutsui 	char *q;
    166      1.17   tsutsui #endif
    167       1.1        pk 
    168       1.1        pk 	for (;;) {
    169       1.1        pk 		while ((ch = *fmt++) != '%') {
    170       1.1        pk 			if (ch == '\0')
    171       1.1        pk 				return;
    172       1.1        pk 			put(ch);
    173       1.1        pk 		}
    174       1.1        pk 		lflag = 0;
    175      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    176      1.17   tsutsui 		width = 0;
    177      1.17   tsutsui #endif
    178      1.16     isaki reswitch:
    179      1.16     isaki 		switch (ch = *fmt++) {
    180      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    181      1.17   tsutsui 		case '#':
    182      1.17   tsutsui 			lflag |= ALT;
    183      1.17   tsutsui 			goto reswitch;
    184      1.17   tsutsui 		case ' ':
    185      1.17   tsutsui 			lflag |= SPACE;
    186      1.17   tsutsui 			goto reswitch;
    187      1.17   tsutsui 		case '-':
    188      1.17   tsutsui 			lflag |= LADJUST;
    189      1.17   tsutsui 			goto reswitch;
    190      1.17   tsutsui 		case '+':
    191      1.17   tsutsui 			lflag |= SIGN;
    192      1.17   tsutsui 			goto reswitch;
    193      1.17   tsutsui 		case '0':
    194      1.17   tsutsui 			lflag |= ZEROPAD;
    195      1.17   tsutsui 			goto reswitch;
    196      1.17   tsutsui 		case '1': case '2': case '3': case '4': case '5':
    197      1.17   tsutsui 		case '6': case '7': case '8': case '9':
    198      1.17   tsutsui 			for (;;) {
    199      1.17   tsutsui 				width *= 10;
    200      1.17   tsutsui 				width += ch - '0';
    201      1.17   tsutsui 				ch = *fmt;
    202      1.17   tsutsui 				if ((unsigned)ch - '0' > 9)
    203      1.17   tsutsui 					break;
    204      1.17   tsutsui 				++fmt;
    205      1.17   tsutsui 			}
    206      1.17   tsutsui #endif
    207      1.17   tsutsui 			goto reswitch;
    208       1.1        pk 		case 'l':
    209      1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    210      1.17   tsutsui 			if (*fmt == 'l') {
    211      1.17   tsutsui 				++fmt;
    212      1.17   tsutsui 				lflag |= LLONG;
    213      1.17   tsutsui 			} else
    214      1.17   tsutsui #endif
    215      1.17   tsutsui 				lflag |= LONG;
    216       1.1        pk 			goto reswitch;
    217      1.14       uwe 		case 't':
    218      1.17   tsutsui 			if (sizeof(PTRDIFF_T) == sizeof(long))
    219      1.17   tsutsui 				lflag |= LONG;
    220      1.14       uwe 			goto reswitch;
    221      1.14       uwe 		case 'z':
    222      1.17   tsutsui 			if (sizeof(ssize_t) == sizeof(long))
    223      1.17   tsutsui 				lflag |= LONG;
    224      1.14       uwe 			goto reswitch;
    225       1.1        pk 		case 'c':
    226       1.1        pk 			ch = va_arg(ap, int);
    227      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    228      1.17   tsutsui 			--width;
    229      1.17   tsutsui #endif
    230      1.17   tsutsui 			RPAD();
    231      1.17   tsutsui 			put(ch & 0xFF);
    232      1.17   tsutsui 			LPAD();
    233       1.1        pk 			break;
    234       1.1        pk 		case 's':
    235       1.1        pk 			p = va_arg(ap, char *);
    236      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    237      1.17   tsutsui 			for (q = p; *q; ++q);
    238      1.17   tsutsui 			width -= q - p;
    239      1.17   tsutsui #endif
    240      1.17   tsutsui 			RPAD();
    241      1.17   tsutsui 			while ((ch = (unsigned char)*p++))
    242       1.1        pk 				put(ch);
    243      1.17   tsutsui 			LPAD();
    244       1.1        pk 			break;
    245       1.1        pk 		case 'd':
    246      1.17   tsutsui 			ul =
    247      1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    248      1.17   tsutsui 			(lflag & LLONG) ? va_arg(ap, longlong_t) :
    249      1.17   tsutsui #endif
    250      1.17   tsutsui 			(lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
    251      1.17   tsutsui 			if ((INTMAX_T)ul < 0) {
    252      1.17   tsutsui 				ul = -(INTMAX_T)ul;
    253      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    254      1.17   tsutsui 				lflag |= NEGATIVE;
    255      1.17   tsutsui #else
    256       1.1        pk 				put('-');
    257      1.17   tsutsui #endif
    258       1.1        pk 			}
    259      1.17   tsutsui 			KPRINTN(10);
    260       1.1        pk 			break;
    261       1.1        pk 		case 'o':
    262      1.17   tsutsui 			KPRINT(8);
    263       1.1        pk 			break;
    264       1.1        pk 		case 'u':
    265      1.17   tsutsui 			KPRINT(10);
    266       1.1        pk 			break;
    267       1.1        pk 		case 'p':
    268      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    269      1.17   tsutsui 			lflag |= (LONG|ALT);
    270      1.17   tsutsui #else
    271       1.1        pk 			put('0');
    272       1.1        pk 			put('x');
    273      1.17   tsutsui #endif
    274      1.15       uwe 			/* FALLTHROUGH */
    275       1.1        pk 		case 'x':
    276      1.17   tsutsui 			KPRINT(16);
    277       1.1        pk 			break;
    278       1.1        pk 		default:
    279       1.7     bjh21 			if (ch == '\0')
    280       1.7     bjh21 				return;
    281       1.1        pk 			put(ch);
    282      1.16     isaki 			break;
    283       1.1        pk 		}
    284       1.1        pk 	}
    285       1.1        pk }
    286       1.1        pk 
    287       1.1        pk static void
    288      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    289      1.17   tsutsui kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
    290      1.17   tsutsui #else
    291      1.17   tsutsui kprintn(void (*put)(int), UINTMAX_T ul, int base)
    292      1.17   tsutsui #endif
    293       1.1        pk {
    294      1.17   tsutsui 					/* hold a INTMAX_T in base 8 */
    295      1.17   tsutsui 	char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
    296      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    297      1.17   tsutsui 	char *q;
    298      1.17   tsutsui #endif
    299       1.1        pk 
    300       1.1        pk 	p = buf;
    301       1.1        pk 	do {
    302      1.11  christos 		*p++ = hexdigits[ul % base];
    303       1.1        pk 	} while (ul /= base);
    304      1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    305      1.17   tsutsui 	q = p;
    306      1.17   tsutsui 	if (lflag & ALT && *(p - 1) != '0') {
    307      1.17   tsutsui 		if (base == 8) {
    308      1.17   tsutsui 			*p++ = '0';
    309      1.17   tsutsui 		} else if (base == 16) {
    310      1.17   tsutsui 			*p++ = 'x';
    311      1.17   tsutsui 			*p++ = '0';
    312      1.17   tsutsui 		}
    313      1.17   tsutsui 	}
    314      1.17   tsutsui 	if (lflag & NEGATIVE)
    315      1.17   tsutsui 		*p++ = '-';
    316      1.17   tsutsui 	else if (lflag & SIGN)
    317      1.17   tsutsui 		*p++ = '+';
    318      1.17   tsutsui 	else if (lflag & SPACE)
    319      1.17   tsutsui 		*p++ = ' ';
    320      1.17   tsutsui 	width -= p - buf;
    321      1.17   tsutsui 	if ((lflag & LADJUST) == 0) {
    322      1.17   tsutsui 		while (p > q)
    323      1.17   tsutsui 			put(*--p);
    324      1.17   tsutsui 	}
    325      1.17   tsutsui #endif
    326      1.17   tsutsui 	RPAD();
    327      1.17   tsutsui 	RZERO();
    328       1.1        pk 	do {
    329       1.1        pk 		put(*--p);
    330       1.1        pk 	} while (p > buf);
    331      1.17   tsutsui 	LPAD();
    332       1.1        pk }
    333