1 /* 2 * Copyright (c) 1998 Todd C. Miller <Todd.Miller (at) courtesan.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * $Id: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $ 28 29 * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc. 30 * All rights reserved. 31 * 32 * This code is derived from software contributed to The NetBSD Foundation 33 * by Klaus Klein and Jason R. Thorpe. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. All advertising materials mentioning features or use of this software 44 * must display the following acknowledgement: 45 * This product includes software developed by the NetBSD 46 * Foundation, Inc. and its contributors. 47 * 4. Neither the name of The NetBSD Foundation nor the names of its 48 * contributors may be used to endorse or promote products derived 49 * from this software without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 52 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 53 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 54 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 55 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 56 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 57 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 58 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 59 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 60 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 61 * POSSIBILITY OF SUCH DAMAGE. 62 * 63 * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $ 64 65 * Copyright (c) 1987, 1993 66 * The Regents of the University of California. All rights reserved. 67 * 68 * Redistribution and use in source and binary forms, with or without 69 * modification, are permitted provided that the following conditions 70 * are met: 71 * 1. Redistributions of source code must retain the above copyright 72 * notice, this list of conditions and the following disclaimer. 73 * 2. Redistributions in binary form must reproduce the above copyright 74 * notice, this list of conditions and the following disclaimer in the 75 * documentation and/or other materials provided with the distribution. 76 * 3. Neither the name of the University nor the names of its contributors 77 * may be used to endorse or promote products derived from this software 78 * without specific prior written permission. 79 * 80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 90 * SUCH DAMAGE. 91 * 92 * $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $ 93 */ 94 #include <LibConfig.h> 95 #include <string.h> 96 #include <fcntl.h> 97 #include <sys/syslimits.h> 98 99 #ifndef HAVE_GETOPT 100 char *optarg; 101 int optind = 1; 102 int 103 getopt(int argc, char **argv, char *args) 104 { 105 size_t n; 106 size_t nlen = strlen(args); 107 char cmd; 108 char rv; 109 110 if (argv[optind] && *argv[optind] == '-') { 111 cmd = *(argv[optind] + 1); 112 113 for (n = 0; n < nlen; n++) { 114 if (args[n] == ':') 115 continue; 116 if (args[n] == cmd) { 117 rv = *(argv[optind] + 1); 118 if (args[n+1] == ':') { 119 if (*(argv[optind] + 2) != '\0') { 120 optarg = argv[optind] + 2; 121 optind += 1; 122 } else { 123 optarg = argv[optind + 1]; 124 optind += 2; 125 } 126 if (!optarg) 127 optarg=""; 128 return rv; 129 } else { 130 optarg = NULL; 131 optind += 1; 132 return rv; 133 } 134 } 135 } 136 } 137 return -1; 138 } 139 #endif 140 141 #define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\')) 142 143 #ifdef HAVE_BASENAME 144 #ifndef PATH_MAX 145 #define PATH_MAX 5000 146 #endif 147 148 char * 149 basename(char *path) 150 { 151 static char singledot[] = "."; 152 static char result[PATH_MAX]; 153 char *p, *lastp; 154 size_t len; 155 156 /* 157 * If `path' is a null pointer or points to an empty string, 158 * return a pointer to the string ".". 159 */ 160 if ((path == NULL) || (*path == '\0')) 161 return (singledot); 162 163 /* Strip trailing slashes, if any. */ 164 lastp = path + strlen(path) - 1; 165 while (lastp != path && ISPATHSEPARATOR(*lastp)) 166 lastp--; 167 168 /* Now find the beginning of this (final) component. */ 169 p = lastp; 170 while (p != path && !ISPATHSEPARATOR(*(p - 1))) 171 p--; 172 173 /* ...and copy the result into the result buffer. */ 174 len = (lastp - p) + 1 /* last char */; 175 if (len > (PATH_MAX - 1)) 176 len = PATH_MAX - 1; 177 178 memcpy(result, p, len); 179 result[len] = '\0'; 180 181 return (result); 182 } 183 #endif 184 185 #if !defined(HAVE_MKSTEMP) && !defined(WIN32) 186 int 187 mkstemp(char *path) 188 { 189 char *start, *trv; 190 unsigned int pid; 191 192 /* To guarantee multiple calls generate unique names even if 193 the file is not created. 676 different possibilities with 7 194 or more X's, 26 with 6 or less. */ 195 static char xtra[2] = "aa"; 196 int xcnt = 0; 197 198 pid = getpid(); 199 200 /* Move to end of path and count trailing X's. */ 201 for (trv = path; *trv; ++trv) 202 if (*trv == 'X') 203 xcnt++; 204 else 205 xcnt = 0; 206 207 /* Use at least one from xtra. Use 2 if more than 6 X's. */ 208 if (*(trv - 1) == 'X') 209 *--trv = xtra[0]; 210 if (xcnt > 6 && *(trv - 1) == 'X') 211 *--trv = xtra[1]; 212 213 /* Set remaining X's to pid digits with 0's to the left. */ 214 while (*--trv == 'X') { 215 *trv = (pid % 10) + '0'; 216 pid /= 10; 217 } 218 219 /* update xtra for next call. */ 220 if (xtra[0] != 'z') 221 xtra[0]++; 222 else { 223 xtra[0] = 'a'; 224 if (xtra[1] != 'z') 225 xtra[1]++; 226 else 227 xtra[1] = 'a'; 228 } 229 230 return open(path, O_CREAT | O_EXCL | O_RDWR, 0600); 231 } 232 #endif 233 234 #ifdef HAVE_FFS 235 int 236 ffs(int x) 237 { 238 int r = 1; 239 if (!x) return 0; 240 if (!(x & 0xffff)) { x >>= 16; r += 16; } 241 if (!(x & 0xff)) { x >>= 8; r += 8; } 242 if (!(x & 0xf)) { x >>= 4; r += 4; } 243 if (!(x & 3)) { x >>= 2; r += 2; } 244 if (!(x & 1)) { x >>= 1; r += 1; } 245 246 return r; 247 } 248 #endif 249 250 /* 251 * Copyright Patrick Powell 1995 252 * This code is based on code written by Patrick Powell (papowell (at) astart.com) 253 * It may be used for any purpose as long as this notice remains intact 254 * on all source code distributions 255 */ 256 257 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) 258 259 static void 260 dopr(char *buffer, size_t maxlen, const char *format, va_list args); 261 262 static void 263 fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, 264 int min, int max); 265 266 static void 267 fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, 268 int min, int max, int flags); 269 270 static void 271 fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, 272 int min, int max, int flags); 273 274 static void 275 dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); 276 277 /* 278 * dopr(): poor man's version of doprintf 279 */ 280 281 /* format read states */ 282 #define DP_S_DEFAULT 0 283 #define DP_S_FLAGS 1 284 #define DP_S_MIN 2 285 #define DP_S_DOT 3 286 #define DP_S_MAX 4 287 #define DP_S_MOD 5 288 #define DP_S_CONV 6 289 #define DP_S_DONE 7 290 291 /* format flags - Bits */ 292 #define DP_F_MINUS (1 << 0) 293 #define DP_F_PLUS (1 << 1) 294 #define DP_F_SPACE (1 << 2) 295 #define DP_F_NUM (1 << 3) 296 #define DP_F_ZERO (1 << 4) 297 #define DP_F_UP (1 << 5) 298 #define DP_F_UNSIGNED (1 << 6) 299 300 /* Conversion Flags */ 301 #define DP_C_SHORT 1 302 #define DP_C_LONG 2 303 #define DP_C_LDOUBLE 3 304 #define DP_C_LONG_LONG 4 305 306 #define char_to_int(p) (p - '0') 307 #define abs_val(p) (p < 0 ? -p : p) 308 309 310 static void 311 dopr(char *buffer, size_t maxlen, const char *format, va_list args) 312 { 313 char *strvalue, ch; 314 long value; 315 long double fvalue; 316 int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0; 317 size_t currlen = 0; 318 319 ch = *format++; 320 321 while (state != DP_S_DONE) { 322 if ((ch == '\0') || (currlen >= maxlen)) 323 state = DP_S_DONE; 324 325 switch(state) { 326 case DP_S_DEFAULT: 327 if (ch == '%') 328 state = DP_S_FLAGS; 329 else 330 dopr_outch(buffer, &currlen, maxlen, ch); 331 ch = *format++; 332 break; 333 case DP_S_FLAGS: 334 switch (ch) { 335 case '-': 336 flags |= DP_F_MINUS; 337 ch = *format++; 338 break; 339 case '+': 340 flags |= DP_F_PLUS; 341 ch = *format++; 342 break; 343 case ' ': 344 flags |= DP_F_SPACE; 345 ch = *format++; 346 break; 347 case '#': 348 flags |= DP_F_NUM; 349 ch = *format++; 350 break; 351 case '0': 352 flags |= DP_F_ZERO; 353 ch = *format++; 354 break; 355 default: 356 state = DP_S_MIN; 357 break; 358 } 359 break; 360 case DP_S_MIN: 361 if (isdigit((unsigned char)ch)) { 362 min = 10 * min + char_to_int (ch); 363 ch = *format++; 364 } else if (ch == '*') { 365 min = va_arg (args, int); 366 ch = *format++; 367 state = DP_S_DOT; 368 } else 369 state = DP_S_DOT; 370 break; 371 case DP_S_DOT: 372 if (ch == '.') { 373 state = DP_S_MAX; 374 ch = *format++; 375 } else 376 state = DP_S_MOD; 377 break; 378 case DP_S_MAX: 379 if (isdigit((unsigned char)ch)) { 380 if (max < 0) 381 max = 0; 382 max = 10 * max + char_to_int(ch); 383 ch = *format++; 384 } else if (ch == '*') { 385 max = va_arg (args, int); 386 ch = *format++; 387 state = DP_S_MOD; 388 } else 389 state = DP_S_MOD; 390 break; 391 case DP_S_MOD: 392 switch (ch) { 393 case 'h': 394 cflags = DP_C_SHORT; 395 ch = *format++; 396 break; 397 case 'l': 398 cflags = DP_C_LONG; 399 ch = *format++; 400 if (ch == 'l') { 401 cflags = DP_C_LONG_LONG; 402 ch = *format++; 403 } 404 break; 405 case 'q': 406 cflags = DP_C_LONG_LONG; 407 ch = *format++; 408 break; 409 case 'L': 410 cflags = DP_C_LDOUBLE; 411 ch = *format++; 412 break; 413 default: 414 break; 415 } 416 state = DP_S_CONV; 417 break; 418 case DP_S_CONV: 419 switch (ch) { 420 case 'd': 421 case 'i': 422 if (cflags == DP_C_SHORT) 423 value = va_arg(args, int); 424 else if (cflags == DP_C_LONG) 425 value = va_arg(args, long int); 426 else if (cflags == DP_C_LONG_LONG) 427 value = va_arg (args, long long); 428 else 429 value = va_arg (args, int); 430 fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags); 431 break; 432 case 'o': 433 flags |= DP_F_UNSIGNED; 434 if (cflags == DP_C_SHORT) 435 value = va_arg(args, unsigned int); 436 else if (cflags == DP_C_LONG) 437 value = va_arg(args, unsigned long int); 438 else if (cflags == DP_C_LONG_LONG) 439 value = va_arg(args, unsigned long long); 440 else 441 value = va_arg(args, unsigned int); 442 fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags); 443 break; 444 case 'u': 445 flags |= DP_F_UNSIGNED; 446 if (cflags == DP_C_SHORT) 447 value = va_arg(args, unsigned int); 448 else if (cflags == DP_C_LONG) 449 value = va_arg(args, unsigned long int); 450 else if (cflags == DP_C_LONG_LONG) 451 value = va_arg(args, unsigned long long); 452 else 453 value = va_arg(args, unsigned int); 454 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); 455 break; 456 case 'X': 457 flags |= DP_F_UP; 458 case 'x': 459 flags |= DP_F_UNSIGNED; 460 if (cflags == DP_C_SHORT) 461 value = va_arg(args, unsigned int); 462 else if (cflags == DP_C_LONG) 463 value = va_arg(args, unsigned long int); 464 else if (cflags == DP_C_LONG_LONG) 465 value = va_arg(args, unsigned long long); 466 else 467 value = va_arg(args, unsigned int); 468 fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags); 469 break; 470 case 'f': 471 if (cflags == DP_C_LDOUBLE) 472 fvalue = va_arg(args, long double); 473 else 474 fvalue = va_arg(args, double); 475 /* um, floating point? */ 476 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags); 477 break; 478 case 'E': 479 flags |= DP_F_UP; 480 case 'e': 481 if (cflags == DP_C_LDOUBLE) 482 fvalue = va_arg(args, long double); 483 else 484 fvalue = va_arg(args, double); 485 break; 486 case 'G': 487 flags |= DP_F_UP; 488 case 'g': 489 if (cflags == DP_C_LDOUBLE) 490 fvalue = va_arg(args, long double); 491 else 492 fvalue = va_arg(args, double); 493 break; 494 case 'c': 495 dopr_outch(buffer, &currlen, maxlen, va_arg(args, int)); 496 break; 497 case 's': 498 strvalue = va_arg(args, char *); 499 if (max < 0) 500 max = maxlen; /* ie, no max */ 501 fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max); 502 break; 503 case 'p': 504 strvalue = va_arg(args, void *); 505 fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); 506 break; 507 case 'n': 508 if (cflags == DP_C_SHORT) { 509 short int *num; 510 num = va_arg(args, short int *); 511 *num = currlen; 512 } else if (cflags == DP_C_LONG) { 513 long int *num; 514 num = va_arg(args, long int *); 515 *num = currlen; 516 } else if (cflags == DP_C_LONG_LONG) { 517 long long *num; 518 num = va_arg(args, long long *); 519 *num = currlen; 520 } else { 521 int *num; 522 num = va_arg(args, int *); 523 *num = currlen; 524 } 525 break; 526 case '%': 527 dopr_outch(buffer, &currlen, maxlen, ch); 528 break; 529 case 'w': /* not supported yet, treat as next char */ 530 ch = *format++; 531 break; 532 default: /* Unknown, skip */ 533 break; 534 } 535 ch = *format++; 536 state = DP_S_DEFAULT; 537 flags = cflags = min = 0; 538 max = -1; 539 break; 540 case DP_S_DONE: 541 break; 542 default: /* hmm? */ 543 break; /* some picky compilers need this */ 544 } 545 } 546 if (currlen < maxlen - 1) 547 buffer[currlen] = '\0'; 548 else 549 buffer[maxlen - 1] = '\0'; 550 } 551 552 static void 553 fmtstr(char *buffer, size_t *currlen, size_t maxlen, 554 char *value, int flags, int min, int max) 555 { 556 int cnt = 0, padlen, strln; /* amount to pad */ 557 558 if (value == 0) 559 value = "<NULL>"; 560 561 for (strln = 0; value[strln]; ++strln); /* strlen */ 562 padlen = min - strln; 563 if (padlen < 0) 564 padlen = 0; 565 if (flags & DP_F_MINUS) 566 padlen = -padlen; /* Left Justify */ 567 568 while ((padlen > 0) && (cnt < max)) { 569 dopr_outch(buffer, currlen, maxlen, ' '); 570 --padlen; 571 ++cnt; 572 } 573 while (*value && (cnt < max)) { 574 dopr_outch(buffer, currlen, maxlen, *value++); 575 ++cnt; 576 } 577 while ((padlen < 0) && (cnt < max)) { 578 dopr_outch(buffer, currlen, maxlen, ' '); 579 ++padlen; 580 ++cnt; 581 } 582 } 583 584 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ 585 586 static void 587 fmtint(char *buffer, size_t *currlen, size_t maxlen, 588 long value, int base, int min, int max, int flags) 589 { 590 unsigned long uvalue; 591 char convert[20]; 592 int signvalue = 0, place = 0, caps = 0; 593 int spadlen = 0; /* amount to space pad */ 594 int zpadlen = 0; /* amount to zero pad */ 595 596 #define PADMAX(x,y) ((x) > (y) ? (x) : (y)) 597 598 if (max < 0) 599 max = 0; 600 601 uvalue = value; 602 603 if (!(flags & DP_F_UNSIGNED)) { 604 if (value < 0) { 605 signvalue = '-'; 606 uvalue = -value; 607 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 608 signvalue = '+'; 609 else if (flags & DP_F_SPACE) 610 signvalue = ' '; 611 } 612 613 if (flags & DP_F_UP) 614 caps = 1; /* Should characters be upper case? */ 615 do { 616 convert[place++] = 617 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 618 [uvalue % (unsigned)base]; 619 uvalue = (uvalue / (unsigned)base ); 620 } while (uvalue && (place < 20)); 621 if (place == 20) 622 place--; 623 convert[place] = 0; 624 625 zpadlen = max - place; 626 spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0); 627 if (zpadlen < 0) 628 zpadlen = 0; 629 if (spadlen < 0) 630 spadlen = 0; 631 if (flags & DP_F_ZERO) { 632 zpadlen = PADMAX(zpadlen, spadlen); 633 spadlen = 0; 634 } 635 if (flags & DP_F_MINUS) 636 spadlen = -spadlen; /* Left Justifty */ 637 638 /* Spaces */ 639 while (spadlen > 0) { 640 dopr_outch(buffer, currlen, maxlen, ' '); 641 --spadlen; 642 } 643 644 /* Sign */ 645 if (signvalue) 646 dopr_outch(buffer, currlen, maxlen, signvalue); 647 648 /* Zeros */ 649 if (zpadlen > 0) { 650 while (zpadlen > 0) { 651 dopr_outch(buffer, currlen, maxlen, '0'); 652 --zpadlen; 653 } 654 } 655 656 /* Digits */ 657 while (place > 0) 658 dopr_outch(buffer, currlen, maxlen, convert[--place]); 659 660 /* Left Justified spaces */ 661 while (spadlen < 0) { 662 dopr_outch (buffer, currlen, maxlen, ' '); 663 ++spadlen; 664 } 665 } 666 667 static long double 668 pow10(int exp) 669 { 670 long double result = 1; 671 672 while (exp) { 673 result *= 10; 674 exp--; 675 } 676 677 return result; 678 } 679 680 static long 681 round(long double value) 682 { 683 long intpart = value; 684 685 value -= intpart; 686 if (value >= 0.5) 687 intpart++; 688 689 return intpart; 690 } 691 692 static void 693 fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, 694 int min, int max, int flags) 695 { 696 char iconvert[20], fconvert[20]; 697 int signvalue = 0, iplace = 0, fplace = 0; 698 int padlen = 0; /* amount to pad */ 699 int zpadlen = 0, caps = 0; 700 long intpart, fracpart; 701 long double ufvalue; 702 703 /* 704 * AIX manpage says the default is 0, but Solaris says the default 705 * is 6, and sprintf on AIX defaults to 6 706 */ 707 if (max < 0) 708 max = 6; 709 710 ufvalue = abs_val(fvalue); 711 712 if (fvalue < 0) 713 signvalue = '-'; 714 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */ 715 signvalue = '+'; 716 else if (flags & DP_F_SPACE) 717 signvalue = ' '; 718 719 intpart = ufvalue; 720 721 /* 722 * Sorry, we only support 9 digits past the decimal because of our 723 * conversion method 724 */ 725 if (max > 9) 726 max = 9; 727 728 /* We "cheat" by converting the fractional part to integer by 729 * multiplying by a factor of 10 730 */ 731 fracpart = round((pow10 (max)) * (ufvalue - intpart)); 732 733 if (fracpart >= pow10 (max)) { 734 intpart++; 735 fracpart -= pow10 (max); 736 } 737 738 /* Convert integer part */ 739 do { 740 iconvert[iplace++] = 741 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 742 [intpart % 10]; 743 intpart = (intpart / 10); 744 } while(intpart && (iplace < 20)); 745 if (iplace == 20) 746 iplace--; 747 iconvert[iplace] = 0; 748 749 /* Convert fractional part */ 750 do { 751 fconvert[fplace++] = 752 (caps ? "0123456789ABCDEF" : "0123456789abcdef") 753 [fracpart % 10]; 754 fracpart = (fracpart / 10); 755 } while(fracpart && (fplace < 20)); 756 if (fplace == 20) 757 fplace--; 758 fconvert[fplace] = 0; 759 760 /* -1 for decimal point, another -1 if we are printing a sign */ 761 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); 762 zpadlen = max - fplace; 763 if (zpadlen < 0) 764 zpadlen = 0; 765 if (padlen < 0) 766 padlen = 0; 767 if (flags & DP_F_MINUS) 768 padlen = -padlen; /* Left Justifty */ 769 770 if ((flags & DP_F_ZERO) && (padlen > 0)) { 771 if (signvalue) { 772 dopr_outch(buffer, currlen, maxlen, signvalue); 773 --padlen; 774 signvalue = 0; 775 } 776 while (padlen > 0) { 777 dopr_outch(buffer, currlen, maxlen, '0'); 778 --padlen; 779 } 780 } 781 while (padlen > 0) { 782 dopr_outch(buffer, currlen, maxlen, ' '); 783 --padlen; 784 } 785 if (signvalue) 786 dopr_outch(buffer, currlen, maxlen, signvalue); 787 788 while (iplace > 0) 789 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]); 790 791 /* 792 * Decimal point. This should probably use locale to find the 793 * correct char to print out. 794 */ 795 dopr_outch(buffer, currlen, maxlen, '.'); 796 797 while (fplace > 0) 798 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]); 799 800 while (zpadlen > 0) { 801 dopr_outch(buffer, currlen, maxlen, '0'); 802 --zpadlen; 803 } 804 805 while (padlen < 0) { 806 dopr_outch(buffer, currlen, maxlen, ' '); 807 ++padlen; 808 } 809 } 810 811 static void 812 dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) 813 { 814 if (*currlen < maxlen) 815 buffer[(*currlen)++] = c; 816 } 817 #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ 818 819 #ifndef HAVE_VSNPRINTF 820 int 821 vsnprintf(char *str, size_t count, const char *fmt, va_list args) 822 { 823 str[0] = 0; 824 dopr(str, count, fmt, args); 825 826 return(strlen(str)); 827 } 828 #endif /* !HAVE_VSNPRINTF */ 829 830 #ifndef HAVE_SNPRINTF 831 int 832 snprintf(char *str,size_t count,const char *fmt,...) 833 { 834 va_list ap; 835 836 va_start(ap, fmt); 837 (void) vsnprintf(str, count, fmt, ap); 838 va_end(ap); 839 840 return(strlen(str)); 841 } 842 843 #endif /* !HAVE_SNPRINTF */ 844