Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

354 lines
7.2 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WSPRINTF.C
  8. * Win16 wsprintf/wvsprintf code
  9. *
  10. * History:
  11. *
  12. * Created 28-May-1991 by Jeff Parsons (jeffpar)
  13. * Copied from WIN31 and edited (as little as possible) for WOW16.
  14. --*/
  15. /*
  16. *
  17. * sprintf.c
  18. *
  19. * Implements Windows friendly versions of sprintf and vsprintf
  20. *
  21. * History:
  22. * 2/15/89 craigc Initial
  23. */
  24. #include "windows.h"
  25. #include "winexp.h"
  26. #define WSPRINTF_LIMIT 1024
  27. extern int near pascal SP_PutNumber(LPSTR, long, int, int, int);
  28. extern void near pascal SP_Reverse(LPSTR lp1, LPSTR lp2);
  29. #define out(c) if (--cchLimit) *lpOut++=(c); else goto errorout
  30. /*
  31. * GetFmtValue
  32. *
  33. * reads a width or precision value from the format string
  34. */
  35. LPCSTR near pascal SP_GetFmtValue(LPCSTR lpch,int FAR *lpw)
  36. {
  37. register int i=0;
  38. while (*lpch>='0' && *lpch<='9')
  39. {
  40. i *= 10;
  41. i += (WORD)(*lpch-'0');
  42. lpch++;
  43. }
  44. *lpw=i;
  45. /* return the address of the first non-digit character */
  46. return lpch;
  47. }
  48. /*
  49. * wvsprintf()
  50. *
  51. * Windows version of vsprintf(). Does not support floating point or
  52. * pointer types, and all strings are assumed to be FAR. Supports only
  53. * the left alignment flag.
  54. *
  55. * Takes pointers to an output buffer, where the string is built, a
  56. * pointer to an input buffer, and a pointer to a list of parameters.
  57. *
  58. * The cdecl function wsprintf() calls this function.
  59. */
  60. int API Iwvsprintf(LPSTR lpOut, LPCSTR lpFmt, LPSTR lpParms)
  61. {
  62. int left;
  63. char prefix;
  64. register int width;
  65. register int prec;
  66. char fillch;
  67. int size;
  68. int sign;
  69. int radix;
  70. int upper;
  71. int cchLimit=WSPRINTF_LIMIT;
  72. int cch;
  73. LPSTR lpT;
  74. union {
  75. long l;
  76. unsigned long ul;
  77. char sz[sizeof(long)];
  78. } val;
  79. while (*lpFmt)
  80. {
  81. if (*lpFmt=='%')
  82. {
  83. /* read the flags. These can be in any order */
  84. left=0;
  85. prefix=0;
  86. while (*++lpFmt)
  87. {
  88. if (*lpFmt=='-')
  89. left++;
  90. else if (*lpFmt=='#')
  91. prefix++;
  92. else
  93. break;
  94. }
  95. /* find fill character */
  96. if (*lpFmt=='0')
  97. {
  98. fillch='0';
  99. lpFmt++;
  100. }
  101. else
  102. fillch=' ';
  103. /* read the width specification */
  104. lpFmt=SP_GetFmtValue(lpFmt,&cch);
  105. width=cch;
  106. /* read the precision */
  107. if (*lpFmt=='.')
  108. {
  109. lpFmt=SP_GetFmtValue(++lpFmt,&cch);
  110. prec=cch;
  111. }
  112. else
  113. prec=-1;
  114. /* get the operand size */
  115. if (*lpFmt=='l')
  116. {
  117. size=1;
  118. lpFmt++;
  119. }
  120. else
  121. {
  122. size=0;
  123. if (*lpFmt=='h')
  124. lpFmt++;
  125. }
  126. upper=0;
  127. sign=0;
  128. radix=10;
  129. switch (*lpFmt)
  130. {
  131. case 0:
  132. goto errorout;
  133. case 'i':
  134. case 'd':
  135. sign++;
  136. case 'u':
  137. /* turn off prefix if decimal */
  138. prefix=0;
  139. donumeric:
  140. /* special cases to act like MSC v5.10 */
  141. if (left || prec>=0)
  142. fillch=' ';
  143. if (size)
  144. val.l=*((long far *)lpParms)++;
  145. else
  146. if (sign)
  147. val.l=(long)*((short far *)lpParms)++;
  148. else
  149. val.ul=(unsigned long)*((unsigned far *)lpParms)++;
  150. if (sign && val.l<0L)
  151. val.l=-val.l;
  152. else
  153. sign=0;
  154. lpT=lpOut;
  155. /* blast the number backwards into the user buffer */
  156. cch=SP_PutNumber(lpOut,val.l,cchLimit,radix,upper);
  157. if (!(cchLimit-=cch))
  158. goto errorout;
  159. lpOut+=cch;
  160. width-=cch;
  161. prec-=cch;
  162. if (prec>0)
  163. width-=prec;
  164. /* fill to the field precision */
  165. while (prec-->0)
  166. out('0');
  167. if (width>0 && !left)
  168. {
  169. /* if we're filling with spaces, put sign first */
  170. if (fillch!='0')
  171. {
  172. if (sign)
  173. {
  174. sign=0;
  175. out('-');
  176. width--;
  177. }
  178. if (prefix)
  179. {
  180. out(prefix);
  181. out('0');
  182. prefix=0;
  183. }
  184. }
  185. if (sign)
  186. width--;
  187. /* fill to the field width */
  188. while (width-->0)
  189. out(fillch);
  190. /* still have a sign? */
  191. if (sign)
  192. out('-');
  193. if (prefix)
  194. {
  195. out(prefix);
  196. out('0');
  197. }
  198. /* now reverse the string in place */
  199. SP_Reverse(lpT,lpOut-1);
  200. }
  201. else
  202. {
  203. /* add the sign character */
  204. if (sign)
  205. {
  206. out('-');
  207. width--;
  208. }
  209. if (prefix)
  210. {
  211. out(prefix);
  212. out('0');
  213. }
  214. /* reverse the string in place */
  215. SP_Reverse(lpT,lpOut-1);
  216. /* pad to the right of the string in case left aligned */
  217. while (width-->0)
  218. out(fillch);
  219. }
  220. break;
  221. case 'X':
  222. upper++;
  223. case 'x':
  224. radix=16;
  225. if (prefix)
  226. if (upper)
  227. prefix='X';
  228. else
  229. prefix='x';
  230. goto donumeric;
  231. case 'c':
  232. val.sz[0]=*lpParms;
  233. val.sz[1]=0;
  234. lpT=val.sz;
  235. cch = 1; // Length is one character.
  236. // Fix for Bug #1862 --01/10/91-- SANKAR --
  237. /* stack aligned to larger size */
  238. lpParms+=sizeof(int);
  239. goto putstring;
  240. case 's':
  241. lpT=*((LPSTR FAR *)lpParms)++;
  242. cch=lstrlen(lpT);
  243. putstring:
  244. if (prec>=0 && cch>prec)
  245. cch=prec;
  246. width -= cch;
  247. if (left)
  248. {
  249. while (cch--)
  250. out(*lpT++);
  251. while (width-->0)
  252. out(fillch);
  253. }
  254. else
  255. {
  256. while (width-->0)
  257. out(fillch);
  258. while (cch--)
  259. out(*lpT++);
  260. }
  261. break;
  262. default:
  263. normalch:
  264. #ifdef FE_SB /* masas : 90-4-26 */
  265. // If last char is a high ansi char, that may cause infinite loop
  266. // In case of Taiwan version(PRC and Korea), this char is treated
  267. // as DBCS lead byte. So we expect trail byte by default. But this
  268. // is not correct.
  269. // if( IsDBCSLeadByte(*lpFmt) ) This is original code
  270. // out(*lpFmt++);
  271. if( IsDBCSLeadByte(*lpFmt) ) {
  272. if( *(lpFmt+1) == '\0' ) {
  273. out('?');
  274. lpFmt++;
  275. continue;
  276. }
  277. else
  278. out(*lpFmt++);
  279. }
  280. #endif
  281. out(*lpFmt);
  282. break;
  283. } /* END OF SWITCH(*lpFmt) */
  284. } /* END OF IF(%) */
  285. else
  286. goto normalch; /* character not a '%', just do it */
  287. /* advance to next format string character */
  288. lpFmt++;
  289. } /* END OF OUTER WHILE LOOP */
  290. errorout:
  291. *lpOut=0;
  292. return WSPRINTF_LIMIT-cchLimit;
  293. }
  294. /*
  295. * wsprintf
  296. *
  297. * Windows version of sprintf
  298. *
  299. */
  300. int FAR cdecl wsprintf(LPSTR lpOut, LPCSTR lpFmt, LPSTR lpParms, ...)
  301. {
  302. return wvsprintf(lpOut,lpFmt,(LPSTR)&lpParms);
  303. }