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