⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 snprintf.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions *//************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh.  This sort of thing is always nasty do deal with.  Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length.  This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 *  This was ugly.  It is still ugly.  I opted out of floating point *  numbers, but the formatter understands just about everything *  from the normal C string format, at least as far as I can tell from *  the Solaris 2.5 printf(3S) man page. * *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 *    Ok, added some minimal floating point support, which means this *    probably requires libm on most operating systems.  Don't yet *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint() *    was pretty badly broken, it just wasn't being exercised in ways *    which showed it, so that's been fixed.  Also, formated the code *    to mutt conventions, and removed dead code left over from the *    original.  Also, there is now a builtin-test, just compile with: *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm *    and run snprintf for results. * *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i *    The PGP code was using unsigned hexadecimal formats. *    Unfortunately, unsigned formats simply didn't work. * *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 *    The original code assumed that both snprintf() and vsnprintf() were *    missing.  Some systems only have snprintf() but not vsnprintf(), so *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * *  Andrew Tridgell (tridge@samba.org) Oct 1998 *    fixed handling of %.0f *    added test for HAVE_LONG_DOUBLE * * tridge@samba.org, idra@samba.org, April 2001 *    got rid of fcvt code (twas buggy and made testing harder) *    added C99 semantics * * markus@oberhumer.com, August 2002 *    large modifications for use in UPX * **************************************************************/#if 1#include "conf.h"#else#include <ctype.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#undef NDEBUG#include <assert.h>#endif#undef LLONG#undef ULLONG#if 1 && defined(acc_int64l_t)#  define LLONG     acc_int64l_t#  define ULLONG    acc_uint64l_t#else#  define LLONG     long int#  define ULLONG    unsigned long int#endif#undef NO_FLOAT#undef LDOUBLE#if 1#  define NO_FLOAT 1#  if (ACC_CC_SUNPROC)#  else#  define float     error no_float#  define double    error no_float#  endif#elif 0 || defined(HAVE_LONG_DOUBLE)#  define LDOUBLE   long double#else#  define LDOUBLE   double#endif/* * dopr(): poor man's version of doprintf *//* format read states */#define DP_S_DEFAULT 0#define DP_S_FLAGS   1#define DP_S_MIN     2#define DP_S_DOT     3#define DP_S_MAX     4#define DP_S_MOD     5#define DP_S_CONV    6#define DP_S_DONE    7/* format flags - Bits */#define DP_F_MINUS  (1 << 0)#define DP_F_PLUS   (1 << 1)#define DP_F_SPACE  (1 << 2)#define DP_F_NUM    (1 << 3)#define DP_F_ZERO   (1 << 4)#define DP_F_UP     (1 << 5)#define DP_F_UNSIGNED   (1 << 6)/* Conversion Flags */#define DP_C_SHORT   1#define DP_C_LONG    2#define DP_C_LDOUBLE 3#define DP_C_LLONG   4#define char_to_int(p) ((p)- '0')#undef MAX#define MAX(p,q) (((p) >= (q)) ? (p) : (q))/************************************************************************* //**************************************************************************/static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, int c){    if (*currlen < maxlen)        buffer[*currlen] = (char) c;    *currlen += 1;}static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,                   const char *value, int flags, int min, int max){    int padlen, strln;     /* amount to pad */    int cnt = 0;#ifdef DEBUG_SNPRINTF    printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);#endif    if (value == NULL)        value = "<NULL>";    for (strln = 0; value[strln]; )     /* strlen */        ++strln;    padlen = min - strln;    if (padlen < 0)        padlen = 0;    if (flags & DP_F_MINUS)        padlen = -padlen; /* Left Justify */    while ((padlen > 0) && (cnt < max)) {        dopr_outch (buffer, currlen, maxlen, ' ');        --padlen;        ++cnt;    }    while (*value && (cnt < max)) {        dopr_outch (buffer, currlen, maxlen, *value++);        ++cnt;    }    while ((padlen < 0) && (cnt < max)) {        dopr_outch (buffer, currlen, maxlen, ' ');        ++padlen;        ++cnt;    }}/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */static void fmtint(char *buffer, size_t *currlen, size_t maxlen,                   LLONG value, unsigned base, int min, int max, int flags){    int signvalue = 0;    ULLONG uvalue;    char convert[64+1];    int place = 0;    int spadlen = 0; /* amount to space pad */    int zpadlen = 0; /* amount to zero pad */    const char *digits;    if (min < 0)        min = 0;    if (max < 0)        max = 0;    uvalue = value;    if (!(flags & DP_F_UNSIGNED)) {        if( value < 0 ) {            signvalue = '-';            uvalue = -value;        } else {            if (flags & DP_F_PLUS)  /* Do a sign (+/i) */                signvalue = '+';            else if (flags & DP_F_SPACE)                signvalue = ' ';        }    }    digits = (flags & DP_F_UP) ? "0123456789ABCDEF" : "0123456789abcdef";    do {        convert[place] = digits[(unsigned) (uvalue % base)];        uvalue /= base;    } while (++place < (int)sizeof(convert) - 1 && uvalue);    convert[place] = 0;    zpadlen = max - place;    spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);    if (zpadlen < 0) zpadlen = 0;    if (spadlen < 0) spadlen = 0;    if (flags & DP_F_ZERO) {        zpadlen = MAX(zpadlen, spadlen);        spadlen = 0;    }    if (flags & DP_F_MINUS)        spadlen = -spadlen; /* Left Justifty */#ifdef DEBUG_SNPRINTF    printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",           zpadlen, spadlen, min, max, place);#endif    /* Spaces */    while (spadlen > 0) {        dopr_outch (buffer, currlen, maxlen, ' ');        --spadlen;    }    /* Sign */    if (signvalue)        dopr_outch (buffer, currlen, maxlen, signvalue);    /* Zeros */    while (zpadlen > 0) {        dopr_outch (buffer, currlen, maxlen, '0');        --zpadlen;    }    /* Digits */    while (place > 0)        dopr_outch (buffer, currlen, maxlen, convert[--place]);    /* Left Justified spaces */    while (spadlen < 0) {        dopr_outch (buffer, currlen, maxlen, ' ');        ++spadlen;    }}/*************************************************************************// floating format support**************************************************************************/#if !defined(NO_FLOAT)static LDOUBLE abs_val(LDOUBLE value){    LDOUBLE result = value;    if (value < 0)        result = -value;    return result;}static LDOUBLE POW10(int exp){    LDOUBLE result = 1;    while (exp) {        result *= 10;        exp--;    }    return result;}static LLONG ROUND(LDOUBLE value){    LLONG intpart;    intpart = (LLONG)value;    value = value - intpart;    if (value >= 0.5) intpart++;    return intpart;}/* a replacement for modf that doesn't need the math library. Should   be portable, but slow */static double my_modf(double x0, double *iptr){    int i;    long l;    double x = x0;    double f = 1.0;    for (i = 0; i < 100; i++) {        l = (long)x;        if (l <= (x+1) && l >= (x-1)) break;        x *= 0.1;        f *= 10.0;    }    if (i == 100) {        /* yikes! the number is beyond what we can handle. What do we do? */        *iptr = 0.0;        return 0;    }    if (i != 0) {        double i2, ret;        ret = my_modf(x0-l*f, &i2);        *iptr = l*f + i2;        return ret;    }    *iptr = l;    return x - *iptr;}static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,                   LDOUBLE fvalue, int min, int max, int flags){    /* avoid warnings with 'gcc -Wshadow' */#undef index#define index iindex    int signvalue = 0;    double ufvalue;    char iconvert[311+1];    char fconvert[311+1];    int iplace = 0;    int fplace = 0;    int padlen = 0; /* amount to pad */    int zpadlen = 0;    const char *digits;    int index;    double intpart;    double fracpart;    double temp;    /*     * AIX manpage says the default is 0, but Solaris says the default     * is 6, and sprintf on AIX defaults to 6     */    if (min < 0)        min = 0;    if (max < 0)        max = 6;    ufvalue = abs_val (fvalue);    if (fvalue < 0) {        signvalue = '-';    } else {        if (flags & DP_F_PLUS) { /* Do a sign (+/i) */            signvalue = '+';        } else {            if (flags & DP_F_SPACE)                signvalue = ' ';        }    }    digits = "0123456789ABCDEF";#if 0    digits = (flags & DP_F_UP) ? "0123456789ABCDEF" : "0123456789abcdef";#endif#if 0     if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */#endif    /*     * Sorry, we only support 16 digits past the decimal because of our     * conversion method     */    if (max > 16)        max = 16;    /* We "cheat" by converting the fractional part to integer by     * multiplying by a factor of 10     */    temp = ufvalue;    my_modf(temp, &intpart);    fracpart = ROUND((POW10(max)) * (ufvalue - intpart));    if (fracpart >= POW10(max)) {        intpart++;        fracpart -= POW10(max);    }    /* Convert integer part */    do {        temp = intpart;        my_modf(intpart*0.1, &intpart);        temp = temp*0.1;        index = (int) ((temp - intpart + 0.05) * 10.0);        /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */        /* printf ("%llf, %f, %x\n", temp, intpart, index); */        iconvert[iplace] = digits[index];    } while (++iplace < (int)sizeof(iconvert) - 1 && intpart);    iconvert[iplace] = 0;    /* Convert fractional part */    if (fracpart)    {        do {            temp = fracpart;            my_modf(fracpart*0.1, &fracpart);            temp = temp*0.1;            index = (int) ((temp - fracpart + 0.05) * 10.0);            /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */            /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */            fconvert[fplace] = digits[index];        } while (++fplace < (int)sizeof(fconvert) - 1 && fracpart);    }    fconvert[fplace] = 0;    /* -1 for decimal point, another -1 if we are printing a sign */    padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);    zpadlen = max - fplace;    if (zpadlen < 0) zpadlen = 0;    if (padlen < 0)        padlen = 0;    if (flags & DP_F_MINUS)        padlen = -padlen; /* Left Justifty */    if ((flags & DP_F_ZERO) && (padlen > 0)) {        if (signvalue) {            dopr_outch (buffer, currlen, maxlen, signvalue);            --padlen;            signvalue = 0;        }        while (padlen > 0) {            dopr_outch (buffer, currlen, maxlen, '0');            --padlen;        }    }    while (padlen > 0) {        dopr_outch (buffer, currlen, maxlen, ' ');        --padlen;    }    if (signvalue)        dopr_outch (buffer, currlen, maxlen, signvalue);    while (iplace > 0)        dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);#ifdef DEBUG_SNPRINTF    printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);#endif    /*     * Decimal point.  This should probably use locale to find the correct     * char to print out.     */    if (max > 0) {        dopr_outch (buffer, currlen, maxlen, '.');        while (fplace > 0)            dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);    }    while (zpadlen > 0) {        dopr_outch (buffer, currlen, maxlen, '0');        --zpadlen;    }    while (padlen < 0) {        dopr_outch (buffer, currlen, maxlen, ' ');        ++padlen;    }#undef index}#endif /* !defined(NO_FLOAT) *//*************************************************************************// dopr()**************************************************************************/static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -