windows-nt/Source/XPSP1/NT/base/mvdm/wow16/user/wsprintf.c

355 lines
7.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
*
* 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);
}