Home | History | Annotate | Line # | Download | only in libsa
subr_prf.c revision 1.21.16.1
      1  1.21.16.1     rmind /*	$NetBSD: subr_prf.c,v 1.21.16.1 2014/05/18 17:46:08 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 
     42        1.1        pk #include "stand.h"
     43        1.1        pk 
     44       1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
     45       1.17   tsutsui #define INTMAX_T	longlong_t
     46       1.17   tsutsui #define UINTMAX_T	u_longlong_t
     47       1.17   tsutsui #else
     48       1.17   tsutsui #define INTMAX_T	long
     49       1.17   tsutsui #define UINTMAX_T	u_long
     50       1.17   tsutsui #endif
     51       1.17   tsutsui 
     52       1.17   tsutsui #if 0 /* XXX: abuse intptr_t until the situation with ptrdiff_t is clear */
     53       1.17   tsutsui #define PTRDIFF_T	ptrdiff_t
     54       1.17   tsutsui #else
     55       1.17   tsutsui #define PTRDIFF_T	intptr_t
     56       1.17   tsutsui #endif
     57       1.17   tsutsui 
     58       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
     59       1.17   tsutsui static void kprintn(void (*)(int), UINTMAX_T, int, int, int);
     60       1.17   tsutsui #else
     61       1.17   tsutsui static void kprintn(void (*)(int), UINTMAX_T, int);
     62       1.17   tsutsui #endif
     63        1.6     bjh21 static void sputchar(int);
     64        1.6     bjh21 static void kdoprnt(void (*)(int), const char *, va_list);
     65        1.1        pk 
     66        1.1        pk static char *sbuf, *ebuf;
     67        1.1        pk 
     68       1.19     joerg const char hexdigits[16] = "0123456789abcdef";
     69       1.11  christos 
     70       1.17   tsutsui #define LONG		0x01
     71       1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
     72       1.17   tsutsui #define LLONG		0x02
     73       1.17   tsutsui #endif
     74       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
     75       1.17   tsutsui #define ALT		0x04
     76       1.17   tsutsui #define SPACE		0x08
     77       1.17   tsutsui #define LADJUST		0x10
     78       1.17   tsutsui #define SIGN		0x20
     79       1.17   tsutsui #define ZEROPAD		0x40
     80       1.17   tsutsui #define NEGATIVE	0x80
     81       1.17   tsutsui #define KPRINTN(base)	kprintn(put, ul, base, lflag, width)
     82  1.21.16.1     rmind #define LZERO()							\
     83       1.17   tsutsui do {								\
     84       1.17   tsutsui 	if ((lflag & (ZEROPAD|LADJUST)) == ZEROPAD) {		\
     85       1.17   tsutsui 		while (width-- > 0)				\
     86       1.17   tsutsui 			put('0');				\
     87       1.17   tsutsui 	}							\
     88       1.17   tsutsui } while (/*CONSTCOND*/0)
     89       1.17   tsutsui #define RPAD()							\
     90       1.17   tsutsui do {								\
     91       1.17   tsutsui 	if (lflag & LADJUST) {					\
     92       1.17   tsutsui 		while (width-- > 0)				\
     93       1.17   tsutsui 			put(' ');				\
     94       1.17   tsutsui 	}							\
     95       1.17   tsutsui } while (/*CONSTCOND*/0)
     96       1.17   tsutsui #define LPAD()							\
     97       1.17   tsutsui do {								\
     98       1.17   tsutsui 	if ((lflag & (ZEROPAD|LADJUST)) == 0) {			\
     99       1.17   tsutsui 		while (width-- > 0)				\
    100       1.17   tsutsui 			put(' ');				\
    101       1.17   tsutsui 	}							\
    102       1.17   tsutsui } while (/*CONSTCOND*/0)
    103       1.17   tsutsui #else	/* LIBSA_PRINTF_WIDTH_SUPPORT */
    104       1.17   tsutsui #define KPRINTN(base)	kprintn(put, ul, base)
    105  1.21.16.1     rmind #define LZERO()		/**/
    106       1.17   tsutsui #define RPAD()		/**/
    107       1.17   tsutsui #define LPAD()		/**/
    108       1.17   tsutsui #endif	/* LIBSA_PRINTF_WIDTH_SUPPORT */
    109       1.17   tsutsui 
    110       1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    111       1.17   tsutsui #define KPRINT(base)						\
    112       1.17   tsutsui do {								\
    113       1.17   tsutsui 	ul = (lflag & LLONG)					\
    114       1.17   tsutsui 	    ? va_arg(ap, u_longlong_t)				\
    115       1.17   tsutsui 	    : (lflag & LONG)					\
    116       1.17   tsutsui 		? va_arg(ap, u_long)				\
    117       1.17   tsutsui 		: va_arg(ap, u_int);				\
    118       1.17   tsutsui 	KPRINTN(base);						\
    119       1.17   tsutsui } while (/*CONSTCOND*/0)
    120       1.17   tsutsui #else	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
    121       1.17   tsutsui #define KPRINT(base)						\
    122       1.17   tsutsui do {								\
    123       1.17   tsutsui 	ul = (lflag & LONG)					\
    124       1.17   tsutsui 	    ? va_arg(ap, u_long) : va_arg(ap, u_int);		\
    125       1.17   tsutsui 	KPRINTN(base);						\
    126       1.17   tsutsui } while (/*CONSTCOND*/0)
    127       1.17   tsutsui #endif	/* LIBSA_PRINTF_LONGLONG_SUPPORT */
    128       1.17   tsutsui 
    129        1.1        pk static void
    130        1.6     bjh21 sputchar(int c)
    131        1.1        pk {
    132        1.6     bjh21 
    133        1.1        pk 	if (sbuf < ebuf)
    134        1.1        pk 		*sbuf++ = c;
    135        1.1        pk }
    136        1.1        pk 
    137        1.1        pk void
    138        1.1        pk vprintf(const char *fmt, va_list ap)
    139        1.1        pk {
    140        1.1        pk 
    141        1.1        pk 	kdoprnt(putchar, fmt, ap);
    142        1.1        pk }
    143        1.1        pk 
    144        1.1        pk int
    145        1.1        pk vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
    146        1.1        pk {
    147        1.1        pk 
    148        1.1        pk 	sbuf = buf;
    149        1.1        pk 	ebuf = buf + size - 1;
    150        1.1        pk 	kdoprnt(sputchar, fmt, ap);
    151        1.1        pk 	*sbuf = '\0';
    152       1.16     isaki 	return sbuf - buf;
    153        1.1        pk }
    154        1.1        pk 
    155        1.5   thorpej static void
    156        1.6     bjh21 kdoprnt(void (*put)(int), const char *fmt, va_list ap)
    157        1.1        pk {
    158        1.3  augustss 	char *p;
    159        1.9      tron 	int ch;
    160       1.17   tsutsui 	UINTMAX_T ul;
    161        1.9      tron 	int lflag;
    162       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    163       1.17   tsutsui 	int width;
    164       1.17   tsutsui 	char *q;
    165       1.17   tsutsui #endif
    166        1.1        pk 
    167        1.1        pk 	for (;;) {
    168        1.1        pk 		while ((ch = *fmt++) != '%') {
    169        1.1        pk 			if (ch == '\0')
    170        1.1        pk 				return;
    171        1.1        pk 			put(ch);
    172        1.1        pk 		}
    173        1.1        pk 		lflag = 0;
    174       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    175       1.17   tsutsui 		width = 0;
    176       1.17   tsutsui #endif
    177       1.16     isaki reswitch:
    178       1.16     isaki 		switch (ch = *fmt++) {
    179       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    180       1.17   tsutsui 		case '#':
    181       1.17   tsutsui 			lflag |= ALT;
    182       1.17   tsutsui 			goto reswitch;
    183       1.17   tsutsui 		case ' ':
    184       1.17   tsutsui 			lflag |= SPACE;
    185       1.17   tsutsui 			goto reswitch;
    186       1.17   tsutsui 		case '-':
    187       1.17   tsutsui 			lflag |= LADJUST;
    188       1.17   tsutsui 			goto reswitch;
    189       1.17   tsutsui 		case '+':
    190       1.17   tsutsui 			lflag |= SIGN;
    191       1.17   tsutsui 			goto reswitch;
    192       1.17   tsutsui 		case '0':
    193       1.17   tsutsui 			lflag |= ZEROPAD;
    194       1.17   tsutsui 			goto reswitch;
    195       1.17   tsutsui 		case '1': case '2': case '3': case '4': case '5':
    196       1.17   tsutsui 		case '6': case '7': case '8': case '9':
    197       1.17   tsutsui 			for (;;) {
    198       1.17   tsutsui 				width *= 10;
    199       1.17   tsutsui 				width += ch - '0';
    200       1.17   tsutsui 				ch = *fmt;
    201       1.17   tsutsui 				if ((unsigned)ch - '0' > 9)
    202       1.17   tsutsui 					break;
    203       1.17   tsutsui 				++fmt;
    204       1.17   tsutsui 			}
    205       1.17   tsutsui #endif
    206       1.17   tsutsui 			goto reswitch;
    207        1.1        pk 		case 'l':
    208       1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    209       1.17   tsutsui 			if (*fmt == 'l') {
    210       1.17   tsutsui 				++fmt;
    211       1.17   tsutsui 				lflag |= LLONG;
    212       1.17   tsutsui 			} else
    213       1.17   tsutsui #endif
    214       1.17   tsutsui 				lflag |= LONG;
    215        1.1        pk 			goto reswitch;
    216  1.21.16.1     rmind 		case 'j':
    217  1.21.16.1     rmind #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    218  1.21.16.1     rmind 			if (sizeof(intmax_t) == sizeof(long long))
    219  1.21.16.1     rmind 				lflag |= LLONG;
    220  1.21.16.1     rmind 			else
    221  1.21.16.1     rmind #endif
    222  1.21.16.1     rmind 			if (sizeof(intmax_t) == sizeof(long))
    223  1.21.16.1     rmind 				lflag |= LONG;
    224  1.21.16.1     rmind 			goto reswitch;
    225       1.14       uwe 		case 't':
    226       1.17   tsutsui 			if (sizeof(PTRDIFF_T) == sizeof(long))
    227       1.17   tsutsui 				lflag |= LONG;
    228       1.14       uwe 			goto reswitch;
    229       1.14       uwe 		case 'z':
    230       1.17   tsutsui 			if (sizeof(ssize_t) == sizeof(long))
    231       1.17   tsutsui 				lflag |= LONG;
    232       1.14       uwe 			goto reswitch;
    233        1.1        pk 		case 'c':
    234        1.1        pk 			ch = va_arg(ap, int);
    235       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    236       1.17   tsutsui 			--width;
    237       1.17   tsutsui #endif
    238       1.17   tsutsui 			LPAD();
    239  1.21.16.1     rmind 			put(ch & 0xFF);
    240  1.21.16.1     rmind 			RPAD();
    241        1.1        pk 			break;
    242        1.1        pk 		case 's':
    243        1.1        pk 			p = va_arg(ap, char *);
    244       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    245       1.20   tsutsui 			for (q = p; *q != '\0'; ++q)
    246       1.20   tsutsui 				continue;
    247       1.17   tsutsui 			width -= q - p;
    248       1.17   tsutsui #endif
    249  1.21.16.1     rmind 			LPAD();
    250       1.17   tsutsui 			while ((ch = (unsigned char)*p++))
    251        1.1        pk 				put(ch);
    252  1.21.16.1     rmind 			RPAD();
    253        1.1        pk 			break;
    254        1.1        pk 		case 'd':
    255       1.17   tsutsui 			ul =
    256       1.17   tsutsui #ifdef LIBSA_PRINTF_LONGLONG_SUPPORT
    257       1.17   tsutsui 			(lflag & LLONG) ? va_arg(ap, longlong_t) :
    258       1.17   tsutsui #endif
    259       1.17   tsutsui 			(lflag & LONG) ? va_arg(ap, long) : va_arg(ap, int);
    260       1.17   tsutsui 			if ((INTMAX_T)ul < 0) {
    261       1.17   tsutsui 				ul = -(INTMAX_T)ul;
    262       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    263       1.17   tsutsui 				lflag |= NEGATIVE;
    264       1.17   tsutsui #else
    265        1.1        pk 				put('-');
    266       1.17   tsutsui #endif
    267        1.1        pk 			}
    268       1.17   tsutsui 			KPRINTN(10);
    269        1.1        pk 			break;
    270        1.1        pk 		case 'o':
    271       1.17   tsutsui 			KPRINT(8);
    272        1.1        pk 			break;
    273        1.1        pk 		case 'u':
    274       1.17   tsutsui 			KPRINT(10);
    275        1.1        pk 			break;
    276        1.1        pk 		case 'p':
    277       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    278       1.17   tsutsui 			lflag |= (LONG|ALT);
    279       1.17   tsutsui #else
    280        1.1        pk 			put('0');
    281        1.1        pk 			put('x');
    282       1.17   tsutsui #endif
    283       1.15       uwe 			/* FALLTHROUGH */
    284        1.1        pk 		case 'x':
    285       1.17   tsutsui 			KPRINT(16);
    286        1.1        pk 			break;
    287        1.1        pk 		default:
    288        1.7     bjh21 			if (ch == '\0')
    289        1.7     bjh21 				return;
    290        1.1        pk 			put(ch);
    291       1.16     isaki 			break;
    292        1.1        pk 		}
    293        1.1        pk 	}
    294        1.1        pk }
    295        1.1        pk 
    296        1.1        pk static void
    297       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    298       1.17   tsutsui kprintn(void (*put)(int), UINTMAX_T ul, int base, int lflag, int width)
    299       1.17   tsutsui #else
    300       1.17   tsutsui kprintn(void (*put)(int), UINTMAX_T ul, int base)
    301       1.17   tsutsui #endif
    302        1.1        pk {
    303       1.17   tsutsui 					/* hold a INTMAX_T in base 8 */
    304       1.17   tsutsui 	char *p, buf[(sizeof(INTMAX_T) * NBBY / 3) + 1 + 2 /* ALT + SIGN */];
    305       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    306       1.17   tsutsui 	char *q;
    307       1.17   tsutsui #endif
    308        1.1        pk 
    309        1.1        pk 	p = buf;
    310        1.1        pk 	do {
    311       1.11  christos 		*p++ = hexdigits[ul % base];
    312        1.1        pk 	} while (ul /= base);
    313       1.17   tsutsui #ifdef LIBSA_PRINTF_WIDTH_SUPPORT
    314       1.17   tsutsui 	q = p;
    315       1.17   tsutsui 	if (lflag & ALT && *(p - 1) != '0') {
    316       1.17   tsutsui 		if (base == 8) {
    317       1.17   tsutsui 			*p++ = '0';
    318       1.17   tsutsui 		} else if (base == 16) {
    319       1.17   tsutsui 			*p++ = 'x';
    320       1.17   tsutsui 			*p++ = '0';
    321       1.17   tsutsui 		}
    322       1.17   tsutsui 	}
    323       1.17   tsutsui 	if (lflag & NEGATIVE)
    324       1.17   tsutsui 		*p++ = '-';
    325       1.17   tsutsui 	else if (lflag & SIGN)
    326       1.17   tsutsui 		*p++ = '+';
    327       1.17   tsutsui 	else if (lflag & SPACE)
    328       1.17   tsutsui 		*p++ = ' ';
    329       1.17   tsutsui 	width -= p - buf;
    330  1.21.16.1     rmind 	if (lflag & ZEROPAD) {
    331       1.17   tsutsui 		while (p > q)
    332       1.17   tsutsui 			put(*--p);
    333       1.17   tsutsui 	}
    334       1.17   tsutsui #endif
    335  1.21.16.1     rmind 	LPAD();
    336  1.21.16.1     rmind 	LZERO();
    337        1.1        pk 	do {
    338        1.1        pk 		put(*--p);
    339        1.1        pk 	} while (p > buf);
    340  1.21.16.1     rmind 	RPAD();
    341        1.1        pk }
    342