1 1.1 itohy /* 2 1.1 itohy * minimal printf for Human68k DOS 3 1.1 itohy * 4 1.5 itohy * written by ITOH Yasufumi 5 1.1 itohy * public domain 6 1.1 itohy * 7 1.5 itohy * $NetBSD: xprintf.c,v 1.5 2011/02/21 02:31:58 itohy 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