Headers and library sources from all versions of Lightspeed C and THINK C
at main 507 lines 9.6 kB view raw
1 2/* 3 * printf.c 4 * 5 * Copyright (c) 1991 Symantec Corporation. All rights reserved. 6 * 7 */ 8 9#include "stdio.h" 10#include "stdarg.h" 11#include "string.h" 12#include "ansi_private.h" 13#include <SANE.h> 14 15#define BUFLEN 512 16#define TRUE 1 17#define FALSE 0 18 19static struct format { 20 unsigned leftJustify : 1; 21 unsigned forceSign : 1; 22 unsigned altForm : 1; 23 unsigned zeroPad : 1; 24 unsigned havePrecision : 1; 25 unsigned hSize : 1; 26 unsigned lSize : 1; 27 unsigned LSize : 1; 28 char sign; 29 char exponent; 30 int fieldWidth; 31 int precision; 32} default_format; 33 34 35struct decrec { 36 char sgn; 37 short exp; 38 char sig[SIGDIGLEN]; 39 short pad; 40 /* following fields aren't used by SANE */ 41 short min; 42 short dot; 43 short max; 44}; 45 46static void ftod(int, int, struct decrec *, long double); 47 48 49int 50vfprintf(FILE *fp, const char *fmt, va_list arg) 51{ 52 register int c, i, j, nwritten = 0; 53 register unsigned long n; 54 long double x; 55 register char *s; 56 char buf[BUFLEN], *digits, *t; 57 struct format F; 58 struct decrec D; 59 60 for (c = *fmt; c; c = *++fmt) { 61 if (c != '%') 62 goto copy1; 63 F = default_format; 64 65 /* decode flags */ 66 67 for (;;) { 68 c = *++fmt; 69 if (c == '-') 70 F.leftJustify = TRUE; 71 else if (c == '+') 72 F.forceSign = TRUE; 73 else if (c == ' ') 74 F.sign = ' '; 75 else if (c == '#') 76 F.altForm = TRUE; 77 else if (c == '0') 78 F.zeroPad = TRUE; 79 else 80 break; 81 } 82 83 /* decode field width */ 84 85 if (c == '*') { 86 if ((F.fieldWidth = va_arg(arg, int)) < 0) { 87 F.leftJustify = TRUE; 88 F.fieldWidth = -F.fieldWidth; 89 } 90 c = *++fmt; 91 } 92 else { 93 for (; c >= '0' && c <= '9'; c = *++fmt) 94 F.fieldWidth = (10 * F.fieldWidth) + (c - '0'); 95 } 96 97 /* decode precision */ 98 99 if (c == '.') { 100 if ((c = *++fmt) == '*') { 101 F.precision = va_arg(arg, int); 102 c = *++fmt; 103 } 104 else { 105 for (; c >= '0' && c <= '9'; c = *++fmt) 106 F.precision = (10 * F.precision) + (c - '0'); 107 } 108 if (F.precision >= 0) 109 F.havePrecision = TRUE; 110 } 111 112 /* perform appropriate conversion */ 113 114 s = &buf[BUFLEN]; 115 if (F.leftJustify) 116 F.zeroPad = FALSE; 117conv: switch (c) { 118 119 /* 'h' size modifier */ 120 121 case 'h': 122 F.hSize = TRUE; 123 c = *++fmt; 124 goto conv; 125 126 /* 'l' size modifier */ 127 128 case 'l': 129 F.lSize = TRUE; 130 c = *++fmt; 131 goto conv; 132 133 /* 'L' size modifier */ 134 135 case 'L': 136 F.LSize = TRUE; 137 c = *++fmt; 138 goto conv; 139 140 /* decimal (signed) */ 141 142 case 'd': 143 case 'i': 144 if (F.lSize) 145 n = va_arg(arg, long); 146 else 147 n = va_arg(arg, int); 148 if (F.hSize) 149 n = (short) n; 150 if ((long) n < 0) { 151 n = -n; 152 F.sign = '-'; 153 } 154 else if (F.forceSign) 155 F.sign = '+'; 156 goto decimal; 157 158 /* decimal (unsigned) */ 159 160 case 'u': 161 if (F.lSize) 162 n = va_arg(arg, unsigned long); 163 else 164 n = va_arg(arg, unsigned int); 165 if (F.hSize) 166 n = (unsigned short) n; 167 F.sign = 0; 168 goto decimal; 169 170 /* decimal (common code) */ 171 172 decimal: 173 if (!F.havePrecision) { 174 if (F.zeroPad) { 175 F.precision = F.fieldWidth; 176 if (F.sign) 177 --F.precision; 178 } 179 if (F.precision < 1) 180 F.precision = 1; 181 } 182 for (i = 0; n; n /= 10, i++) 183 *--s = n % 10 + '0'; 184 for (; i < F.precision; i++) 185 *--s = '0'; 186 if (F.sign) { 187 *--s = F.sign; 188 i++; 189 } 190 break; 191 192 /* octal (unsigned) */ 193 194 case 'o': 195 if (F.lSize) 196 n = va_arg(arg, unsigned long); 197 else 198 n = va_arg(arg, unsigned int); 199 if (F.hSize) 200 n = (unsigned short) n; 201 if (!F.havePrecision) { 202 if (F.zeroPad) 203 F.precision = F.fieldWidth; 204 if (F.precision < 1) 205 F.precision = 1; 206 } 207 for (i = 0; n; n /= 8, i++) 208 *--s = n % 8 + '0'; 209 if (F.altForm && i && *s != '0') { 210 *--s = '0'; 211 i++; 212 } 213 for (; i < F.precision; i++) 214 *--s = '0'; 215 break; 216 217 /* hexadecimal (unsigned) */ 218 219 case 'p': 220 F.havePrecision = F.lSize = TRUE; 221 F.precision = 8; 222 /* ... */ 223 case 'X': 224 digits = "0123456789ABCDEF"; 225 goto hexadecimal; 226 case 'x': 227 digits = "0123456789abcdef"; 228 /* ... */ 229 hexadecimal: 230 if (F.lSize) 231 n = va_arg(arg, unsigned long); 232 else 233 n = va_arg(arg, unsigned int); 234 if (F.hSize) 235 n = (unsigned short) n; 236 if (!F.havePrecision) { 237 if (F.zeroPad) { 238 F.precision = F.fieldWidth; 239 if (F.altForm) 240 F.precision -= 2; 241 } 242 if (F.precision < 1) 243 F.precision = 1; 244 } 245 for (i = 0; n; n /= 16, i++) 246 *--s = digits[n % 16]; 247 for (; i < F.precision; i++) 248 *--s = '0'; 249 if (F.altForm) { 250 *--s = c; 251 *--s = '0'; 252 i += 2; 253 } 254 break; 255 256#ifndef _NOFLOATING_ 257 /* fixed-point */ 258 259 case 'f': 260 if (F.LSize) 261 x = va_arg(arg, long double); 262 else 263 x = va_arg(arg, double); 264 if (!F.havePrecision) 265 F.precision = 6; 266 ftod(1, F.precision, &D, x); 267 D.dot = D.exp + D.sig[0]; 268 if ((D.min = D.dot) > 1) 269 D.min = 1; 270 D.max = D.dot + F.precision; 271 if (D.max - D.min > 508) 272 memcpy(D.sig, "\6>>>>>>", 7); 273 goto floating; 274 275 /* floating-point */ 276 277 case 'e': 278 case 'E': 279 if (F.LSize) 280 x = va_arg(arg, long double); 281 else 282 x = va_arg(arg, double); 283 if (!F.havePrecision) 284 F.precision = 6; 285 F.exponent = c; 286 ftod(0, D.max = F.precision + 1, &D, x); 287 D.min = D.dot = 1; 288 D.exp += D.sig[0] - 1; 289 goto floating; 290 291 /* "general" notation */ 292 293 case 'g': 294 case 'G': 295 if (F.LSize) 296 x = va_arg(arg, long double); 297 else 298 x = va_arg(arg, double); 299 if (!F.havePrecision) 300 F.precision = 6; 301 else if (F.precision == 0) 302 F.precision = 1; 303 F.exponent = c - 2; 304 ftod(0, D.max = F.precision, &D, x); 305 D.min = D.dot = 1; 306 D.exp += D.sig[0] - 1; 307 if (D.exp >= -4 && D.exp < F.precision) { 308 F.exponent = 0; 309 if ((D.dot += D.exp) < 1) 310 D.min = D.dot; 311 } 312 if (!F.altForm && D.max > D.sig[0]) { 313 if ((D.max = D.sig[0]) < D.dot) 314 D.max = D.dot; 315 } 316 goto floating; 317 318 /* floating (common code) */ 319 320 floating: 321 if (D.sig[1] > '9') { 322 F.exponent = FALSE; 323 D.dot = 0; 324 D.min = 1; 325 D.max = D.sig[0]; 326 } 327 i = 0; 328 if (F.exponent) { 329 n = D.exp < 0 ? -D.exp : D.exp; 330 for (; n; n /= 10, i++) 331 *--s = n % 10 + '0'; 332 for (; i < 2; i++) 333 *--s = '0'; 334 *--s = D.exp < 0 ? '-' : '+'; 335 *--s = F.exponent; 336 i += 2; 337 } 338 j = D.max; 339 if (j == D.dot && !F.altForm) 340 ++D.dot; 341 do { 342 if (j == D.dot) { 343 *--s = '.'; 344 i++; 345 } 346 *--s = j > 0 && j <= D.sig[0] ? D.sig[j] : '0'; 347 } while (--j >= D.min); 348 i += D.max - j; 349 if (D.sgn) 350 F.sign = '-'; 351 else if (F.forceSign) 352 F.sign = '+'; 353 if (F.zeroPad) { 354 j = F.fieldWidth; 355 if (F.sign) 356 --j; 357 for (; i < j; i++) 358 *--s = '0'; 359 } 360 if (F.sign) { 361 *--s = F.sign; 362 i++; 363 } 364 break; 365#endif _NOFLOATING_ 366 367 /* character */ 368 369 case 'c': 370 *--s = va_arg(arg, int); 371 i = 1; 372 break; 373 374 /* string */ 375 376 case 's': 377 s = va_arg(arg, char *); 378 if (F.altForm) { 379 i = (unsigned char) *s++; 380 if (F.havePrecision && i > F.precision) 381 i = F.precision; 382 } 383 else { 384 if (!F.havePrecision) 385 i = strlen(s); 386 else if (t = memchr(s, '\0', F.precision)) 387 i = t - s; 388 else 389 i = F.precision; 390 } 391 break; 392 393 /* store # bytes written so far */ 394 395 case 'n': 396 s = va_arg(arg, void *); 397 if (F.hSize) 398 * (short *) s = nwritten; 399 else if (F.lSize) 400 * (long *) s = nwritten; 401 else 402 * (int *) s = nwritten; 403 continue; 404 405 /* oops - unknown conversion, abort */ 406 407 default: 408 if (c != '%') 409 goto done; 410 copy1: 411 if (putc(c, fp) < 0) 412 return(EOF); 413 ++nwritten; 414 continue; 415 } 416 417 /* pad on the left */ 418 419 if (i < F.fieldWidth && !F.leftJustify) { 420 do { 421 if (putc(' ', fp) < 0) 422 return(EOF); 423 ++nwritten; 424 } while (i < --F.fieldWidth); 425 } 426 427 /* write the converted result */ 428 429 if (fwrite(s, 1, i, fp) != i) 430 return(EOF); 431 nwritten += i; 432 433 /* pad on the right */ 434 435 for (; i < F.fieldWidth; i++) { 436 if (putc(' ', fp) < 0) 437 return(EOF); 438 ++nwritten; 439 } 440 } 441 442 /* all done! */ 443 444done: 445 return(nwritten); 446} 447 448 449/* ---------- floating-point conversion ---------- */ 450 451#ifndef _NOFLOATING_ 452static void 453ftod(int fixed, int precision, struct decrec *d, long double x) 454{ 455 struct { char style; short digits; } form; 456 int i; 457 register short *p = (short *) &x; 458 459 /* point to SANE extended */ 460 461#if __option(mc68881) && __option(native_fp) 462 p[1] = p[0]; 463#endif 464#if __option(mc68881) || !__option(native_fp) 465 p++; 466#endif 467 468 /* convert to decimal record */ 469 470 if (precision >= sizeof d->sig) 471 precision = sizeof d->sig - 1; 472 form.style = fixed; 473 form.digits = precision; 474 fp68k(&form, p, d, (short)FX2DEC); 475 476 /* handle fixed-point overflow */ 477 478 if (d->sig[1] == '?') { 479 form.style = 0; 480 form.digits = sizeof d->sig - 1; 481 fp68k(&form, p, d, (short)FX2DEC); 482 } 483 484 /* strip trailing zeroes */ 485 486 for (i = d->sig[0]; i > 1 && d->sig[i] == '0'; --i) 487 ++d->exp; 488 d->sig[0] = i; 489 490 /* format 0, INF, NAN */ 491 492 if (d->sig[1] == '0') { 493 d->sgn = 0; /* delete to allow printing "-0" */ 494 d->exp = 0; 495 } 496 else if (d->sig[1] == 'I') { 497 d->sig[0] = 3; 498 d->sig[2] = 'N'; 499 d->sig[3] = 'F'; 500 } 501 else if (d->sig[1] == 'N') { 502 d->sig[0] = 5; 503 d->sig[2] = 'A'; 504 d->sig[3] = 'N'; 505 } 506} 507#endif _NOFLOATING_