Home | History | Annotate | Download | only in Uefi
      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