printf.c

来自「MPI stands for the Message Passing Inter」· C语言 代码 · 共 306 行

C
306
字号
/* * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana *                         University Research and Technology *                         Corporation.  All rights reserved. * Copyright (c) 2004-2006 The University of Tennessee and The University *                         of Tennessee Research Foundation.  All rights *                         reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,  *                         University of Stuttgart.  All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. *                         All rights reserved. * $COPYRIGHT$ *  * Additional copyrights may follow *  * $HEADER$ *//* * Buffer safe printf functions for portability to archaic platforms. */#include "opal_config.h"#include "opal/util/printf.h"#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>/* * Make a good guess about how long a printf-style varargs formatted * string will be once all the % escapes are filled in.  We don't * handle every % escape here, but we handle enough, and then add a * fudge factor in at the end. */static int guess_strlen(const char *fmt, va_list ap){    char *sarg;    double darg;    float farg;    size_t i;    int iarg;    int len;    long larg;    /* Start off with a fudge factor of 128 to handle the % escapes that       we aren't calculating here */    len = (int)strlen(fmt) + 128;    for (i = 0; i < strlen(fmt); ++i) {        if ('%' == fmt[i] && i + 1 < strlen(fmt)            && '%' != fmt[i + 1]) {            ++i;            switch (fmt[i]) {            case 's':                sarg = va_arg(ap, char *);                /* If there's an arg, get the strlen, otherwise we'll                 * use (null) */                if (NULL != sarg)                    len += (int)strlen(sarg);                else                    len += 5;                break;            case 'd':            case 'i':                iarg = va_arg(ap, int);                /* Alloc for minus sign */                if (iarg < 0)                    ++len;                /* Now get the log10 */                do {                    ++len;                    iarg /= 10;                } while (0 != iarg);                break;            case 'x':            case 'X':                iarg = va_arg(ap, int);                /* Now get the log16 */                do {                    ++len;                    iarg /= 16;                } while (0 != iarg);                break;            case 'f':                farg = (float)va_arg(ap, int);                /* Alloc for minus sign */                if (farg < 0) {                    ++len;                    farg = -farg;                }                /* Alloc for 3 decimal places + '.' */                len += 4;                /* Now get the log10 */                do {                    ++len;                    farg /= 10.0;                } while (0 != farg);                break;            case 'g':                darg = va_arg(ap, int);                /* Alloc for minus sign */                if (darg < 0) {                    ++len;                    darg = -darg;                }                /* Alloc for 3 decimal places + '.' */                len += 4;                /* Now get the log10 */                do {                    ++len;                    darg /= 10.0;                } while (0 != darg);                break;            case 'l':                /* Get %ld %lx %lX %lf */                if (i + 1 < strlen(fmt)) {                    ++i;                    switch (fmt[i]) {                    case 'x':                    case 'X':                        larg = va_arg(ap, int);                        /* Now get the log16 */                        do {                            ++len;                            larg /= 16;                        } while (0 != larg);                        break;                    case 'f':                        darg = va_arg(ap, int);                        /* Alloc for minus sign */                        if (darg < 0) {                            ++len;                            darg = -darg;                        }                        /* Alloc for 3 decimal places + '.' */                        len += 4;                        /* Now get the log10 */                        do {                            ++len;                            darg /= 10.0;                        } while (0 != darg);                        break;                    case 'd':                    default:                        larg = va_arg(ap, int);                        /* Now get the log10 */                        do {                            ++len;                            larg /= 10;                        } while (0 != larg);                        break;                    }                }            default:                break;            }        }    }    return len;}int opal_asprintf(char **ptr, const char *fmt, ...){    int length;    va_list ap;    va_start(ap, fmt);    length = opal_vasprintf(ptr, fmt, ap);    va_end(ap);    return length;}int opal_vasprintf(char **ptr, const char *fmt, va_list ap){    int length;    va_list ap2;    /* va_list might have pointer to internal state and using       it twice is a bad idea.  So make a copy for the second       use.  Copy order taken from Autoconf docs. */#if OMPI_HAVE_VA_COPY  va_copy(ap2, ap);#elif OMPI_HAVE_UNDERSCORE_VA_COPY  __va_copy(ap2, ap);#else  memcpy (&ap2, &ap, sizeof(va_list));#endif    /* guess the size */    length = guess_strlen(fmt, ap);    /* allocate a buffer */    *ptr = (char *) malloc((size_t) length + 1);    if (NULL == *ptr) {        errno = ENOMEM;        return -1;    }    /* fill the buffer */    length = vsprintf(*ptr, fmt, ap2);    va_end(ap2);    /* realloc */    *ptr = (char*) realloc(*ptr, (size_t) length + 1);    if (NULL == *ptr) {        errno = ENOMEM;        return -1;    }    return length;}int opal_snprintf(char *str, size_t size, const char *fmt, ...){    int length;    va_list ap;    va_start(ap, fmt);    length = opal_vsnprintf(str, size, fmt, ap);    va_end(ap);    return length;}int opal_vsnprintf(char *str, size_t size, const char *fmt, va_list ap){    int length;    char *buf;    length = opal_vasprintf(&buf, fmt, ap);    if (length < 0) {        return length;    }    /* return the length when given a null buffer (C99) */    if (str) {        if ((size_t) length < size) {            strcpy(str, buf);        } else {            memcpy(str, buf, size - 1);            str[size] = '\0';        }    }    return length;}#ifdef TESTint main(int argc, char *argv[]){    char a[10];    char b[173];    char *s;    int length;    puts("test for NULL buffer in snprintf:");    length = opal_snprintf(NULL, 0, "this is a string %d", 1004);    printf("length = %d\n", length);    puts("test of snprintf to an undersize buffer:");    length = opal_snprintf(a, sizeof(a), "this is a string %d", 1004);    printf("string = %s\n", a);    printf("length = %d\n", length);    printf("strlen = %d\n", (int) strlen(a));    puts("test of snprintf to an oversize buffer:");    length = opal_snprintf(b, sizeof(b), "this is a string %d", 1004);    printf("string = %s\n", b);    printf("length = %d\n", length);    printf("strlen = %d\n", (int) strlen(b));    puts("test of asprintf:");    length = opal_asprintf(&s, "this is a string %d", 1004);    printf("string = %s\n", s);    printf("length = %d\n", length);    printf("strlen = %d\n", (int) strlen(s));    free(s);    return 0;}#endif

⌨️ 快捷键说明

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