Home | History | Annotate | Line # | Download | only in common
xprintf.c revision 1.4
      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.4    dsl  *	$NetBSD: xprintf.c,v 1.4 2009/03/14 21:04:17 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.4    dsl numstr(char *buf, long val, int base, int sign)
     63  1.1  itohy {
     64  1.1  itohy 	unsigned long v;
     65  1.1  itohy 	char rev[32];
     66  1.1  itohy 	char *r = rev, *b = buf;
     67  1.1  itohy 
     68  1.1  itohy 	/* negative? */
     69  1.1  itohy 	if (sign && val < 0) {
     70  1.1  itohy 		v = -val;
     71  1.1  itohy 		*b++ = '-';
     72  1.1  itohy 	} else {
     73  1.1  itohy 		v = val;
     74  1.1  itohy 	}
     75  1.1  itohy 
     76  1.1  itohy 	/* inverse order */
     77  1.1  itohy 	do {
     78  1.1  itohy 		*r++ = "0123456789abcdef"[v % base];
     79  1.1  itohy 		v /= base;
     80  1.1  itohy 	} while (v);
     81  1.1  itohy 
     82  1.1  itohy 	/* reverse string */
     83  1.1  itohy 	while (r > rev)
     84  1.1  itohy 		*b++ = *--r;
     85  1.1  itohy 
     86  1.1  itohy 	*b = '\0';
     87  1.1  itohy 	return buf;
     88  1.1  itohy }
     89  1.1  itohy 
     90  1.1  itohy /*
     91  1.1  itohy  * supported format: %x, %p, %s, %c, %d, %u, %o
     92  1.1  itohy  * \n is converted to \r\n
     93  1.1  itohy  *
     94  1.1  itohy  * XXX argument/parameter types are not strictly handled
     95  1.1  itohy  */
     96  1.1  itohy size_t
     97  1.3    dsl xvsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
     98  1.1  itohy {
     99  1.1  itohy 	char *b = buf;
    100  1.1  itohy 	const char *s;
    101  1.1  itohy 	char numbuf[32];
    102  1.1  itohy 
    103  1.1  itohy 	while (*fmt && len > 1) {
    104  1.1  itohy 		if (*fmt != '%') {
    105  1.1  itohy #ifdef SJIS
    106  1.1  itohy 			if (IS_SJIS1(*fmt) && IS_SJIS2(fmt[1])) {
    107  1.1  itohy 				if (len <= 2)
    108  1.1  itohy 					break;	/* not enough space */
    109  1.1  itohy 				*b++ = *fmt++;
    110  1.1  itohy 				len--;
    111  1.1  itohy 			}
    112  1.1  itohy #endif
    113  1.1  itohy 			if (*fmt == '\n' && (b == buf || b[-1] != '\r')) {
    114  1.1  itohy 				if (len <= 2)
    115  1.1  itohy 					break;
    116  1.1  itohy 				*b++ = '\r';
    117  1.1  itohy 				len--;
    118  1.1  itohy 			}
    119  1.1  itohy 			*b++ = *fmt++;
    120  1.1  itohy 			len--;
    121  1.1  itohy 			continue;
    122  1.1  itohy 		}
    123  1.1  itohy 
    124  1.1  itohy 		/* %? */
    125  1.1  itohy 		fmt++;
    126  1.1  itohy 		switch (*fmt++) {
    127  1.1  itohy 		case '%':	/* "%%" -> literal % */
    128  1.1  itohy 			*b++ = '%';
    129  1.1  itohy 			len--;
    130  1.1  itohy 			break;
    131  1.1  itohy 
    132  1.1  itohy 		case 'd':
    133  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 10, 1);
    134  1.1  itohy 		copy_string:
    135  1.1  itohy 			for ( ; *s && len > 1; len--)
    136  1.1  itohy 				*b++ = *s++;
    137  1.1  itohy 			break;
    138  1.1  itohy 
    139  1.1  itohy 		case 'u':
    140  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 10, 0);
    141  1.1  itohy 			goto copy_string;
    142  1.1  itohy 
    143  1.1  itohy 		case 'p':
    144  1.1  itohy 			*b++ = '0';
    145  1.1  itohy 			len--;
    146  1.1  itohy 			if (len > 1) {
    147  1.1  itohy 				*b++ = 'x';
    148  1.1  itohy 				len--;
    149  1.1  itohy 			}
    150  1.1  itohy 			/* FALLTHROUGH */
    151  1.1  itohy 		case 'x':
    152  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 16, 0);
    153  1.1  itohy 			goto copy_string;
    154  1.1  itohy 
    155  1.1  itohy 		case 'o':
    156  1.1  itohy 			s = numstr(numbuf, va_arg(ap, long), 8, 0);
    157  1.1  itohy 			goto copy_string;
    158  1.1  itohy 
    159  1.1  itohy 		case 's':
    160  1.1  itohy 			s = va_arg(ap, char *);
    161  1.1  itohy 			while (*s && len > 1) {
    162  1.1  itohy #ifdef SJIS
    163  1.1  itohy 				if (IS_SJIS1(*s) && IS_SJIS2(s[1])) {
    164  1.1  itohy 					if (len <= 2)
    165  1.1  itohy 						goto break_loop;
    166  1.1  itohy 					*b++ = *s++;
    167  1.1  itohy 					len--;
    168  1.1  itohy 				}
    169  1.1  itohy #endif
    170  1.1  itohy 				if (*s == '\n' && (b == buf || b[-1] != '\r')) {
    171  1.1  itohy 					if (len <= 2)
    172  1.1  itohy 						goto break_loop;
    173  1.1  itohy 					*b++ = '\r';
    174  1.1  itohy 					len--;
    175  1.1  itohy 				}
    176  1.1  itohy 				*b++ = *s++;
    177  1.1  itohy 				len--;
    178  1.1  itohy 			}
    179  1.1  itohy 			break;
    180  1.1  itohy 
    181  1.1  itohy 		case 'c':
    182  1.1  itohy 			*b++ = va_arg(ap, int);
    183  1.1  itohy 			len--;
    184  1.1  itohy 			break;
    185  1.1  itohy 		}
    186  1.1  itohy 	}
    187  1.1  itohy break_loop:
    188  1.1  itohy 
    189  1.1  itohy 	*b = '\0';
    190  1.1  itohy 	return (char *)b - buf;
    191  1.1  itohy }
    192  1.1  itohy 
    193  1.1  itohy #ifdef __STDC__
    194  1.1  itohy #define VA_START(a, v)	va_start(a, v)
    195  1.1  itohy #else
    196  1.1  itohy #define VA_START(a, v)	va_start(a)
    197  1.1  itohy #endif
    198  1.1  itohy 
    199  1.1  itohy #ifdef __STDC__
    200  1.1  itohy size_t
    201  1.1  itohy xsnprintf(char *buf, size_t len, const char *fmt, ...)
    202  1.1  itohy #else
    203  1.1  itohy size_t
    204  1.1  itohy xsnprintf(buf, len, fmt, va_alist)
    205  1.1  itohy 	char *buf;
    206  1.1  itohy 	size_t len;
    207  1.1  itohy 	const char *fmt;
    208  1.1  itohy 	va_dcl
    209  1.1  itohy #endif
    210  1.1  itohy {
    211  1.1  itohy 	va_list ap;
    212  1.1  itohy 	size_t ret;
    213  1.1  itohy 
    214  1.1  itohy 	VA_START(ap, fmt);
    215  1.1  itohy 	ret = xvsnprintf(buf, len, fmt, ap);
    216  1.1  itohy 	va_end(ap);
    217  1.1  itohy 
    218  1.1  itohy 	return ret;
    219  1.1  itohy }
    220  1.1  itohy 
    221  1.1  itohy size_t
    222  1.3    dsl xvfdprintf(int fd, const char *fmt, va_list ap)
    223  1.1  itohy {
    224  1.1  itohy 	char buf[PRINTF_BUFSZ];
    225  1.1  itohy 	size_t ret;
    226  1.1  itohy 
    227  1.1  itohy 	ret = xvsnprintf(buf, sizeof buf, fmt, ap);
    228  1.1  itohy 	if (ret)
    229  1.1  itohy 		ret = DOS_WRITE(fd, buf, ret);
    230  1.1  itohy 
    231  1.1  itohy 	return ret;
    232  1.1  itohy }
    233  1.1  itohy 
    234  1.1  itohy #ifdef __STDC__
    235  1.1  itohy size_t
    236  1.1  itohy xprintf(const char *fmt, ...)
    237  1.1  itohy #else
    238  1.1  itohy size_t
    239  1.1  itohy xprintf(fmt, va_alist)
    240  1.1  itohy 	const char *fmt;
    241  1.1  itohy 	va_dcl
    242  1.1  itohy #endif
    243  1.1  itohy {
    244  1.1  itohy 	va_list ap;
    245  1.1  itohy 	size_t ret;
    246  1.1  itohy 
    247  1.1  itohy 	VA_START(ap, fmt);
    248  1.1  itohy 	ret = xvfdprintf(1, fmt, ap);
    249  1.1  itohy 	va_end(ap);
    250  1.1  itohy 
    251  1.1  itohy 	return ret;
    252  1.1  itohy }
    253  1.1  itohy 
    254  1.1  itohy #ifdef __STDC__
    255  1.1  itohy size_t
    256  1.1  itohy xerrprintf(const char *fmt, ...)
    257  1.1  itohy #else
    258  1.1  itohy size_t
    259  1.1  itohy xerrprintf(fmt, va_alist)
    260  1.1  itohy 	const char *fmt;
    261  1.1  itohy 	va_dcl
    262  1.1  itohy #endif
    263  1.1  itohy {
    264  1.1  itohy 	va_list ap;
    265  1.1  itohy 	size_t ret;
    266  1.1  itohy 
    267  1.1  itohy 	VA_START(ap, fmt);
    268  1.1  itohy 	ret = xvfdprintf(2, fmt, ap);
    269  1.1  itohy 	va_end(ap);
    270  1.1  itohy 
    271  1.1  itohy 	return ret;
    272  1.1  itohy }
    273  1.1  itohy 
    274  1.1  itohy __dead void
    275  1.1  itohy #ifdef __STDC__
    276  1.1  itohy xerr(int eval, const char *fmt, ...)
    277  1.1  itohy #else
    278  1.1  itohy xerr(eval, fmt, va_alist)
    279  1.1  itohy 	int eval;
    280  1.1  itohy 	const char *fmt;
    281  1.1  itohy 	va_dcl
    282  1.1  itohy #endif
    283  1.1  itohy {
    284  1.1  itohy 	int e = dos_errno;
    285  1.1  itohy 	va_list ap;
    286  1.1  itohy 
    287  1.1  itohy 	xerrprintf("%s: ", __progname);
    288  1.1  itohy 	if (fmt) {
    289  1.1  itohy 		VA_START(ap, fmt);
    290  1.1  itohy 		xvfdprintf(2, fmt, ap);
    291  1.1  itohy 		va_end(ap);
    292  1.1  itohy 		xerrprintf(": ");
    293  1.1  itohy 	}
    294  1.1  itohy 	xerrprintf("%s\n", dos_strerror(e));
    295  1.1  itohy 	DOS_EXIT2(eval);
    296  1.1  itohy }
    297  1.1  itohy 
    298  1.1  itohy __dead void
    299  1.1  itohy #ifdef __STDC__
    300  1.1  itohy xerrx(int eval, const char *fmt, ...)
    301  1.1  itohy #else
    302  1.1  itohy xerrx(eval, fmt, va_alist)
    303  1.1  itohy 	int eval;
    304  1.1  itohy 	const char *fmt;
    305  1.1  itohy 	va_dcl
    306  1.1  itohy #endif
    307  1.1  itohy {
    308  1.1  itohy 	va_list ap;
    309  1.1  itohy 
    310  1.1  itohy 	xerrprintf("%s: ", __progname);
    311  1.1  itohy 	if (fmt) {
    312  1.1  itohy 		VA_START(ap, fmt);
    313  1.1  itohy 		xvfdprintf(2, fmt, ap);
    314  1.1  itohy 		va_end(ap);
    315  1.1  itohy 	}
    316  1.1  itohy 	xerrprintf("\n");
    317  1.1  itohy 	DOS_EXIT2(eval);
    318  1.1  itohy }
    319  1.1  itohy 
    320  1.1  itohy void
    321  1.1  itohy #ifdef __STDC__
    322  1.1  itohy xwarn(const char *fmt, ...)
    323  1.1  itohy #else
    324  1.1  itohy xwarn(fmt, va_alist)
    325  1.1  itohy 	const char *fmt;
    326  1.1  itohy 	va_dcl
    327  1.1  itohy #endif
    328  1.1  itohy {
    329  1.1  itohy 	int e = dos_errno;
    330  1.1  itohy 	va_list ap;
    331  1.1  itohy 
    332  1.1  itohy 	xerrprintf("%s: ", __progname);
    333  1.1  itohy 	if (fmt) {
    334  1.1  itohy 		VA_START(ap, fmt);
    335  1.1  itohy 		xvfdprintf(2, fmt, ap);
    336  1.1  itohy 		va_end(ap);
    337  1.1  itohy 		xerrprintf(": ");
    338  1.1  itohy 	}
    339  1.1  itohy 	xerrprintf("%s\n", dos_strerror(e));
    340  1.1  itohy }
    341  1.1  itohy 
    342  1.1  itohy void
    343  1.1  itohy #ifdef __STDC__
    344  1.1  itohy xwarnx(const char *fmt, ...)
    345  1.1  itohy #else
    346  1.1  itohy xwarnx(fmt, va_alist)
    347  1.1  itohy 	const char *fmt;
    348  1.1  itohy 	va_dcl
    349  1.1  itohy #endif
    350  1.1  itohy {
    351  1.1  itohy 	va_list ap;
    352  1.1  itohy 
    353  1.1  itohy 	xerrprintf("%s: ", __progname);
    354  1.1  itohy 	if (fmt) {
    355  1.1  itohy 		VA_START(ap, fmt);
    356  1.1  itohy 		xvfdprintf(2, fmt, ap);
    357  1.1  itohy 		va_end(ap);
    358  1.1  itohy 	}
    359  1.1  itohy 	xerrprintf("\n");
    360  1.1  itohy }
    361