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