📄 ttyio.c
字号:
varp = (void *)&w0; break; case 'l': varp = (void *)&lng; break; default: varp = NULL; break; } fieldlen = fplen(sp, varp);#else fieldlen = fplen(sp, vp); /* figger display size of this var */#endif /* PRINTF_STDARG */ if (*cp == '.') /* do we have a max field size? */ { cp++; /* point to number past '.' */ maxfieldlen = setnum(&cp); } else { maxfieldlen = LINESIZE; } if (maxfieldlen < (int)fieldlen) { fieldlen = maxfieldlen; } if (minfieldlen > fieldlen) { postfill = minfieldlen - fieldlen; } else { postfill = 0; } if ((postfill + fieldlen) > LINESIZE) { postfill = 0; /* sanity check*/ } } if (swap) /* caller wanted right adjustment, swap prefill/postfill */ { swap = (int)prefill; prefill = postfill; postfill = (unsigned)swap; } while (prefill--) { doputchar(fillchar); /* do any pre-field padding */ }#endif /* FIELDWIDTH */#ifdef PRINTF_STDARG switch (*sp) { case 'p': /* '%p' - pointer */#ifdef SEG16_16 /* do seg:offset variety */ hexword(outctxp, w1); /* display segment word */ doputchar(':'); hexword(outctxp, w0); /* display offset word */#else /* 32 bit flat */ hexword(outctxp, (unsigned)(lng >> 16)); hexword(outctxp, (unsigned)(lng & 0x0000FFFF));#endif /* SEG16_16 */ /* else fall to 32 bit code */ break; case 'x': /* '%x' - this always does 0 prefill */ if (tmp > 255) hexword(outctxp, tmp); else hexbyte(outctxp, tmp); break; case 'd': /* '%d' */ declong(outctxp, (long) i0); break; case 'u': /* '%u' */ declong(outctxp, (unsigned long) w0); break; case 'c': /* '%c' */ doputchar(c); break; case 's': /* '%s' */ i = 0; while (cap && (*cap) && (i++ < maxfieldlen)) doputchar(*cap++); break; case 'l': sp++; if (*sp == 'x') /* '%lx' */ { hexword(outctxp, (unsigned)(lng >> 16)); hexword(outctxp, (unsigned)(lng & 0x0000FFFF)); } else if(*sp == 'd' || *sp == 'u') /* '%ld' or '%lu' */ { declong(outctxp, lng); /* we treat %lu as %ld. */ } /* else '%l?', ignore it */ break; default: /* %?, ignore it */ break; } /* end switch *sp */#else /* PRINTF_STDARG */ switch (*sp) { case 'p': /* '%p' - pointer */#ifdef SEG16_16 /* do seg:offset variety */ /* display segment word */ hexword(outctxp, (unsigned)*(vp+1)); doputchar(':'); /* display offset word */ hexword(outctxp, (unsigned)*vp); vp += 2; /* bump var pointer past two words */#else /* 32 bit flat */ lng = *vp; hexword(outctxp, (unsigned)(lng >> 16)); hexword(outctxp, (unsigned)(lng & 0x0000FFFF)); vp += 4/sizeof(*vp); /* 2 or 1 */ #endif /* SEG16_16 */ /* else fall to 32 bit code */ break; case 'x': /* '%x' - this always does 0 prefill */ tmp = *(unsigned *)vp++; if (tmp > 255) hexword(outctxp, tmp); else hexbyte(outctxp, tmp); break; case 'd': /* '%d' */ declong(outctxp, (long)*vp++); break; case 'u': /* '%u' */ declong(outctxp, (unsigned long)*(unsigned *)vp); vp++; break; case 'c': /* '%c' */ doputchar((unsigned char)(*vp++)); break; case 's': /* '%s' */ cp = *(char **)vp; vp += sizeof(char*)/sizeof(int); i = 0; while (*cp && i++ < maxfieldlen) doputchar(*cp++); break; case 'l': sp++; if (*sp == 'x') /* '%lx' */ { /* lng = *vp; */ lng = *((unsigned long *) vp); hexword(outctxp, (unsigned)(lng >> 16)); hexword(outctxp, (unsigned)(lng & 0x0000FFFF)); vp += 4/sizeof(*vp); /* 2 or 1 */ } else if(*sp == 'd' || *sp == 'u') /* '%ld' or '%lu' */ { /* we treat %lu as %ld. */ declong(outctxp, *(long *)vp); vp += 2; } /* else '%l?', ignore it */ break; default: /* %?, ignore it */ break; } /* end switch *sp */#endif /* PRINTF_STDARG */#ifdef FIELDWIDTH while (postfill--) { doputchar(fillchar); /* do any post-field padding */ }#endif /* FIELDWIDTH */ sp++; /* point past '%?' */ } /* end while *sp */ if (outctxp->target) *(outctxp->target) = '\0'; /* Null terminate the string */ return (int)(outctxp->outlen);}/* FUNCTION: hexword() * * hexword(x) - print 16 bit value as hexadecimal * * PARAM1: char ** targ * PARAM2: unsigned x * * RETURNS: */static voidhexword(struct output_ctx * outctxp, unsigned x){ doputchar(digits[x >> 12]); doputchar(digits[(x >> 8) & 0x0f]); doputchar(digits[(x >> 4) & 0x0f]); doputchar(digits[x & 0x0f]);}/* FUNCTION: hexbyte() * * PARAM1: char ** targ * PARAM2: unsigned x * * RETURNS: */static voidhexbyte(struct output_ctx * outctxp, unsigned x){ doputchar(digits[(x >> 4) & 0x0f]); doputchar(digits[x & 0x0f]);} /* FUNCTION: declong() * * declong(char*, long) - print a long to target as a decimal number. * Assumes signed, prepends '-' if negative. * * * PARAM1: char ** targ * PARAM2: long lg * * RETURNS: *//* This should be local to declong, but Microsoft C 5.1 * breaks if it is. They use implicit lib calls to do long integer * math, and the calls pass pointers to the longs, which assumes the * longs are in local data space. */long tens;static voiddeclong(struct output_ctx * outctxp, long lg){ int digit; if (lg == 0) { doputchar('0'); return; } else if(lg < 0L) { doputchar('-'); lg = -lg; } /* make "tens" the highest power of 10 smaller than lg */ tens = 1; while ((lg/10) >= tens) tens *= 10; while (tens) { digit = (int)(lg/tens); /* get highest digit in lg */ doputchar(digits[digit]); lg -= ((long)digit * tens); tens /= 10; }}#ifdef FIELDWIDTH/* FUNCTION: setnum() * * returns the value of fieldwidth digits from a * printf format string. fptr should be a pointer to a pointer to one * or more fieldwidth digits. On return, is advanced past the digits * and the value of the digits is returned as an int. * * * PARAM1: char ** nptr * * RETURNS: returns the value of fieldwidth digits from a * printf format string */int snval; /* return value, breaks if on stack */intsetnum(char ** nptr){ snval = 0; while (**nptr >= '0' && **nptr <= '9') /* scan through digits */ { snval *= 10; /* calculate return value */ snval += **nptr - '0'; /* bump pointer (not pointer to pointer) past valid digits */ (*nptr)++; } return(snval);}/* FUNCTION: fplen() * * fplen(sp, varp) - returns the number of chars required to print * the value pointed to by varp when formatted accoring to the string * pointer to by sp. * * * PARAM1: char * sp * PARAM2: void * varp * * RETURNS: */long lng1, lng2; /* scratch value for longs */intfplen(char * sp, void * varp){ char * cp; /* define the maximum digits needed to display a long value in * decimal. Say , sizeof(long) = 4. So it has 8*4=32 bits. * 2^10=1024. So for every 10 bits, we can show 3 digits. So for * long, this value would be 32*3/10=96/10=9. And then we add one * more digit for the roundoff. max_long_dig is used to prevent * long overflow in lng1. There are better ways to prevent this, * but very difficult to verify whether we made the perfect fix. * Hence for now, this should do. */ static int max_long_dig = (8 * sizeof(long) * 3)/10+1; snval = 0; /* use this for return value */ lng1 = 1; /* for figuring lengths of decimal numbers */ switch (*sp) /* switch on conversion char */ { case 's': cp = *(char**)varp; while (*cp++) snval++; return(snval); case 'c': return(1); case 'x': return(4); case 'p': return(9); case 'd': case 'u': lng2 = *(long *)varp; if (lng2 == 0) return(1); if (lng2 < 0) /* if variable value is negative... */ { if (*sp == 'd') /* format is signded decimal */ { snval++; /* add space for '-' sign */ lng2 = -lng2; } else /* *sp == 'u' - format is unsigned */ lng2 &= 0xffff; } while (lng1 <= lng2) { lng1 *= 10; snval++; if ( snval >= max_long_dig ) { /* If we don't stop now, there lng1 will have long overflow */ break; } } return(snval); case 'l': switch (*(sp+1)) { case 'x': /* '%lx' always 8 bytes */ return(8); case 'u': /* treat %lu like %ld */ case 'd': lng2 = (*(long *)(varp)); if (lng2 == 0) return(1); if (lng2 < 0) { snval++; /* add space for '-' sign */ lng2 = -lng2; } while (lng1 <= lng2) { lng1 *= 10; snval++; if ( snval >= max_long_dig ) { /* If we don't stop now, there lng1 will have long overflow */ break; } } return(snval); default: return(0); } default: return(0); }}#endif /* FIELDWIDTH */#endif /* NATIVE_PRINTF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -