/*++ * * WOW v1.0 * * Copyright (c) 1991, Microsoft Corporation * * WSPRINTF.C * Win16 wsprintf/wvsprintf code * * History: * * Created 28-May-1991 by Jeff Parsons (jeffpar) * Copied from WIN31 and edited (as little as possible) for WOW16. --*/ /* * * sprintf.c * * Implements Windows friendly versions of sprintf and vsprintf * * History: * 2/15/89 craigc Initial */ #include "windows.h" #include "winexp.h" #define WSPRINTF_LIMIT 1024 extern int near pascal SP_PutNumber(LPSTR, long, int, int, int); extern void near pascal SP_Reverse(LPSTR lp1, LPSTR lp2); #define out(c) if (--cchLimit) *lpOut++=(c); else goto errorout /* * GetFmtValue * * reads a width or precision value from the format string */ LPCSTR near pascal SP_GetFmtValue(LPCSTR lpch,int FAR *lpw) { register int i=0; while (*lpch>='0' && *lpch<='9') { i *= 10; i += (WORD)(*lpch-'0'); lpch++; } *lpw=i; /* return the address of the first non-digit character */ return lpch; } /* * wvsprintf() * * Windows version of vsprintf(). Does not support floating point or * pointer types, and all strings are assumed to be FAR. Supports only * the left alignment flag. * * Takes pointers to an output buffer, where the string is built, a * pointer to an input buffer, and a pointer to a list of parameters. * * The cdecl function wsprintf() calls this function. */ int API Iwvsprintf(LPSTR lpOut, LPCSTR lpFmt, LPSTR lpParms) { int left; char prefix; register int width; register int prec; char fillch; int size; int sign; int radix; int upper; int cchLimit=WSPRINTF_LIMIT; int cch; LPSTR lpT; union { long l; unsigned long ul; char sz[sizeof(long)]; } val; while (*lpFmt) { if (*lpFmt=='%') { /* read the flags. These can be in any order */ left=0; prefix=0; while (*++lpFmt) { if (*lpFmt=='-') left++; else if (*lpFmt=='#') prefix++; else break; } /* find fill character */ if (*lpFmt=='0') { fillch='0'; lpFmt++; } else fillch=' '; /* read the width specification */ lpFmt=SP_GetFmtValue(lpFmt,&cch); width=cch; /* read the precision */ if (*lpFmt=='.') { lpFmt=SP_GetFmtValue(++lpFmt,&cch); prec=cch; } else prec=-1; /* get the operand size */ if (*lpFmt=='l') { size=1; lpFmt++; } else { size=0; if (*lpFmt=='h') lpFmt++; } upper=0; sign=0; radix=10; switch (*lpFmt) { case 0: goto errorout; case 'i': case 'd': sign++; case 'u': /* turn off prefix if decimal */ prefix=0; donumeric: /* special cases to act like MSC v5.10 */ if (left || prec>=0) fillch=' '; if (size) val.l=*((long far *)lpParms)++; else if (sign) val.l=(long)*((short far *)lpParms)++; else val.ul=(unsigned long)*((unsigned far *)lpParms)++; if (sign && val.l<0L) val.l=-val.l; else sign=0; lpT=lpOut; /* blast the number backwards into the user buffer */ cch=SP_PutNumber(lpOut,val.l,cchLimit,radix,upper); if (!(cchLimit-=cch)) goto errorout; lpOut+=cch; width-=cch; prec-=cch; if (prec>0) width-=prec; /* fill to the field precision */ while (prec-->0) out('0'); if (width>0 && !left) { /* if we're filling with spaces, put sign first */ if (fillch!='0') { if (sign) { sign=0; out('-'); width--; } if (prefix) { out(prefix); out('0'); prefix=0; } } if (sign) width--; /* fill to the field width */ while (width-->0) out(fillch); /* still have a sign? */ if (sign) out('-'); if (prefix) { out(prefix); out('0'); } /* now reverse the string in place */ SP_Reverse(lpT,lpOut-1); } else { /* add the sign character */ if (sign) { out('-'); width--; } if (prefix) { out(prefix); out('0'); } /* reverse the string in place */ SP_Reverse(lpT,lpOut-1); /* pad to the right of the string in case left aligned */ while (width-->0) out(fillch); } break; case 'X': upper++; case 'x': radix=16; if (prefix) if (upper) prefix='X'; else prefix='x'; goto donumeric; case 'c': val.sz[0]=*lpParms; val.sz[1]=0; lpT=val.sz; cch = 1; // Length is one character. // Fix for Bug #1862 --01/10/91-- SANKAR -- /* stack aligned to larger size */ lpParms+=sizeof(int); goto putstring; case 's': lpT=*((LPSTR FAR *)lpParms)++; cch=lstrlen(lpT); putstring: if (prec>=0 && cch>prec) cch=prec; width -= cch; if (left) { while (cch--) out(*lpT++); while (width-->0) out(fillch); } else { while (width-->0) out(fillch); while (cch--) out(*lpT++); } break; default: normalch: #ifdef FE_SB /* masas : 90-4-26 */ // If last char is a high ansi char, that may cause infinite loop // In case of Taiwan version(PRC and Korea), this char is treated // as DBCS lead byte. So we expect trail byte by default. But this // is not correct. // if( IsDBCSLeadByte(*lpFmt) ) This is original code // out(*lpFmt++); if( IsDBCSLeadByte(*lpFmt) ) { if( *(lpFmt+1) == '\0' ) { out('?'); lpFmt++; continue; } else out(*lpFmt++); } #endif out(*lpFmt); break; } /* END OF SWITCH(*lpFmt) */ } /* END OF IF(%) */ else goto normalch; /* character not a '%', just do it */ /* advance to next format string character */ lpFmt++; } /* END OF OUTER WHILE LOOP */ errorout: *lpOut=0; return WSPRINTF_LIMIT-cchLimit; } /* * wsprintf * * Windows version of sprintf * */ int FAR cdecl wsprintf(LPSTR lpOut, LPCSTR lpFmt, LPSTR lpParms, ...) { return wvsprintf(lpOut,lpFmt,(LPSTR)&lpParms); }