Home | History | Annotate | Line # | Download | only in common
xprintf.c revision 1.1.168.1
      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.1.168.1    jym  *	$NetBSD: xprintf.c,v 1.1.168.1 2009/05/13 17:18:43 jym 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.1.168.1    jym 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.168.1    jym 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.1.168.1    jym 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.1.168.1    jym 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