* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / mip / compat.c
blob7e7886d513ec51583c88b1108ccb6c44300509da
1 /*
2 * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
3 * All rights reserved.
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.
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.
27 * $Id: compat.c,v 1.9 2010/02/25 15:31:40 ragge Exp $
30 /*-
31 * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
32 * All rights reserved.
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Klaus Klein and Jason R. Thorpe.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
58 * $NetBSD: basename.c,v 1.9 2009/11/24 13:34:20 tnozaki Exp $
62 * Copyright (c) 1987, 1993
63 * The Regents of the University of California. All rights reserved.
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
67 * are met:
68 * 1. Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in the
72 * documentation and/or other materials provided with the distribution.
73 * 3. Neither the name of the University nor the names of its contributors
74 * may be used to endorse or promote products derived from this software
75 * without specific prior written permission.
77 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
78 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 * SUCH DAMAGE.
89 * $NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp $
92 #include <string.h>
93 #include <fcntl.h>
95 #include "config.h"
96 #define MKEXT /* XXX */
97 #include "manifest.h"
99 #ifndef HAVE_STRLCAT
101 * Appends src to string dst of size siz (unlike strncat, siz is the
102 * full size of dst, not space left). At most siz-1 characters
103 * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
104 * Returns strlen(initial dst) + strlen(src); if retval >= siz,
105 * truncation occurred.
107 size_t
108 strlcat(char *dst, const char *src, size_t siz)
110 char *d = dst;
111 const char *s = src;
112 size_t n = siz;
113 size_t dlen;
115 /* Find the end of dst and adjust bytes left but don't go past end */
116 while (n-- != 0 && *d != '\0')
117 d++;
118 dlen = d - dst;
119 n = siz - dlen;
121 if (n == 0)
122 return(dlen + strlen(s));
123 while (*s != '\0') {
124 if (n != 1) {
125 *d++ = *s;
126 n--;
128 s++;
130 *d = '\0';
132 return(dlen + (s - src)); /* count does not include NUL */
134 #endif
137 #ifndef HAVE_STRLCPY
139 * Copy src to string dst of size siz. At most siz-1 characters
140 * will be copied. Always NUL terminates (unless siz == 0).
141 * Returns strlen(src); if retval >= siz, truncation occurred.
143 size_t
144 strlcpy(char *dst, const char *src, size_t siz)
146 char *d = dst;
147 const char *s = src;
148 size_t n = siz;
150 /* Copy as many bytes as will fit */
151 if (n != 0 && --n != 0) {
152 do {
153 if ((*d++ = *s++) == 0)
154 break;
155 } while (--n != 0);
158 /* Not enough room in dst, add NUL and traverse rest of src */
159 if (n == 0) {
160 if (siz != 0)
161 *d = '\0'; /* NUL-terminate dst */
162 while (*s++)
166 return(s - src - 1); /* count does not include NUL */
168 #endif
170 #ifndef HAVE_GETOPT
171 char *optarg;
172 int optind = 1;
174 getopt(int argc, char **argv, char *args)
176 int n;
177 int nlen = strlen(args);
178 char cmd;
179 char rv;
181 if (argv[optind] && *argv[optind] == '-') {
182 cmd = *(argv[optind] + 1);
184 for (n = 0; n < nlen; n++) {
185 if (args[n] == ':')
186 continue;
187 if (args[n] == cmd) {
188 rv = *(argv[optind] + 1);
189 if (args[n+1] == ':') {
190 if (*(argv[optind] + 2) != '\0') {
191 optarg = argv[optind] + 2;
192 optind += 1;
193 } else {
194 optarg = argv[optind + 1];
195 optind += 2;
197 if (!optarg)
198 optarg="";
199 return rv;
200 } else {
201 optarg = NULL;
202 optind += 1;
203 return rv;
209 return -1;
211 #endif
213 #ifdef WIN32
214 #define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))
215 #else
216 #define ISPATHSEPARATOR(x) (x == '/')
217 #endif
219 #ifndef HAVE_BASENAME
220 #ifndef PATH_MAX
221 #define PATH_MAX 5000
222 #endif
224 char *
225 basename(char *path)
227 static char result[PATH_MAX];
228 char *p, *lastp;
229 size_t len;
232 * If `path' is a null pointer or points to an empty string,
233 * return a pointer to the string ".".
235 if ((path == NULL) || (*path == '\0')) {
236 result[0] = '.';
237 result[1] = '\0';
239 return (result);
242 /* Strip trailing slashes, if any. */
243 lastp = path + strlen(path) - 1;
244 while (lastp != path && ISPATHSEPARATOR(*lastp))
245 lastp--;
247 /* Now find the beginning of this (final) component. */
248 p = lastp;
249 while (p != path && !ISPATHSEPARATOR(*(p - 1)))
250 p--;
252 /* ...and copy the result into the result buffer. */
253 len = (lastp - p) + 1 /* last char */;
254 if (len > (PATH_MAX - 1))
255 len = PATH_MAX - 1;
257 memcpy(result, p, len);
258 result[len] = '\0';
260 return (result);
262 #endif
264 #if !defined(HAVE_MKSTEMP) && !defined(WIN32)
266 mkstemp(char *path)
268 char *start, *trv;
269 unsigned int pid;
271 /* To guarantee multiple calls generate unique names even if
272 the file is not created. 676 different possibilities with 7
273 or more X's, 26 with 6 or less. */
274 static char xtra[2] = "aa";
275 int xcnt = 0;
277 pid = getpid();
279 /* Move to end of path and count trailing X's. */
280 for (trv = path; *trv; ++trv)
281 if (*trv == 'X')
282 xcnt++;
283 else
284 xcnt = 0;
286 /* Use at least one from xtra. Use 2 if more than 6 X's. */
287 if (*(trv - 1) == 'X')
288 *--trv = xtra[0];
289 if (xcnt > 6 && *(trv - 1) == 'X')
290 *--trv = xtra[1];
292 /* Set remaining X's to pid digits with 0's to the left. */
293 while (*--trv == 'X') {
294 *trv = (pid % 10) + '0';
295 pid /= 10;
298 /* update xtra for next call. */
299 if (xtra[0] != 'z')
300 xtra[0]++;
301 else {
302 xtra[0] = 'a';
303 if (xtra[1] != 'z')
304 xtra[1]++;
305 else
306 xtra[1] = 'a';
309 return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
311 #endif
313 #ifndef HAVE_FFS
315 ffs(int x)
317 int r = 1;
318 if (!x) return 0;
319 if (!(x & 0xffff)) { x >>= 16; r += 16; }
320 if (!(x & 0xff)) { x >>= 8; r += 8; }
321 if (!(x & 0xf)) { x >>= 4; r += 4; }
322 if (!(x & 3)) { x >>= 2; r += 2; }
323 if (!(x & 1)) { x >>= 1; r += 1; }
325 return r;
327 #endif
330 * Copyright Patrick Powell 1995
331 * This code is based on code written by Patrick Powell (papowell@astart.com)
332 * It may be used for any purpose as long as this notice remains intact
333 * on all source code distributions
336 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
338 static void
339 dopr(char *buffer, size_t maxlen, const char *format, va_list args);
341 static void
342 fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
343 int min, int max);
345 static void
346 fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
347 int min, int max, int flags);
349 static void
350 fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
351 int min, int max, int flags);
353 static void
354 dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
357 * dopr(): poor man's version of doprintf
360 /* format read states */
361 #define DP_S_DEFAULT 0
362 #define DP_S_FLAGS 1
363 #define DP_S_MIN 2
364 #define DP_S_DOT 3
365 #define DP_S_MAX 4
366 #define DP_S_MOD 5
367 #define DP_S_CONV 6
368 #define DP_S_DONE 7
370 /* format flags - Bits */
371 #define DP_F_MINUS (1 << 0)
372 #define DP_F_PLUS (1 << 1)
373 #define DP_F_SPACE (1 << 2)
374 #define DP_F_NUM (1 << 3)
375 #define DP_F_ZERO (1 << 4)
376 #define DP_F_UP (1 << 5)
377 #define DP_F_UNSIGNED (1 << 6)
379 /* Conversion Flags */
380 #define DP_C_SHORT 1
381 #define DP_C_LONG 2
382 #define DP_C_LDOUBLE 3
383 #define DP_C_LONG_LONG 4
385 #define char_to_int(p) (p - '0')
386 #define abs_val(p) (p < 0 ? -p : p)
389 static void
390 dopr(char *buffer, size_t maxlen, const char *format, va_list args)
392 char *strvalue, ch;
393 long value;
394 long double fvalue;
395 int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;
396 size_t currlen = 0;
398 ch = *format++;
400 while (state != DP_S_DONE) {
401 if ((ch == '\0') || (currlen >= maxlen))
402 state = DP_S_DONE;
404 switch(state) {
405 case DP_S_DEFAULT:
406 if (ch == '%')
407 state = DP_S_FLAGS;
408 else
409 dopr_outch(buffer, &currlen, maxlen, ch);
410 ch = *format++;
411 break;
412 case DP_S_FLAGS:
413 switch (ch) {
414 case '-':
415 flags |= DP_F_MINUS;
416 ch = *format++;
417 break;
418 case '+':
419 flags |= DP_F_PLUS;
420 ch = *format++;
421 break;
422 case ' ':
423 flags |= DP_F_SPACE;
424 ch = *format++;
425 break;
426 case '#':
427 flags |= DP_F_NUM;
428 ch = *format++;
429 break;
430 case '0':
431 flags |= DP_F_ZERO;
432 ch = *format++;
433 break;
434 default:
435 state = DP_S_MIN;
436 break;
438 break;
439 case DP_S_MIN:
440 if (isdigit((unsigned char)ch)) {
441 min = 10 * min + char_to_int (ch);
442 ch = *format++;
443 } else if (ch == '*') {
444 min = va_arg (args, int);
445 ch = *format++;
446 state = DP_S_DOT;
447 } else
448 state = DP_S_DOT;
449 break;
450 case DP_S_DOT:
451 if (ch == '.') {
452 state = DP_S_MAX;
453 ch = *format++;
454 } else
455 state = DP_S_MOD;
456 break;
457 case DP_S_MAX:
458 if (isdigit((unsigned char)ch)) {
459 if (max < 0)
460 max = 0;
461 max = 10 * max + char_to_int(ch);
462 ch = *format++;
463 } else if (ch == '*') {
464 max = va_arg (args, int);
465 ch = *format++;
466 state = DP_S_MOD;
467 } else
468 state = DP_S_MOD;
469 break;
470 case DP_S_MOD:
471 switch (ch) {
472 case 'h':
473 cflags = DP_C_SHORT;
474 ch = *format++;
475 break;
476 case 'l':
477 cflags = DP_C_LONG;
478 ch = *format++;
479 if (ch == 'l') {
480 cflags = DP_C_LONG_LONG;
481 ch = *format++;
483 break;
484 case 'q':
485 cflags = DP_C_LONG_LONG;
486 ch = *format++;
487 break;
488 case 'L':
489 cflags = DP_C_LDOUBLE;
490 ch = *format++;
491 break;
492 default:
493 break;
495 state = DP_S_CONV;
496 break;
497 case DP_S_CONV:
498 switch (ch) {
499 case 'd':
500 case 'i':
501 if (cflags == DP_C_SHORT)
502 value = va_arg(args, int);
503 else if (cflags == DP_C_LONG)
504 value = va_arg(args, long int);
505 else if (cflags == DP_C_LONG_LONG)
506 value = va_arg (args, long long);
507 else
508 value = va_arg (args, int);
509 fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
510 break;
511 case 'o':
512 flags |= DP_F_UNSIGNED;
513 if (cflags == DP_C_SHORT)
514 value = va_arg(args, unsigned int);
515 else if (cflags == DP_C_LONG)
516 value = va_arg(args, unsigned long int);
517 else if (cflags == DP_C_LONG_LONG)
518 value = va_arg(args, unsigned long long);
519 else
520 value = va_arg(args, unsigned int);
521 fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
522 break;
523 case 'u':
524 flags |= DP_F_UNSIGNED;
525 if (cflags == DP_C_SHORT)
526 value = va_arg(args, unsigned int);
527 else if (cflags == DP_C_LONG)
528 value = va_arg(args, unsigned long int);
529 else if (cflags == DP_C_LONG_LONG)
530 value = va_arg(args, unsigned long long);
531 else
532 value = va_arg(args, unsigned int);
533 fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
534 break;
535 case 'X':
536 flags |= DP_F_UP;
537 case 'x':
538 flags |= DP_F_UNSIGNED;
539 if (cflags == DP_C_SHORT)
540 value = va_arg(args, unsigned int);
541 else if (cflags == DP_C_LONG)
542 value = va_arg(args, unsigned long int);
543 else if (cflags == DP_C_LONG_LONG)
544 value = va_arg(args, unsigned long long);
545 else
546 value = va_arg(args, unsigned int);
547 fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
548 break;
549 case 'f':
550 if (cflags == DP_C_LDOUBLE)
551 fvalue = va_arg(args, long double);
552 else
553 fvalue = va_arg(args, double);
554 /* um, floating point? */
555 fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
556 break;
557 case 'E':
558 flags |= DP_F_UP;
559 case 'e':
560 if (cflags == DP_C_LDOUBLE)
561 fvalue = va_arg(args, long double);
562 else
563 fvalue = va_arg(args, double);
564 break;
565 case 'G':
566 flags |= DP_F_UP;
567 case 'g':
568 if (cflags == DP_C_LDOUBLE)
569 fvalue = va_arg(args, long double);
570 else
571 fvalue = va_arg(args, double);
572 break;
573 case 'c':
574 dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
575 break;
576 case 's':
577 strvalue = va_arg(args, char *);
578 if (max < 0)
579 max = maxlen; /* ie, no max */
580 fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
581 break;
582 case 'p':
583 strvalue = va_arg(args, void *);
584 fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
585 break;
586 case 'n':
587 if (cflags == DP_C_SHORT) {
588 short int *num;
589 num = va_arg(args, short int *);
590 *num = currlen;
591 } else if (cflags == DP_C_LONG) {
592 long int *num;
593 num = va_arg(args, long int *);
594 *num = currlen;
595 } else if (cflags == DP_C_LONG_LONG) {
596 long long *num;
597 num = va_arg(args, long long *);
598 *num = currlen;
599 } else {
600 int *num;
601 num = va_arg(args, int *);
602 *num = currlen;
604 break;
605 case '%':
606 dopr_outch(buffer, &currlen, maxlen, ch);
607 break;
608 case 'w': /* not supported yet, treat as next char */
609 ch = *format++;
610 break;
611 default: /* Unknown, skip */
612 break;
614 ch = *format++;
615 state = DP_S_DEFAULT;
616 flags = cflags = min = 0;
617 max = -1;
618 break;
619 case DP_S_DONE:
620 break;
621 default: /* hmm? */
622 break; /* some picky compilers need this */
625 if (currlen < maxlen - 1)
626 buffer[currlen] = '\0';
627 else
628 buffer[maxlen - 1] = '\0';
631 static void
632 fmtstr(char *buffer, size_t *currlen, size_t maxlen,
633 char *value, int flags, int min, int max)
635 int cnt = 0, padlen, strln; /* amount to pad */
637 if (value == 0)
638 value = "<NULL>";
640 for (strln = 0; value[strln]; ++strln); /* strlen */
641 padlen = min - strln;
642 if (padlen < 0)
643 padlen = 0;
644 if (flags & DP_F_MINUS)
645 padlen = -padlen; /* Left Justify */
647 while ((padlen > 0) && (cnt < max)) {
648 dopr_outch(buffer, currlen, maxlen, ' ');
649 --padlen;
650 ++cnt;
652 while (*value && (cnt < max)) {
653 dopr_outch(buffer, currlen, maxlen, *value++);
654 ++cnt;
656 while ((padlen < 0) && (cnt < max)) {
657 dopr_outch(buffer, currlen, maxlen, ' ');
658 ++padlen;
659 ++cnt;
663 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
665 static void
666 fmtint(char *buffer, size_t *currlen, size_t maxlen,
667 long value, int base, int min, int max, int flags)
669 unsigned long uvalue;
670 char convert[20];
671 int signvalue = 0, place = 0, caps = 0;
672 int spadlen = 0; /* amount to space pad */
673 int zpadlen = 0; /* amount to zero pad */
675 #define PADMAX(x,y) ((x) > (y) ? (x) : (y))
677 if (max < 0)
678 max = 0;
680 uvalue = value;
682 if (!(flags & DP_F_UNSIGNED)) {
683 if (value < 0) {
684 signvalue = '-';
685 uvalue = -value;
686 } else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
687 signvalue = '+';
688 else if (flags & DP_F_SPACE)
689 signvalue = ' ';
692 if (flags & DP_F_UP)
693 caps = 1; /* Should characters be upper case? */
694 do {
695 convert[place++] =
696 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
697 [uvalue % (unsigned)base];
698 uvalue = (uvalue / (unsigned)base );
699 } while (uvalue && (place < 20));
700 if (place == 20)
701 place--;
702 convert[place] = 0;
704 zpadlen = max - place;
705 spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);
706 if (zpadlen < 0)
707 zpadlen = 0;
708 if (spadlen < 0)
709 spadlen = 0;
710 if (flags & DP_F_ZERO) {
711 zpadlen = PADMAX(zpadlen, spadlen);
712 spadlen = 0;
714 if (flags & DP_F_MINUS)
715 spadlen = -spadlen; /* Left Justifty */
717 /* Spaces */
718 while (spadlen > 0) {
719 dopr_outch(buffer, currlen, maxlen, ' ');
720 --spadlen;
723 /* Sign */
724 if (signvalue)
725 dopr_outch(buffer, currlen, maxlen, signvalue);
727 /* Zeros */
728 if (zpadlen > 0) {
729 while (zpadlen > 0) {
730 dopr_outch(buffer, currlen, maxlen, '0');
731 --zpadlen;
735 /* Digits */
736 while (place > 0)
737 dopr_outch(buffer, currlen, maxlen, convert[--place]);
739 /* Left Justified spaces */
740 while (spadlen < 0) {
741 dopr_outch (buffer, currlen, maxlen, ' ');
742 ++spadlen;
746 static long double
747 pow10(int exp)
749 long double result = 1;
751 while (exp) {
752 result *= 10;
753 exp--;
756 return result;
759 static long
760 round(long double value)
762 long intpart = value;
764 value -= intpart;
765 if (value >= 0.5)
766 intpart++;
768 return intpart;
771 static void
772 fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
773 int min, int max, int flags)
775 char iconvert[20], fconvert[20];
776 int signvalue = 0, iplace = 0, fplace = 0;
777 int padlen = 0; /* amount to pad */
778 int zpadlen = 0, caps = 0;
779 long intpart, fracpart;
780 long double ufvalue;
783 * AIX manpage says the default is 0, but Solaris says the default
784 * is 6, and sprintf on AIX defaults to 6
786 if (max < 0)
787 max = 6;
789 ufvalue = abs_val(fvalue);
791 if (fvalue < 0)
792 signvalue = '-';
793 else if (flags & DP_F_PLUS) /* Do a sign (+/i) */
794 signvalue = '+';
795 else if (flags & DP_F_SPACE)
796 signvalue = ' ';
798 intpart = ufvalue;
801 * Sorry, we only support 9 digits past the decimal because of our
802 * conversion method
804 if (max > 9)
805 max = 9;
807 /* We "cheat" by converting the fractional part to integer by
808 * multiplying by a factor of 10
810 fracpart = round((pow10 (max)) * (ufvalue - intpart));
812 if (fracpart >= pow10 (max)) {
813 intpart++;
814 fracpart -= pow10 (max);
817 /* Convert integer part */
818 do {
819 iconvert[iplace++] =
820 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
821 [intpart % 10];
822 intpart = (intpart / 10);
823 } while(intpart && (iplace < 20));
824 if (iplace == 20)
825 iplace--;
826 iconvert[iplace] = 0;
828 /* Convert fractional part */
829 do {
830 fconvert[fplace++] =
831 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
832 [fracpart % 10];
833 fracpart = (fracpart / 10);
834 } while(fracpart && (fplace < 20));
835 if (fplace == 20)
836 fplace--;
837 fconvert[fplace] = 0;
839 /* -1 for decimal point, another -1 if we are printing a sign */
840 padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
841 zpadlen = max - fplace;
842 if (zpadlen < 0)
843 zpadlen = 0;
844 if (padlen < 0)
845 padlen = 0;
846 if (flags & DP_F_MINUS)
847 padlen = -padlen; /* Left Justifty */
849 if ((flags & DP_F_ZERO) && (padlen > 0)) {
850 if (signvalue) {
851 dopr_outch(buffer, currlen, maxlen, signvalue);
852 --padlen;
853 signvalue = 0;
855 while (padlen > 0) {
856 dopr_outch(buffer, currlen, maxlen, '0');
857 --padlen;
860 while (padlen > 0) {
861 dopr_outch(buffer, currlen, maxlen, ' ');
862 --padlen;
864 if (signvalue)
865 dopr_outch(buffer, currlen, maxlen, signvalue);
867 while (iplace > 0)
868 dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
871 * Decimal point. This should probably use locale to find the
872 * correct char to print out.
874 dopr_outch(buffer, currlen, maxlen, '.');
876 while (fplace > 0)
877 dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
879 while (zpadlen > 0) {
880 dopr_outch(buffer, currlen, maxlen, '0');
881 --zpadlen;
884 while (padlen < 0) {
885 dopr_outch(buffer, currlen, maxlen, ' ');
886 ++padlen;
890 static void
891 dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
893 if (*currlen < maxlen)
894 buffer[(*currlen)++] = c;
896 #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
898 #ifndef HAVE_VSNPRINTF
899 int
900 vsnprintf(char *str, size_t count, const char *fmt, va_list args)
902 str[0] = 0;
903 dopr(str, count, fmt, args);
905 return(strlen(str));
907 #endif /* !HAVE_VSNPRINTF */
909 #ifndef HAVE_SNPRINTF
910 int
911 snprintf(char *str,size_t count,const char *fmt,...)
913 va_list ap;
915 va_start(ap, fmt);
916 (void) vsnprintf(str, count, fmt, ap);
917 va_end(ap);
919 return(strlen(str));
922 #endif /* !HAVE_SNPRINTF */