EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

StdLib/LibC/Uefi/compat.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. The name of the author may not be used to endorse or promote products
00014  *    derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
00017  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00018  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
00019  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00020  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00021  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00022  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00023  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00025  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  * $Id: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
00028 
00029  * Copyright (c) 1997, 2002 The NetBSD Foundation, Inc.
00030  * All rights reserved.
00031  *
00032  * This code is derived from software contributed to The NetBSD Foundation
00033  * by Klaus Klein and Jason R. Thorpe.
00034  *
00035  * Redistribution and use in source and binary forms, with or without
00036  * modification, are permitted provided that the following conditions
00037  * are met:
00038  * 1. Redistributions of source code must retain the above copyright
00039  *    notice, this list of conditions and the following disclaimer.
00040  * 2. Redistributions in binary form must reproduce the above copyright
00041  *    notice, this list of conditions and the following disclaimer in the
00042  *    documentation and/or other materials provided with the distribution.
00043  * 3. All advertising materials mentioning features or use of this software
00044  *    must display the following acknowledgement:
00045  *        This product includes software developed by the NetBSD
00046  *        Foundation, Inc. and its contributors.
00047  * 4. Neither the name of The NetBSD Foundation nor the names of its
00048  *    contributors may be used to endorse or promote products derived
00049  *    from this software without specific prior written permission.
00050  *
00051  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
00052  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00053  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00054  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
00055  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00056  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00057  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00058  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00059  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00060  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00061  * POSSIBILITY OF SUCH DAMAGE.
00062  *
00063  *  $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
00064 
00065  * Copyright (c) 1987, 1993
00066  *  The Regents of the University of California.  All rights reserved.
00067  *
00068  * Redistribution and use in source and binary forms, with or without
00069  * modification, are permitted provided that the following conditions
00070  * are met:
00071  * 1. Redistributions of source code must retain the above copyright
00072  *    notice, this list of conditions and the following disclaimer.
00073  * 2. Redistributions in binary form must reproduce the above copyright
00074  *    notice, this list of conditions and the following disclaimer in the
00075  *    documentation and/or other materials provided with the distribution.
00076  * 3. Neither the name of the University nor the names of its contributors
00077  *    may be used to endorse or promote products derived from this software
00078  *    without specific prior written permission.
00079  *
00080  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00081  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00082  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00083  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00084  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00085  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00086  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00087  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00088  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00089  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00090  * SUCH DAMAGE.
00091  *
00092  *  $NetBSD: compat.c,v 1.1.1.1 2008/08/24 05:33:08 gmcgarry Exp $
00093  */
00094 #include  <LibConfig.h>
00095 #include  <string.h>
00096 #include  <fcntl.h>
00097 #include  <sys/syslimits.h>
00098 
00099 #ifndef HAVE_GETOPT
00100 char *optarg;
00101 int optind = 1;
00102 int
00103 getopt(int argc, char **argv, char *args)
00104 {
00105         size_t n;
00106   size_t nlen = strlen(args);
00107         char cmd;
00108         char rv;
00109 
00110         if (argv[optind] && *argv[optind] == '-') {
00111                 cmd = *(argv[optind] + 1);
00112 
00113                 for (n = 0; n < nlen; n++) {
00114                         if (args[n] == ':')
00115         continue;
00116                         if (args[n] == cmd) {
00117                                 rv = *(argv[optind] + 1);
00118                                 if (args[n+1] == ':') {
00119           if (*(argv[optind] + 2) != '\0') {
00120                                           optarg = argv[optind] + 2;
00121             optind += 1;
00122           } else {
00123                                           optarg = argv[optind + 1];
00124                                           optind += 2;
00125           }
00126                                         if (!optarg)
00127              optarg="";
00128                                         return rv;
00129                                 } else {
00130                                         optarg = NULL;
00131                                         optind += 1;
00132                                         return rv;
00133                                 }
00134                         }
00135                 }
00136         }
00137         return -1;
00138 }
00139 #endif
00140 
00141 #define ISPATHSEPARATOR(x) ((x == '/') || (x == '\\'))
00142 
00143 #ifdef HAVE_BASENAME
00144 #ifndef PATH_MAX
00145   #define PATH_MAX 5000
00146 #endif
00147 
00148 char *
00149 basename(char *path)
00150 {
00151   static char singledot[] = ".";
00152   static char result[PATH_MAX];
00153   char *p, *lastp;
00154   size_t len;
00155 
00156   /*
00157    * If `path' is a null pointer or points to an empty string,
00158    * return a pointer to the string ".".
00159    */
00160   if ((path == NULL) || (*path == '\0'))
00161     return (singledot);
00162 
00163   /* Strip trailing slashes, if any. */
00164   lastp = path + strlen(path) - 1;
00165   while (lastp != path && ISPATHSEPARATOR(*lastp))
00166     lastp--;
00167 
00168   /* Now find the beginning of this (final) component. */
00169   p = lastp;
00170   while (p != path && !ISPATHSEPARATOR(*(p - 1)))
00171     p--;
00172 
00173   /* ...and copy the result into the result buffer. */
00174   len = (lastp - p) + 1 /* last char */;
00175   if (len > (PATH_MAX - 1))
00176     len = PATH_MAX - 1;
00177 
00178   memcpy(result, p, len);
00179   result[len] = '\0';
00180 
00181   return (result);
00182 }
00183 #endif
00184 
00185 #if !defined(HAVE_MKSTEMP) && !defined(WIN32)
00186 int
00187 mkstemp(char *path)
00188 {
00189   char *start, *trv;
00190   unsigned int pid;
00191 
00192   /* To guarantee multiple calls generate unique names even if
00193      the file is not created. 676 different possibilities with 7
00194      or more X's, 26 with 6 or less. */
00195   static char xtra[2] = "aa";
00196   int xcnt = 0;
00197 
00198   pid = getpid();
00199 
00200   /* Move to end of path and count trailing X's. */
00201   for (trv = path; *trv; ++trv)
00202     if (*trv == 'X')
00203       xcnt++;
00204     else
00205       xcnt = 0;
00206 
00207   /* Use at least one from xtra.  Use 2 if more than 6 X's. */
00208   if (*(trv - 1) == 'X')
00209     *--trv = xtra[0];
00210   if (xcnt > 6 && *(trv - 1) == 'X')
00211     *--trv = xtra[1];
00212 
00213   /* Set remaining X's to pid digits with 0's to the left. */
00214   while (*--trv == 'X') {
00215     *trv = (pid % 10) + '0';
00216     pid /= 10;
00217   }
00218 
00219   /* update xtra for next call. */
00220   if (xtra[0] != 'z')
00221     xtra[0]++;
00222   else {
00223     xtra[0] = 'a';
00224     if (xtra[1] != 'z')
00225       xtra[1]++;
00226     else
00227       xtra[1] = 'a';
00228   }
00229 
00230   return open(path, O_CREAT | O_EXCL | O_RDWR, 0600);
00231 }
00232 #endif
00233 
00234 #ifdef HAVE_FFS
00235 int
00236 ffs(int x)
00237 {
00238   int r = 1;
00239   if (!x) return 0;
00240   if (!(x & 0xffff)) { x >>= 16; r += 16; }
00241   if (!(x &   0xff)) { x >>= 8;  r += 8;  }
00242   if (!(x &    0xf)) { x >>= 4;  r += 4;  }
00243   if (!(x &      3)) { x >>= 2;  r += 2;  }
00244   if (!(x &      1)) { x >>= 1;  r += 1;  }
00245 
00246   return r;
00247 }
00248 #endif
00249 
00250 /*
00251  * Copyright Patrick Powell 1995
00252  * This code is based on code written by Patrick Powell (papowell@astart.com)
00253  * It may be used for any purpose as long as this notice remains intact
00254  * on all source code distributions
00255  */
00256 
00257 #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)
00258 
00259 static void
00260 dopr(char *buffer, size_t maxlen, const char *format, va_list args);
00261 
00262 static void
00263 fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,
00264     int min, int max);
00265 
00266 static void
00267 fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,
00268     int min, int max, int flags);
00269 
00270 static void
00271 fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
00272     int min, int max, int flags);
00273 
00274 static void
00275 dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
00276 
00277 /*
00278  * dopr(): poor man's version of doprintf
00279  */
00280 
00281 /* format read states */
00282 #define DP_S_DEFAULT 0
00283 #define DP_S_FLAGS   1
00284 #define DP_S_MIN     2
00285 #define DP_S_DOT     3
00286 #define DP_S_MAX     4
00287 #define DP_S_MOD     5
00288 #define DP_S_CONV    6
00289 #define DP_S_DONE    7
00290 
00291 /* format flags - Bits */
00292 #define DP_F_MINUS  (1 << 0)
00293 #define DP_F_PLUS   (1 << 1)
00294 #define DP_F_SPACE  (1 << 2)
00295 #define DP_F_NUM    (1 << 3)
00296 #define DP_F_ZERO   (1 << 4)
00297 #define DP_F_UP     (1 << 5)
00298 #define DP_F_UNSIGNED   (1 << 6)
00299 
00300 /* Conversion Flags */
00301 #define DP_C_SHORT     1
00302 #define DP_C_LONG      2
00303 #define DP_C_LDOUBLE   3
00304 #define DP_C_LONG_LONG 4
00305 
00306 #define char_to_int(p) (p - '0')
00307 #define abs_val(p) (p < 0 ? -p : p)
00308 
00309 
00310 static void
00311 dopr(char *buffer, size_t maxlen, const char *format, va_list args)
00312 {
00313   char *strvalue, ch;
00314   long value;
00315   long double fvalue;
00316   int min = 0, max = -1, state = DP_S_DEFAULT, flags = 0, cflags = 0;
00317   size_t currlen = 0;
00318 
00319   ch = *format++;
00320 
00321   while (state != DP_S_DONE) {
00322     if ((ch == '\0') || (currlen >= maxlen))
00323       state = DP_S_DONE;
00324 
00325     switch(state) {
00326     case DP_S_DEFAULT:
00327       if (ch == '%')
00328         state = DP_S_FLAGS;
00329       else
00330         dopr_outch(buffer, &currlen, maxlen, ch);
00331       ch = *format++;
00332       break;
00333     case DP_S_FLAGS:
00334       switch (ch) {
00335       case '-':
00336         flags |= DP_F_MINUS;
00337         ch = *format++;
00338         break;
00339       case '+':
00340         flags |= DP_F_PLUS;
00341         ch = *format++;
00342         break;
00343       case ' ':
00344         flags |= DP_F_SPACE;
00345         ch = *format++;
00346         break;
00347       case '#':
00348         flags |= DP_F_NUM;
00349         ch = *format++;
00350         break;
00351       case '0':
00352         flags |= DP_F_ZERO;
00353         ch = *format++;
00354         break;
00355       default:
00356         state = DP_S_MIN;
00357         break;
00358       }
00359       break;
00360     case DP_S_MIN:
00361       if (isdigit((unsigned char)ch)) {
00362         min = 10 * min + char_to_int (ch);
00363         ch = *format++;
00364       } else if (ch == '*') {
00365         min = va_arg (args, int);
00366         ch = *format++;
00367         state = DP_S_DOT;
00368       } else
00369         state = DP_S_DOT;
00370       break;
00371     case DP_S_DOT:
00372       if (ch == '.') {
00373         state = DP_S_MAX;
00374         ch = *format++;
00375       } else
00376         state = DP_S_MOD;
00377       break;
00378     case DP_S_MAX:
00379       if (isdigit((unsigned char)ch)) {
00380         if (max < 0)
00381           max = 0;
00382         max = 10 * max + char_to_int(ch);
00383         ch = *format++;
00384       } else if (ch == '*') {
00385         max = va_arg (args, int);
00386         ch = *format++;
00387         state = DP_S_MOD;
00388       } else
00389         state = DP_S_MOD;
00390       break;
00391     case DP_S_MOD:
00392       switch (ch) {
00393       case 'h':
00394         cflags = DP_C_SHORT;
00395         ch = *format++;
00396         break;
00397       case 'l':
00398         cflags = DP_C_LONG;
00399         ch = *format++;
00400         if (ch == 'l') {
00401           cflags = DP_C_LONG_LONG;
00402           ch = *format++;
00403         }
00404         break;
00405       case 'q':
00406         cflags = DP_C_LONG_LONG;
00407         ch = *format++;
00408         break;
00409       case 'L':
00410         cflags = DP_C_LDOUBLE;
00411         ch = *format++;
00412         break;
00413       default:
00414         break;
00415       }
00416       state = DP_S_CONV;
00417       break;
00418     case DP_S_CONV:
00419       switch (ch) {
00420       case 'd':
00421       case 'i':
00422         if (cflags == DP_C_SHORT)
00423           value = va_arg(args, int);
00424         else if (cflags == DP_C_LONG)
00425           value = va_arg(args, long int);
00426         else if (cflags == DP_C_LONG_LONG)
00427           value = va_arg (args, long long);
00428         else
00429           value = va_arg (args, int);
00430         fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);
00431         break;
00432       case 'o':
00433         flags |= DP_F_UNSIGNED;
00434         if (cflags == DP_C_SHORT)
00435           value = va_arg(args, unsigned int);
00436         else if (cflags == DP_C_LONG)
00437           value = va_arg(args, unsigned long int);
00438         else if (cflags == DP_C_LONG_LONG)
00439           value = va_arg(args, unsigned long long);
00440         else
00441           value = va_arg(args, unsigned int);
00442         fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);
00443         break;
00444       case 'u':
00445         flags |= DP_F_UNSIGNED;
00446         if (cflags == DP_C_SHORT)
00447           value = va_arg(args, unsigned int);
00448         else if (cflags == DP_C_LONG)
00449           value = va_arg(args, unsigned long int);
00450         else if (cflags == DP_C_LONG_LONG)
00451           value = va_arg(args, unsigned long long);
00452         else
00453           value = va_arg(args, unsigned int);
00454         fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
00455         break;
00456       case 'X':
00457         flags |= DP_F_UP;
00458       case 'x':
00459         flags |= DP_F_UNSIGNED;
00460         if (cflags == DP_C_SHORT)
00461           value = va_arg(args, unsigned int);
00462         else if (cflags == DP_C_LONG)
00463           value = va_arg(args, unsigned long int);
00464         else if (cflags == DP_C_LONG_LONG)
00465           value = va_arg(args, unsigned long long);
00466         else
00467           value = va_arg(args, unsigned int);
00468         fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);
00469         break;
00470       case 'f':
00471         if (cflags == DP_C_LDOUBLE)
00472           fvalue = va_arg(args, long double);
00473         else
00474           fvalue = va_arg(args, double);
00475         /* um, floating point? */
00476         fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);
00477         break;
00478       case 'E':
00479         flags |= DP_F_UP;
00480       case 'e':
00481         if (cflags == DP_C_LDOUBLE)
00482           fvalue = va_arg(args, long double);
00483         else
00484           fvalue = va_arg(args, double);
00485         break;
00486       case 'G':
00487         flags |= DP_F_UP;
00488       case 'g':
00489         if (cflags == DP_C_LDOUBLE)
00490           fvalue = va_arg(args, long double);
00491         else
00492           fvalue = va_arg(args, double);
00493         break;
00494       case 'c':
00495         dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));
00496         break;
00497       case 's':
00498         strvalue = va_arg(args, char *);
00499         if (max < 0)
00500           max = maxlen; /* ie, no max */
00501         fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);
00502         break;
00503       case 'p':
00504         strvalue = va_arg(args, void *);
00505         fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
00506         break;
00507       case 'n':
00508         if (cflags == DP_C_SHORT) {
00509           short int *num;
00510           num = va_arg(args, short int *);
00511           *num = currlen;
00512         } else if (cflags == DP_C_LONG) {
00513           long int *num;
00514           num = va_arg(args, long int *);
00515           *num = currlen;
00516         } else if (cflags == DP_C_LONG_LONG) {
00517           long long *num;
00518           num = va_arg(args, long long *);
00519           *num = currlen;
00520         } else {
00521           int *num;
00522           num = va_arg(args, int *);
00523           *num = currlen;
00524         }
00525         break;
00526       case '%':
00527         dopr_outch(buffer, &currlen, maxlen, ch);
00528         break;
00529       case 'w': /* not supported yet, treat as next char */
00530         ch = *format++;
00531         break;
00532       default: /* Unknown, skip */
00533       break;
00534       }
00535       ch = *format++;
00536       state = DP_S_DEFAULT;
00537       flags = cflags = min = 0;
00538       max = -1;
00539       break;
00540     case DP_S_DONE:
00541       break;
00542     default: /* hmm? */
00543       break; /* some picky compilers need this */
00544     }
00545   }
00546   if (currlen < maxlen - 1)
00547     buffer[currlen] = '\0';
00548   else
00549     buffer[maxlen - 1] = '\0';
00550 }
00551 
00552 static void
00553 fmtstr(char *buffer, size_t *currlen, size_t maxlen,
00554     char *value, int flags, int min, int max)
00555 {
00556   int cnt = 0, padlen, strln;     /* amount to pad */
00557 
00558   if (value == 0)
00559     value = "<NULL>";
00560 
00561   for (strln = 0; value[strln]; ++strln); /* strlen */
00562   padlen = min - strln;
00563   if (padlen < 0)
00564     padlen = 0;
00565   if (flags & DP_F_MINUS)
00566     padlen = -padlen; /* Left Justify */
00567 
00568   while ((padlen > 0) && (cnt < max)) {
00569     dopr_outch(buffer, currlen, maxlen, ' ');
00570     --padlen;
00571     ++cnt;
00572   }
00573   while (*value && (cnt < max)) {
00574     dopr_outch(buffer, currlen, maxlen, *value++);
00575     ++cnt;
00576   }
00577   while ((padlen < 0) && (cnt < max)) {
00578     dopr_outch(buffer, currlen, maxlen, ' ');
00579     ++padlen;
00580     ++cnt;
00581   }
00582 }
00583 
00584 /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
00585 
00586 static void
00587 fmtint(char *buffer, size_t *currlen, size_t maxlen,
00588     long value, int base, int min, int max, int flags)
00589 {
00590   unsigned long uvalue;
00591   char convert[20];
00592   int signvalue = 0, place = 0, caps = 0;
00593   int spadlen = 0; /* amount to space pad */
00594   int zpadlen = 0; /* amount to zero pad */
00595 
00596 #define PADMAX(x,y) ((x) > (y) ? (x) : (y))
00597 
00598   if (max < 0)
00599     max = 0;
00600 
00601   uvalue = value;
00602 
00603   if (!(flags & DP_F_UNSIGNED)) {
00604     if (value < 0) {
00605       signvalue = '-';
00606       uvalue = -value;
00607     } else if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
00608       signvalue = '+';
00609     else if (flags & DP_F_SPACE)
00610       signvalue = ' ';
00611   }
00612 
00613   if (flags & DP_F_UP)
00614     caps = 1; /* Should characters be upper case? */
00615   do {
00616     convert[place++] =
00617         (caps ? "0123456789ABCDEF" : "0123456789abcdef")
00618         [uvalue % (unsigned)base];
00619     uvalue = (uvalue / (unsigned)base );
00620   } while (uvalue && (place < 20));
00621   if (place == 20)
00622     place--;
00623   convert[place] = 0;
00624 
00625   zpadlen = max - place;
00626   spadlen = min - PADMAX(max, place) - (signvalue ? 1 : 0);
00627   if (zpadlen < 0)
00628     zpadlen = 0;
00629   if (spadlen < 0)
00630     spadlen = 0;
00631   if (flags & DP_F_ZERO) {
00632     zpadlen = PADMAX(zpadlen, spadlen);
00633     spadlen = 0;
00634   }
00635   if (flags & DP_F_MINUS)
00636     spadlen = -spadlen; /* Left Justifty */
00637 
00638   /* Spaces */
00639   while (spadlen > 0) {
00640     dopr_outch(buffer, currlen, maxlen, ' ');
00641     --spadlen;
00642   }
00643 
00644   /* Sign */
00645   if (signvalue)
00646     dopr_outch(buffer, currlen, maxlen, signvalue);
00647 
00648   /* Zeros */
00649   if (zpadlen > 0) {
00650     while (zpadlen > 0) {
00651       dopr_outch(buffer, currlen, maxlen, '0');
00652       --zpadlen;
00653     }
00654   }
00655 
00656   /* Digits */
00657   while (place > 0)
00658     dopr_outch(buffer, currlen, maxlen, convert[--place]);
00659 
00660   /* Left Justified spaces */
00661   while (spadlen < 0) {
00662     dopr_outch (buffer, currlen, maxlen, ' ');
00663     ++spadlen;
00664   }
00665 }
00666 
00667 static long double
00668 pow10(int exp)
00669 {
00670   long double result = 1;
00671 
00672   while (exp) {
00673     result *= 10;
00674     exp--;
00675   }
00676 
00677   return result;
00678 }
00679 
00680 static long
00681 round(long double value)
00682 {
00683   long intpart = value;
00684 
00685   value -= intpart;
00686   if (value >= 0.5)
00687     intpart++;
00688 
00689   return intpart;
00690 }
00691 
00692 static void
00693 fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,
00694       int min, int max, int flags)
00695 {
00696   char iconvert[20], fconvert[20];
00697   int signvalue = 0, iplace = 0, fplace = 0;
00698   int padlen = 0; /* amount to pad */
00699   int zpadlen = 0, caps = 0;
00700   long intpart, fracpart;
00701   long double ufvalue;
00702 
00703   /*
00704    * AIX manpage says the default is 0, but Solaris says the default
00705    * is 6, and sprintf on AIX defaults to 6
00706    */
00707   if (max < 0)
00708     max = 6;
00709 
00710   ufvalue = abs_val(fvalue);
00711 
00712   if (fvalue < 0)
00713     signvalue = '-';
00714   else if (flags & DP_F_PLUS)  /* Do a sign (+/i) */
00715     signvalue = '+';
00716   else if (flags & DP_F_SPACE)
00717     signvalue = ' ';
00718 
00719   intpart = ufvalue;
00720 
00721   /*
00722    * Sorry, we only support 9 digits past the decimal because of our
00723    * conversion method
00724    */
00725   if (max > 9)
00726     max = 9;
00727 
00728   /* We "cheat" by converting the fractional part to integer by
00729    * multiplying by a factor of 10
00730    */
00731   fracpart = round((pow10 (max)) * (ufvalue - intpart));
00732 
00733   if (fracpart >= pow10 (max)) {
00734     intpart++;
00735     fracpart -= pow10 (max);
00736   }
00737 
00738   /* Convert integer part */
00739   do {
00740     iconvert[iplace++] =
00741         (caps ? "0123456789ABCDEF" : "0123456789abcdef")
00742         [intpart % 10];
00743     intpart = (intpart / 10);
00744   } while(intpart && (iplace < 20));
00745   if (iplace == 20)
00746     iplace--;
00747   iconvert[iplace] = 0;
00748 
00749   /* Convert fractional part */
00750   do {
00751     fconvert[fplace++] =
00752         (caps ? "0123456789ABCDEF" : "0123456789abcdef")
00753         [fracpart % 10];
00754     fracpart = (fracpart / 10);
00755   } while(fracpart && (fplace < 20));
00756   if (fplace == 20)
00757     fplace--;
00758   fconvert[fplace] = 0;
00759 
00760   /* -1 for decimal point, another -1 if we are printing a sign */
00761   padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
00762   zpadlen = max - fplace;
00763   if (zpadlen < 0)
00764     zpadlen = 0;
00765   if (padlen < 0)
00766     padlen = 0;
00767   if (flags & DP_F_MINUS)
00768     padlen = -padlen; /* Left Justifty */
00769 
00770   if ((flags & DP_F_ZERO) && (padlen > 0)) {
00771     if (signvalue) {
00772       dopr_outch(buffer, currlen, maxlen, signvalue);
00773       --padlen;
00774       signvalue = 0;
00775     }
00776     while (padlen > 0) {
00777       dopr_outch(buffer, currlen, maxlen, '0');
00778       --padlen;
00779     }
00780   }
00781   while (padlen > 0) {
00782     dopr_outch(buffer, currlen, maxlen, ' ');
00783     --padlen;
00784   }
00785   if (signvalue)
00786     dopr_outch(buffer, currlen, maxlen, signvalue);
00787 
00788   while (iplace > 0)
00789     dopr_outch(buffer, currlen, maxlen, iconvert[--iplace]);
00790 
00791   /*
00792    * Decimal point.  This should probably use locale to find the
00793    * correct char to print out.
00794    */
00795   dopr_outch(buffer, currlen, maxlen, '.');
00796 
00797   while (fplace > 0)
00798     dopr_outch(buffer, currlen, maxlen, fconvert[--fplace]);
00799 
00800   while (zpadlen > 0) {
00801     dopr_outch(buffer, currlen, maxlen, '0');
00802     --zpadlen;
00803   }
00804 
00805   while (padlen < 0) {
00806     dopr_outch(buffer, currlen, maxlen, ' ');
00807     ++padlen;
00808   }
00809 }
00810 
00811 static void
00812 dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
00813 {
00814   if (*currlen < maxlen)
00815     buffer[(*currlen)++] = c;
00816 }
00817 #endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */
00818 
00819 #ifndef HAVE_VSNPRINTF
00820 int
00821 vsnprintf(char *str, size_t count, const char *fmt, va_list args)
00822 {
00823   str[0] = 0;
00824   dopr(str, count, fmt, args);
00825 
00826   return(strlen(str));
00827 }
00828 #endif /* !HAVE_VSNPRINTF */
00829 
00830 #ifndef HAVE_SNPRINTF
00831 int
00832 snprintf(char *str,size_t count,const char *fmt,...)
00833 {
00834   va_list ap;
00835 
00836   va_start(ap, fmt);
00837   (void) vsnprintf(str, count, fmt, ap);
00838   va_end(ap);
00839 
00840   return(strlen(str));
00841 }
00842 
00843 #endif /* !HAVE_SNPRINTF */
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines