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

📄 psnprintf.c

📁 COS 0.0.1.rar Cos操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This is part of psnprintf-0.4, see the file "license-psnprintf-0.4".  Originally by Alex Holkner.  Changed 16/10/04 for cos by Paul Barker:	Stripped out all floating point stuff.	Changed headers to fit with cos. 06/11/04:	Added initialisation for several vars to get rid of warnings.*/#include <cosbase.h>#include <cos/mem.h> /* for memset */#include <cos/string.h> /* for strlen */#include <psnprintf.h>int psnprintf(char *str, size_t n, const char *format, ...){    va_list args;    int ret;        va_start(args, format);    ret = pvsnprintf(str, n, format, args);    va_end(args);    return ret;}#define STATE_NONE 0#define STATE_OPERATOR 1 /* Just received % */#define STATE_FLAG 2     /* Just received a flag or prefix or width */#define STATE_WIDTH 3#define STATE_BEFORE_PRECISION 4 /* just got dot */#define STATE_PRECISION 5 /* got at least one number after dot */#define STATE_PREFIX 6   /* just received prefix (h, l or L) */#define UNKNOWN_WIDTH 0#define VARIABLE_WIDTH -2#define UNKNOWN_PRECISION -1#define VARIABLE_PRECISION -2/* Following macros give reusable switch cases, used in combination * depending on current state. Sucks to do these as macros, but should  * give the compiler lots of freedom to optimize. */#define CHECK_FLAG \    case '-':  \        flags |= FLAG_LEFT_ALIGN; \        state = STATE_FLAG; \        break; \    case '+': \        flags |= FLAG_SIGNED; \        state = STATE_FLAG; \        break; \    case '0': \        flags |= FLAG_ZERO_PAD; \        state = STATE_FLAG; \        break; \    case ' ': \        flags |= FLAG_SIGN_PAD; \        state = STATE_FLAG; \        break; \    case '#': \        flags |= FLAG_HASH; \        state = STATE_FLAG; \        break;        #define CHECK_WIDTH \    case '1': \    case '2': \    case '3': \    case '4': \    case '5': \    case '6': \    case '7': \    case '8': \    case '9': \        width = *pfmt - '0'; /* convert to integer */ \        state = STATE_WIDTH; \        break; \    case '*': \        width = VARIABLE_WIDTH; \        state = STATE_WIDTH; \        break;#define CHECK_PRECISION \    case '.': \        precision = 0; \        state = STATE_BEFORE_PRECISION; \        break; #define CHECK_PREFIX \    case 'h': \    case 'l': \    case 'L': \        prefix = *pfmt; \        state = STATE_PREFIX; \        break;#define GET_VARS \    if (width == VARIABLE_WIDTH) \        width = va_arg(ap, int); \    if (precision == VARIABLE_PRECISION) \        precision = va_arg(ap, int);#define CHECK_TYPE \    case 'd': \    case 'i': \    case 'u': \    case 'o': \    case 'x': \    case 'X': \    case 'p': \        GET_VARS \        ncount += pvsnfmt_int(&pinsertion, &nmax, *pfmt, flags, width, precision, prefix, &ap); \        state = STATE_NONE; \        break; \    case 'c': \        GET_VARS \        ncount += pvsnfmt_char(&pinsertion, &nmax, *pfmt, flags, width, precision, prefix, &ap); \        state = STATE_NONE; \        break; \    case 's': \        GET_VARS \        ncount += pvsnfmt_str(&pinsertion, &nmax, *pfmt, flags, width, precision, prefix, &ap); \        state = STATE_NONE; \        break; \    case 'n': \        *(va_arg(ap, int *)) = ncount; \        state = STATE_NONE; \        break;#define PUTCHAR(ch) \    if (nmax > 1) \    { \        *pinsertion++ = ch;  \        nmax--; \    } \    ncount++;        int pvsnprintf(char *str, size_t nmax, const char *format, va_list ap){    /* nmax gives total size of buffer including null     * null is ALWAYS added, even if buffer too small for format      * (contrary to C99)     */         char *pinsertion = str;    const char *pfmt = format;    int ncount = 0;     /* number of characters printed so far */    int state = STATE_NONE;    char flags = 0;    int width = 0;    int precision = 0;    char prefix = 0;        while (*pfmt)    {        switch (state)        {        case STATE_NONE:            switch (*pfmt)            {            case '%':                state = STATE_OPERATOR;                flags = FLAG_DEFAULT;                width = UNKNOWN_WIDTH;                precision = UNKNOWN_PRECISION;                prefix = '\0';                break;                            default:                PUTCHAR(*pfmt)            }            break;                    case STATE_OPERATOR:            switch (*pfmt)            {                CHECK_FLAG                CHECK_WIDTH                CHECK_PRECISION                CHECK_PREFIX                CHECK_TYPE            default:                PUTCHAR(*pfmt) /* Unknown format, just print it (e.g. "%%") */                state = STATE_NONE;            }            break;        case STATE_FLAG:            switch (*pfmt)            {                CHECK_FLAG                CHECK_WIDTH                CHECK_PRECISION                CHECK_PREFIX                CHECK_TYPE            }            break;                case STATE_WIDTH:            if (*pfmt >= '0' && *pfmt <= '9' && width != -1)            {                width = width * 10 + (*pfmt - '0');                break;            }            switch (*pfmt)            {                CHECK_PRECISION                CHECK_PREFIX                CHECK_TYPE            }            break;                    case STATE_BEFORE_PRECISION:            if (*pfmt >= '0' && *pfmt <= '9')            {                precision = *pfmt - '0';                state = STATE_PRECISION;            }            else if (*pfmt == '*')            {                precision = VARIABLE_PRECISION;                state = STATE_PRECISION;            }            switch (*pfmt)            {                CHECK_PREFIX                CHECK_TYPE            }            break;                    case STATE_PRECISION:            if (*pfmt >= '0' && *pfmt <= '9' && precision != -1)            {                precision = precision * 10 + (*pfmt - '0');                break;            }            switch (*pfmt)            {                CHECK_PREFIX                CHECK_TYPE            }            break;                    case STATE_PREFIX:            switch (*pfmt)            {                CHECK_TYPE            }                                } /* switch state */        pfmt++;            } /* while *pfmt */        /* Add null if there is room     * NOTE there is always room even if str doesn't fit unless     * nmax initially passed in as 0.  fmt functions take care to     * always leave at least one free byte at end.     */    if (nmax > 0)        *pinsertion = '\0';        return ncount;}int pvsnfmt_char(char **pinsertion, size_t *nmax, const char fmt, int flags,                  int width, int precision, char prefix, va_list *ap){    if (*nmax > 1)    {        *(*pinsertion)++ = (char) va_arg(*ap, int);        (*nmax)--;    }    return 1;}/* strnlen not available on all platforms.. maybe autoconf it? */size_t pstrnlen(const char *s, size_t count){    const char *p = s;    while (*p && count-- > 0)        p++;        return p - s;}    /* Format a string into the buffer.  Parameters: *   **pinsertion   Pointer to pointer to buffer (can be reference to NULL) *   *nmax          Pointer to size of buffer.  This is may be modified *   fmt            Format character ('s') *   flags          0 or combination of flags (see .h file for #defines) *   width          Width of string, as defined in printf *   precision      Precision of string, as defined in printf *   ap             Argument list */    int pvsnfmt_str(char **pinsertion, size_t *nmax, const char fmt, int flags,                 int width, int precision, char prefix, va_list *ap){    const char *str = va_arg(*ap, const char *);    int nprinted;    int len;    int pad = 0;        /* Get width magnitude, set aligment flag */    if (width < 0)    {        width = -width;        flags |= FLAG_LEFT_ALIGN;    }        /* Truncate due to precision */    if (precision < 0)        len = strlen(str);    else        len = pstrnlen(str, precision);            /* Determine padding length */    if (width > len)        pad = width - len;        /* Exit if just counting (not printing) */    if (*nmax <= 1)        return len + pad;        /* If right-aligned, print pad */    if ( !(flags & FLAG_LEFT_ALIGN) )    {        char padchar;        if (flags & FLAG_ZERO_PAD)            padchar = '0';        else            padchar = ' ';                if (*nmax - 1 < pad)            nprinted = *nmax - 1;        else

⌨️ 快捷键说明

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