4 * Copyright 1996 Alexandre Julliard
12 #include "stackframe.h"
16 #define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
17 #define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
18 #define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
19 #define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
20 #define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
21 #define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
22 #define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
44 /***********************************************************************
45 * WPRINTF_ParseFormatA
47 * Parse a format specification. A format specification has the form:
49 * [-][#][0][width][.precision]type
51 * Return value is the length of the format specification in characters.
53 static INT32
WPRINTF_ParseFormatA( LPCSTR format
, WPRINTF_FORMAT
*res
)
60 if (*p
== '-') { res
->flags
|= WPRINTF_LEFTALIGN
; p
++; }
61 if (*p
== '#') { res
->flags
|= WPRINTF_PREFIX_HEX
; p
++; }
62 if (*p
== '0') { res
->flags
|= WPRINTF_ZEROPAD
; p
++; }
63 while ((*p
>= '0') && (*p
<= '9')) /* width field */
65 res
->width
= res
->width
* 10 + *p
- '0';
68 if (*p
== '.') /* precision field */
71 while ((*p
>= '0') && (*p
<= '9'))
73 res
->precision
= res
->precision
* 10 + *p
- '0';
77 if (*p
== 'l') { res
->flags
|= WPRINTF_LONG
; p
++; }
78 else if (*p
== 'h') { res
->flags
|= WPRINTF_SHORT
; p
++; }
79 else if (*p
== 'w') { res
->flags
|= WPRINTF_WIDE
; p
++; }
83 res
->type
= (res
->flags
& WPRINTF_LONG
) ? WPR_WCHAR
: WPR_CHAR
;
86 res
->type
= (res
->flags
& WPRINTF_SHORT
) ? WPR_CHAR
: WPR_WCHAR
;
90 res
->type
= WPR_SIGNED
;
93 res
->type
= (res
->flags
& (WPRINTF_LONG
|WPRINTF_WIDE
))
94 ? WPR_WSTRING
: WPR_STRING
;
97 res
->type
= (res
->flags
& (WPRINTF_SHORT
|WPRINTF_WIDE
))
98 ? WPR_STRING
: WPR_WSTRING
;
101 res
->type
= WPR_UNSIGNED
;
104 res
->flags
|= WPRINTF_UPPER_HEX
;
107 res
->type
= WPR_HEXA
;
110 fprintf( stderr
, "wvsprintf32A: unknown format '%c'\n", *p
);
113 return (INT32
)(p
- format
) + 1;
117 /***********************************************************************
118 * WPRINTF_ParseFormatW
120 * Parse a format specification. A format specification has the form:
122 * [-][#][0][width][.precision]type
124 * Return value is the length of the format specification in characters.
126 static INT32
WPRINTF_ParseFormatW( LPCWSTR format
, WPRINTF_FORMAT
*res
)
133 if (*p
== '-') { res
->flags
|= WPRINTF_LEFTALIGN
; p
++; }
134 if (*p
== '#') { res
->flags
|= WPRINTF_PREFIX_HEX
; p
++; }
135 if (*p
== '0') { res
->flags
|= WPRINTF_ZEROPAD
; p
++; }
136 while ((*p
>= '0') && (*p
<= '9')) /* width field */
138 res
->width
= res
->width
* 10 + *p
- '0';
141 if (*p
== '.') /* precision field */
144 while ((*p
>= '0') && (*p
<= '9'))
146 res
->precision
= res
->precision
* 10 + *p
- '0';
150 if (*p
== 'l') { res
->flags
|= WPRINTF_LONG
; p
++; }
151 else if (*p
== 'h') { res
->flags
|= WPRINTF_SHORT
; p
++; }
152 else if (*p
== 'w') { res
->flags
|= WPRINTF_WIDE
; p
++; }
156 res
->type
= (res
->flags
& WPRINTF_SHORT
) ? WPR_CHAR
: WPR_WCHAR
;
159 res
->type
= (res
->flags
& WPRINTF_LONG
) ? WPR_WCHAR
: WPR_CHAR
;
163 res
->type
= WPR_SIGNED
;
166 res
->type
= ((res
->flags
& WPRINTF_SHORT
) && !(res
->flags
& WPRINTF_WIDE
)) ? WPR_STRING
: WPR_WSTRING
;
169 res
->type
= (res
->flags
& (WPRINTF_LONG
|WPRINTF_WIDE
)) ? WPR_WSTRING
: WPR_STRING
;
172 res
->type
= WPR_UNSIGNED
;
175 res
->flags
|= WPRINTF_UPPER_HEX
;
178 res
->type
= WPR_HEXA
;
181 fprintf( stderr
, "wvsprintf32W: unknown format '%c'\n", (CHAR
)*p
);
184 return (INT32
)(p
- format
) + 1;
188 /***********************************************************************
191 static UINT32
WPRINTF_GetLen( WPRINTF_FORMAT
*format
, LPCVOID arg
,
192 LPSTR number
, UINT32 maxlen
)
196 if (format
->flags
& WPRINTF_LEFTALIGN
) format
->flags
&= ~WPRINTF_ZEROPAD
;
197 if (format
->width
> maxlen
) format
->width
= maxlen
;
202 return (format
->precision
= 1);
204 for (len
= 0; !format
->precision
|| (len
< format
->precision
); len
++)
205 if (!*(*(LPCSTR
*)arg
+ len
)) break;
206 if (len
> maxlen
) len
= maxlen
;
207 return (format
->precision
= len
);
209 for (len
= 0; !format
->precision
|| (len
< format
->precision
); len
++)
210 if (!*(*(LPCWSTR
*)arg
+ len
)) break;
211 if (len
> maxlen
) len
= maxlen
;
212 return (format
->precision
= len
);
214 len
= sprintf( number
, "%d", *(INT32
*)arg
);
217 len
= sprintf( number
, "%u", *(UINT32
*)arg
);
220 len
= sprintf( number
,
221 (format
->flags
& WPRINTF_UPPER_HEX
) ? "%X" : "%x",
223 if (format
->flags
& WPRINTF_PREFIX_HEX
) len
+= 2;
228 if (len
> maxlen
) len
= maxlen
;
229 if (format
->precision
< len
) format
->precision
= len
;
230 if (format
->precision
> maxlen
) format
->precision
= maxlen
;
231 if ((format
->flags
& WPRINTF_ZEROPAD
) && (format
->width
> format
->precision
))
232 format
->precision
= format
->width
;
237 /***********************************************************************
238 * wvsnprintf16 (Not a Windows API)
240 INT16 WINAPI
wvsnprintf16( LPSTR buffer
, UINT16 maxlen
, LPCSTR spec
,
243 WPRINTF_FORMAT format
;
249 while (*spec
&& (maxlen
> 1))
251 if (*spec
!= '%') { *p
++ = *spec
++; maxlen
--; continue; }
253 if (*spec
== '%') { *p
++ = *spec
++; maxlen
--; continue; }
254 spec
+= WPRINTF_ParseFormatA( spec
, &format
);
257 case WPR_WCHAR
: /* No Unicode in Win16 */
259 cur_arg
= (DWORD
)VA_ARG16( args
, CHAR
);
261 case WPR_WSTRING
: /* No Unicode in Win16 */
263 cur_arg
= (DWORD
)VA_ARG16( args
, SEGPTR
);
264 if (IsBadReadPtr16( (SEGPTR
)cur_arg
, 1 )) cur_arg
= (DWORD
)"";
265 else cur_arg
= (DWORD
)PTR_SEG_TO_LIN( (SEGPTR
)cur_arg
);
268 if (!(format
.flags
& WPRINTF_LONG
))
270 cur_arg
= (DWORD
)(INT32
)VA_ARG16( args
, INT16
);
276 if (format
.flags
& WPRINTF_LONG
)
277 cur_arg
= (DWORD
)VA_ARG16( args
, UINT32
);
279 cur_arg
= (DWORD
)VA_ARG16( args
, UINT16
);
282 len
= WPRINTF_GetLen( &format
, &cur_arg
, number
, maxlen
- 1 );
283 if (!(format
.flags
& WPRINTF_LEFTALIGN
))
284 for (i
= format
.precision
; i
< format
.width
; i
++, maxlen
--)
290 if ((*p
= (CHAR
)cur_arg
)) p
++;
291 else if (format
.width
> 1) *p
++ = ' ';
296 if (len
) memcpy( p
, (LPCSTR
)cur_arg
, len
);
300 if ((format
.flags
& WPRINTF_PREFIX_HEX
) && (maxlen
> 3))
303 *p
++ = (format
.flags
& WPRINTF_UPPER_HEX
) ? 'X' : 'x';
306 format
.precision
-= 2;
312 for (i
= len
; i
< format
.precision
; i
++, maxlen
--) *p
++ = '0';
313 if (len
) memcpy( p
, number
, len
);
317 if (format
.flags
& WPRINTF_LEFTALIGN
)
318 for (i
= format
.precision
; i
< format
.width
; i
++, maxlen
--)
323 return (maxlen
> 1) ? (INT32
)(p
- buffer
) : -1;
327 /***********************************************************************
328 * wvsnprintf32A (Not a Windows API)
330 INT32 WINAPI
wvsnprintf32A( LPSTR buffer
, UINT32 maxlen
, LPCSTR spec
,
333 WPRINTF_FORMAT format
;
338 while (*spec
&& (maxlen
> 1))
340 if (*spec
!= '%') { *p
++ = *spec
++; maxlen
--; continue; }
342 if (*spec
== '%') { *p
++ = *spec
++; maxlen
--; continue; }
343 spec
+= WPRINTF_ParseFormatA( spec
, &format
);
344 len
= WPRINTF_GetLen( &format
, args
, number
, maxlen
- 1 );
345 if (!(format
.flags
& WPRINTF_LEFTALIGN
))
346 for (i
= format
.precision
; i
< format
.width
; i
++, maxlen
--)
351 if ((*p
= (CHAR
)va_arg( args
, WCHAR
))) p
++;
352 else if (format
.width
> 1) *p
++ = ' ';
356 if ((*p
= va_arg( args
, CHAR
))) p
++;
357 else if (format
.width
> 1) *p
++ = ' ';
361 memcpy( p
, va_arg( args
, LPCSTR
), len
);
366 LPCWSTR ptr
= va_arg( args
, LPCWSTR
);
367 for (i
= 0; i
< len
; i
++) *p
++ = (CHAR
)*ptr
++;
371 if ((format
.flags
& WPRINTF_PREFIX_HEX
) && (maxlen
> 3))
374 *p
++ = (format
.flags
& WPRINTF_UPPER_HEX
) ? 'X' : 'x';
377 format
.precision
-= 2;
383 for (i
= len
; i
< format
.precision
; i
++, maxlen
--) *p
++ = '0';
384 memcpy( p
, number
, len
);
386 (void)va_arg( args
, INT32
); /* Go to the next arg */
389 if (format
.flags
& WPRINTF_LEFTALIGN
)
390 for (i
= format
.precision
; i
< format
.width
; i
++, maxlen
--)
395 dprintf_string(stddeb
,"%s\n",buffer
);
396 return (maxlen
> 1) ? (INT32
)(p
- buffer
) : -1;
400 /***********************************************************************
401 * wvsnprintf32W (Not a Windows API)
403 INT32 WINAPI
wvsnprintf32W( LPWSTR buffer
, UINT32 maxlen
, LPCWSTR spec
,
406 WPRINTF_FORMAT format
;
411 while (*spec
&& (maxlen
> 1))
413 if (*spec
!= '%') { *p
++ = *spec
++; maxlen
--; continue; }
415 if (*spec
== '%') { *p
++ = *spec
++; maxlen
--; continue; }
416 spec
+= WPRINTF_ParseFormatW( spec
, &format
);
417 len
= WPRINTF_GetLen( &format
, args
, number
, maxlen
- 1 );
418 if (!(format
.flags
& WPRINTF_LEFTALIGN
))
419 for (i
= format
.precision
; i
< format
.width
; i
++, maxlen
--)
424 if ((*p
= va_arg( args
, WCHAR
))) p
++;
425 else if (format
.width
> 1) *p
++ = ' ';
429 if ((*p
= (WCHAR
)va_arg( args
, CHAR
))) p
++;
430 else if (format
.width
> 1) *p
++ = ' ';
435 LPCSTR ptr
= va_arg( args
, LPCSTR
);
436 for (i
= 0; i
< len
; i
++) *p
++ = (WCHAR
)*ptr
++;
440 if (len
) memcpy( p
, va_arg( args
, LPCWSTR
), len
* sizeof(WCHAR
) );
444 if ((format
.flags
& WPRINTF_PREFIX_HEX
) && (maxlen
> 3))
447 *p
++ = (format
.flags
& WPRINTF_UPPER_HEX
) ? 'X' : 'x';
450 format
.precision
-= 2;
456 for (i
= len
; i
< format
.precision
; i
++, maxlen
--) *p
++ = '0';
457 for (i
= 0; i
< len
; i
++) *p
++ = (WCHAR
)number
[i
];
458 (void)va_arg( args
, INT32
); /* Go to the next arg */
461 if (format
.flags
& WPRINTF_LEFTALIGN
)
462 for (i
= format
.precision
; i
< format
.width
; i
++, maxlen
--)
467 return (maxlen
> 1) ? (INT32
)(p
- buffer
) : -1;
471 /***********************************************************************
472 * wvsprintf16 (USER.421)
474 INT16 WINAPI
wvsprintf16( LPSTR buffer
, LPCSTR spec
, LPCVOID args
)
476 dprintf_string(stddeb
,"wvsprintf16 for %p got ",buffer
);
477 return wvsnprintf16( buffer
, 0xffff, spec
, args
);
481 /***********************************************************************
482 * wvsprintf32A (USER32.586)
484 INT32 WINAPI
wvsprintf32A( LPSTR buffer
, LPCSTR spec
, va_list args
)
486 dprintf_string(stddeb
,"wvsprintf32A for %p got ",buffer
);
487 return wvsnprintf32A( buffer
, 0xffffffff, spec
, args
);
491 /***********************************************************************
492 * wvsprintf32W (USER32.587)
494 INT32 WINAPI
wvsprintf32W( LPWSTR buffer
, LPCWSTR spec
, va_list args
)
496 dprintf_string(stddeb
,"wvsprintf32W for %p got ",buffer
);
497 return wvsnprintf32W( buffer
, 0xffffffff, spec
, args
);
501 /***********************************************************************
502 * wsprintf16 (USER.420)
504 /* Winelib version */
505 INT16 WINAPIV
wsprintf16( LPSTR buffer
, LPCSTR spec
, ... )
510 dprintf_string(stddeb
,"wsprintf16 for %p got ",buffer
);
511 va_start( valist
, spec
);
512 /* Note: we call the 32-bit version, because the args are 32-bit */
513 res
= (INT16
)wvsnprintf32A( buffer
, 0xffffffff, spec
, valist
);
518 /* Emulator version */
519 INT16 WINAPIV
WIN16_wsprintf16(void)
525 VA_START16( valist
);
526 buffer
= VA_ARG16( valist
, SEGPTR
);
527 spec
= VA_ARG16( valist
, SEGPTR
);
528 dprintf_string(stddeb
,"WIN16_wsprintf16 got ");
529 res
= wvsnprintf16( (LPSTR
)PTR_SEG_TO_LIN(buffer
), 0xffff,
530 (LPCSTR
)PTR_SEG_TO_LIN(spec
), valist
);
536 /***********************************************************************
537 * wsprintf32A (USER32.585)
539 INT32 WINAPIV
wsprintf32A( LPSTR buffer
, LPCSTR spec
, ... )
544 dprintf_string(stddeb
,"wsprintf32A for %p got ",buffer
);
545 va_start( valist
, spec
);
546 res
= wvsnprintf32A( buffer
, 0xffffffff, spec
, valist
);
552 /***********************************************************************
553 * wsprintf32W (USER32.586)
555 INT32 WINAPIV
wsprintf32W( LPWSTR buffer
, LPCWSTR spec
, ... )
560 dprintf_string(stddeb
,"wsprintf32W for %p\n",buffer
);
561 va_start( valist
, spec
);
562 res
= wvsnprintf32W( buffer
, 0xffffffff, spec
, valist
);
568 /***********************************************************************
569 * wsnprintf16 (Not a Windows API)
571 INT16 WINAPIV
wsnprintf16( LPSTR buffer
, UINT16 maxlen
, LPCSTR spec
, ... )
576 va_start( valist
, spec
);
577 res
= wvsnprintf16( buffer
, maxlen
, spec
, valist
);
583 /***********************************************************************
584 * wsnprintf32A (Not a Windows API)
586 INT32 WINAPIV
wsnprintf32A( LPSTR buffer
, UINT32 maxlen
, LPCSTR spec
, ... )
591 va_start( valist
, spec
);
592 res
= wvsnprintf32A( buffer
, maxlen
, spec
, valist
);
598 /***********************************************************************
599 * wsnprintf32W (Not a Windows API)
601 INT32 WINAPIV
wsnprintf32W( LPWSTR buffer
, UINT32 maxlen
, LPCWSTR spec
, ... )
606 va_start( valist
, spec
);
607 res
= wvsnprintf32W( buffer
, maxlen
, spec
, valist
);