Home | History | Annotate | Line # | Download | only in common
xprintf.c revision 1.3
      1  1.1  itohy /*
      2  1.1  itohy  *	minimal printf for Human68k DOS
      3  1.1  itohy  *
      4  1.1  itohy  *	written by Yasha (ITOH Yasufumi)
      5  1.1  itohy  *	public domain
      6  1.1  itohy  *
      7  1.3    dsl  *	$NetBSD: xprintf.c,v 1.3 2009/03/14 15:36:15 dsl Exp $
      8  1.1  itohy  */
      9  1.1  itohy 
     10  1.1  itohy #include <sys/types.h>
     11  1.1  itohy #ifdef __STDC__
     12  1.1  itohy # include <stdarg.h>
     13  1.1  itohy #else
     14  1.1  itohy # include <varargs.h>
     15  1.1  itohy #endif
     16  1.1  itohy 
     17  1.1  itohy #include <dos.h>
     18  1.1  itohy #include <dos_errno.h>
     19  1.1  itohy 
     20  1.1  itohy #include "xprintf.h"
     21  1.1  itohy 
     22  1.1  itohy /*
     23  1.1  itohy  * From ISO/IEC 9899:1990
     24  1.1  itohy  * 7.9.6.1 The fprintf function
     25  1.1  itohy  * ...
     26  1.1  itohy  * Environment limit
     27  1.1  itohy  *    The minimum value for the maximum number of characters
     28  1.1  itohy  * produced by any single conversion shall be 509.
     29  1.1  itohy  *
     30  1.1  itohy  * so the following value shall not be smaller than 510
     31  1.1  itohy  * if you want to conform ANSI C (it is only a guideline
     32  1.1  itohy  * and maybe no sense on this code, of course :-).
     33  1.1  itohy  */
     34  1.1  itohy #define PRINTF_BUFSZ	4096
     35  1.1  itohy 
     36  1.1  itohy /*
     37  1.1  itohy  * Shift-JIS kanji support
     38  1.1  itohy  * (No special handling needed for EUC)
     39  1.1  itohy  */
     40  1.1  itohy #define SJIS
     41  1.1  itohy 
     42  1.1  itohy #ifdef SJIS
     43  1.1  itohy #define UC(c)		((unsigned char) (c))
     44  1.1  itohy #define IS_SJIS1(c)	((UC(c) > 0x80 && UC(c) < 0xa0) ||	\
     45  1.1  itohy 				(UC(c) >= 0xe0 && UC(c) <= 0xfc))
     46  1.1  itohy #define IS_SJIS2(c)	(UC(c) >= 0x40 && UC(c) <= 0xfc && UC(c) != 0x7f)
     47  1.1  itohy #endif
     48  1.1  itohy 
     49  1.1  itohy #if !defined(__STDC__) && !defined(const)
     50  1.1  itohy #define const
     51  1.1  itohy #endif
     52  1.1  itohy 
     53  1.1  itohy extern const char *const __progname;
     54  1.1  itohy 
     55  1.2    dsl static char * numstr(char *buf, long val, int base, int sign);
     56  1.1  itohy 
     57  1.1  itohy /*
     58  1.1  itohy  * convert number to string
     59  1.1  itohy  * buf must have enough space
     60  1.1  itohy  */
     61  1.1  itohy static char *
     62  1.1  itohy numstr(buf, val, base, sign)
     63  1.1  itohy 	char *buf;
     64  1.1  itohy 	long val;
     65  1.1  itohy 	int base, sign;
     66  1.1  itohy {
     67  1.1  itohy 	unsigned long v;
     68  1.1  itohy 	char rev[32];
     69  1.1  itohy 	char *r = rev, *b = buf;
     70  1.1  itohy 
     71  1.1  itohy 	/* negative? */
     72  1.1  itohy 	if (sign && val < 0) {
     73  1.1  itohy 		v = -val;
     74  1.1  itohy 		*b++ = '-';
     75  1.1  itohy 	} else {
     76  1.1  itohy 		v = val;
     77  1.1  itohy 	}
     78  1.1  itohy 
     79  1.1  itohy 	/* inverse order */
     80  1.1  itohy 	do {
     81  1.1  itohy 		*r++ = "0123456789abcdef"[v % base];
     82  1.1  itohy 		v /= base;
     83  1.1  itohy 	} while (v);
     84  1.1  itohy 
     85  1.1  itohy 	/* reverse string */
     86  1.1  itohy 	while (r > rev)
     87  1.1  itohy 		*b++ = *--r;
     88  1.1  itohy 
     89  1.1  itohy 	*b = '\0';
     90  1.1  itohy 	return buf;
     91  1.1  itohy }
     92  1.1  itohy 
     93  1.1  itohy /*
     94  1.1  itohy  * supported format: %x, %p, %s, %c, %d, %u, %o
     95  1.1  itohy  * \n is converted to \r\n
     96  1.1  itohy  *
     97  1.1  itohy  * XXX argument/parameter types are not strictly handled
     98  1.1  itohy  */
     99  1.1  itohy size_t
    100  1.3    dsl xvsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
    101  1.1  itohy {
    102  1.1  itohy 	char *b = buf;
    103  1.1  itohy 	const char *s;
    104  1.1  itohy 	char numbuf[32];
    105  1.1  itohy 
    106  1.1  itohy 	while (*fmt && len > 1) {
    107  1.1  itohy 		if (*fmt != '%') {
    108  1.1  itohy #ifdef SJIS
    109  1.1  itohy 			if (IS_SJIS1(*fmt) && IS_SJIS2(fmt[1])) {
    110  1.1  itohy 				if (len <= 2)
    111  1.1  itohy 					break;	/* not enough space */
    112  1.1  itohy 				*b++ = *fmt++;
    113  1.1  itohy 				len--;
    114  1.1  itohy 			}
    115  1.1  itohy #endif
    116  1.1  itohy 			if (*fmt == '\n' && (b == buf || b[-1] != '\r')) {
    117  1.1  itohy 				if (len <= 2)
    118  1.1  itohy 					break;
    119  1.1  itohy 				*b++ = '\r';
    120  1.1  itohy 				len--;
    121  1.1  itohy 			}
    122  1.1  itohy 			*b++ = *fmt++;
    123  1.1  itohy 			len--;
    124  1.1  itohy 			continue;
    125  1.1  itohy 		}
    126  1.1  itohy 
    127  1.1  itohy 		/* %? */
    128  1.1  itohy 		fmt++;
    129  1.1  itohy 		switch (*fmt++) {
    130  1.1  itohy 		case '%':	/* "%%" -> literal % */
    131  1.1  itohy 			*b++ = '%';
    132  1.1  itohy 			len--;
    133  1.1  itohy 			break;
    134  1.1  itohy 
    135  1.1  itohy 		case 'd':
    136  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 10, 1);
    137  1.1  itohy 		copy_string:
    138  1.1  itohy 			for ( ; *s && len > 1; len--)
    139  1.1  itohy 				*b++ = *s++;
    140  1.1  itohy 			break;
    141  1.1  itohy 
    142  1.1  itohy 		case 'u':
    143  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 10, 0);
    144  1.1  itohy 			goto copy_string;
    145  1.1  itohy 
    146  1.1  itohy 		case 'p':
    147  1.1  itohy 			*b++ = '0';
    148  1.1  itohy 			len--;
    149  1.1  itohy 			if (len > 1) {
    150  1.1  itohy 				*b++ = 'x';
    151  1.1  itohy 				len--;
    152  1.1  itohy 			}
    153  1.1  itohy 			/* FALLTHROUGH */
    154  1.1  itohy 		case 'x':
    155  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 16, 0);
    156  1.1  itohy 			goto copy_string;
    157  1.1  itohy 
    158  1.1  itohy 		case 'o':
    159  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 8, 0);
    160  1.1  itohy 			goto copy_string;
    161  1.1  itohy 
    162  1.1  itohy 		case 's':
    163  1.1  itohy 			s = va_arg(ap, char *);
    164  1.1  itohy 			while (*s && len > 1) {
    165  1.1  itohy #ifdef SJIS
    166  1.1  itohy 				if (IS_SJIS1(*s) && IS_SJIS2(s[1])) {
    167  1.1  itohy 					if (len <= 2)
    168  1.1  itohy 						goto break_loop;
    169  1.1  itohy 					*b++ = *s++;
    170  1.1  itohy 					len--;
    171  1.1  itohy 				}
    172  1.1  itohy #endif
    173  1.1  itohy 				if (*s == '\n' && (b == buf || b[-1] != '\r')) {
    174  1.1  itohy 					if (len <= 2)
    175  1.1  itohy 						goto break_loop;
    176  1.1  itohy 					*b++ = '\r';
    177  1.1  itohy 					len--;
    178  1.1  itohy 				}
    179  1.1  itohy 				*b++ = *s++;
    180  1.1  itohy 				len--;
    181  1.1  itohy 			}
    182  1.1  itohy 			break;
    183  1.1  itohy 
    184  1.1  itohy 		case 'c':
    185  1.1  itohy 			*b++ = va_arg(ap, int);
    186  1.1  itohy 			len--;
    187  1.1  itohy 			break;
    188  1.1  itohy 		}
    189  1.1  itohy 	}
    190  1.1  itohy break_loop:
    191  1.1  itohy 
    192  1.1  itohy 	*b = '\0';
    193  1.1  itohy 	return (char *)b - buf;
    194  1.1  itohy }
    195  1.1  itohy 
    196  1.1  itohy #ifdef __STDC__
    197  1.1  itohy #define VA_START(a, v)	va_start(a, v)
    198  1.1  itohy #else
    199  1.1  itohy #define VA_START(a, v)	va_start(a)
    200  1.1  itohy #endif
    201  1.1  itohy 
    202  1.1  itohy #ifdef __STDC__
    203  1.1  itohy size_t
    204  1.1  itohy xsnprintf(char *buf, size_t len, const char *fmt, ...)
    205  1.1  itohy #else
    206  1.1  itohy size_t
    207  1.1  itohy xsnprintf(buf, len, fmt, va_alist)
    208  1.1  itohy 	char *buf;
    209  1.1  itohy 	size_t len;
    210  1.1  itohy 	const char *fmt;
    211  1.1  itohy 	va_dcl
    212  1.1  itohy #endif
    213  1.1  itohy {
    214  1.1  itohy 	va_list ap;
    215  1.1  itohy 	size_t ret;
    216  1.1  itohy 
    217  1.1  itohy 	VA_START(ap, fmt);
    218  1.1  itohy 	ret = xvsnprintf(buf, len, fmt, ap);
    219  1.1  itohy 	va_end(ap);
    220  1.1  itohy 
    221  1.1  itohy 	return ret;
    222  1.1  itohy }
    223  1.1  itohy 
    224  1.1  itohy size_t
    225  1.3    dsl xvfdprintf(int fd, const char *fmt, va_list ap)
    226  1.1  itohy {
    227  1.1  itohy 	char buf[PRINTF_BUFSZ];
    228  1.1  itohy 	size_t ret;
    229  1.1  itohy 
    230  1.1  itohy 	ret = xvsnprintf(buf, sizeof buf, fmt, ap);
    231  1.1  itohy 	if (ret)
    232  1.1  itohy 		ret = DOS_WRITE(fd, buf, ret);
    233  1.1  itohy 
    234  1.1  itohy 	return ret;
    235  1.1  itohy }
    236  1.1  itohy 
    237  1.1  itohy #ifdef __STDC__
    238  1.1  itohy size_t
    239  1.1  itohy xprintf(const char *fmt, ...)
    240  1.1  itohy #else
    241  1.1  itohy size_t
    242  1.1  itohy xprintf(fmt, va_alist)
    243  1.1  itohy 	const char *fmt;
    244  1.1  itohy 	va_dcl
    245  1.1  itohy #endif
    246  1.1  itohy {
    247  1.1  itohy 	va_list ap;
    248  1.1  itohy 	size_t ret;
    249  1.1  itohy 
    250  1.1  itohy 	VA_START(ap, fmt);
    251  1.1  itohy 	ret = xvfdprintf(1, fmt, ap);
    252  1.1  itohy 	va_end(ap);
    253  1.1  itohy 
    254  1.1  itohy 	return ret;
    255  1.1  itohy }
    256  1.1  itohy 
    257  1.1  itohy #ifdef __STDC__
    258  1.1  itohy size_t
    259  1.1  itohy xerrprintf(const char *fmt, ...)
    260  1.1  itohy #else
    261  1.1  itohy size_t
    262  1.1  itohy xerrprintf(fmt, va_alist)
    263  1.1  itohy 	const char *fmt;
    264  1.1  itohy 	va_dcl
    265  1.1  itohy #endif
    266  1.1  itohy {
    267  1.1  itohy 	va_list ap;
    268  1.1  itohy 	size_t ret;
    269  1.1  itohy 
    270  1.1  itohy 	VA_START(ap, fmt);
    271  1.1  itohy 	ret = xvfdprintf(2, fmt, ap);
    272  1.1  itohy 	va_end(ap);
    273  1.1  itohy 
    274  1.1  itohy 	return ret;
    275  1.1  itohy }
    276  1.1  itohy 
    277  1.1  itohy __dead void
    278  1.1  itohy #ifdef __STDC__
    279  1.1  itohy xerr(int eval, const char *fmt, ...)
    280  1.1  itohy #else
    281  1.1  itohy xerr(eval, fmt, va_alist)
    282  1.1  itohy 	int eval;
    283  1.1  itohy 	const char *fmt;
    284  1.1  itohy 	va_dcl
    285  1.1  itohy #endif
    286  1.1  itohy {
    287  1.1  itohy 	int e = dos_errno;
    288  1.1  itohy 	va_list ap;
    289  1.1  itohy 
    290  1.1  itohy 	xerrprintf("%s: ", __progname);
    291  1.1  itohy 	if (fmt) {
    292  1.1  itohy 		VA_START(ap, fmt);
    293  1.1  itohy 		xvfdprintf(2, fmt, ap);
    294  1.1  itohy 		va_end(ap);
    295  1.1  itohy 		xerrprintf(": ");
    296  1.1  itohy 	}
    297  1.1  itohy 	xerrprintf("%s\n", dos_strerror(e));
    298  1.1  itohy 	DOS_EXIT2(eval);
    299  1.1  itohy }
    300  1.1  itohy 
    301  1.1  itohy __dead void
    302  1.1  itohy #ifdef __STDC__
    303  1.1  itohy xerrx(int eval, const char *fmt, ...)
    304  1.1  itohy #else
    305  1.1  itohy xerrx(eval, fmt, va_alist)
    306  1.1  itohy 	int eval;
    307  1.1  itohy 	const char *fmt;
    308  1.1  itohy 	va_dcl
    309  1.1  itohy #endif
    310  1.1  itohy {
    311  1.1  itohy 	va_list ap;
    312  1.1  itohy 
    313  1.1  itohy 	xerrprintf("%s: ", __progname);
    314  1.1  itohy 	if (fmt) {
    315  1.1  itohy 		VA_START(ap, fmt);
    316  1.1  itohy 		xvfdprintf(2, fmt, ap);
    317  1.1  itohy 		va_end(ap);
    318  1.1  itohy 	}
    319  1.1  itohy 	xerrprintf("\n");
    320  1.1  itohy 	DOS_EXIT2(eval);
    321  1.1  itohy }
    322  1.1  itohy 
    323  1.1  itohy void
    324  1.1  itohy #ifdef __STDC__
    325  1.1  itohy xwarn(const char *fmt, ...)
    326  1.1  itohy #else
    327  1.1  itohy xwarn(fmt, va_alist)
    328  1.1  itohy 	const char *fmt;
    329  1.1  itohy 	va_dcl
    330  1.1  itohy #endif
    331  1.1  itohy {
    332  1.1  itohy 	int e = dos_errno;
    333  1.1  itohy 	va_list ap;
    334  1.1  itohy 
    335  1.1  itohy 	xerrprintf("%s: ", __progname);
    336  1.1  itohy 	if (fmt) {
    337  1.1  itohy 		VA_START(ap, fmt);
    338  1.1  itohy 		xvfdprintf(2, fmt, ap);
    339  1.1  itohy 		va_end(ap);
    340  1.1  itohy 		xerrprintf(": ");
    341  1.1  itohy 	}
    342  1.1  itohy 	xerrprintf("%s\n", dos_strerror(e));
    343  1.1  itohy }
    344  1.1  itohy 
    345  1.1  itohy void
    346  1.1  itohy #ifdef __STDC__
    347  1.1  itohy xwarnx(const char *fmt, ...)
    348  1.1  itohy #else
    349  1.1  itohy xwarnx(fmt, va_alist)
    350  1.1  itohy 	const char *fmt;
    351  1.1  itohy 	va_dcl
    352  1.1  itohy #endif
    353  1.1  itohy {
    354  1.1  itohy 	va_list ap;
    355  1.1  itohy 
    356  1.1  itohy 	xerrprintf("%s: ", __progname);
    357  1.1  itohy 	if (fmt) {
    358  1.1  itohy 		VA_START(ap, fmt);
    359  1.1  itohy 		xvfdprintf(2, fmt, ap);
    360  1.1  itohy 		va_end(ap);
    361  1.1  itohy 	}
    362  1.1  itohy 	xerrprintf("\n");
    363  1.1  itohy }
    364