mprintf.c
来自「完整的Bell实验室的嵌入式文件系统TFS」· C语言 代码 · 共 429 行
C
429 行
/* mprintf.c: * A small, but useful printf. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "cpuio.h"#include "genlib.h"#include "stddefs.h"#include "ctype.h"/* printf.c... * This is my homegrown printf. It is VERY limited, but useful * for small applications that should avoid wasting memory. * The %s, %c, %d, %x formats are supported to some degree. * I also added %I and %M... * %I assumes that the argument is a long and it converts it to * a string in IP format (a.b.c.d). * %M assumes that the argument is a pointer to an array of 6 bytes * and it converts it to a string in MAC format (x:y:z:a:b:c). * * So why don't I use varargs?... * Yep, it sure would look nicer, and would eliminate the clumsy limit * of 12 arguments, but so far I haven't had a problem with any of the * CPUs I've ported to and it eliminates the headache of dealing * with varargs vs stdargs depending on the compiler. * */#define MAXARGS 12#define HDRSIZE 4#define PSIZE 128#define NEGATIVE 1#define POSITIVE 2#define SCREENWIDTH 80intlong_to_dec(long lval,char *buf,char *hdr){ short size, i, minsize; long value; char *base, fill; base = buf; minsize = 0; /* hdr would be '8' in the format %8d, for example */ if (hdr[0]) { if (hdr[0] == '0') fill = '0'; else fill = ' '; minsize = (short)atoi(hdr); for(i=0;i<minsize;i++) *buf++ = fill; } buf = base; /* First determine how many ascii digits are needed. */ value = abs(lval); size = 0; while (value > 0) { size++; value /= 10; } if (lval < 0) size++; if (minsize > size) size = minsize; buf += size; /* Now build the string. */ value = abs(lval); if (value == 0) { if (minsize==0) { *base = '0'; size = 1; } else *--buf = '0'; } else { while (value > 0) { *--buf = (char)(value % 10) + '0'; value /= 10; } } if (lval < 0) *--buf = '-'; base[size] = 0; return((int)size);}intlong_to_ip(long lval,char *buf,char *hdr){ int i, j, len; unsigned char *lp; len = 0; lp = (char *)&lval; for(j=0;j<4;j++) { i = long_to_dec(*lp++,buf,hdr); buf += i; *buf++ = '.'; len += (i + 1); } buf--; len--; return(len);}intlong_to_hex(long lval,char *buf,char *hdr){ static char *hexdigits = "0123456789abcdef"; ulong value; short size, i, minsize; char *base; base = buf; /* hdr would be '02' in the format %02x, for example */ minsize = 0; if (hdr[0]) { if (hdr[1]) { minsize = (short)(hdr[1]&0xf); for(i=0;i<minsize;i++) *buf++ = hdr[0]; } else { minsize = (short)(hdr[0]&0xf); for(i=0;i<minsize;i++) *buf++ = ' '; } } buf = base; /* First determine how many ascii digits are needed. */ value = lval; size = 0; while (value > 0) { size++; value /= 16; } if (minsize > size) size = minsize; buf += size; /* Now build the string. */ value = lval; while (value > 0) { *--buf = hexdigits[(int)(value % 16)]; value /= 16; } if ((!lval) && (!size)) buf[size++] = '0'; buf[size] = 0; return((int)size);}intbin_to_mac(uchar *ibin,char *buf,char *hdr){ int i, j, len; len = 0; for(j=0;j<6;j++) { i = long_to_hex(*ibin++,buf,hdr); buf += i; *buf++ = ':'; len += (i + 1); } buf--; len--; return(len);}/* build_string(): * Build a string from 'src' to 'dest' based on the hdr and sign * values. Return the size of the string (may include left or right * justified padding). */intbuild_string(char *src,char *dest,char *hdr,int sign){ char *cp1; short minsize, i, j; if (!src) { strcpy(dest,"NULL_POINTER"); return(12); } if (!*src) return(0); if (!hdr[0]) { j = 0; while(*src) { *dest++ = *src++; j++; } return(j); } minsize = atoi(hdr); i = 0; cp1 = (char *)src; while(*cp1) { i++; cp1++; } cp1 = (char *)src; j = 0; if (minsize > i) { if (sign == POSITIVE) { while(minsize > i) { j++; *dest++ = ' '; minsize--; } while(*cp1) { j++; *dest++ = *cp1++; } } else { while(*cp1) { j++; *dest++ = *cp1++; } while(minsize > i) { j++; *dest++ = ' '; minsize--; } } } else { while(*cp1) { j++; *dest++ = *cp1++; } } return(j);}/* snprintf(): * Backend to all the others below it. * Formats incoming argument list based on format string. * Terminates population of buffer if it is to exceed the * specified buffer size. * NOTE: the buffer size check is not complete... It's barely started! */intsnprintf(char *buf,int bsize,char *fmt, long arg1,long arg2,long arg3,long arg4, long arg5, long arg6, long arg7,long arg8,long arg9,long arg10,long arg11,long arg12){ int i, sign; char *cp, hdr[HDRSIZE], *base; long args[MAXARGS], nextarg; bsize--; /* Decrement by one to save space for NULL */ args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; base = buf; cp = fmt; nextarg = 0; for(i=0;i<HDRSIZE;i++) hdr[i] = 0; while(*cp) { if (nextarg >= MAXARGS) { puts("sprintf arg overflow\n"); return(0); } if (*cp != '%') { *buf++ = *cp++; continue; } cp++; if (*cp == '%') { *buf++ = *cp++; continue; } sign = POSITIVE; if (*cp == '-') { sign = NEGATIVE; cp++; } if (isdigit(*cp)) { for(i=0;i<(HDRSIZE-1);i++) { if (isdigit(*cp)) hdr[i] = *cp++; else break; } } if (*cp == 'l') /* Ignore the 'long' designator */ cp++; switch(*cp) { case 'c': /* Character conversion */ *buf++ = (char)args[nextarg++]; break; case 's': /* String conversion */ i = build_string((char *)args[nextarg++],buf,hdr,sign); buf += i; break; case 'M': /* MAC address conversion */ i = bin_to_mac((char *)args[nextarg++],buf,hdr); buf += i; break; case 'I': /* IP address conversion */ i = long_to_ip(args[nextarg++],buf,hdr); buf += i; break; case 'd': /* Decimal conversion */ i = long_to_dec(args[nextarg++],buf,hdr); buf += i; break; case 'x': /* Hex conversion */ case 'X': i = long_to_hex(args[nextarg++],buf,hdr); buf += i; break; default: *buf++ = *cp; break; } cp++; if (hdr[0]) { for(i=0;i<HDRSIZE;i++) hdr[i] = 0; } } *buf = 0; return(buf-base);}/* sprintf(): * puts formatted string into buffer. * Yep, if you use more than 12 args this breaks... * So use something else! */intsprintf(char *buf, char *fmt, long arg1,long arg2,long arg3, long arg4, long arg5, long arg6, long arg7,long arg8,long arg9, long arg10, long arg11, long arg12){ int tot; tot = snprintf(buf,999999,fmt, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); return(tot);}/* printf(): * Yep, it breaks if there are more than PSIZE characters in the string * built by sprintf. */intprintf(char *fmt, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7,long arg8,long arg9, long arg10, long arg11, long arg12){ int i, tot; char pbuf[PSIZE]; tot = snprintf(pbuf,PSIZE,fmt, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); for(i=0;i<tot;i++) putchar(pbuf[i]); return(tot);}/* cprintf(): * Same as printf, but center text based on SCREENWIDTH by * inserting whitespace. */intcprintf(char *fmt, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6, long arg7,long arg8,long arg9, long arg10, long arg11, long arg12){ int i, tot, spaces; char pbuf[PSIZE]; tot = snprintf(pbuf,PSIZE,fmt, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12); if (tot < SCREENWIDTH) { spaces = (SCREENWIDTH-tot)/2; for(i=0;i<spaces;i++) putchar(' '); } else spaces = 0; for(i=0;i<tot;i++) putchar(pbuf[i]); return(tot+spaces);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?