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.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
getopt(int argc,char ** argv,char * args)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 *
basename(char * path)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
mkstemp(char * path)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
ffs(int x)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@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
dopr(char * buffer,size_t maxlen,const char * format,va_list args)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
fmtstr(char * buffer,size_t * currlen,size_t maxlen,char * value,int flags,int min,int max)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
fmtint(char * buffer,size_t * currlen,size_t maxlen,long value,int base,int min,int max,int flags)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
pow10(int exp)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
round(long double value)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
fmtfp(char * buffer,size_t * currlen,size_t maxlen,long double fvalue,int min,int max,int flags)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
dopr_outch(char * buffer,size_t * currlen,size_t maxlen,char c)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
vsnprintf(char * str,size_t count,const char * fmt,va_list args)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
snprintf(char * str,size_t count,const char * fmt,...)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