mshtml: Implement IHTMLDOMNode previousSibling.
[wine] / dlls / msvcrt / tests / printf.c
1 /*
2  * Conformance tests for *printf functions.
3  *
4  * Copyright 2002 Uwe Bonnes
5  * Copyright 2004 Aneurin Price
6  * Copyright 2005 Mike McCormack
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 /* With Visual Studio >= 2005,  swprintf() takes an extra parameter unless
24  * the following macro is defined.
25  */
26 #define _CRT_NON_CONFORMING_SWPRINTFS
27  
28 #include <stdio.h>
29 #include <errno.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34
35 #include "wine/test.h"
36
37 static int (__cdecl *p__vscprintf)(const char *format, __ms_va_list valist);
38 static int (__cdecl *p__vscwprintf)(const wchar_t *format, __ms_va_list valist);
39 static int (__cdecl *p__vsnwprintf_s)(wchar_t *str, size_t sizeOfBuffer,
40                                       size_t count, const wchar_t *format,
41                                       __ms_va_list valist);
42 static int (__cdecl *p__ecvt_s)(char *buffer, size_t length, double number,
43                                 int ndigits, int *decpt, int *sign);
44 static int (__cdecl *p__fcvt_s)(char *buffer, size_t length, double number,
45                                 int ndigits, int *decpt, int *sign);
46 static unsigned int (__cdecl *p__get_output_format)(void);
47
48 static void init( void )
49 {
50     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
51
52     p__vscprintf = (void *)GetProcAddress(hmod, "_vscprintf");
53     p__vscwprintf = (void *)GetProcAddress(hmod, "_vscwprintf");
54     p__vsnwprintf_s = (void *)GetProcAddress(hmod, "_vsnwprintf_s");
55     p__ecvt_s = (void *)GetProcAddress(hmod, "_ecvt_s");
56     p__fcvt_s = (void *)GetProcAddress(hmod, "_fcvt_s");
57     p__get_output_format = (void *)GetProcAddress(hmod, "_get_output_format");
58 }
59
60 static void test_sprintf( void )
61 {
62     char buffer[100];
63     const char *format;
64     double pnumber=789456123;
65     int x, r;
66     WCHAR wide[] = { 'w','i','d','e',0};
67
68     format = "%+#23.15e";
69     r = sprintf(buffer,format,pnumber);
70     ok(!strcmp(buffer,"+7.894561230000000e+008"),"+#23.15e failed: '%s'\n", buffer);
71     ok( r==23, "return count wrong\n");
72
73     format = "%-#23.15e";
74     r = sprintf(buffer,format,pnumber);
75     ok(!strcmp(buffer,"7.894561230000000e+008 "),"-#23.15e failed: '%s'\n", buffer);
76     ok( r==23, "return count wrong\n");
77
78     format = "%#23.15e";
79     r = sprintf(buffer,format,pnumber);
80     ok(!strcmp(buffer," 7.894561230000000e+008"),"#23.15e failed: '%s'\n", buffer);
81     ok( r==23, "return count wrong\n");
82
83     format = "%#1.1g";
84     r = sprintf(buffer,format,pnumber);
85     ok(!strcmp(buffer,"8.e+008"),"#1.1g failed: '%s'\n", buffer);
86     ok( r==7, "return count wrong\n");
87
88     format = "%I64d";
89     r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
90     ok(!strcmp(buffer,"-8589934591"),"Problem with long long\n");
91     ok( r==11, "return count wrong\n");
92
93     format = "%+8I64d";
94     r = sprintf(buffer,format,(LONGLONG)100);
95     ok(!strcmp(buffer,"    +100") && r==8,"+8I64d failed: '%s'\n", buffer);
96
97     format = "%+.8I64d";
98     r = sprintf(buffer,format,(LONGLONG)100);
99     ok(!strcmp(buffer,"+00000100") && r==9,"+.8I64d failed: '%s'\n", buffer);
100
101     format = "%+10.8I64d";
102     r = sprintf(buffer,format,(LONGLONG)100);
103     ok(!strcmp(buffer," +00000100") && r==10,"+10.8I64d failed: '%s'\n", buffer);
104     format = "%_1I64d";
105     r = sprintf(buffer,format,(LONGLONG)100);
106     ok(!strcmp(buffer,"_1I64d") && r==6,"_1I64d failed\n");
107
108     format = "%-1.5I64d";
109     r = sprintf(buffer,format,(LONGLONG)-100);
110     ok(!strcmp(buffer,"-00100") && r==6,"-1.5I64d failed: '%s'\n", buffer);
111
112     format = "%5I64d";
113     r = sprintf(buffer,format,(LONGLONG)100);
114     ok(!strcmp(buffer,"  100") && r==5,"5I64d failed: '%s'\n", buffer);
115
116     format = "%5I64d";
117     r = sprintf(buffer,format,(LONGLONG)-100);
118     ok(!strcmp(buffer," -100") && r==5,"5I64d failed: '%s'\n", buffer);
119
120     format = "%-5I64d";
121     r = sprintf(buffer,format,(LONGLONG)100);
122     ok(!strcmp(buffer,"100  ") && r==5,"-5I64d failed: '%s'\n", buffer);
123
124     format = "%-5I64d";
125     r = sprintf(buffer,format,(LONGLONG)-100);
126     ok(!strcmp(buffer,"-100 ") && r==5,"-5I64d failed: '%s'\n", buffer);
127
128     format = "%-.5I64d";
129     r = sprintf(buffer,format,(LONGLONG)100);
130     ok(!strcmp(buffer,"00100") && r==5,"-.5I64d failed: '%s'\n", buffer);
131
132     format = "%-.5I64d";
133     r = sprintf(buffer,format,(LONGLONG)-100);
134     ok(!strcmp(buffer,"-00100") && r==6,"-.5I64d failed: '%s'\n", buffer);
135
136     format = "%-8.5I64d";
137     r = sprintf(buffer,format,(LONGLONG)100);
138     ok(!strcmp(buffer,"00100   ") && r==8,"-8.5I64d failed: '%s'\n", buffer);
139
140     format = "%-8.5I64d";
141     r = sprintf(buffer,format,(LONGLONG)-100);
142     ok(!strcmp(buffer,"-00100  ") && r==8,"-8.5I64d failed: '%s'\n", buffer);
143
144     format = "%05I64d";
145     r = sprintf(buffer,format,(LONGLONG)100);
146     ok(!strcmp(buffer,"00100") && r==5,"05I64d failed: '%s'\n", buffer);
147
148     format = "%05I64d";
149     r = sprintf(buffer,format,(LONGLONG)-100);
150     ok(!strcmp(buffer,"-0100") && r==5,"05I64d failed: '%s'\n", buffer);
151
152     format = "% I64d";
153     r = sprintf(buffer,format,(LONGLONG)100);
154     ok(!strcmp(buffer," 100") && r==4,"' I64d' failed: '%s'\n", buffer);
155
156     format = "% I64d";
157     r = sprintf(buffer,format,(LONGLONG)-100);
158     ok(!strcmp(buffer,"-100") && r==4,"' I64d' failed: '%s'\n", buffer);
159
160     format = "% 5I64d";
161     r = sprintf(buffer,format,(LONGLONG)100);
162     ok(!strcmp(buffer,"  100") && r==5,"' 5I64d' failed: '%s'\n", buffer);
163
164     format = "% 5I64d";
165     r = sprintf(buffer,format,(LONGLONG)-100);
166     ok(!strcmp(buffer," -100") && r==5,"' 5I64d' failed: '%s'\n", buffer);
167
168     format = "% .5I64d";
169     r = sprintf(buffer,format,(LONGLONG)100);
170     ok(!strcmp(buffer," 00100") && r==6,"' .5I64d' failed: '%s'\n", buffer);
171
172     format = "% .5I64d";
173     r = sprintf(buffer,format,(LONGLONG)-100);
174     ok(!strcmp(buffer,"-00100") && r==6,"' .5I64d' failed: '%s'\n", buffer);
175
176     format = "% 8.5I64d";
177     r = sprintf(buffer,format,(LONGLONG)100);
178     ok(!strcmp(buffer,"   00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer);
179
180     format = "% 8.5I64d";
181     r = sprintf(buffer,format,(LONGLONG)-100);
182     ok(!strcmp(buffer,"  -00100") && r==8,"' 8.5I64d' failed: '%s'\n", buffer);
183
184     format = "%.0I64d";
185     r = sprintf(buffer,format,(LONGLONG)0);
186     ok(r==0,".0I64d failed: '%s'\n", buffer);
187
188     format = "%#+21.18I64x";
189     r = sprintf(buffer,format,(LONGLONG)-100);
190     ok(!strcmp(buffer," 0x00ffffffffffffff9c") && r==21,"#+21.18I64x failed: '%s'\n", buffer);
191
192     format = "%#.25I64o";
193     r = sprintf(buffer,format,(LONGLONG)-100);
194     ok(!strcmp(buffer,"0001777777777777777777634") && r==25,"#.25I64o failed: '%s'\n", buffer);
195
196     format = "%#+24.20I64o";
197     r = sprintf(buffer,format,(LONGLONG)-100);
198     ok(!strcmp(buffer," 01777777777777777777634") && r==24,"#+24.20I64o failed: '%s'\n", buffer);
199
200     format = "%#+18.21I64X";
201     r = sprintf(buffer,format,(LONGLONG)-100);
202     ok(!strcmp(buffer,"0X00000FFFFFFFFFFFFFF9C") && r==23,"#+18.21I64X failed: '%s '\n", buffer);
203
204     format = "%#+20.24I64o";
205     r = sprintf(buffer,format,(LONGLONG)-100);
206     ok(!strcmp(buffer,"001777777777777777777634") && r==24,"#+20.24I64o failed: '%s'\n", buffer);
207
208     format = "%#+25.22I64u";
209     r = sprintf(buffer,format,(LONGLONG)-1);
210     ok(!strcmp(buffer,"   0018446744073709551615") && r==25,"#+25.22I64u conversion failed: '%s'\n", buffer);
211
212     format = "%#+25.22I64u";
213     r = sprintf(buffer,format,(LONGLONG)-1);
214     ok(!strcmp(buffer,"   0018446744073709551615") && r==25,"#+25.22I64u failed: '%s'\n", buffer);
215
216     format = "%#+30.25I64u";
217     r = sprintf(buffer,format,(LONGLONG)-1);
218     ok(!strcmp(buffer,"     0000018446744073709551615") && r==30,"#+30.25I64u failed: '%s'\n", buffer);
219
220     format = "%+#25.22I64d";
221     r = sprintf(buffer,format,(LONGLONG)-1);
222     ok(!strcmp(buffer,"  -0000000000000000000001") && r==25,"+#25.22I64d failed: '%s'\n", buffer);
223
224     format = "%#-8.5I64o";
225     r = sprintf(buffer,format,(LONGLONG)100);
226     ok(!strcmp(buffer,"00144   ") && r==8,"-8.5I64o failed: '%s'\n", buffer);
227
228     format = "%#-+ 08.5I64d";
229     r = sprintf(buffer,format,(LONGLONG)100);
230     ok(!strcmp(buffer,"+00100  ") && r==8,"'#-+ 08.5I64d failed: '%s'\n", buffer);
231
232     format = "%#-+ 08.5I64d";
233     r = sprintf(buffer,format,(LONGLONG)100);
234     ok(!strcmp(buffer,"+00100  ") && r==8,"#-+ 08.5I64d failed: '%s'\n", buffer);
235
236     format = "%.80I64d";
237     r = sprintf(buffer,format,(LONGLONG)1);
238     ok(r==80,"%s format failed\n", format);
239
240     format = "% .80I64d";
241     r = sprintf(buffer,format,(LONGLONG)1);
242     ok(r==81,"%s format failed\n", format);
243
244     format = "% .80d";
245     r = sprintf(buffer,format,1);
246     ok(r==81,"%s format failed\n", format);
247
248     format = "%lld";
249     r = sprintf(buffer,format,((ULONGLONG)0xffffffff)*0xffffffff);
250     ok( r == 1 || r == 11, "return count wrong %d\n", r);
251     if (r == 11)  /* %ll works on Vista */
252         ok(!strcmp(buffer, "-8589934591"), "Problem with \"ll\" interpretation '%s'\n", buffer);
253     else
254         ok(!strcmp(buffer, "1"), "Problem with \"ll\" interpretation '%s'\n", buffer);
255
256     format = "%I";
257     r = sprintf(buffer,format,1);
258     ok(!strcmp(buffer, "I"), "Problem with \"I\" interpretation\n");
259     ok( r==1, "return count wrong\n");
260
261     format = "%I0d";
262     r = sprintf(buffer,format,1);
263     ok(!strcmp(buffer,"I0d"),"I0d failed\n");
264     ok( r==3, "return count wrong\n");
265
266     format = "%I32d";
267     r = sprintf(buffer,format,1);
268     if (r == 1)
269     {
270         ok(!strcmp(buffer,"1"),"I32d failed, got '%s'\n",buffer);
271     }
272     else
273     {
274         /* Older versions don't grok I32 format */
275         ok(r == 4 && !strcmp(buffer,"I32d"),"I32d failed, got '%s',%d\n",buffer,r);
276     }
277
278     format = "%I64D";
279     r = sprintf(buffer,format,(LONGLONG)-1);
280     ok(!strcmp(buffer,"D"),"I64D failed: %s\n",buffer);
281     ok( r==1, "return count wrong\n");
282
283     format = "% d";
284     r = sprintf(buffer,format,1);
285     ok(!strcmp(buffer, " 1"),"Problem with sign place-holder: '%s'\n",buffer);
286     ok( r==2, "return count wrong\n");
287
288     format = "%+ d";
289     r = sprintf(buffer,format,1);
290     ok(!strcmp(buffer, "+1"),"Problem with sign flags: '%s'\n",buffer);
291     ok( r==2, "return count wrong\n");
292
293     format = "%S";
294     r = sprintf(buffer,format,wide);
295     ok(!strcmp(buffer,"wide"),"Problem with wide string format\n");
296     ok( r==4, "return count wrong\n");
297
298     format = "%04c";
299     r = sprintf(buffer,format,'1');
300     ok(!strcmp(buffer,"0001"),"Character not zero-prefixed \"%s\"\n",buffer);
301     ok( r==4, "return count wrong\n");
302
303     format = "%-04c";
304     r = sprintf(buffer,format,'1');
305     ok(!strcmp(buffer,"1   "),"Character zero-padded and/or not left-adjusted \"%s\"\n",buffer);
306     ok( r==4, "return count wrong\n");
307
308     if (sizeof(void *) == 8)
309     {
310         format = "%p";
311         r = sprintf(buffer,format,(void *)57);
312         ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
313         ok( r==16, "return count wrong\n");
314
315         format = "%#020p";
316         r = sprintf(buffer,format,(void *)57);
317         ok(!strcmp(buffer,"  0X0000000000000039"),"Pointer formatted incorrectly\n");
318         ok( r==20, "return count wrong\n");
319
320         format = "%Fp";
321         r = sprintf(buffer,format,(void *)57);
322         ok(!strcmp(buffer,"0000000000000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
323         ok( r==16, "return count wrong\n");
324
325         format = "%#-020p";
326         r = sprintf(buffer,format,(void *)57);
327         ok(!strcmp(buffer,"0X0000000000000039  "),"Pointer formatted incorrectly\n");
328         ok( r==20, "return count wrong\n");
329     }
330     else
331     {
332         format = "%p";
333         r = sprintf(buffer,format,(void *)57);
334         ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
335         ok( r==8, "return count wrong\n");
336
337         format = "%#012p";
338         r = sprintf(buffer,format,(void *)57);
339         ok(!strcmp(buffer,"  0X00000039"),"Pointer formatted incorrectly\n");
340         ok( r==12, "return count wrong\n");
341
342         format = "%Fp";
343         r = sprintf(buffer,format,(void *)57);
344         ok(!strcmp(buffer,"00000039"),"Pointer formatted incorrectly \"%s\"\n",buffer);
345         ok( r==8, "return count wrong\n");
346
347         format = "%#-012p";
348         r = sprintf(buffer,format,(void *)57);
349         ok(!strcmp(buffer,"0X00000039  "),"Pointer formatted incorrectly\n");
350         ok( r==12, "return count wrong\n");
351     }
352
353     format = "%04s";
354     r = sprintf(buffer,format,"foo");
355     ok(!strcmp(buffer,"0foo"),"String not zero-prefixed \"%s\"\n",buffer);
356     ok( r==4, "return count wrong\n");
357
358     format = "%.1s";
359     r = sprintf(buffer,format,"foo");
360     ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
361     ok( r==1, "return count wrong\n");
362
363     format = "%.*s";
364     r = sprintf(buffer,format,1,"foo");
365     ok(!strcmp(buffer,"f"),"Precision ignored \"%s\"\n",buffer);
366     ok( r==1, "return count wrong\n");
367
368     format = "%*s";
369     r = sprintf(buffer,format,-5,"foo");
370     ok(!strcmp(buffer,"foo  "),"Negative field width ignored \"%s\"\n",buffer);
371     ok( r==5, "return count wrong\n");
372
373     format = "hello";
374     r = sprintf(buffer, format);
375     ok(!strcmp(buffer,"hello"), "failed\n");
376     ok( r==5, "return count wrong\n");
377
378     format = "%ws";
379     r = sprintf(buffer, format, wide);
380     ok(!strcmp(buffer,"wide"), "failed\n");
381     ok( r==4, "return count wrong\n");
382
383     format = "%-10ws";
384     r = sprintf(buffer, format, wide );
385     ok(!strcmp(buffer,"wide      "), "failed\n");
386     ok( r==10, "return count wrong\n");
387
388     format = "%10ws";
389     r = sprintf(buffer, format, wide );
390     ok(!strcmp(buffer,"      wide"), "failed\n");
391     ok( r==10, "return count wrong\n");
392
393     format = "%#+ -03whlls";
394     r = sprintf(buffer, format, wide );
395     ok(!strcmp(buffer,"wide"), "failed\n");
396     ok( r==4, "return count wrong\n");
397
398     format = "%w0s";
399     r = sprintf(buffer, format, wide );
400     ok(!strcmp(buffer,"0s"), "failed\n");
401     ok( r==2, "return count wrong\n");
402
403     format = "%w-s";
404     r = sprintf(buffer, format, wide );
405     ok(!strcmp(buffer,"-s"), "failed\n");
406     ok( r==2, "return count wrong\n");
407
408     format = "%ls";
409     r = sprintf(buffer, format, wide );
410     ok(!strcmp(buffer,"wide"), "failed\n");
411     ok( r==4, "return count wrong\n");
412
413     format = "%Ls";
414     r = sprintf(buffer, format, "not wide" );
415     ok(!strcmp(buffer,"not wide"), "failed\n");
416     ok( r==8, "return count wrong\n");
417
418     format = "%b";
419     r = sprintf(buffer, format);
420     ok(!strcmp(buffer,"b"), "failed\n");
421     ok( r==1, "return count wrong\n");
422
423     format = "%3c";
424     r = sprintf(buffer, format,'a');
425     ok(!strcmp(buffer,"  a"), "failed\n");
426     ok( r==3, "return count wrong\n");
427
428     format = "%3d";
429     r = sprintf(buffer, format,1234);
430     ok(!strcmp(buffer,"1234"), "failed\n");
431     ok( r==4, "return count wrong\n");
432
433     format = "%3h";
434     r = sprintf(buffer, format);
435     ok(!strcmp(buffer,""), "failed\n");
436     ok( r==0, "return count wrong\n");
437
438     format = "%j%k%m%q%r%t%v%y%z";
439     r = sprintf(buffer, format);
440     ok(!strcmp(buffer,"jkmqrtvyz"), "failed\n");
441     ok( r==9, "return count wrong\n");
442
443     format = "asdf%n";
444     x = 0;
445     r = sprintf(buffer, format, &x );
446     if (r == -1)
447     {
448         /* %n format is disabled by default on vista */
449         /* FIXME: should test with _set_printf_count_output */
450         ok(x == 0, "should not write to x: %d\n", x);
451     }
452     else
453     {
454         ok(x == 4, "should write to x: %d\n", x);
455         ok(!strcmp(buffer,"asdf"), "failed\n");
456         ok( r==4, "return count wrong: %d\n", r);
457     }
458
459     format = "%-1d";
460     r = sprintf(buffer, format,2);
461     ok(!strcmp(buffer,"2"), "failed\n");
462     ok( r==1, "return count wrong\n");
463
464     format = "%2.4f";
465     r = sprintf(buffer, format,8.6);
466     ok(!strcmp(buffer,"8.6000"), "failed\n");
467     ok( r==6, "return count wrong\n");
468
469     format = "%0f";
470     r = sprintf(buffer, format,0.6);
471     ok(!strcmp(buffer,"0.600000"), "failed\n");
472     ok( r==8, "return count wrong\n");
473
474     format = "%.0f";
475     r = sprintf(buffer, format,0.6);
476     ok(!strcmp(buffer,"1"), "failed\n");
477     ok( r==1, "return count wrong\n");
478
479     format = "%2.4e";
480     r = sprintf(buffer, format,8.6);
481     ok(!strcmp(buffer,"8.6000e+000"), "failed\n");
482     ok( r==11, "return count wrong\n");
483
484     format = "%2.4g";
485     r = sprintf(buffer, format,8.6);
486     ok(!strcmp(buffer,"8.6"), "failed\n");
487     ok( r==3, "return count wrong\n");
488
489     format = "%-i";
490     r = sprintf(buffer, format,-1);
491     ok(!strcmp(buffer,"-1"), "failed\n");
492     ok( r==2, "return count wrong\n");
493
494     format = "%-i";
495     r = sprintf(buffer, format,1);
496     ok(!strcmp(buffer,"1"), "failed\n");
497     ok( r==1, "return count wrong\n");
498
499     format = "%+i";
500     r = sprintf(buffer, format,1);
501     ok(!strcmp(buffer,"+1"), "failed\n");
502     ok( r==2, "return count wrong\n");
503
504     format = "%o";
505     r = sprintf(buffer, format,10);
506     ok(!strcmp(buffer,"12"), "failed\n");
507     ok( r==2, "return count wrong\n");
508
509     format = "%p";
510     r = sprintf(buffer, format,0);
511     if (sizeof(void *) == 8)
512     {
513         ok(!strcmp(buffer,"0000000000000000"), "failed\n");
514         ok( r==16, "return count wrong\n");
515     }
516     else
517     {
518         ok(!strcmp(buffer,"00000000"), "failed\n");
519         ok( r==8, "return count wrong\n");
520     }
521
522     format = "%s";
523     r = sprintf(buffer, format,0);
524     ok(!strcmp(buffer,"(null)"), "failed\n");
525     ok( r==6, "return count wrong\n");
526
527     format = "%s";
528     r = sprintf(buffer, format,"%%%%");
529     ok(!strcmp(buffer,"%%%%"), "failed\n");
530     ok( r==4, "return count wrong\n");
531
532     format = "%u";
533     r = sprintf(buffer, format,-1);
534     ok(!strcmp(buffer,"4294967295"), "failed\n");
535     ok( r==10, "return count wrong\n");
536
537     format = "%w";
538     r = sprintf(buffer, format,-1);
539     ok(!strcmp(buffer,""), "failed\n");
540     ok( r==0, "return count wrong\n");
541
542     format = "%h";
543     r = sprintf(buffer, format,-1);
544     ok(!strcmp(buffer,""), "failed\n");
545     ok( r==0, "return count wrong\n");
546
547     format = "%z";
548     r = sprintf(buffer, format,-1);
549     ok(!strcmp(buffer,"z"), "failed\n");
550     ok( r==1, "return count wrong\n");
551
552     format = "%j";
553     r = sprintf(buffer, format,-1);
554     ok(!strcmp(buffer,"j"), "failed\n");
555     ok( r==1, "return count wrong\n");
556
557     format = "%F";
558     r = sprintf(buffer, format,-1);
559     ok(!strcmp(buffer,""), "failed\n");
560     ok( r==0, "return count wrong\n");
561
562     format = "%H";
563     r = sprintf(buffer, format,-1);
564     ok(!strcmp(buffer,"H"), "failed\n");
565     ok( r==1, "return count wrong\n");
566
567     format = "x%cx";
568     r = sprintf(buffer, format, 0x100+'X');
569     ok(!strcmp(buffer,"xXx"), "failed\n");
570     ok( r==3, "return count wrong\n");
571
572     format = "%%0";
573     r = sprintf(buffer, format);
574     ok(!strcmp(buffer,"%0"), "failed: \"%s\"\n", buffer);
575     ok( r==2, "return count wrong\n");
576 }
577
578 static void test_swprintf( void )
579 {
580     wchar_t buffer[100];
581     const wchar_t I64d[] = {'%','I','6','4','d',0};
582     double pnumber=789456123;
583     const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0};
584     const wchar_t e008[] = {'e','+','0','0','8',0};
585     const wchar_t string_w[] = {'s','t','r','i','n','g',0};
586     const char string[] = "string";
587     const wchar_t S[]={'%','S',0};
588     const wchar_t hs[] = {'%', 'h', 's', 0};
589
590     swprintf(buffer,TwentyThreePoint15e,pnumber);
591     ok(wcsstr(buffer,e008) != 0,"Sprintf different\n");
592     swprintf(buffer,I64d,((ULONGLONG)0xffffffff)*0xffffffff);
593       ok(wcslen(buffer) == 11,"Problem with long long\n");
594     swprintf(buffer,S,string);
595       ok(wcslen(buffer) == 6,"Problem with \"%%S\" interpretation\n");
596    swprintf(buffer, hs, string);
597    ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n");
598 }
599
600 static void test_snprintf (void)
601 {
602     struct snprintf_test {
603         const char *format;
604         int expected;
605     };
606     /* Pre-2.1 libc behaviour, not C99 compliant. */
607     const struct snprintf_test tests[] = {{"short", 5},
608                                           {"justfit", 7},
609                                           {"justfits", 8},
610                                           {"muchlonger", -1}};
611     char buffer[8];
612     const int bufsiz = sizeof buffer;
613     unsigned int i;
614
615     for (i = 0; i < sizeof tests / sizeof tests[0]; i++) {
616         const char *fmt  = tests[i].format;
617         const int expect = tests[i].expected;
618         const int n      = _snprintf (buffer, bufsiz, fmt);
619         const int valid  = n < 0 ? bufsiz : (n == bufsiz ? n : n+1);
620
621         ok (n == expect, "\"%s\": expected %d, returned %d\n",
622             fmt, expect, n);
623         ok (!memcmp (fmt, buffer, valid),
624             "\"%s\": rendered \"%.*s\"\n", fmt, valid, buffer);
625     };
626 }
627
628 static void test_fcvt(void)
629 {
630     char *str;
631     int dec=100, sign=100;
632     
633     /* Numbers less than 1.0 with different precisions */
634     str = _fcvt(0.0001, 1, &dec, &sign );
635     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
636     ok( -3 == dec, "dec wrong %d\n", dec);
637     ok( 0 == sign, "sign wrong\n");
638
639     str = _fcvt(0.0001, -10, &dec, &sign );
640     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
641     ok( -3 == dec, "dec wrong %d\n", dec);
642     ok( 0 == sign, "sign wrong\n");
643
644     str = _fcvt(0.0001, 10, &dec, &sign );
645     ok( 0 == strcmp(str,"1000000"), "bad return '%s'\n", str);
646     ok( -3 == dec, "dec wrong %d\n", dec);
647     ok( 0 == sign, "sign wrong\n");
648
649     /* Basic sign test */
650     str = _fcvt(-111.0001, 5, &dec, &sign );
651     ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
652     ok( 3 == dec, "dec wrong %d\n", dec);
653     ok( 1 == sign, "sign wrong\n");
654
655     str = _fcvt(111.0001, 5, &dec, &sign );
656     ok( 0 == strcmp(str,"11100010"), "bad return '%s'\n", str);
657     ok( 3 == dec, "dec wrong\n");
658     ok( 0 == sign, "sign wrong\n");
659
660     /* 0.0 with different precisions */
661     str = _fcvt(0.0, 5, &dec, &sign );
662     ok( 0 == strcmp(str,"00000"), "bad return '%s'\n", str);
663     ok( 0 == dec, "dec wrong %d\n", dec);
664     ok( 0 == sign, "sign wrong\n");
665
666     str = _fcvt(0.0, 0, &dec, &sign );
667     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
668     ok( 0 == dec, "dec wrong %d\n", dec);
669     ok( 0 == sign, "sign wrong\n");
670
671     str = _fcvt(0.0, -1, &dec, &sign );
672     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
673     ok( 0 == dec, "dec wrong %d\n", dec);
674     ok( 0 == sign, "sign wrong\n");
675
676     /* Numbers > 1.0 with 0 or -ve precision */
677     str = _fcvt(-123.0001, 0, &dec, &sign );
678     ok( 0 == strcmp(str,"123"), "bad return '%s'\n", str);
679     ok( 3 == dec, "dec wrong %d\n", dec);
680     ok( 1 == sign, "sign wrong\n");
681
682     str = _fcvt(-123.0001, -1, &dec, &sign );
683     ok( 0 == strcmp(str,"12"), "bad return '%s'\n", str);
684     ok( 3 == dec, "dec wrong %d\n", dec);
685     ok( 1 == sign, "sign wrong\n");
686
687     str = _fcvt(-123.0001, -2, &dec, &sign );
688     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
689     ok( 3 == dec, "dec wrong %d\n", dec);
690     ok( 1 == sign, "sign wrong\n");
691
692     str = _fcvt(-123.0001, -3, &dec, &sign );
693     ok( 0 == strcmp(str,""), "bad return '%s'\n", str);
694     ok( 3 == dec, "dec wrong %d\n", dec);
695     ok( 1 == sign, "sign wrong\n");
696
697     /* Numbers > 1.0, but with rounding at the point of precision */
698     str = _fcvt(99.99, 1, &dec, &sign );
699     ok( 0 == strcmp(str,"1000"), "bad return '%s'\n", str);
700     ok( 3 == dec, "dec wrong %d\n", dec);
701     ok( 0 == sign, "sign wrong\n");
702
703     /* Numbers < 1.0 where rounding occurs at the point of precision */
704     str = _fcvt(0.00636, 2, &dec, &sign );
705     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
706     ok( -1 == dec, "dec wrong %d\n", dec);
707     ok( 0 == sign, "sign wrong\n");
708
709     str = _fcvt(0.00636, 3, &dec, &sign );
710     ok( 0 == strcmp(str,"6"), "bad return '%s'\n", str);
711     ok( -2 == dec, "dec wrong %d\n", dec);
712     ok( 0 == sign, "sign wrong\n");
713
714     str = _fcvt(0.09999999996, 2, &dec, &sign );
715     ok( 0 == strcmp(str,"10"), "bad return '%s'\n", str);
716     ok( 0 == dec, "dec wrong %d\n", dec);
717     ok( 0 == sign, "sign wrong\n");
718
719     str = _fcvt(0.6, 0, &dec, &sign );
720     ok( 0 == strcmp(str,"1"), "bad return '%s'\n", str);
721     ok( 1 == dec, "dec wrong %d\n", dec);
722     ok( 0 == sign, "sign wrong\n");
723 }
724
725 /* Don't test nrdigits < 0, msvcrt on Win9x and NT4 will corrupt memory by
726  * writing outside allocated memory */
727 static struct {
728     double value;
729     int nrdigits;
730     const char *expstr_e;
731     const char *expstr_f;
732     int expdecpt_e;
733     int expdecpt_f;
734     int expsign;
735 } test_cvt_testcases[] = {
736     {          45.0,   2,        "45",           "4500",          2,      2,      0 },
737     /* Numbers less than 1.0 with different precisions */
738     {        0.0001,   1,         "1",               "",         -3,     -3,     0 },
739     {        0.0001,  10,"1000000000",        "1000000",         -3,     -3,     0 },
740     /* Basic sign test */
741     {     -111.0001,   5,     "11100",       "11100010",          3,      3,     1 },
742     {      111.0001,   5,     "11100",       "11100010",          3,      3,     0 },
743     /* big numbers with low precision */
744     {        3333.3,   2,        "33",         "333330",          4,      4,     0 },
745     {999999999999.9,   3,       "100","999999999999900",         13,     12,     0 },
746     /* 0.0 with different precisions */
747     {           0.0,   5,     "00000",          "00000",          0,      0,     0 },
748     {           0.0,   0,          "",               "",          0,      0,     0 },
749     {           0.0,  -1,          "",               "",          0,      0,     0 },
750     /* Numbers > 1.0 with 0 or -ve precision */
751     {     -123.0001,   0,          "",            "123",          3,      3,     1 },
752     {     -123.0001,  -1,          "",             "12",          3,      3,     1 },
753     {     -123.0001,  -2,          "",              "1",          3,      3,     1 },
754     {     -123.0001,  -3,          "",               "",          3,      3,     1 },
755     /* Numbers > 1.0, but with rounding at the point of precision */
756     {         99.99,   1,         "1",           "1000",          3,      3,     0 },
757     /* Numbers < 1.0 where rounding occurs at the point of precision */
758     {        0.0063,   2,        "63",              "1",         -2,     -1,     0 },
759     {        0.0063,   3,        "630",             "6",         -2,     -2,     0 },
760     { 0.09999999996,   2,        "10",             "10",          0,      0,     0 },
761     {           0.6,   1,         "6",              "6",          0,      0,     0 },
762     {           0.6,   0,          "",              "1",          1,      1,     0 },
763     {           0.4,   0,          "",               "",          0,      0,     0 },
764     {          0.49,   0,          "",               "",          0,      0,     0 },
765     {          0.51,   0,          "",              "1",          1,      1,     0 },
766     /* ask for ridiculous precision, ruin formatting this table */
767     {           1.0,  30, "100000000000000000000000000000",
768                       "1000000000000000000000000000000",          1,      1,      0},
769     {           123456789012345678901.0,  30, "123456789012345680000000000000",
770                       "123456789012345680000000000000000000000000000000000",         21,    21,      0},
771     /* end marker */
772     { 0, 0, "END"}
773 };
774
775 static void test_xcvt(void)
776 {
777     char *str;
778     int i, decpt, sign, err;
779
780     for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
781         decpt = sign = 100;
782         str = _ecvt( test_cvt_testcases[i].value,
783                 test_cvt_testcases[i].nrdigits,
784                 &decpt,
785                 &sign);
786         ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
787                "_ecvt() bad return, got \n'%s' expected \n'%s'\n", str,
788               test_cvt_testcases[i].expstr_e);
789         ok( decpt == test_cvt_testcases[i].expdecpt_e,
790                 "_ecvt() decimal point wrong, got %d expected %d\n", decpt,
791                 test_cvt_testcases[i].expdecpt_e);
792         ok( sign == test_cvt_testcases[i].expsign,
793                 "_ecvt() sign wrong, got %d expected %d\n", sign,
794                 test_cvt_testcases[i].expsign);
795     }
796     for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
797         decpt = sign = 100;
798         str = _fcvt( test_cvt_testcases[i].value,
799                 test_cvt_testcases[i].nrdigits,
800                 &decpt,
801                 &sign);
802         ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
803                "_fcvt() bad return, got \n'%s' expected \n'%s'\n", str,
804               test_cvt_testcases[i].expstr_f);
805         ok( decpt == test_cvt_testcases[i].expdecpt_f,
806                 "_fcvt() decimal point wrong, got %d expected %d\n", decpt,
807                 test_cvt_testcases[i].expdecpt_f);
808         ok( sign == test_cvt_testcases[i].expsign,
809                 "_fcvt() sign wrong, got %d expected %d\n", sign,
810                 test_cvt_testcases[i].expsign);
811     }
812
813     if (p__ecvt_s)
814     {
815         str = malloc(1024);
816         for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
817             decpt = sign = 100;
818             err = p__ecvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign);
819             ok(err == 0, "_ecvt_s() failed with error code %d\n", err);
820             ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_e, 15),
821                    "_ecvt_s() bad return, got \n'%s' expected \n'%s'\n", str,
822                   test_cvt_testcases[i].expstr_e);
823             ok( decpt == test_cvt_testcases[i].expdecpt_e,
824                     "_ecvt_s() decimal point wrong, got %d expected %d\n", decpt,
825                     test_cvt_testcases[i].expdecpt_e);
826             ok( sign == test_cvt_testcases[i].expsign,
827                     "_ecvt_s() sign wrong, got %d expected %d\n", sign,
828                     test_cvt_testcases[i].expsign);
829         }
830         free(str);
831     }
832     else
833         win_skip("_ecvt_s not available\n");
834
835     if (p__fcvt_s)
836     {
837         int i;
838
839         str = malloc(1024);
840
841         /* invalid arguments */
842         err = p__fcvt_s(NULL, 0, 0.0, 0, &i, &i);
843         ok(err == EINVAL, "got %d, expected EINVAL\n", err);
844
845         err = p__fcvt_s(str, 0, 0.0, 0, &i, &i);
846         ok(err == EINVAL, "got %d, expected EINVAL\n", err);
847
848         str[0] = ' ';
849         str[1] = 0;
850         err = p__fcvt_s(str, -1, 0.0, 0, &i, &i);
851         ok(err == 0, "got %d, expected 0\n", err);
852         ok(str[0] == 0, "got %c, expected 0\n", str[0]);
853         ok(str[1] == 0, "got %c, expected 0\n", str[1]);
854
855         err = p__fcvt_s(str, 1, 0.0, 0, NULL, &i);
856         ok(err == EINVAL, "got %d, expected EINVAL\n", err);
857
858         err = p__fcvt_s(str, 1, 0.0, 0, &i, NULL);
859         ok(err == EINVAL, "got %d, expected EINVAL\n", err);
860
861         for( i = 0; strcmp( test_cvt_testcases[i].expstr_e, "END"); i++){
862             decpt = sign = 100;
863             err = p__fcvt_s(str, 1024, test_cvt_testcases[i].value, test_cvt_testcases[i].nrdigits, &decpt, &sign);
864             ok(err == 0, "_fcvt_s() failed with error code %d\n", err);
865             ok( 0 == strncmp( str, test_cvt_testcases[i].expstr_f, 15),
866                    "_fcvt_s() bad return, got '%s' expected '%s'. test %d\n", str,
867                   test_cvt_testcases[i].expstr_f, i);
868             ok( decpt == test_cvt_testcases[i].expdecpt_f,
869                     "_fcvt_s() decimal point wrong, got %d expected %d\n", decpt,
870                     test_cvt_testcases[i].expdecpt_f);
871             ok( sign == test_cvt_testcases[i].expsign,
872                     "_fcvt_s() sign wrong, got %d expected %d\n", sign,
873                     test_cvt_testcases[i].expsign);
874         }
875         free(str);
876     }
877     else
878         win_skip("_fcvt_s not available\n");
879 }
880
881 static int __cdecl _vsnwprintf_wrapper(wchar_t *str, size_t len, const wchar_t *format, ...)
882 {
883     int ret;
884     __ms_va_list valist;
885     __ms_va_start(valist, format);
886     ret = _vsnwprintf(str, len, format, valist);
887     __ms_va_end(valist);
888     return ret;
889 }
890
891 static void test_vsnwprintf(void)
892 {
893     const wchar_t format[] = {'%','w','s','%','w','s','%','w','s',0};
894     const wchar_t one[]    = {'o','n','e',0};
895     const wchar_t two[]    = {'t','w','o',0};
896     const wchar_t three[]  = {'t','h','r','e','e',0};
897
898     int ret;
899     wchar_t str[32];
900     char buf[32];
901
902     ret = _vsnwprintf_wrapper( str, sizeof(str)/sizeof(str[0]), format, one, two, three );
903
904     ok( ret == 11, "got %d expected 11\n", ret );
905     WideCharToMultiByte( CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL );
906     ok( !strcmp(buf, "onetwothree"), "got %s expected 'onetwothree'\n", buf );
907 }
908
909 static int __cdecl _vscprintf_wrapper(const char *format, ...)
910 {
911     int ret;
912     __ms_va_list valist;
913     __ms_va_start(valist, format);
914     ret = p__vscprintf(format, valist);
915     __ms_va_end(valist);
916     return ret;
917 }
918
919 static void test_vscprintf(void)
920 {
921     int ret;
922
923     if (!p__vscprintf)
924     {
925        win_skip("_vscprintf not available\n");
926        return;
927     }
928
929     ret = _vscprintf_wrapper( "%s %d", "number", 1 );
930     ok( ret == 8, "got %d expected 8\n", ret );
931 }
932
933 static int __cdecl _vscwprintf_wrapper(const wchar_t *format, ...)
934 {
935     int ret;
936     __ms_va_list valist;
937     __ms_va_start(valist, format);
938     ret = p__vscwprintf(format, valist);
939     __ms_va_end(valist);
940     return ret;
941 }
942
943 static void test_vscwprintf(void)
944 {
945     const wchar_t format[] = {'%','s',' ','%','d',0};
946     const wchar_t number[] = {'n','u','m','b','e','r',0};
947
948     int ret;
949
950     if (!p__vscwprintf)
951     {
952         win_skip("_vscwprintf not available\n");
953         return;
954     }
955
956     ret = _vscwprintf_wrapper( format, number, 1 );
957     ok( ret == 8, "got %d expected 8\n", ret );
958 }
959
960 static int __cdecl _vsnwprintf_s_wrapper(wchar_t *str, size_t sizeOfBuffer,
961                                  size_t count, const wchar_t *format, ...)
962 {
963     int ret;
964     __ms_va_list valist;
965     __ms_va_start(valist, format);
966     ret = p__vsnwprintf_s(str, sizeOfBuffer, count, format, valist);
967     __ms_va_end(valist);
968     return ret;
969 }
970
971 static void test_vsnwprintf_s(void)
972 {
973     const wchar_t format[] = { 'A','B','%','u','C',0 };
974     const wchar_t out7[] = { 'A','B','1','2','3','C',0 };
975     const wchar_t out6[] = { 'A','B','1','2','3',0 };
976     const wchar_t out2[] = { 'A',0 };
977     const wchar_t out1[] = { 0 };
978     wchar_t buffer[14] = { 0 };
979     int exp, got;
980
981     if (!p__vsnwprintf_s)
982     {
983         win_skip("_vsnwprintf_s not available\n");
984         return;
985     }
986
987     /* Enough room. */
988     exp = wcslen(out7);
989
990     got = _vsnwprintf_s_wrapper(buffer, 14, _TRUNCATE, format, 123);
991     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
992     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
993
994     got = _vsnwprintf_s_wrapper(buffer, 12, _TRUNCATE, format, 123);
995     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
996     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
997
998     got = _vsnwprintf_s_wrapper(buffer, 7, _TRUNCATE, format, 123);
999     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
1000     ok( !wcscmp(out7, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1001
1002     /* Not enough room. */
1003     exp = -1;
1004
1005     got = _vsnwprintf_s_wrapper(buffer, 6, _TRUNCATE, format, 123);
1006     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
1007     ok( !wcscmp(out6, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1008
1009     got = _vsnwprintf_s_wrapper(buffer, 2, _TRUNCATE, format, 123);
1010     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
1011     ok( !wcscmp(out2, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1012
1013     got = _vsnwprintf_s_wrapper(buffer, 1, _TRUNCATE, format, 123);
1014     ok( exp == got, "length wrong, expect=%d, got=%d\n", exp, got);
1015     ok( !wcscmp(out1, buffer), "buffer wrong, got=%s\n", wine_dbgstr_w(buffer));
1016 }
1017
1018 static void test__get_output_format(void)
1019 {
1020     unsigned int ret;
1021
1022     if (!p__get_output_format)
1023     {
1024         win_skip("_get_output_format not available\n");
1025         return;
1026     }
1027
1028     ret = p__get_output_format();
1029     ok(ret == 0, "got %d\n", ret);
1030 }
1031
1032 START_TEST(printf)
1033 {
1034     init();
1035
1036     test_sprintf();
1037     test_swprintf();
1038     test_snprintf();
1039     test_fcvt();
1040     test_xcvt();
1041     test_vsnwprintf();
1042     test_vscprintf();
1043     test_vscwprintf();
1044     test_vsnwprintf_s();
1045     test__get_output_format();
1046 }