1/* 2 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@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.13 2015/07/24 08:26:05 ragge Exp 28 * $NetBSD: compat.c,v 1.1.1.6 2016/02/09 20:29:14 plunky Exp $ 29 */ 30 31/* 32 * Copyright (c) 1987, 1993 33 * The Regents of the University of California. All rights reserved. 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. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 * 59 * NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp 60 */ 61 62#include <string.h> 63 64#include "config.h" 65#include "compat.h" 66 67#ifndef HAVE_STRLCAT 68/* 69 * Appends src to string dst of size siz (unlike strncat, siz is the 70 * full size of dst, not space left). At most siz-1 characters 71 * will be copied. Always NUL terminates (unless siz <= strlen(dst)). 72 * Returns strlen(initial dst) + strlen(src); if retval >= siz, 73 * truncation occurred. 74 */ 75size_t 76strlcat(char *dst, const char *src, size_t siz) 77{ 78 char *d = dst; 79 const char *s = src; 80 size_t n = siz; 81 size_t dlen; 82 83 /* Find the end of dst and adjust bytes left but don't go past end */ 84 while (n-- != 0 && *d != '\0') 85 d++; 86 dlen = d - dst; 87 n = siz - dlen; 88 89 if (n == 0) 90 return(dlen + strlen(s)); 91 while (*s != '\0') { 92 if (n != 1) { 93 *d++ = *s; 94 n--; 95 } 96 s++; 97 } 98 *d = '\0'; 99 100 return(dlen + (s - src)); /* count does not include NUL */ 101} 102#endif 103 104 105#ifndef HAVE_STRLCPY 106/* 107 * Copy src to string dst of size siz. At most siz-1 characters 108 * will be copied. Always NUL terminates (unless siz == 0). 109 * Returns strlen(src); if retval >= siz, truncation occurred. 110 */ 111size_t 112strlcpy(char *dst, const char *src, size_t siz) 113{ 114 char *d = dst; 115 const char *s = src; 116 size_t n = siz; 117 118 /* Copy as many bytes as will fit */ 119 if (n != 0 && --n != 0) { 120 do { 121 if ((*d++ = *s++) == 0) 122 break; 123 } while (--n != 0); 124 } 125 126 /* Not enough room in dst, add NUL and traverse rest of src */ 127 if (n == 0) { 128 if (siz != 0) 129 *d = '\0'; /* NUL-terminate dst */ 130 while (*s++) 131 ; 132 } 133 134 return(s - src - 1); /* count does not include NUL */ 135} 136#endif 137 138#ifndef HAVE_GETOPT 139char *optarg; 140int optind = 1; 141int 142getopt(int argc, char * const argv[], const char *args) 143{ 144 int n; 145 int nlen = strlen(args); 146 char cmd; 147 char rv; 148 149 if (argv[optind] && *argv[optind] == '-') { 150 cmd = *(argv[optind] + 1); 151 152 for (n = 0; n < nlen; n++) { 153 if (args[n] == ':') 154 continue; 155 if (args[n] == cmd) { 156 rv = *(argv[optind] + 1); 157 if (args[n+1] == ':') { 158 if (*(argv[optind] + 2) != '\0') { 159 optarg = argv[optind] + 2; 160 optind += 1; 161 } else { 162 optarg = argv[optind + 1]; 163 optind += 2; 164 } 165 if (!optarg) 166 optarg=""; 167 return rv; 168 } else { 169 optarg = NULL; 170 optind += 1; 171 return rv; 172 } 173 } 174 } 175 } 176 177 return -1; 178} 179#endif 180 181#if !defined(HAVE_MKSTEMP) && !defined(_WIN32) 182#include <fcntl.h> /* open() */ 183#include <unistd.h> /* getpid() */ 184 185int 186mkstemp(char *path) 187{ 188 char *trv; 189 unsigned int pid; 190 191 /* To guarantee multiple calls generate unique names even if 192 the file is not created. 676 different possibilities with 7 193 or more X's, 26 with 6 or less. */ 194 static char xtra[2] = "aa"; 195 int xcnt = 0; 196 197 pid = getpid(); 198 199 /* Move to end of path and count trailing X's. */ 200 for (trv = path; *trv; ++trv) 201 if (*trv == 'X') 202 xcnt++; 203 else 204 xcnt = 0; 205 206 /* Use at least one from xtra. Use 2 if more than 6 X's. */ 207 if (*(trv - 1) == 'X') 208 *--trv = xtra[0]; 209 if (xcnt > 6 && *(trv - 1) == 'X') 210 *--trv = xtra[1]; 211 212 /* Set remaining X's to pid digits with 0's to the left. */ 213 while (*--trv == 'X') { 214 *trv = (pid % 10) + '0'; 215 pid /= 10; 216 } 217 218 /* update xtra for next call. */ 219 if (xtra[0] != 'z') 220 xtra[0]++; 221 else { 222 xtra[0] = 'a'; 223 if (xtra[1] != 'z') 224 xtra[1]++; 225 else 226 xtra[1] = 'a'; 227 } 228 229 return open(path, O_CREAT | O_EXCL | O_RDWR, 0600); 230} 231#endif 232 233#ifndef HAVE_FFS 234int 235ffs(int x) 236{ 237 int r = 1; 238 if (!x) return 0; 239 if (!(x & 0xffff)) { x >>= 16; r += 16; } 240 if (!(x & 0xff)) { x >>= 8; r += 8; } 241 if (!(x & 0xf)) { x >>= 4; r += 4; } 242 if (!(x & 3)) { x >>= 2; r += 2; } 243 if (!(x & 1)) { x >>= 1; r += 1; } 244 245 return r; 246} 247#endif 248 249/* 250 * Copyright Patrick Powell 1995 251 * This code is based on code written by Patrick Powell (papowell@astart.com) 252 * It may be used for any purpose as long as this notice remains intact 253 * on all source code distributions 254 */ 255 256#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) 257#include <ctype.h> /* isdigit() */ 258 259static void 260dopr(char *buffer, size_t maxlen, const char *format, va_list args); 261 262static void 263fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, 264 int min, int max); 265 266static void 267fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, 268 int min, int max, int flags); 269 270static void 271fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue, 272 int min, int max, int flags); 273 274static void 275dopr_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 310static void 311dopr(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 552static void 553fmtstr(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 586static void 587fmtint(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 667static long double 668ldpow10(int exp) 669{ 670 long double result = 1; 671 672 while (exp) { 673 result *= 10; 674 exp--; 675 } 676 677 return result; 678} 679 680static long 681lroundl(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 692static void 693fmtfp(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 = lroundl((ldpow10 (max)) * (ufvalue - intpart)); 732 733 if (fracpart >= ldpow10 (max)) { 734 intpart++; 735 fracpart -= ldpow10 (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 811static void 812dopr_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 820int 821vsnprintf(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 831int 832snprintf(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