Release 1.5.29.
[wine] / dlls / msvcp90 / locale.c
1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22
23 #include "msvcp90.h"
24 #include "locale.h"
25 #include "errno.h"
26 #include "limits.h"
27 #include "math.h"
28 #include "stdio.h"
29 #include "wctype.h"
30 #include "time.h"
31
32 #include "wine/list.h"
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winnls.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
40
41 char* __cdecl _Getdays(void);
42 char* __cdecl _Getmonths(void);
43 void* __cdecl _Gettnames(void);
44 unsigned int __cdecl ___lc_codepage_func(void);
45 LCID* __cdecl ___lc_handle_func(void);
46 const locale_facet* __thiscall locale__Getfacet(const locale*, MSVCP_size_t);
47 MSVCP_size_t __cdecl _Strftime(char*, MSVCP_size_t, const char*,
48         const struct tm*, struct __lc_time_data*);
49
50 typedef int category;
51
52 typedef struct {
53     MSVCP_size_t id;
54 } locale_id;
55
56 typedef struct _locale__Locimp {
57     locale_facet facet;
58     locale_facet **facetvec;
59     MSVCP_size_t facet_cnt;
60     category catmask;
61     MSVCP_bool transparent;
62     basic_string_char name;
63 } locale__Locimp;
64
65 typedef struct {
66     void *timeptr;
67 } _Timevec;
68
69 typedef struct {
70     _Lockit lock;
71     basic_string_char days;
72     basic_string_char months;
73     basic_string_char oldlocname;
74     basic_string_char newlocname;
75 } _Locinfo;
76
77 typedef struct {
78     LCID handle;
79     unsigned page;
80 } _Collvec;
81
82 typedef struct {
83     locale_facet facet;
84     _Collvec coll;
85 } collate;
86
87 typedef struct {
88     locale_facet facet;
89     const char *grouping;
90     char dp;
91     char sep;
92     const char *false_name;
93     const char *true_name;
94 } numpunct_char;
95
96 typedef struct {
97     locale_facet facet;
98     const char *grouping;
99     wchar_t dp;
100     wchar_t sep;
101     const wchar_t *false_name;
102     const wchar_t *true_name;
103 } numpunct_wchar;
104
105 typedef struct {
106     locale_facet facet;
107     _Timevec time;
108     _Cvtvec cvt;
109 } time_put;
110
111 /* ?_Id_cnt@id@locale@std@@0HA */
112 int locale_id__Id_cnt = 0;
113
114 static locale__Locimp *global_locale;
115 static locale classic_locale;
116
117 /* ?_Clocptr@_Locimp@locale@std@@0PAV123@A */
118 /* ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA */
119 locale__Locimp *locale__Locimp__Clocptr = NULL;
120
121 static char istreambuf_iterator_char_val(istreambuf_iterator_char *this)
122 {
123     if(this->strbuf && !this->got) {
124         int c = basic_streambuf_char_sgetc(this->strbuf);
125         if(c == EOF)
126             this->strbuf = NULL;
127         else
128             this->val = c;
129     }
130
131     this->got = TRUE;
132     return this->val;
133 }
134
135 static wchar_t istreambuf_iterator_wchar_val(istreambuf_iterator_wchar *this)
136 {
137     if(this->strbuf && !this->got) {
138         unsigned short c = basic_streambuf_wchar_sgetc(this->strbuf);
139         if(c == WEOF)
140             this->strbuf = NULL;
141         else
142             this->val = c;
143     }
144
145     this->got = TRUE;
146     return this->val;
147 }
148
149 static void istreambuf_iterator_char_inc(istreambuf_iterator_char *this)
150 {
151     if(!this->strbuf || basic_streambuf_char_sbumpc(this->strbuf)==EOF) {
152         this->strbuf = NULL;
153         this->got = TRUE;
154     }else {
155         this->got = FALSE;
156         istreambuf_iterator_char_val(this);
157     }
158 }
159
160 static void istreambuf_iterator_wchar_inc(istreambuf_iterator_wchar *this)
161 {
162     if(!this->strbuf || basic_streambuf_wchar_sbumpc(this->strbuf)==WEOF) {
163         this->strbuf = NULL;
164         this->got = TRUE;
165     }else {
166         this->got = FALSE;
167         istreambuf_iterator_wchar_val(this);
168     }
169 }
170
171 static void ostreambuf_iterator_char_put(ostreambuf_iterator_char *this, char ch)
172 {
173     if(this->failed || basic_streambuf_char_sputc(this->strbuf, ch)==EOF)
174         this->failed = TRUE;
175 }
176
177 static void ostreambuf_iterator_wchar_put(ostreambuf_iterator_wchar *this, wchar_t ch)
178 {
179     if(this->failed || basic_streambuf_wchar_sputc(this->strbuf, ch)==WEOF)
180         this->failed = TRUE;
181 }
182
183 /* ??1facet@locale@std@@UAE@XZ */
184 /* ??1facet@locale@std@@UEAA@XZ */
185 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
186 void __thiscall locale_facet_dtor(locale_facet *this)
187 {
188     TRACE("(%p)\n", this);
189 }
190
191 DEFINE_THISCALL_WRAPPER(locale_facet_vector_dtor, 8)
192 #define call_locale_facet_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0, \
193         locale_facet*, (locale_facet*, unsigned int), (this, flags))
194 locale_facet* __thiscall locale_facet_vector_dtor(locale_facet *this, unsigned int flags)
195 {
196     TRACE("(%p %x)\n", this, flags);
197     if(flags & 2) {
198         /* we have an array, with the number of elements stored before the first object */
199         INT_PTR i, *ptr = (INT_PTR *)this-1;
200
201         for(i=*ptr-1; i>=0; i--)
202             locale_facet_dtor(this+i);
203         MSVCRT_operator_delete(ptr);
204     } else {
205         locale_facet_dtor(this);
206         if(flags & 1)
207             MSVCRT_operator_delete(this);
208     }
209
210     return this;
211 }
212
213 typedef struct
214 {
215     locale_facet *fac;
216     struct list entry;
217 } facets_elem;
218 static struct list lazy_facets = LIST_INIT(lazy_facets);
219
220 /* Not exported from msvcp90 */
221 /* ?facet_Register@facet@locale@std@@CAXPAV123@@Z */
222 /* ?facet_Register@facet@locale@std@@CAXPEAV123@@Z */
223 void __cdecl locale_facet_register(locale_facet *add)
224 {
225     facets_elem *head = MSVCRT_operator_new(sizeof(*head));
226     if(!head) {
227         ERR("Out of memory\n");
228         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
229     }
230
231     head->fac = add;
232     list_add_head(&lazy_facets, &head->entry);
233 }
234
235 /* Not exported from msvcp90 */
236 /* ?_Register@facet@locale@std@@QAEXXZ */
237 /* ?_Register@facet@locale@std@@QEAAXXZ */
238 DEFINE_THISCALL_WRAPPER(locale_facet__Register, 4)
239 void __thiscall locale_facet__Register(locale_facet *this)
240 {
241     TRACE("(%p)\n", this);
242     locale_facet_register(this);
243 }
244
245 /* Not exported from msvcp90 */
246 /* ??_7facet@locale@std@@6B@ */
247 extern const vtable_ptr MSVCP_locale_facet_vtable;
248
249 /* ??0id@locale@std@@QAE@I@Z */
250 /* ??0id@locale@std@@QEAA@_K@Z */
251 DEFINE_THISCALL_WRAPPER(locale_id_ctor_id, 8)
252 locale_id* __thiscall locale_id_ctor_id(locale_id *this, MSVCP_size_t id)
253 {
254     TRACE("(%p %lu)\n", this, id);
255
256     this->id = id;
257     return this;
258 }
259
260 /* ??_Fid@locale@std@@QAEXXZ */
261 /* ??_Fid@locale@std@@QEAAXXZ */
262 DEFINE_THISCALL_WRAPPER(locale_id_ctor, 4)
263 locale_id* __thiscall locale_id_ctor(locale_id *this)
264 {
265     TRACE("(%p)\n", this);
266
267     this->id = 0;
268     return this;
269 }
270
271 /* ??Bid@locale@std@@QAEIXZ */
272 /* ??Bid@locale@std@@QEAA_KXZ */
273 DEFINE_THISCALL_WRAPPER(locale_id_operator_size_t, 4)
274 MSVCP_size_t __thiscall locale_id_operator_size_t(locale_id *this)
275 {
276     _Lockit lock;
277
278     TRACE("(%p)\n", this);
279
280     if(!this->id) {
281         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
282         this->id = ++locale_id__Id_cnt;
283         _Lockit_dtor(&lock);
284     }
285
286     return this->id;
287 }
288
289 /* ?_Id_cnt_func@id@locale@std@@CAAAHXZ */
290 /* ?_Id_cnt_func@id@locale@std@@CAAEAHXZ */
291 int* __cdecl locale_id__Id_cnt_func(void)
292 {
293     TRACE("\n");
294     return &locale_id__Id_cnt;
295 }
296
297 /* ??_Ffacet@locale@std@@QAEXXZ */
298 /* ??_Ffacet@locale@std@@QEAAXXZ */
299 DEFINE_THISCALL_WRAPPER(locale_facet_ctor, 4)
300 locale_facet* __thiscall locale_facet_ctor(locale_facet *this)
301 {
302     TRACE("(%p)\n", this);
303     this->vtable = &MSVCP_locale_facet_vtable;
304     this->refs = 0;
305     return this;
306 }
307
308 /* ??0facet@locale@std@@IAE@I@Z */
309 /* ??0facet@locale@std@@IEAA@_K@Z */
310 DEFINE_THISCALL_WRAPPER(locale_facet_ctor_refs, 8)
311 locale_facet* __thiscall locale_facet_ctor_refs(locale_facet *this, MSVCP_size_t refs)
312 {
313     TRACE("(%p %lu)\n", this, refs);
314     this->vtable = &MSVCP_locale_facet_vtable;
315     this->refs = refs;
316     return this;
317 }
318
319 /* ?_Incref@facet@locale@std@@QAEXXZ */
320 /* ?_Incref@facet@locale@std@@QEAAXXZ */
321 DEFINE_THISCALL_WRAPPER(locale_facet__Incref, 4)
322 void __thiscall locale_facet__Incref(locale_facet *this)
323 {
324     _Lockit lock;
325
326     TRACE("(%p)\n", this);
327
328     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
329     this->refs++;
330     _Lockit_dtor(&lock);
331 }
332
333 /* ?_Decref@facet@locale@std@@QAEPAV123@XZ */
334 /* ?_Decref@facet@locale@std@@QEAAPEAV123@XZ */
335 DEFINE_THISCALL_WRAPPER(locale_facet__Decref, 4)
336 locale_facet* __thiscall locale_facet__Decref(locale_facet *this)
337 {
338     _Lockit lock;
339     locale_facet *ret;
340
341     TRACE("(%p)\n", this);
342
343     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
344     if(this->refs)
345         this->refs--;
346
347     ret = this->refs ? NULL : this;
348     _Lockit_dtor(&lock);
349
350     return ret;
351 }
352
353 /* ?_Getcat@facet@locale@std@@SAIPAPBV123@PBV23@@Z */
354 /* ?_Getcat@facet@locale@std@@SA_KPEAPEBV123@PEBV23@@Z */
355 MSVCP_size_t __cdecl locale_facet__Getcat(const locale_facet **facet, const locale *loc)
356 {
357     TRACE("(%p %p)\n", facet, loc);
358     return -1;
359 }
360
361 /* ??0_Timevec@std@@QAE@ABV01@@Z */
362 /* ??0_Timevec@std@@QEAA@AEBV01@@Z */
363 /* This copy constructor modifies copied object */
364 DEFINE_THISCALL_WRAPPER(_Timevec_copy_ctor, 8)
365 _Timevec* __thiscall _Timevec_copy_ctor(_Timevec *this, _Timevec *copy)
366 {
367     TRACE("(%p %p)\n", this, copy);
368     this->timeptr = copy->timeptr;
369     copy->timeptr = NULL;
370     return this;
371 }
372
373 /* ??0_Timevec@std@@QAE@PAX@Z */
374 /* ??0_Timevec@std@@QEAA@PEAX@Z */
375 DEFINE_THISCALL_WRAPPER(_Timevec_ctor_timeptr, 8)
376 _Timevec* __thiscall _Timevec_ctor_timeptr(_Timevec *this, void *timeptr)
377 {
378     TRACE("(%p %p)\n", this, timeptr);
379     this->timeptr = timeptr;
380     return this;
381 }
382
383 /* ??_F_Timevec@std@@QAEXXZ */
384 /* ??_F_Timevec@std@@QEAAXXZ */
385 DEFINE_THISCALL_WRAPPER(_Timevec_ctor, 4)
386 _Timevec* __thiscall _Timevec_ctor(_Timevec *this)
387 {
388     TRACE("(%p)\n", this);
389     this->timeptr = NULL;
390     return this;
391 }
392
393 /* ??1_Timevec@std@@QAE@XZ */
394 /* ??1_Timevec@std@@QEAA@XZ */
395 DEFINE_THISCALL_WRAPPER(_Timevec_dtor, 4)
396 void __thiscall _Timevec_dtor(_Timevec *this)
397 {
398     TRACE("(%p)\n", this);
399     free(this->timeptr);
400 }
401
402 /* ??4_Timevec@std@@QAEAAV01@ABV01@@Z */
403 /* ??4_Timevec@std@@QEAAAEAV01@AEBV01@@Z */
404 DEFINE_THISCALL_WRAPPER(_Timevec_op_assign, 8)
405 _Timevec* __thiscall _Timevec_op_assign(_Timevec *this, _Timevec *right)
406 {
407     TRACE("(%p %p)\n", this, right);
408     this->timeptr = right->timeptr;
409     right->timeptr = NULL;
410     return this;
411 }
412
413 /* ?_Getptr@_Timevec@std@@QBEPAXXZ */
414 /* ?_Getptr@_Timevec@std@@QEBAPEAXXZ */
415 DEFINE_THISCALL_WRAPPER(_Timevec__Getptr, 4)
416 void* __thiscall _Timevec__Getptr(_Timevec *this)
417 {
418     TRACE("(%p)\n", this);
419     return this->timeptr;
420 }
421
422 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@HPBD@Z */
423 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@HPEBD@Z */
424 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cat_cstr(_Locinfo *locinfo, int category, const char *locstr)
425 {
426     const char *locale = NULL;
427
428     /* This function is probably modifying more global objects */
429     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
430
431     if(!locstr)
432         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
433
434     _Lockit_ctor_locktype(&locinfo->lock, _LOCK_LOCALE);
435     MSVCP_basic_string_char_ctor_cstr(&locinfo->days, "");
436     MSVCP_basic_string_char_ctor_cstr(&locinfo->months, "");
437     MSVCP_basic_string_char_ctor_cstr(&locinfo->oldlocname, setlocale(LC_ALL, NULL));
438
439     if(category)
440         locale = setlocale(LC_ALL, locstr);
441     else
442         locale = setlocale(LC_ALL, NULL);
443
444     if(locale)
445         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
446     else
447         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
448
449     return locinfo;
450 }
451
452 /* ??0_Locinfo@std@@QAE@HPBD@Z */
453 /* ??0_Locinfo@std@@QEAA@HPEBD@Z */
454 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cat_cstr, 12)
455 _Locinfo* __thiscall _Locinfo_ctor_cat_cstr(_Locinfo *this, int category, const char *locstr)
456 {
457     return _Locinfo__Locinfo_ctor_cat_cstr(this, category, locstr);
458 }
459
460 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z */
461 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z */
462 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_bstr(_Locinfo *locinfo, const basic_string_char *locstr)
463 {
464     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, MSVCP_basic_string_char_c_str(locstr));
465 }
466
467 /* ??0_Locinfo@std@@QAE@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z */
468 /* ??0_Locinfo@std@@QEAA@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z */
469 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_bstr, 8)
470 _Locinfo* __thiscall _Locinfo_ctor_bstr(_Locinfo *this, const basic_string_char *locstr)
471 {
472     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, MSVCP_basic_string_char_c_str(locstr));
473 }
474
475 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z */
476 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@PEBD@Z */
477 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cstr(_Locinfo *locinfo, const char *locstr)
478 {
479     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, locstr);
480 }
481
482 /* ??0_Locinfo@std@@QAE@PBD@Z */
483 /* ??0_Locinfo@std@@QEAA@PEBD@Z */
484 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cstr, 8)
485 _Locinfo* __thiscall _Locinfo_ctor_cstr(_Locinfo *this, const char *locstr)
486 {
487     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, locstr);
488 }
489
490 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z */
491 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPEAV12@@Z */
492 void __cdecl _Locinfo__Locinfo_dtor(_Locinfo *locinfo)
493 {
494     TRACE("(%p)\n", locinfo);
495
496     setlocale(LC_ALL, MSVCP_basic_string_char_c_str(&locinfo->oldlocname));
497     MSVCP_basic_string_char_dtor(&locinfo->days);
498     MSVCP_basic_string_char_dtor(&locinfo->months);
499     MSVCP_basic_string_char_dtor(&locinfo->oldlocname);
500     MSVCP_basic_string_char_dtor(&locinfo->newlocname);
501     _Lockit_dtor(&locinfo->lock);
502 }
503
504 /* ??_F_Locinfo@std@@QAEXXZ */
505 /* ??_F_Locinfo@std@@QEAAXXZ */
506 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor, 4)
507 _Locinfo* __thiscall _Locinfo_ctor(_Locinfo *this)
508 {
509     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, "C");
510 }
511
512 /* ??1_Locinfo@std@@QAE@XZ */
513 /* ??1_Locinfo@std@@QEAA@XZ */
514 DEFINE_THISCALL_WRAPPER(_Locinfo_dtor, 4)
515 void __thiscall _Locinfo_dtor(_Locinfo *this)
516 {
517     _Locinfo__Locinfo_dtor(this);
518 }
519
520 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAAV12@PAV12@HPBD@Z */
521 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAEAV12@PEAV12@HPEBD@Z */
522 _Locinfo* __cdecl _Locinfo__Locinfo_Addcats(_Locinfo *locinfo, int category, const char *locstr)
523 {
524     const char *locale = NULL;
525
526     /* This function is probably modifying more global objects */
527     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
528     if(!locstr)
529         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
530
531     MSVCP_basic_string_char_dtor(&locinfo->newlocname);
532
533     if(category)
534         locale = setlocale(LC_ALL, locstr);
535     else
536         locale = setlocale(LC_ALL, NULL);
537
538     if(locale)
539         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, locale);
540     else
541         MSVCP_basic_string_char_ctor_cstr(&locinfo->newlocname, "*");
542
543     return locinfo;
544 }
545
546 /* ?_Addcats@_Locinfo@std@@QAEAAV12@HPBD@Z */
547 /* ?_Addcats@_Locinfo@std@@QEAAAEAV12@HPEBD@Z */
548 DEFINE_THISCALL_WRAPPER(_Locinfo__Addcats, 12)
549 _Locinfo* __thiscall _Locinfo__Addcats(_Locinfo *this, int category, const char *locstr)
550 {
551     return _Locinfo__Locinfo_Addcats(this, category, locstr);
552 }
553
554 /* _Getcoll */
555 ULONGLONG __cdecl _Getcoll(void)
556 {
557     union {
558         _Collvec collvec;
559         ULONGLONG ull;
560     } ret;
561     _locale_t locale = _get_current_locale();
562
563     TRACE("\n");
564
565     ret.collvec.page = locale->locinfo->lc_collate_cp;
566     ret.collvec.handle = locale->locinfo->lc_handle[LC_COLLATE];
567     _free_locale(locale);
568     return ret.ull;
569 }
570
571 /* ?_Getcoll@_Locinfo@std@@QBE?AU_Collvec@@XZ */
572 /* ?_Getcoll@_Locinfo@std@@QEBA?AU_Collvec@@XZ */
573 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcoll, 8)
574 _Collvec* __thiscall _Locinfo__Getcoll(const _Locinfo *this, _Collvec *ret)
575 {
576     ULONGLONG ull = _Getcoll();
577     memcpy(ret, &ull, sizeof(ull));
578     return ret;
579 }
580
581 /* _Getctype */
582 _Ctypevec* __cdecl _Getctype(_Ctypevec *ret)
583 {
584     _locale_t locale = _get_current_locale();
585     short *table;
586
587     TRACE("\n");
588
589     ret->page = locale->locinfo->lc_codepage;
590     ret->handle = locale->locinfo->lc_handle[LC_COLLATE];
591     ret->delfl = TRUE;
592     table = malloc(sizeof(short[256]));
593     if(!table) {
594         _free_locale(locale);
595         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
596     }
597     memcpy(table, locale->locinfo->pctype, sizeof(short[256]));
598     ret->table = table;
599     _free_locale(locale);
600     return ret;
601 }
602
603 /* ?_Getctype@_Locinfo@std@@QBE?AU_Ctypevec@@XZ */
604 /* ?_Getctype@_Locinfo@std@@QEBA?AU_Ctypevec@@XZ */
605 DEFINE_THISCALL_WRAPPER(_Locinfo__Getctype, 8)
606 _Ctypevec* __thiscall _Locinfo__Getctype(const _Locinfo *this, _Ctypevec *ret)
607 {
608     return _Getctype(ret);
609 }
610
611 /* _Getcvt */
612 ULONGLONG __cdecl _Getcvt(void)
613 {
614     _locale_t locale = _get_current_locale();
615     union {
616         _Cvtvec cvtvec;
617         ULONGLONG ull;
618     } ret;
619
620     TRACE("\n");
621
622     ret.cvtvec.page = locale->locinfo->lc_codepage;
623     ret.cvtvec.handle = locale->locinfo->lc_handle[LC_CTYPE];
624     _free_locale(locale);
625     return ret.ull;
626 }
627
628 /* ?_Getcvt@_Locinfo@std@@QBE?AU_Cvtvec@@XZ */
629 /* ?_Getcvt@_Locinfo@std@@QEBA?AU_Cvtvec@@XZ */
630 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcvt, 8)
631 _Cvtvec* __thiscall _Locinfo__Getcvt(const _Locinfo *this, _Cvtvec *ret)
632 {
633     ULONGLONG ull = _Getcvt();
634     memcpy(ret, &ull, sizeof(ull));
635     return ret;
636 }
637
638 /* ?_Getdateorder@_Locinfo@std@@QBEHXZ */
639 /* ?_Getdateorder@_Locinfo@std@@QEBAHXZ */
640 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdateorder, 4)
641 int __thiscall _Locinfo__Getdateorder(const _Locinfo *this)
642 {
643     FIXME("(%p) stub\n", this);
644     return 0;
645 }
646
647 /* ?_Getdays@_Locinfo@std@@QBEPBDXZ */
648 /* ?_Getdays@_Locinfo@std@@QEBAPEBDXZ */
649 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdays, 4)
650 const char* __thiscall _Locinfo__Getdays(_Locinfo *this)
651 {
652     char *days = _Getdays();
653
654     TRACE("(%p)\n", this);
655
656     if(days) {
657         MSVCP_basic_string_char_dtor(&this->days);
658         MSVCP_basic_string_char_ctor_cstr(&this->days, days);
659         free(days);
660     }
661
662     return this->days.size ? MSVCP_basic_string_char_c_str(&this->days) :
663         ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
664 }
665
666 /* ?_Getmonths@_Locinfo@std@@QBEPBDXZ */
667 /* ?_Getmonths@_Locinfo@std@@QEBAPEBDXZ */
668 DEFINE_THISCALL_WRAPPER(_Locinfo__Getmonths, 4)
669 const char* __thiscall _Locinfo__Getmonths(_Locinfo *this)
670 {
671     char *months = _Getmonths();
672
673     TRACE("(%p)\n", this);
674
675     if(months) {
676         MSVCP_basic_string_char_dtor(&this->months);
677         MSVCP_basic_string_char_ctor_cstr(&this->months, months);
678         free(months);
679     }
680
681     return this->months.size ? MSVCP_basic_string_char_c_str(&this->months) :
682         ":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June:Jul:July"
683         ":Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
684 }
685
686 /* ?_Getfalse@_Locinfo@std@@QBEPBDXZ */
687 /* ?_Getfalse@_Locinfo@std@@QEBAPEBDXZ */
688 DEFINE_THISCALL_WRAPPER(_Locinfo__Getfalse, 4)
689 const char* __thiscall _Locinfo__Getfalse(const _Locinfo *this)
690 {
691     TRACE("(%p)\n", this);
692     return "false";
693 }
694
695 /* ?_Gettrue@_Locinfo@std@@QBEPBDXZ */
696 /* ?_Gettrue@_Locinfo@std@@QEBAPEBDXZ */
697 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettrue, 4)
698 const char* __thiscall _Locinfo__Gettrue(const _Locinfo *this)
699 {
700     TRACE("(%p)\n", this);
701     return "true";
702 }
703
704 /* ?_Getlconv@_Locinfo@std@@QBEPBUlconv@@XZ */
705 /* ?_Getlconv@_Locinfo@std@@QEBAPEBUlconv@@XZ */
706 DEFINE_THISCALL_WRAPPER(_Locinfo__Getlconv, 4)
707 const struct lconv* __thiscall _Locinfo__Getlconv(const _Locinfo *this)
708 {
709     TRACE("(%p)\n", this);
710     return localeconv();
711 }
712
713 /* ?_Getname@_Locinfo@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
714 /* ?_Getname@_Locinfo@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
715 DEFINE_THISCALL_WRAPPER(_Locinfo__Getname, 8)
716 basic_string_char* __thiscall _Locinfo__Getname(const _Locinfo *this, basic_string_char *ret)
717 {
718     TRACE("(%p)\n", this);
719
720     MSVCP_basic_string_char_copy_ctor(ret, &this->newlocname);
721     return ret;
722 }
723
724 /* ?_Gettnames@_Locinfo@std@@QBE?AV_Timevec@2@XZ */
725 /* ?_Gettnames@_Locinfo@std@@QEBA?AV_Timevec@2@XZ */
726 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettnames, 8)
727 _Timevec*__thiscall _Locinfo__Gettnames(const _Locinfo *this, _Timevec *ret)
728 {
729     TRACE("(%p)\n", this);
730
731     _Timevec_ctor_timeptr(ret, _Gettnames());
732     return ret;
733 }
734
735 /* ?id@?$collate@D@std@@2V0locale@2@A */
736 locale_id collate_char_id = {0};
737
738 /* ??_7?$collate@D@std@@6B@ */
739 extern const vtable_ptr MSVCP_collate_char_vtable;
740
741 /* ?_Init@?$collate@D@std@@IAEXABV_Locinfo@2@@Z */
742 /* ?_Init@?$collate@D@std@@IEAAXAEBV_Locinfo@2@@Z */
743 DEFINE_THISCALL_WRAPPER(collate_char__Init, 8)
744 void __thiscall collate_char__Init(collate *this, const _Locinfo *locinfo)
745 {
746     TRACE("(%p %p)\n", this, locinfo);
747     _Locinfo__Getcoll(locinfo, &this->coll);
748 }
749
750 /* ??0?$collate@D@std@@IAE@PBDI@Z */
751 /* ??0?$collate@D@std@@IEAA@PEBD_K@Z */
752 DEFINE_THISCALL_WRAPPER(collate_char_ctor_name, 12)
753 collate* __thiscall collate_char_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
754 {
755     _Locinfo locinfo;
756
757     TRACE("(%p %s %lu)\n", this, name, refs);
758
759     locale_facet_ctor_refs(&this->facet, refs);
760     this->facet.vtable = &MSVCP_collate_char_vtable;
761
762     _Locinfo_ctor_cstr(&locinfo, name);
763     collate_char__Init(this, &locinfo);
764     _Locinfo_dtor(&locinfo);
765     return this;
766 }
767
768 /* ??0?$collate@D@std@@QAE@ABV_Locinfo@1@I@Z */
769 /* ??0?$collate@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
770 DEFINE_THISCALL_WRAPPER(collate_char_ctor_locinfo, 12)
771 collate* __thiscall collate_char_ctor_locinfo(collate *this, const _Locinfo *locinfo, MSVCP_size_t refs)
772 {
773     TRACE("(%p %p %lu)\n", this, locinfo, refs);
774
775     locale_facet_ctor_refs(&this->facet, refs);
776     this->facet.vtable = &MSVCP_collate_char_vtable;
777     collate_char__Init(this, locinfo);
778     return this;
779 }
780
781 /* ??0?$collate@D@std@@QAE@I@Z */
782 /* ??0?$collate@D@std@@QEAA@_K@Z */
783 DEFINE_THISCALL_WRAPPER(collate_char_ctor_refs, 8)
784 collate* __thiscall collate_char_ctor_refs(collate *this, MSVCP_size_t refs)
785 {
786     return collate_char_ctor_name(this, "C", refs);
787 }
788
789 /* ??1?$collate@D@std@@MAE@XZ */
790 /* ??1?$collate@D@std@@MEAA@XZ */
791 DEFINE_THISCALL_WRAPPER(collate_char_dtor, 4)
792 void __thiscall collate_char_dtor(collate *this)
793 {
794     TRACE("(%p)\n", this);
795 }
796
797 DEFINE_THISCALL_WRAPPER(collate_char_vector_dtor, 8)
798 collate* __thiscall collate_char_vector_dtor(collate *this, unsigned int flags)
799 {
800     TRACE("(%p %x)\n", this, flags);
801     if(flags & 2) {
802         /* we have an array, with the number of elements stored before the first object */
803         INT_PTR i, *ptr = (INT_PTR *)this-1;
804
805         for(i=*ptr-1; i>=0; i--)
806             collate_char_dtor(this+i);
807         MSVCRT_operator_delete(ptr);
808     } else {
809         collate_char_dtor(this);
810         if(flags & 1)
811             MSVCRT_operator_delete(this);
812     }
813
814     return this;
815 }
816
817 /* ??_F?$collate@D@std@@QAEXXZ */
818 /* ??_F?$collate@D@std@@QEAAXXZ */
819 DEFINE_THISCALL_WRAPPER(collate_char_ctor, 4)
820 collate* __thiscall collate_char_ctor(collate *this)
821 {
822     return collate_char_ctor_name(this, "C", 0);
823 }
824
825 /* ?_Getcat@?$collate@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
826 /* ?_Getcat@?$collate@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
827 MSVCP_size_t __cdecl collate_char__Getcat(const locale_facet **facet, const locale *loc)
828 {
829     TRACE("(%p %p)\n", facet, loc);
830
831     if(facet && !*facet) {
832         *facet = MSVCRT_operator_new(sizeof(collate));
833         if(!*facet) {
834             ERR("Out of memory\n");
835             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
836             return 0;
837         }
838         collate_char_ctor_name((collate*)*facet,
839                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
840     }
841
842     return LC_COLLATE;
843 }
844
845 static collate* collate_char_use_facet(const locale *loc)
846 {
847     static collate *obj = NULL;
848
849     _Lockit lock;
850     const locale_facet *fac;
851
852     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
853     fac = locale__Getfacet(loc, locale_id_operator_size_t(&collate_char_id));
854     if(fac) {
855         _Lockit_dtor(&lock);
856         return (collate*)fac;
857     }
858
859     if(obj) {
860         _Lockit_dtor(&lock);
861         return obj;
862     }
863
864     collate_char__Getcat(&fac, loc);
865     obj = (collate*)fac;
866     locale_facet__Incref(&obj->facet);
867     locale_facet_register(&obj->facet);
868     _Lockit_dtor(&lock);
869
870     return obj;
871 }
872
873 /* _Strcoll */
874 int __cdecl _Strcoll(const char *first1, const char *last1, const char *first2,
875         const char *last2, const _Collvec *coll)
876 {
877     LCID lcid;
878
879     TRACE("(%s %s)\n", debugstr_an(first1, last1-first1), debugstr_an(first2, last2-first2));
880
881     if(coll)
882         lcid = coll->handle;
883     else
884         lcid = ___lc_handle_func()[LC_COLLATE];
885     return CompareStringA(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
886 }
887
888 /* ?do_compare@?$collate@D@std@@MBEHPBD000@Z */
889 /* ?do_compare@?$collate@D@std@@MEBAHPEBD000@Z */
890 DEFINE_THISCALL_WRAPPER(collate_char_do_compare, 20)
891 #define call_collate_char_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
892         (const collate*, const char*, const char*, const char*, const char*), \
893         (this, first1, last1, first2, last2))
894 int __thiscall collate_char_do_compare(const collate *this, const char *first1,
895         const char *last1, const char *first2, const char *last2)
896 {
897     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
898     return _Strcoll(first1, last1, first2, last2, &this->coll);
899 }
900
901 /* ?compare@?$collate@D@std@@QBEHPBD000@Z */
902 /* ?compare@?$collate@D@std@@QEBAHPEBD000@Z */
903 DEFINE_THISCALL_WRAPPER(collate_char_compare, 20)
904 int __thiscall collate_char_compare(const collate *this, const char *first1,
905         const char *last1, const char *first2, const char *last2)
906 {
907     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
908     return call_collate_char_do_compare(this, first1, last1, first2, last2);
909 }
910
911 /* ?do_hash@?$collate@D@std@@MBEJPBD0@Z */
912 /* ?do_hash@?$collate@D@std@@MEBAJPEBD0@Z */
913 DEFINE_THISCALL_WRAPPER(collate_char_do_hash, 12)
914 #define call_collate_char_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
915         (const collate*, const char*, const char*), (this, first, last))
916 LONG __thiscall collate_char_do_hash(const collate *this,
917         const char *first, const char *last)
918 {
919     ULONG ret = 0;
920
921     TRACE("(%p %p %p)\n", this, first, last);
922
923     for(; first<last; first++)
924         ret = (ret<<8 | ret>>24) + *first;
925     return ret;
926 }
927
928 /* ?hash@?$collate@D@std@@QBEJPBD0@Z */
929 /* ?hash@?$collate@D@std@@QEBAJPEBD0@Z */
930 DEFINE_THISCALL_WRAPPER(collate_char_hash, 12)
931 LONG __thiscall collate_char_hash(const collate *this,
932         const char *first, const char *last)
933 {
934     TRACE("(%p %p %p)\n", this, first, last);
935     return call_collate_char_do_hash(this, first, last);
936 }
937
938 /* ?do_transform@?$collate@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
939 /* ?do_transform@?$collate@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
940 DEFINE_THISCALL_WRAPPER(collate_char_do_transform, 16)
941 basic_string_char* __thiscall collate_char_do_transform(const collate *this,
942         basic_string_char *ret, const char *first, const char *last)
943 {
944     FIXME("(%p %p %p) stub\n", this, first, last);
945     return ret;
946 }
947
948 /* ?transform@?$collate@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
949 /* ?transform@?$collate@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
950 DEFINE_THISCALL_WRAPPER(collate_char_transform, 16)
951 basic_string_char* __thiscall collate_char_transform(const collate *this,
952         basic_string_char *ret, const char *first, const char *last)
953 {
954     FIXME("(%p %p %p) stub\n", this, first, last);
955     return ret;
956 }
957
958 /* ?id@?$collate@_W@std@@2V0locale@2@A */
959 locale_id collate_wchar_id = {0};
960 /* ?id@?$collate@G@std@@2V0locale@2@A */
961 locale_id collate_short_id = {0};
962
963 /* ??_7?$collate@_W@std@@6B@ */
964 extern const vtable_ptr MSVCP_collate_wchar_vtable;
965 /* ??_7?$collate@G@std@@6B@ */
966 extern const vtable_ptr MSVCP_collate_short_vtable;
967
968 /* ?_Init@?$collate@_W@std@@IAEXABV_Locinfo@2@@Z */
969 /* ?_Init@?$collate@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
970 /* ?_Init@?$collate@G@std@@IAEXABV_Locinfo@2@@Z */
971 /* ?_Init@?$collate@G@std@@IEAAXAEBV_Locinfo@2@@Z */
972 DEFINE_THISCALL_WRAPPER(collate_wchar__Init, 8)
973 void __thiscall collate_wchar__Init(collate *this, const _Locinfo *locinfo)
974 {
975     TRACE("(%p %p)\n", this, locinfo);
976     _Locinfo__Getcoll(locinfo, &this->coll);
977 }
978
979 /* ??0?$collate@_W@std@@IAE@PBDI@Z */
980 /* ??0?$collate@_W@std@@IEAA@PEBD_K@Z */
981 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_name, 12)
982 collate* __thiscall collate_wchar_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
983 {
984     _Locinfo locinfo;
985
986     TRACE("(%p %s %lu)\n", this, name, refs);
987
988     locale_facet_ctor_refs(&this->facet, refs);
989     this->facet.vtable = &MSVCP_collate_wchar_vtable;
990
991     _Locinfo_ctor_cstr(&locinfo, name);
992     collate_wchar__Init(this, &locinfo);
993     _Locinfo_dtor(&locinfo);
994     return this;
995 }
996
997 /* ??0?$collate@G@std@@IAE@PBDI@Z */
998 /* ??0?$collate@G@std@@IEAA@PEBD_K@Z */
999 DEFINE_THISCALL_WRAPPER(collate_short_ctor_name, 12)
1000 collate* __thiscall collate_short_ctor_name(collate *this, const char *name, MSVCP_size_t refs)
1001 {
1002     collate *ret = collate_wchar_ctor_name(this, name, refs);
1003     ret->facet.vtable = &MSVCP_collate_short_vtable;
1004     return ret;
1005 }
1006
1007 /* ??0?$collate@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1008 /* ??0?$collate@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1009 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_locinfo, 12)
1010 collate* __thiscall collate_wchar_ctor_locinfo(collate *this, const _Locinfo *locinfo, MSVCP_size_t refs)
1011 {
1012     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1013
1014     locale_facet_ctor_refs(&this->facet, refs);
1015     this->facet.vtable = &MSVCP_collate_wchar_vtable;
1016     collate_wchar__Init(this, locinfo);
1017     return this;
1018 }
1019
1020 /* ??0?$collate@G@std@@QAE@ABV_Locinfo@1@I@Z */
1021 /* ??0?$collate@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1022 DEFINE_THISCALL_WRAPPER(collate_short_ctor_locinfo, 12)
1023 collate* __thiscall collate_short_ctor_locinfo(collate *this, const _Locinfo *locinfo, MSVCP_size_t refs)
1024 {
1025     collate *ret = collate_wchar_ctor_locinfo(this, locinfo, refs);
1026     ret->facet.vtable = &MSVCP_collate_short_vtable;
1027     return ret;
1028 }
1029
1030 /* ??0?$collate@_W@std@@QAE@I@Z */
1031 /* ??0?$collate@_W@std@@QEAA@_K@Z */
1032 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor_refs, 8)
1033 collate* __thiscall collate_wchar_ctor_refs(collate *this, MSVCP_size_t refs)
1034 {
1035     return collate_wchar_ctor_name(this, "C", refs);
1036 }
1037
1038 /* ??0?$collate@G@std@@QAE@I@Z */
1039 /* ??0?$collate@G@std@@QEAA@_K@Z */
1040 DEFINE_THISCALL_WRAPPER(collate_short_ctor_refs, 8)
1041 collate* __thiscall collate_short_ctor_refs(collate *this, MSVCP_size_t refs)
1042 {
1043     collate *ret = collate_wchar_ctor_refs(this, refs);
1044     ret->facet.vtable = &MSVCP_collate_short_vtable;
1045     return ret;
1046 }
1047
1048 /* ??1?$collate@_W@std@@MAE@XZ */
1049 /* ??1?$collate@_W@std@@MEAA@XZ */
1050 /* ??1?$collate@G@std@@MAE@XZ */
1051 /* ??1?$collate@G@std@@MEAA@XZ */
1052 DEFINE_THISCALL_WRAPPER(collate_wchar_dtor, 4)
1053 void __thiscall collate_wchar_dtor(collate *this)
1054 {
1055     TRACE("(%p)\n", this);
1056 }
1057
1058 DEFINE_THISCALL_WRAPPER(collate_wchar_vector_dtor, 8)
1059 collate* __thiscall collate_wchar_vector_dtor(collate *this, unsigned int flags)
1060 {
1061     TRACE("(%p %x)\n", this, flags);
1062     if(flags & 2) {
1063         /* we have an array, with the number of elements stored before the first object */
1064         INT_PTR i, *ptr = (INT_PTR *)this-1;
1065
1066         for(i=*ptr-1; i>=0; i--)
1067             collate_wchar_dtor(this+i);
1068         MSVCRT_operator_delete(ptr);
1069     } else {
1070         collate_wchar_dtor(this);
1071         if(flags & 1)
1072             MSVCRT_operator_delete(this);
1073     }
1074
1075     return this;
1076 }
1077
1078 /* ??_F?$collate@_W@std@@QAEXXZ */
1079 /* ??_F?$collate@_W@std@@QEAAXXZ */
1080 DEFINE_THISCALL_WRAPPER(collate_wchar_ctor, 4)
1081 collate* __thiscall collate_wchar_ctor(collate *this)
1082 {
1083     return collate_wchar_ctor_name(this, "C", 0);
1084 }
1085
1086 /* ??_F?$collate@G@std@@QAEXXZ */
1087 /* ??_F?$collate@G@std@@QEAAXXZ */
1088 DEFINE_THISCALL_WRAPPER(collate_short_ctor, 4)
1089 collate* __thiscall collate_short_ctor(collate *this)
1090 {
1091     collate *ret = collate_wchar_ctor(this);
1092     ret->facet.vtable = &MSVCP_collate_short_vtable;
1093     return ret;
1094 }
1095
1096 /* ?_Getcat@?$collate@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1097 /* ?_Getcat@?$collate@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1098 MSVCP_size_t __cdecl collate_wchar__Getcat(const locale_facet **facet, const locale *loc)
1099 {
1100     TRACE("(%p %p)\n", facet, loc);
1101
1102     if(facet && !*facet) {
1103         *facet = MSVCRT_operator_new(sizeof(collate));
1104         if(!*facet) {
1105             ERR("Out of memory\n");
1106             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1107             return 0;
1108         }
1109         collate_wchar_ctor_name((collate*)*facet,
1110                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
1111     }
1112
1113     return LC_COLLATE;
1114 }
1115
1116 static collate* collate_wchar_use_facet(const locale *loc)
1117 {
1118         static collate *obj = NULL;
1119
1120         _Lockit lock;
1121         const locale_facet *fac;
1122
1123         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1124         fac = locale__Getfacet(loc, locale_id_operator_size_t(&collate_wchar_id));
1125         if(fac) {
1126             _Lockit_dtor(&lock);
1127             return (collate*)fac;
1128         }
1129
1130         if(obj) {
1131             _Lockit_dtor(&lock);
1132             return obj;
1133         }
1134
1135         collate_wchar__Getcat(&fac, loc);
1136         obj = (collate*)fac;
1137         locale_facet__Incref(&obj->facet);
1138         locale_facet_register(&obj->facet);
1139         _Lockit_dtor(&lock);
1140
1141         return obj;
1142 }
1143
1144 /* ?_Getcat@?$collate@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1145 /* ?_Getcat@?$collate@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1146 MSVCP_size_t __cdecl collate_short__Getcat(const locale_facet **facet, const locale *loc)
1147 {
1148     if(facet && !*facet) {
1149         collate_wchar__Getcat(facet, loc);
1150         (*(locale_facet**)facet)->vtable = &MSVCP_collate_short_vtable;
1151     }
1152
1153     return LC_COLLATE;
1154 }
1155
1156 static collate* collate_short_use_facet(const locale *loc)
1157 {
1158     static collate *obj = NULL;
1159
1160     _Lockit lock;
1161     const locale_facet *fac;
1162
1163     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1164     fac = locale__Getfacet(loc, locale_id_operator_size_t(&collate_short_id));
1165     if(fac) {
1166         _Lockit_dtor(&lock);
1167         return (collate*)fac;
1168     }
1169
1170     if(obj) {
1171         _Lockit_dtor(&lock);
1172         return obj;
1173     }
1174
1175     collate_short__Getcat(&fac, loc);
1176     obj = (collate*)fac;
1177     locale_facet__Incref(&obj->facet);
1178     locale_facet_register(&obj->facet);
1179     _Lockit_dtor(&lock);
1180
1181     return obj;
1182 }
1183
1184 /* _Wcscoll */
1185 int __cdecl _Wcscoll(const wchar_t *first1, const wchar_t *last1, const wchar_t *first2,
1186         const wchar_t *last2, const _Collvec *coll)
1187 {
1188     LCID lcid;
1189
1190     TRACE("(%s %s)\n", debugstr_wn(first1, last1-first1), debugstr_wn(first2, last2-first2));
1191
1192     if(coll)
1193         lcid = coll->handle;
1194     else
1195         lcid = ___lc_handle_func()[LC_COLLATE];
1196     return CompareStringW(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
1197 }
1198
1199 /* ?do_compare@?$collate@_W@std@@MBEHPB_W000@Z */
1200 /* ?do_compare@?$collate@_W@std@@MEBAHPEB_W000@Z */
1201 /* ?do_compare@?$collate@G@std@@MBEHPBG000@Z */
1202 /* ?do_compare@?$collate@G@std@@MEBAHPEBG000@Z */
1203 DEFINE_THISCALL_WRAPPER(collate_wchar_do_compare, 20)
1204 #define call_collate_wchar_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
1205         (const collate*, const wchar_t*, const wchar_t*, const wchar_t*, const wchar_t*), \
1206         (this, first1, last1, first2, last2))
1207 int __thiscall collate_wchar_do_compare(const collate *this, const wchar_t *first1,
1208         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
1209 {
1210     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
1211     return _Wcscoll(first1, last1, first2, last2, &this->coll);
1212 }
1213
1214 /* ?compare@?$collate@_W@std@@QBEHPB_W000@Z */
1215 /* ?compare@?$collate@_W@std@@QEBAHPEB_W000@Z */
1216 /* ?compare@?$collate@G@std@@QBEHPBG000@Z */
1217 /* ?compare@?$collate@G@std@@QEBAHPEBG000@Z */
1218 DEFINE_THISCALL_WRAPPER(collate_wchar_compare, 20)
1219 int __thiscall collate_wchar_compare(const collate *this, const wchar_t *first1,
1220         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
1221 {
1222     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
1223     return call_collate_wchar_do_compare(this, first1, last1, first2, last2);
1224 }
1225
1226 /* ?do_hash@?$collate@_W@std@@MBEJPB_W0@Z */
1227 /* ?do_hash@?$collate@_W@std@@MEBAJPEB_W0@Z */
1228 /* ?do_hash@?$collate@G@std@@MBEJPBG0@Z */
1229 /* ?do_hash@?$collate@G@std@@MEBAJPEBG0@Z */
1230 DEFINE_THISCALL_WRAPPER(collate_wchar_do_hash, 12)
1231 #define call_collate_wchar_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
1232         (const collate*, const wchar_t*, const wchar_t*), (this, first, last))
1233 LONG __thiscall collate_wchar_do_hash(const collate *this,
1234         const wchar_t *first, const wchar_t *last)
1235 {
1236     ULONG ret = 0;
1237
1238     TRACE("(%p %p %p)\n", this, first, last);
1239
1240     for(; first<last; first++)
1241         ret = (ret<<8 | ret>>24) + *first;
1242     return ret;
1243 }
1244
1245 /* ?hash@?$collate@_W@std@@QBEJPB_W0@Z */
1246 /* ?hash@?$collate@_W@std@@QEBAJPEB_W0@Z */
1247 /* ?hash@?$collate@G@std@@QBEJPBG0@Z */
1248 /* ?hash@?$collate@G@std@@QEBAJPEBG0@Z */
1249 DEFINE_THISCALL_WRAPPER(collate_wchar_hash, 12)
1250 LONG __thiscall collate_wchar_hash(const collate *this,
1251         const wchar_t *first, const wchar_t *last)
1252 {
1253     TRACE("(%p %p %p)\n", this, first, last);
1254     return call_collate_wchar_do_hash(this, first, last);
1255 }
1256
1257 /* ?do_transform@?$collate@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1258 /* ?do_transform@?$collate@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1259 /* ?do_transform@?$collate@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1260 /* ?do_transform@?$collate@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1261 DEFINE_THISCALL_WRAPPER(collate_wchar_do_transform, 16)
1262 basic_string_wchar* __thiscall collate_wchar_do_transform(const collate *this,
1263         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1264 {
1265     FIXME("(%p %p %p) stub\n", this, first, last);
1266     return ret;
1267 }
1268
1269 /* ?transform@?$collate@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
1270 /* ?transform@?$collate@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
1271 /* ?transform@?$collate@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
1272 /* ?transform@?$collate@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
1273 DEFINE_THISCALL_WRAPPER(collate_wchar_transform, 16)
1274 basic_string_wchar* __thiscall collate_wchar_transform(const collate *this,
1275         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
1276 {
1277     FIXME("(%p %p %p) stub\n", this, first, last);
1278     return ret;
1279 }
1280
1281 /* ??_7ctype_base@std@@6B@ */
1282 extern const vtable_ptr MSVCP_ctype_base_vtable;
1283
1284 /* ??0ctype_base@std@@QAE@I@Z */
1285 /* ??0ctype_base@std@@QEAA@_K@Z */
1286 DEFINE_THISCALL_WRAPPER(ctype_base_ctor_refs, 8)
1287 ctype_base* __thiscall ctype_base_ctor_refs(ctype_base *this, MSVCP_size_t refs)
1288 {
1289     TRACE("(%p %lu)\n", this, refs);
1290     locale_facet_ctor_refs(&this->facet, refs);
1291     this->facet.vtable = &MSVCP_ctype_base_vtable;
1292     return this;
1293 }
1294
1295 /* ??_Fctype_base@std@@QAEXXZ */
1296 /* ??_Fctype_base@std@@QEAAXXZ */
1297 DEFINE_THISCALL_WRAPPER(ctype_base_ctor, 4)
1298 ctype_base* __thiscall ctype_base_ctor(ctype_base *this)
1299 {
1300     TRACE("(%p)\n", this);
1301     locale_facet_ctor_refs(&this->facet, 0);
1302     this->facet.vtable = &MSVCP_ctype_base_vtable;
1303     return this;
1304 }
1305
1306 /* ??1ctype_base@std@@UAE@XZ */
1307 /* ??1ctype_base@std@@UEAA@XZ */
1308 DEFINE_THISCALL_WRAPPER(ctype_base_dtor, 4)
1309 void __thiscall ctype_base_dtor(ctype_base *this)
1310 {
1311     TRACE("(%p)\n", this);
1312 }
1313
1314 DEFINE_THISCALL_WRAPPER(ctype_base_vector_dtor, 8)
1315 ctype_base* __thiscall ctype_base_vector_dtor(ctype_base *this, unsigned int flags)
1316 {
1317     TRACE("(%p %x)\n", this, flags);
1318     if(flags & 2) {
1319         /* we have an array, with the number of elements stored before the first object */
1320         INT_PTR i, *ptr = (INT_PTR *)this-1;
1321
1322         for(i=*ptr-1; i>=0; i--)
1323             ctype_base_dtor(this+i);
1324         MSVCRT_operator_delete(ptr);
1325     } else {
1326         ctype_base_dtor(this);
1327         if(flags & 1)
1328             MSVCRT_operator_delete(this);
1329     }
1330
1331     return this;
1332 }
1333
1334 /* ?_Xran@ctype_base@std@@KAXXZ */
1335 void __cdecl ctype_base__Xran(void)
1336 {
1337     throw_exception(EXCEPTION_OUT_OF_RANGE, "out of range in ctype<T>");
1338 }
1339
1340 /* ?id@?$ctype@D@std@@2V0locale@2@A */
1341 locale_id ctype_char_id = {0};
1342 /* ?table_size@?$ctype@D@std@@2IB */
1343 /* ?table_size@?$ctype@D@std@@2_KB */
1344 MSVCP_size_t ctype_char_table_size = 256;
1345
1346 /* ??_7?$ctype@D@std@@6B@ */
1347 extern const vtable_ptr MSVCP_ctype_char_vtable;
1348
1349 /* ?_Id_func@?$ctype@D@std@@SAAAVid@locale@2@XZ */
1350 /* ?_Id_func@?$ctype@D@std@@SAAEAVid@locale@2@XZ */
1351 locale_id* __cdecl ctype_char__Id_func(void)
1352 {
1353     TRACE("()\n");
1354     return &ctype_char_id;
1355 }
1356
1357 /* ?_Init@?$ctype@D@std@@IAEXABV_Locinfo@2@@Z */
1358 /* ?_Init@?$ctype@D@std@@IEAAXAEBV_Locinfo@2@@Z */
1359 DEFINE_THISCALL_WRAPPER(ctype_char__Init, 8)
1360 void __thiscall ctype_char__Init(ctype_char *this, const _Locinfo *locinfo)
1361 {
1362     TRACE("(%p %p)\n", this, locinfo);
1363     _Locinfo__Getctype(locinfo, &this->ctype);
1364 }
1365
1366 /* ?_Tidy@?$ctype@D@std@@IAEXXZ */
1367 /* ?_Tidy@?$ctype@D@std@@IEAAXXZ */
1368 DEFINE_THISCALL_WRAPPER(ctype_char__Tidy, 4)
1369 void __thiscall ctype_char__Tidy(ctype_char *this)
1370 {
1371     TRACE("(%p)\n", this);
1372
1373     if(this->ctype.delfl)
1374         free((short*)this->ctype.table);
1375 }
1376
1377 /* ?classic_table@?$ctype@D@std@@KAPBFXZ */
1378 /* ?classic_table@?$ctype@D@std@@KAPEBFXZ */
1379 const short* __cdecl ctype_char_classic_table(void)
1380 {
1381     TRACE("()\n");
1382     return &((short*)GetProcAddress(GetModuleHandleA("msvcrt.dll"), "_ctype"))[1];
1383 }
1384
1385 /* ??0?$ctype@D@std@@QAE@ABV_Locinfo@1@I@Z */
1386 /* ??0?$ctype@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1387 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_locinfo, 12)
1388 ctype_char* __thiscall ctype_char_ctor_locinfo(ctype_char *this,
1389         const _Locinfo *locinfo, MSVCP_size_t refs)
1390 {
1391     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1392     ctype_base_ctor_refs(&this->base, refs);
1393     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1394     ctype_char__Init(this, locinfo);
1395     return this;
1396 }
1397
1398 /* ??0?$ctype@D@std@@QAE@PBF_NI@Z */
1399 /* ??0?$ctype@D@std@@QEAA@PEBF_N_K@Z */
1400 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_table, 16)
1401 ctype_char* __thiscall ctype_char_ctor_table(ctype_char *this,
1402         const short *table, MSVCP_bool delete, MSVCP_size_t refs)
1403 {
1404     _Locinfo locinfo;
1405
1406     TRACE("(%p %p %d %lu)\n", this, table, delete, refs);
1407
1408     ctype_base_ctor_refs(&this->base, refs);
1409     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
1410
1411     _Locinfo_ctor(&locinfo);
1412     ctype_char__Init(this, &locinfo);
1413     _Locinfo_dtor(&locinfo);
1414
1415     if(table) {
1416         ctype_char__Tidy(this);
1417         this->ctype.table = table;
1418         this->ctype.delfl = delete;
1419     }
1420     return this;
1421 }
1422
1423 /* ??_F?$ctype@D@std@@QAEXXZ */
1424 /* ??_F?$ctype@D@std@@QEAAXXZ */
1425 DEFINE_THISCALL_WRAPPER(ctype_char_ctor, 4)
1426 ctype_char* __thiscall ctype_char_ctor(ctype_char *this)
1427 {
1428     return ctype_char_ctor_table(this, NULL, FALSE, 0);
1429 }
1430
1431 /* ??1?$ctype@D@std@@MAE@XZ */
1432 /* ??1?$ctype@D@std@@MEAA@XZ */
1433 DEFINE_THISCALL_WRAPPER(ctype_char_dtor, 4)
1434 void __thiscall ctype_char_dtor(ctype_char *this)
1435 {
1436     TRACE("(%p)\n", this);
1437     ctype_char__Tidy(this);
1438 }
1439
1440 DEFINE_THISCALL_WRAPPER(ctype_char_vector_dtor, 8)
1441 ctype_char* __thiscall ctype_char_vector_dtor(ctype_char *this, unsigned int flags)
1442 {
1443     TRACE("(%p %x)\n", this, flags);
1444     if(flags & 2) {
1445         /* we have an array, with the number of elements stored before the first object */
1446         INT_PTR i, *ptr = (INT_PTR *)this-1;
1447
1448         for(i=*ptr-1; i>=0; i--)
1449             ctype_char_dtor(this+i);
1450         MSVCRT_operator_delete(ptr);
1451     } else {
1452         ctype_char_dtor(this);
1453         if(flags & 1)
1454             MSVCRT_operator_delete(this);
1455     }
1456
1457     return this;
1458 }
1459
1460 /* ?do_narrow@?$ctype@D@std@@MBEDDD@Z */
1461 /* ?do_narrow@?$ctype@D@std@@MEBADDD@Z */
1462 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow_ch, 12)
1463 #define call_ctype_char_do_narrow_ch(this, ch, unused) CALL_VTBL_FUNC(this, 36, \
1464         char, (const ctype_char*, char, char), (this, ch, unused))
1465 char __thiscall ctype_char_do_narrow_ch(const ctype_char *this, char ch, char unused)
1466 {
1467     TRACE("(%p %c %c)\n", this, ch, unused);
1468     return ch;
1469 }
1470
1471 /* ?do_narrow@?$ctype@D@std@@MBEPBDPBD0DPAD@Z */
1472 /* ?do_narrow@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD@Z */
1473 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow, 20)
1474 #define call_ctype_char_do_narrow(this, first, last, unused, dest) CALL_VTBL_FUNC(this, 32, \
1475         const char*, (const ctype_char*, const char*, const char*, char, char*), \
1476         (this, first, last, unused, dest))
1477 const char* __thiscall ctype_char_do_narrow(const ctype_char *this,
1478         const char *first, const char *last, char unused, char *dest)
1479 {
1480     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1481     memcpy(dest, first, last-first);
1482     return last;
1483 }
1484
1485 /* ?_Do_narrow_s@?$ctype@D@std@@MBEPBDPBD0DPADI@Z */
1486 /* ?_Do_narrow_s@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD_K@Z */
1487 DEFINE_THISCALL_WRAPPER(ctype_char__Do_narrow_s, 24)
1488 #define call_ctype_char__Do_narrow_s(this, first, last, unused, dest, size) CALL_VTBL_FUNC(this, 40, \
1489         const char*, (const ctype_char*, const char*, const char*, char, char*, MSVCP_size_t), \
1490         (this, first, last, unused, dest, size))
1491 const char* __thiscall ctype_char__Do_narrow_s(const ctype_char *this, const char *first,
1492         const char *last, char unused, char *dest, MSVCP_size_t size)
1493 {
1494     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1495     memcpy_s(dest, size, first, last-first);
1496     return last;
1497 }
1498
1499 /* ?narrow@?$ctype@D@std@@QBEDDD@Z */
1500 /* ?narrow@?$ctype@D@std@@QEBADDD@Z */
1501 DEFINE_THISCALL_WRAPPER(ctype_char_narrow_ch, 12)
1502 char __thiscall ctype_char_narrow_ch(const ctype_char *this, char ch, char dflt)
1503 {
1504     TRACE("(%p %c %c)\n", this, ch, dflt);
1505     return call_ctype_char_do_narrow_ch(this, ch, dflt);
1506 }
1507
1508 /* ?narrow@?$ctype@D@std@@QBEPBDPBD0DPAD@Z */
1509 /* ?narrow@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD@Z */
1510 DEFINE_THISCALL_WRAPPER(ctype_char_narrow, 20)
1511 const char* __thiscall ctype_char_narrow(const ctype_char *this,
1512         const char *first, const char *last, char dflt, char *dest)
1513 {
1514     TRACE("(%p %p %p %c %p)\n", this, first, last, dflt, dest);
1515     return call_ctype_char_do_narrow(this, first, last, dflt, dest);
1516 }
1517
1518 /* ?_Narrow_s@?$ctype@D@std@@QBEPBDPBD0DPADI@Z */
1519 /* ?_Narrow_s@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD_K@Z */
1520 DEFINE_THISCALL_WRAPPER(ctype_char__Narrow_s, 24)
1521 const char* __thiscall ctype_char__Narrow_s(const ctype_char *this, const char *first,
1522         const char *last, char dflt, char *dest, MSVCP_size_t size)
1523 {
1524     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1525     return call_ctype_char__Do_narrow_s(this, first, last, dflt, dest, size);
1526 }
1527
1528 /* ?do_widen@?$ctype@D@std@@MBEDD@Z */
1529 /* ?do_widen@?$ctype@D@std@@MEBADD@Z */
1530 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen_ch, 8)
1531 #define call_ctype_char_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1532         char, (const ctype_char*, char), (this, ch))
1533 char __thiscall ctype_char_do_widen_ch(const ctype_char *this, char ch)
1534 {
1535     TRACE("(%p %c)\n", this, ch);
1536     return ch;
1537 }
1538
1539 /* ?do_widen@?$ctype@D@std@@MBEPBDPBD0PAD@Z */
1540 /* ?do_widen@?$ctype@D@std@@MEBAPEBDPEBD0PEAD@Z */
1541 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen, 16)
1542 #define call_ctype_char_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 20, \
1543         const char*, (const ctype_char*, const char*, const char*, char*), \
1544         (this, first, last, dest))
1545 const char* __thiscall ctype_char_do_widen(const ctype_char *this,
1546         const char *first, const char *last, char *dest)
1547 {
1548     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1549     memcpy(dest, first, last-first);
1550     return last;
1551 }
1552
1553 /* ?_Do_widen_s@?$ctype@D@std@@MBEPBDPBD0PADI@Z */
1554 /* ?_Do_widen_s@?$ctype@D@std@@MEBAPEBDPEBD0PEAD_K@Z */
1555 DEFINE_THISCALL_WRAPPER(ctype_char__Do_widen_s, 20)
1556 #define call_ctype_char__Do_widen_s(this, first, last, dest, size) CALL_VTBL_FUNC(this, 28, \
1557         const char*, (const ctype_char*, const char*, const char*, char*, MSVCP_size_t), \
1558         (this, first, last, dest, size))
1559 const char* __thiscall ctype_char__Do_widen_s(const ctype_char *this,
1560         const char *first, const char *last, char *dest, MSVCP_size_t size)
1561 {
1562     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1563     memcpy_s(dest, size, first, last-first);
1564     return last;
1565 }
1566
1567 /* ?widen@?$ctype@D@std@@QBEDD@Z */
1568 /* ?widen@?$ctype@D@std@@QEBADD@Z */
1569 DEFINE_THISCALL_WRAPPER(ctype_char_widen_ch, 8)
1570 char __thiscall ctype_char_widen_ch(const ctype_char *this, char ch)
1571 {
1572     TRACE("(%p %c)\n", this, ch);
1573     return call_ctype_char_do_widen_ch(this, ch);
1574 }
1575
1576 /* ?widen@?$ctype@D@std@@QBEPBDPBD0PAD@Z */
1577 /* ?widen@?$ctype@D@std@@QEBAPEBDPEBD0PEAD@Z */
1578 DEFINE_THISCALL_WRAPPER(ctype_char_widen, 16)
1579 const char* __thiscall ctype_char_widen(const ctype_char *this,
1580         const char *first, const char *last, char *dest)
1581 {
1582     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1583     return call_ctype_char_do_widen(this, first, last, dest);
1584 }
1585
1586 /* ?_Widen_s@?$ctype@D@std@@QBEPBDPBD0PADI@Z */
1587 /* ?_Widen_s@?$ctype@D@std@@QEBAPEBDPEBD0PEAD_K@Z */
1588 DEFINE_THISCALL_WRAPPER(ctype_char__Widen_s, 20)
1589 const char* __thiscall ctype_char__Widen_s(const ctype_char *this,
1590         const char *first, const char *last, char *dest, MSVCP_size_t size)
1591 {
1592     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
1593     return call_ctype_char__Do_widen_s(this, first, last, dest, size);
1594 }
1595
1596 /* ?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1597 /* ?_Getcat@?$ctype@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1598 MSVCP_size_t __cdecl ctype_char__Getcat(const locale_facet **facet, const locale *loc)
1599 {
1600     TRACE("(%p %p)\n", facet, loc);
1601
1602     if(facet && !*facet) {
1603         _Locinfo locinfo;
1604
1605         *facet = MSVCRT_operator_new(sizeof(ctype_char));
1606         if(!*facet) {
1607             ERR("Out of memory\n");
1608             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1609             return 0;
1610         }
1611
1612         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
1613         ctype_char_ctor_locinfo((ctype_char*)*facet, &locinfo, 0);
1614         _Locinfo_dtor(&locinfo);
1615     }
1616
1617     return LC_CTYPE;
1618 }
1619
1620 ctype_char* ctype_char_use_facet(const locale *loc)
1621 {
1622     static ctype_char *obj = NULL;
1623
1624     _Lockit lock;
1625     const locale_facet *fac;
1626
1627     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1628     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_char_id));
1629     if(fac) {
1630         _Lockit_dtor(&lock);
1631         return (ctype_char*)fac;
1632     }
1633
1634     if(obj) {
1635         _Lockit_dtor(&lock);
1636         return obj;
1637     }
1638
1639     ctype_char__Getcat(&fac, loc);
1640     obj = (ctype_char*)fac;
1641     locale_facet__Incref(&obj->base.facet);
1642     locale_facet_register(&obj->base.facet);
1643     _Lockit_dtor(&lock);
1644
1645     return obj;
1646 }
1647
1648 /* _Tolower */
1649 int __cdecl _Tolower(int ch, const _Ctypevec *ctype)
1650 {
1651     unsigned int cp;
1652
1653     TRACE("%d %p\n", ch, ctype);
1654
1655     if(ctype)
1656         cp = ctype->page;
1657     else
1658         cp = ___lc_codepage_func();
1659
1660     /* Don't convert to unicode in case of C locale */
1661     if(!cp) {
1662         if(ch>='A' && ch<='Z')
1663             ch = ch-'A'+'a';
1664         return ch;
1665     } else {
1666         WCHAR wide, lower;
1667         char str[2];
1668         int size;
1669
1670         if(ch > 255) {
1671             str[0] = (ch>>8) & 255;
1672             str[1] = ch & 255;
1673             size = 2;
1674         } else {
1675             str[0] = ch & 255;
1676             size = 1;
1677         }
1678
1679         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1680             return ch;
1681
1682         lower = tolowerW(wide);
1683         if(lower == wide)
1684             return ch;
1685
1686         WideCharToMultiByte(cp, 0, &lower, 1, str, 2, NULL, NULL);
1687
1688         return str[0] + (str[1]<<8);
1689     }
1690 }
1691
1692 /* ?do_tolower@?$ctype@D@std@@MBEDD@Z */
1693 /* ?do_tolower@?$ctype@D@std@@MEBADD@Z */
1694 #define call_ctype_char_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 8, \
1695         char, (const ctype_char*, char), (this, ch))
1696 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower_ch, 8)
1697 char __thiscall ctype_char_do_tolower_ch(const ctype_char *this, char ch)
1698 {
1699     TRACE("(%p %c)\n", this, ch);
1700     return _Tolower(ch, &this->ctype);
1701 }
1702
1703 /* ?do_tolower@?$ctype@D@std@@MBEPBDPADPBD@Z */
1704 /* ?do_tolower@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1705 #define call_ctype_char_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 4, \
1706         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1707 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower, 12)
1708 const char* __thiscall ctype_char_do_tolower(const ctype_char *this, char *first, const char *last)
1709 {
1710     TRACE("(%p %p %p)\n", this, first, last);
1711     for(; first<last; first++)
1712         *first = _Tolower(*first, &this->ctype);
1713     return last;
1714 }
1715
1716 /* ?tolower@?$ctype@D@std@@QBEDD@Z */
1717 /* ?tolower@?$ctype@D@std@@QEBADD@Z */
1718 DEFINE_THISCALL_WRAPPER(ctype_char_tolower_ch, 8)
1719 char __thiscall ctype_char_tolower_ch(const ctype_char *this, char ch)
1720 {
1721     TRACE("(%p %c)\n", this, ch);
1722     return call_ctype_char_do_tolower_ch(this, ch);
1723 }
1724
1725 /* ?tolower@?$ctype@D@std@@QBEPBDPADPBD@Z */
1726 /* ?tolower@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1727 DEFINE_THISCALL_WRAPPER(ctype_char_tolower, 12)
1728 const char* __thiscall ctype_char_tolower(const ctype_char *this, char *first, const char *last)
1729 {
1730     TRACE("(%p %p %p)\n", this, first, last);
1731     return call_ctype_char_do_tolower(this, first, last);
1732 }
1733
1734 /* _Toupper */
1735 int __cdecl _Toupper(int ch, const _Ctypevec *ctype)
1736 {
1737     unsigned int cp;
1738
1739     TRACE("%d %p\n", ch, ctype);
1740
1741     if(ctype)
1742         cp = ctype->page;
1743     else
1744         cp = ___lc_codepage_func();
1745
1746     /* Don't convert to unicode in case of C locale */
1747     if(!cp) {
1748         if(ch>='a' && ch<='z')
1749             ch = ch-'a'+'A';
1750         return ch;
1751     } else {
1752         WCHAR wide, upper;
1753         char str[2];
1754         int size;
1755
1756         if(ch > 255) {
1757             str[0] = (ch>>8) & 255;
1758             str[1] = ch & 255;
1759             size = 2;
1760         } else {
1761             str[0] = ch & 255;
1762             size = 1;
1763         }
1764
1765         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1766             return ch;
1767
1768         upper = toupperW(wide);
1769         if(upper == wide)
1770             return ch;
1771
1772         WideCharToMultiByte(cp, 0, &upper, 1, str, 2, NULL, NULL);
1773
1774         return str[0] + (str[1]<<8);
1775     }
1776 }
1777
1778 /* ?do_toupper@?$ctype@D@std@@MBEDD@Z */
1779 /* ?do_toupper@?$ctype@D@std@@MEBADD@Z */
1780 #define call_ctype_char_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 16, \
1781         char, (const ctype_char*, char), (this, ch))
1782 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper_ch, 8)
1783 char __thiscall ctype_char_do_toupper_ch(const ctype_char *this, char ch)
1784 {
1785     TRACE("(%p %c)\n", this, ch);
1786     return _Toupper(ch, &this->ctype);
1787 }
1788
1789 /* ?do_toupper@?$ctype@D@std@@MBEPBDPADPBD@Z */
1790 /* ?do_toupper@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1791 #define call_ctype_char_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 12, \
1792         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1793 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper, 12)
1794 const char* __thiscall ctype_char_do_toupper(const ctype_char *this,
1795         char *first, const char *last)
1796 {
1797     TRACE("(%p %p %p)\n", this, first, last);
1798     for(; first<last; first++)
1799         *first = _Toupper(*first, &this->ctype);
1800     return last;
1801 }
1802
1803 /* ?toupper@?$ctype@D@std@@QBEDD@Z */
1804 /* ?toupper@?$ctype@D@std@@QEBADD@Z */
1805 DEFINE_THISCALL_WRAPPER(ctype_char_toupper_ch, 8)
1806 char __thiscall ctype_char_toupper_ch(const ctype_char *this, char ch)
1807 {
1808     TRACE("(%p %c)\n", this, ch);
1809     return call_ctype_char_do_toupper_ch(this, ch);
1810 }
1811
1812 /* ?toupper@?$ctype@D@std@@QBEPBDPADPBD@Z */
1813 /* ?toupper@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1814 DEFINE_THISCALL_WRAPPER(ctype_char_toupper, 12)
1815 const char* __thiscall ctype_char_toupper(const ctype_char *this, char *first, const char *last)
1816 {
1817     TRACE("(%p %p %p)\n", this, first, last);
1818     return call_ctype_char_do_toupper(this, first, last);
1819 }
1820
1821 /* ?is@?$ctype@D@std@@QBE_NFD@Z */
1822 /* ?is@?$ctype@D@std@@QEBA_NFD@Z */
1823 DEFINE_THISCALL_WRAPPER(ctype_char_is_ch, 12)
1824 MSVCP_bool __thiscall ctype_char_is_ch(const ctype_char *this, short mask, char ch)
1825 {
1826     TRACE("(%p %x %c)\n", this, mask, ch);
1827     return (this->ctype.table[(unsigned char)ch] & mask) != 0;
1828 }
1829
1830 /* ?is@?$ctype@D@std@@QBEPBDPBD0PAF@Z */
1831 /* ?is@?$ctype@D@std@@QEBAPEBDPEBD0PEAF@Z */
1832 DEFINE_THISCALL_WRAPPER(ctype_char_is, 16)
1833 const char* __thiscall ctype_char_is(const ctype_char *this, const char *first, const char *last, short *dest)
1834 {
1835     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1836     for(; first<last; first++)
1837         *dest++ = this->ctype.table[(unsigned char)*first];
1838     return last;
1839 }
1840
1841 /* ?scan_is@?$ctype@D@std@@QBEPBDFPBD0@Z */
1842 /* ?scan_is@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1843 DEFINE_THISCALL_WRAPPER(ctype_char_scan_is, 16)
1844 const char* __thiscall ctype_char_scan_is(const ctype_char *this, short mask, const char *first, const char *last)
1845 {
1846     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1847     for(; first<last; first++)
1848         if(!ctype_char_is_ch(this, mask, *first))
1849             break;
1850     return first;
1851 }
1852
1853 /* ?scan_not@?$ctype@D@std@@QBEPBDFPBD0@Z */
1854 /* ?scan_not@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1855 DEFINE_THISCALL_WRAPPER(ctype_char_scan_not, 16)
1856 const char* __thiscall ctype_char_scan_not(const ctype_char *this, short mask, const char *first, const char *last)
1857 {
1858     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1859     for(; first<last; first++)
1860         if(ctype_char_is_ch(this, mask, *first))
1861             break;
1862     return first;
1863 }
1864
1865 /* ?table@?$ctype@D@std@@IBEPBFXZ */
1866 /* ?table@?$ctype@D@std@@IEBAPEBFXZ */
1867 DEFINE_THISCALL_WRAPPER(ctype_char_table, 4)
1868 const short* __thiscall ctype_char_table(const ctype_char *this)
1869 {
1870     TRACE("(%p)\n", this);
1871     return this->ctype.table;
1872 }
1873
1874 /* ?id@?$ctype@_W@std@@2V0locale@2@A */
1875 locale_id ctype_wchar_id = {0};
1876 /* ?id@?$ctype@G@std@@2V0locale@2@A */
1877 locale_id ctype_short_id = {0};
1878
1879 /* ??_7?$ctype@_W@std@@6B@ */
1880 extern const vtable_ptr MSVCP_ctype_wchar_vtable;
1881 /* ??_7?$ctype@G@std@@6B@ */
1882 extern const vtable_ptr MSVCP_ctype_short_vtable;
1883
1884 /* ?_Id_func@?$ctype@_W@std@@SAAAVid@locale@2@XZ */
1885 /* ?_Id_func@?$ctype@_W@std@@SAAEAVid@locale@2@XZ */
1886 locale_id* __cdecl ctype_wchar__Id_func(void)
1887 {
1888     TRACE("()\n");
1889     return &ctype_wchar_id;
1890 }
1891
1892 /* ?_Id_func@?$ctype@G@std@@SAAAVid@locale@2@XZ */
1893 /* ?_Id_func@?$ctype@G@std@@SAAEAVid@locale@2@XZ */
1894 locale_id* __cdecl ctype_short__Id_func(void)
1895 {
1896     TRACE("()\n");
1897     return &ctype_short_id;
1898 }
1899
1900 /* ?_Init@?$ctype@_W@std@@IAEXABV_Locinfo@2@@Z */
1901 /* ?_Init@?$ctype@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
1902 /* ?_Init@?$ctype@G@std@@IAEXABV_Locinfo@2@@Z */
1903 /* ?_Init@?$ctype@G@std@@IEAAXAEBV_Locinfo@2@@Z */
1904 DEFINE_THISCALL_WRAPPER(ctype_wchar__Init, 8)
1905 void __thiscall ctype_wchar__Init(ctype_wchar *this, const _Locinfo *locinfo)
1906 {
1907     TRACE("(%p %p)\n", this, locinfo);
1908     _Locinfo__Getctype(locinfo, &this->ctype);
1909     _Locinfo__Getcvt(locinfo, &this->cvt);
1910 }
1911
1912 /* ??0?$ctype@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1913 /* ??0?$ctype@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1914 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_locinfo, 12)
1915 ctype_wchar* __thiscall ctype_wchar_ctor_locinfo(ctype_wchar *this,
1916         const _Locinfo *locinfo, MSVCP_size_t refs)
1917 {
1918     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1919     ctype_base_ctor_refs(&this->base, refs);
1920     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1921     ctype_wchar__Init(this, locinfo);
1922     return this;
1923 }
1924
1925 /* ??0?$ctype@G@std@@QAE@ABV_Locinfo@1@I@Z */
1926 /* ??0?$ctype@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1927 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_locinfo, 12)
1928 ctype_wchar* __thiscall ctype_short_ctor_locinfo(ctype_wchar *this,
1929         const _Locinfo *locinfo, MSVCP_size_t refs)
1930 {
1931     ctype_wchar *ret = ctype_wchar_ctor_locinfo(this, locinfo, refs);
1932     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1933     return ret;
1934 }
1935
1936 /* ??0?$ctype@_W@std@@QAE@I@Z */
1937 /* ??0?$ctype@_W@std@@QEAA@_K@Z */
1938 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_refs, 8)
1939 ctype_wchar* __thiscall ctype_wchar_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1940 {
1941     _Locinfo locinfo;
1942
1943     TRACE("(%p %lu)\n", this, refs);
1944
1945     ctype_base_ctor_refs(&this->base, refs);
1946     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1947
1948     _Locinfo_ctor(&locinfo);
1949     ctype_wchar__Init(this, &locinfo);
1950     _Locinfo_dtor(&locinfo);
1951     return this;
1952 }
1953
1954 /* ??0?$ctype@G@std@@QAE@I@Z */
1955 /* ??0?$ctype@G@std@@QEAA@_K@Z */
1956 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_refs, 8)
1957 ctype_wchar* __thiscall ctype_short_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1958 {
1959     ctype_wchar *ret = ctype_wchar_ctor_refs(this, refs);
1960     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1961     return ret;
1962 }
1963
1964 /* ??0?$ctype@G@std@@IAE@PBDI@Z */
1965 /* ??0?$ctype@G@std@@IEAA@PEBD_K@Z */
1966 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_name, 12)
1967 ctype_wchar* __thiscall ctype_short_ctor_name(ctype_wchar *this,
1968     const char *name, MSVCP_size_t refs)
1969 {
1970     _Locinfo locinfo;
1971
1972     TRACE("(%p %s %lu)\n", this, debugstr_a(name), refs);
1973
1974     ctype_base_ctor_refs(&this->base, refs);
1975     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1976
1977     _Locinfo_ctor_cstr(&locinfo, name);
1978     ctype_wchar__Init(this, &locinfo);
1979     _Locinfo_dtor(&locinfo);
1980     return this;
1981 }
1982
1983 /* ??_F?$ctype@_W@std@@QAEXXZ */
1984 /* ??_F?$ctype@_W@std@@QEAAXXZ */
1985 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor, 4)
1986 ctype_wchar* __thiscall ctype_wchar_ctor(ctype_wchar *this)
1987 {
1988     TRACE("(%p)\n", this);
1989     return ctype_short_ctor_refs(this, 0);
1990 }
1991
1992 /* ??_F?$ctype@G@std@@QAEXXZ */
1993 /* ??_F?$ctype@G@std@@QEAAXXZ */
1994 DEFINE_THISCALL_WRAPPER(ctype_short_ctor, 4)
1995 ctype_wchar* __thiscall ctype_short_ctor(ctype_wchar *this)
1996 {
1997     ctype_wchar *ret = ctype_wchar_ctor(this);
1998     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1999     return ret;
2000 }
2001
2002 /* ??1?$ctype@_W@std@@MAE@XZ */
2003 /* ??1?$ctype@_W@std@@MEAA@XZ */
2004 /* ??1?$ctype@G@std@@MAE@XZ */
2005 /* ??1?$ctype@G@std@@MEAA@XZ */
2006 DEFINE_THISCALL_WRAPPER(ctype_wchar_dtor, 4)
2007 void __thiscall ctype_wchar_dtor(ctype_wchar *this)
2008 {
2009     TRACE("(%p)\n", this);
2010     if(this->ctype.delfl)
2011         free((void*)this->ctype.table);
2012 }
2013
2014 DEFINE_THISCALL_WRAPPER(ctype_wchar_vector_dtor, 8)
2015 ctype_wchar* __thiscall ctype_wchar_vector_dtor(ctype_wchar *this, unsigned int flags)
2016 {
2017     TRACE("(%p %x)\n", this, flags);
2018     if(flags & 2) {
2019         /* we have an array, with the number of elements stored before the first object */
2020         INT_PTR i, *ptr = (INT_PTR *)this-1;
2021
2022         for(i=*ptr-1; i>=0; i--)
2023             ctype_wchar_dtor(this+i);
2024         MSVCRT_operator_delete(ptr);
2025     } else {
2026         ctype_wchar_dtor(this);
2027         if(flags & 1)
2028             MSVCRT_operator_delete(this);
2029     }
2030
2031     return this;
2032 }
2033
2034 /* _Wcrtomb */
2035 int __cdecl _Wcrtomb(char *s, wchar_t wch, int *state, const _Cvtvec *cvt)
2036 {
2037     int cp, size;
2038     BOOL def;
2039
2040     TRACE("%p %d %p %p\n", s, wch, state, cvt);
2041
2042     if(cvt)
2043         cp = cvt->page;
2044     else
2045         cp = ___lc_codepage_func();
2046
2047     if(!cp) {
2048         if(wch > 255) {
2049            *_errno() = EILSEQ;
2050            return -1;
2051         }
2052
2053         *s = wch & 255;
2054         return 1;
2055     }
2056
2057     size = WideCharToMultiByte(cp, 0, &wch, 1, s, MB_LEN_MAX, NULL, &def);
2058     if(!size || def) {
2059         *_errno() = EILSEQ;
2060         return -1;
2061     }
2062
2063     return size;
2064 }
2065
2066 /* ?_Donarrow@?$ctype@_W@std@@IBED_WD@Z */
2067 /* ?_Donarrow@?$ctype@_W@std@@IEBAD_WD@Z */
2068 /* ?_Donarrow@?$ctype@G@std@@IBEDGD@Z */
2069 /* ?_Donarrow@?$ctype@G@std@@IEBADGD@Z */
2070 DEFINE_THISCALL_WRAPPER(ctype_wchar__Donarrow, 12)
2071 char __thiscall ctype_wchar__Donarrow(const ctype_wchar *this, wchar_t ch, char dflt)
2072 {
2073     char buf[MB_LEN_MAX];
2074
2075     TRACE("(%p %d %d)\n", this, ch, dflt);
2076
2077     return _Wcrtomb(buf, ch, NULL, &this->cvt)==1 ? buf[0] : dflt;
2078 }
2079
2080 /* ?do_narrow@?$ctype@_W@std@@MBED_WD@Z */
2081 /* ?do_narrow@?$ctype@_W@std@@MEBAD_WD@Z */
2082 /* ?do_narrow@?$ctype@G@std@@MBEDGD@Z */
2083 /* ?do_narrow@?$ctype@G@std@@MEBADGD@Z */
2084 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow_ch, 12)
2085 #define call_ctype_wchar_do_narrow_ch(this, ch, dflt) CALL_VTBL_FUNC(this, 52, \
2086         char, (const ctype_wchar*, wchar_t, char), (this, ch, dflt))
2087 char __thiscall ctype_wchar_do_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
2088 {
2089     return ctype_wchar__Donarrow(this, ch, dflt);
2090 }
2091
2092 /* ?do_narrow@?$ctype@_W@std@@MBEPB_WPB_W0DPAD@Z */
2093 /* ?do_narrow@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD@Z */
2094 /* ?do_narrow@?$ctype@G@std@@MBEPBGPBG0DPAD@Z */
2095 /* ?do_narrow@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD@Z */
2096 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow, 20)
2097 #define call_ctype_wchar_do_narrow(this, first, last, dflt, dest) CALL_VTBL_FUNC(this, 48, \
2098         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*), \
2099         (this, first, last, dflt, dest))
2100 const wchar_t* __thiscall ctype_wchar_do_narrow(const ctype_wchar *this,
2101         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
2102 {
2103     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
2104     for(; first<last; first++)
2105         *dest++ = ctype_wchar__Donarrow(this, *first, dflt);
2106     return last;
2107 }
2108
2109 /* ?_Do_narrow_s@?$ctype@_W@std@@MBEPB_WPB_W0DPADI@Z */
2110 /* ?_Do_narrow_s@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD_K@Z */
2111 /* ?_Do_narrow_s@?$ctype@G@std@@MBEPBGPBG0DPADI@Z */
2112 /* ?_Do_narrow_s@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD_K@Z */
2113 DEFINE_THISCALL_WRAPPER(ctype_wchar__Do_narrow_s, 24)
2114 #define call_ctype_wchar__Do_narrow_s(this, first, last, dflt, dest, size) CALL_VTBL_FUNC(this, 56, \
2115         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*, MSVCP_size_t), \
2116         (this, first, last, dflt, dest, size))
2117 const wchar_t* __thiscall ctype_wchar__Do_narrow_s(const ctype_wchar *this,
2118         const wchar_t *first, const wchar_t *last, char dflt, char *dest, MSVCP_size_t size)
2119 {
2120     TRACE("(%p %p %p %d %p %lu)\n", this, first, last, dflt, dest, size);
2121     /* This function converts all multi-byte characters to dflt,
2122      * thanks to it result size is known before converting */
2123     if(last-first > size)
2124         ctype_base__Xran();
2125     return ctype_wchar_do_narrow(this, first, last, dflt, dest);
2126 }
2127
2128 /* ?narrow@?$ctype@_W@std@@QBED_WD@Z */
2129 /* ?narrow@?$ctype@_W@std@@QEBAD_WD@Z */
2130 /* ?narrow@?$ctype@G@std@@QBEDGD@Z */
2131 /* ?narrow@?$ctype@G@std@@QEBADGD@Z */
2132 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow_ch, 12)
2133 char __thiscall ctype_wchar_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
2134 {
2135     TRACE("(%p %d %d)\n", this, ch, dflt);
2136     return call_ctype_wchar_do_narrow_ch(this, ch, dflt);
2137 }
2138
2139 /* ?narrow@?$ctype@_W@std@@QBEPB_WPB_W0DPAD@Z */
2140 /* ?narrow@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD@Z */
2141 /* ?narrow@?$ctype@G@std@@QBEPBGPBG0DPAD@Z */
2142 /* ?narrow@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD@Z */
2143 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow, 20)
2144 const wchar_t* __thiscall ctype_wchar_narrow(const ctype_wchar *this,
2145         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
2146 {
2147     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
2148     return call_ctype_wchar_do_narrow(this, first, last, dflt, dest);
2149 }
2150
2151 /* ?_Narrow_s@?$ctype@_W@std@@QBEPB_WPB_W0DPADI@Z */
2152 /* ?_Narrow_s@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD_K@Z */
2153 /* ?_Narrow_s@?$ctype@G@std@@QBEPBGPBG0DPADI@Z */
2154 /* ?_Narrow_s@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD_K@Z */
2155 DEFINE_THISCALL_WRAPPER(ctype_wchar__Narrow_s, 24)
2156 const wchar_t* __thiscall ctype_wchar__Narrow_s(const ctype_wchar *this, const wchar_t *first,
2157         const wchar_t *last, char dflt, char *dest, MSVCP_size_t size)
2158 {
2159     TRACE("(%p %p %p %d %p %lu)\n", this, first, last, dflt, dest, size);
2160     return call_ctype_wchar__Do_narrow_s(this, first, last, dflt, dest, size);
2161 }
2162
2163 /* _Mbrtowc */
2164 int __cdecl _Mbrtowc(wchar_t *out, const char *in, MSVCP_size_t len, int *state, const _Cvtvec *cvt)
2165 {
2166     int i, cp;
2167     CPINFO cp_info;
2168     BOOL is_lead;
2169
2170     TRACE("(%p %p %lu %p %p)\n", out, in, len, state, cvt);
2171
2172     if(!len)
2173         return 0;
2174
2175     if(cvt)
2176         cp = cvt->page;
2177     else
2178         cp = ___lc_codepage_func();
2179
2180     if(!cp) {
2181         if(out)
2182             *out = (unsigned char)*in;
2183
2184         *state = 0;
2185         return *in ? 1 : 0;
2186     }
2187
2188     if(*state) {
2189         ((char*)state)[1] = *in;
2190
2191         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, (char*)state, 2, out, out ? 1 : 0)) {
2192             *state = 0;
2193             *_errno() = EILSEQ;
2194             return -1;
2195         }
2196
2197         *state = 0;
2198         return 2;
2199     }
2200
2201     GetCPInfo(cp, &cp_info);
2202     is_lead = FALSE;
2203     for(i=0; i<MAX_LEADBYTES; i+=2) {
2204         if(!cp_info.LeadByte[i+1])
2205             break;
2206         if((unsigned char)*in>=cp_info.LeadByte[i] && (unsigned char)*in<=cp_info.LeadByte[i+1]) {
2207             is_lead = TRUE;
2208             break;
2209         }
2210     }
2211
2212     if(is_lead) {
2213         if(len == 1) {
2214             *state = (unsigned char)*in;
2215             return -2;
2216         }
2217
2218         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 2, out, out ? 1 : 0)) {
2219             *_errno() = EILSEQ;
2220             return -1;
2221         }
2222         return 2;
2223     }
2224
2225     if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 1, out, out ? 1 : 0)) {
2226         *_errno() = EILSEQ;
2227         return -1;
2228     }
2229     return 1;
2230 }
2231
2232 /* ?_Dowiden@?$ctype@_W@std@@IBE_WD@Z */
2233 /* ?_Dowiden@?$ctype@_W@std@@IEBA_WD@Z */
2234 /* ?_Dowiden@?$ctype@G@std@@IBEGD@Z */
2235 /* ?_Dowiden@?$ctype@G@std@@IEBAGD@Z */
2236 DEFINE_THISCALL_WRAPPER(ctype_wchar__Dowiden, 8)
2237 wchar_t __thiscall ctype_wchar__Dowiden(const ctype_wchar *this, char ch)
2238 {
2239     wchar_t ret;
2240     int state = 0;
2241     TRACE("(%p %d)\n", this, ch);
2242     return _Mbrtowc(&ret, &ch, 1, &state, &this->cvt)<0 ? WEOF : ret;
2243 }
2244
2245 /* ?do_widen@?$ctype@_W@std@@MBE_WD@Z */
2246 /* ?do_widen@?$ctype@_W@std@@MEBA_WD@Z */
2247 /* ?do_widen@?$ctype@G@std@@MBEGD@Z */
2248 /* ?do_widen@?$ctype@G@std@@MEBAGD@Z */
2249 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen_ch, 8)
2250 #define call_ctype_wchar_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 40, \
2251         wchar_t, (const ctype_wchar*, char), (this, ch))
2252 wchar_t __thiscall ctype_wchar_do_widen_ch(const ctype_wchar *this, char ch)
2253 {
2254     return ctype_wchar__Dowiden(this, ch);
2255 }
2256
2257 /* ?do_widen@?$ctype@_W@std@@MBEPBDPBD0PA_W@Z */
2258 /* ?do_widen@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W@Z */
2259 /* ?do_widen@?$ctype@G@std@@MBEPBDPBD0PAG@Z */
2260 /* ?do_widen@?$ctype@G@std@@MEBAPEBDPEBD0PEAG@Z */
2261 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen, 16)
2262 #define call_ctype_wchar_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 36, \
2263         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*), \
2264         (this, first, last, dest))
2265 const char* __thiscall ctype_wchar_do_widen(const ctype_wchar *this,
2266         const char *first, const char *last, wchar_t *dest)
2267 {
2268     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2269     for(; first<last; first++)
2270         *dest++ = ctype_wchar__Dowiden(this, *first);
2271     return last;
2272 }
2273
2274 /* ?_Do_widen_s@?$ctype@_W@std@@MBEPBDPBD0PA_WI@Z */
2275 /* ?_Do_widen_s@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W_K@Z */
2276 /* ?_Do_widen_s@?$ctype@G@std@@MBEPBDPBD0PAGI@Z */
2277 /* ?_Do_widen_s@?$ctype@G@std@@MEBAPEBDPEBD0PEAG_K@Z */
2278 DEFINE_THISCALL_WRAPPER(ctype_wchar__Do_widen_s, 20)
2279 #define call_ctype_wchar__Do_widen_s(this, first, last, dest, size) CALL_VTBL_FUNC(this, 44, \
2280         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*, MSVCP_size_t), \
2281         (this, first, last, dest, size))
2282 const char* __thiscall ctype_wchar__Do_widen_s(const ctype_wchar *this,
2283         const char *first, const char *last, wchar_t *dest, MSVCP_size_t size)
2284 {
2285     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
2286     /* This function converts all multi-byte characters to WEOF,
2287      * thanks to it result size is known before converting */
2288     if(size < last-first)
2289         ctype_base__Xran();
2290     return ctype_wchar_do_widen(this, first, last, dest);
2291 }
2292
2293 /* ?widen@?$ctype@_W@std@@QBE_WD@Z */
2294 /* ?widen@?$ctype@_W@std@@QEBA_WD@Z */
2295 /* ?widen@?$ctype@G@std@@QBEGD@Z */
2296 /* ?widen@?$ctype@G@std@@QEBAGD@Z */
2297 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen_ch, 8)
2298 wchar_t __thiscall ctype_wchar_widen_ch(const ctype_wchar *this, char ch)
2299 {
2300     TRACE("(%p %d)\n", this, ch);
2301     return call_ctype_wchar_do_widen_ch(this, ch);
2302 }
2303
2304 /* ?widen@?$ctype@_W@std@@QBEPBDPBD0PA_W@Z */
2305 /* ?widen@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W@Z */
2306 /* ?widen@?$ctype@G@std@@QBEPBDPBD0PAG@Z */
2307 /* ?widen@?$ctype@G@std@@QEBAPEBDPEBD0PEAG@Z */
2308 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen, 16)
2309 const char* __thiscall ctype_wchar_widen(const ctype_wchar *this,
2310         const char *first, const char *last, wchar_t *dest)
2311 {
2312     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2313     return call_ctype_wchar_do_widen(this, first, last, dest);
2314 }
2315
2316 /* ?_Widen_s@?$ctype@_W@std@@QBEPBDPBD0PA_WI@Z */
2317 /* ?_Widen_s@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W_K@Z */
2318 /* ?_Widen_s@?$ctype@G@std@@QBEPBDPBD0PAGI@Z */
2319 /* ?_Widen_s@?$ctype@G@std@@QEBAPEBDPEBD0PEAG_K@Z */
2320 DEFINE_THISCALL_WRAPPER(ctype_wchar__Widen_s, 20)
2321 const char* __thiscall ctype_wchar__Widen_s(const ctype_wchar *this,
2322         const char *first, const char *last, wchar_t *dest, MSVCP_size_t size)
2323 {
2324     TRACE("(%p %p %p %p %lu)\n", this, first, last, dest, size);
2325     return call_ctype_wchar__Do_widen_s(this, first, last, dest, size);
2326 }
2327
2328 /* ?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2329 /* ?_Getcat@?$ctype@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2330 MSVCP_size_t __cdecl ctype_wchar__Getcat(const locale_facet **facet, const locale *loc)
2331 {
2332     TRACE("(%p %p)\n", facet, loc);
2333
2334     if(facet && !*facet) {
2335         _Locinfo locinfo;
2336
2337         *facet = MSVCRT_operator_new(sizeof(ctype_wchar));
2338         if(!*facet) {
2339             ERR("Out of memory\n");
2340             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2341             return 0;
2342         }
2343
2344         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
2345         ctype_wchar_ctor_locinfo((ctype_wchar*)*facet, &locinfo, 0);
2346         _Locinfo_dtor(&locinfo);
2347     }
2348
2349     return LC_CTYPE;
2350 }
2351
2352 /* ?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2353 /* ?_Getcat@?$ctype@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2354 MSVCP_size_t __cdecl ctype_short__Getcat(const locale_facet **facet, const locale *loc)
2355 {
2356     if(facet && !*facet) {
2357         ctype_wchar__Getcat(facet, loc);
2358         (*(locale_facet**)facet)->vtable = &MSVCP_ctype_short_vtable;
2359     }
2360
2361     return LC_CTYPE;
2362 }
2363
2364 /* _Towlower */
2365 wchar_t __cdecl _Towlower(wchar_t ch, const _Ctypevec *ctype)
2366 {
2367     TRACE("(%d %p)\n", ch, ctype);
2368     return tolowerW(ch);
2369 }
2370
2371 ctype_wchar* ctype_wchar_use_facet(const locale *loc)
2372 {
2373     static ctype_wchar *obj = NULL;
2374
2375     _Lockit lock;
2376     const locale_facet *fac;
2377
2378     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2379     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_wchar_id));
2380     if(fac) {
2381         _Lockit_dtor(&lock);
2382         return (ctype_wchar*)fac;
2383     }
2384
2385     if(obj) {
2386         _Lockit_dtor(&lock);
2387         return obj;
2388     }
2389
2390     ctype_wchar__Getcat(&fac, loc);
2391     obj = (ctype_wchar*)fac;
2392     locale_facet__Incref(&obj->base.facet);
2393     locale_facet_register(&obj->base.facet);
2394     _Lockit_dtor(&lock);
2395
2396     return obj;
2397 }
2398
2399 ctype_wchar* ctype_short_use_facet(const locale *loc)
2400 {
2401     static ctype_wchar *obj = NULL;
2402
2403     _Lockit lock;
2404     const locale_facet *fac;
2405
2406     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2407     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_short_id));
2408     if(fac) {
2409         _Lockit_dtor(&lock);
2410         return (ctype_wchar*)fac;
2411     }
2412
2413     if(obj) {
2414         _Lockit_dtor(&lock);
2415         return obj;
2416     }
2417
2418     ctype_short__Getcat(&fac, loc);
2419     obj = (ctype_wchar*)fac;
2420     locale_facet__Incref(&obj->base.facet);
2421     locale_facet_register(&obj->base.facet);
2422     _Lockit_dtor(&lock);
2423
2424     return obj;
2425 }
2426
2427 /* ?do_tolower@?$ctype@_W@std@@MBE_W_W@Z */
2428 /* ?do_tolower@?$ctype@_W@std@@MEBA_W_W@Z */
2429 /* ?do_tolower@?$ctype@G@std@@MBEGG@Z */
2430 /* ?do_tolower@?$ctype@G@std@@MEBAGG@Z */
2431 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower_ch, 8)
2432 #define call_ctype_wchar_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
2433         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2434 wchar_t __thiscall ctype_wchar_do_tolower_ch(const ctype_wchar *this, wchar_t ch)
2435 {
2436     return _Towlower(ch, &this->ctype);
2437 }
2438
2439 /* ?do_tolower@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2440 /* ?do_tolower@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2441 /* ?do_tolower@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2442 /* ?do_tolower@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2443 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower, 12)
2444 #define call_ctype_wchar_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 20, \
2445         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2446         (this, first, last))
2447 const wchar_t* __thiscall ctype_wchar_do_tolower(const ctype_wchar *this,
2448         wchar_t *first, const wchar_t *last)
2449 {
2450     TRACE("(%p %p %p)\n", this, first, last);
2451     for(; first<last; first++)
2452         *first = _Towlower(*first, &this->ctype);
2453     return last;
2454 }
2455
2456 /* ?tolower@?$ctype@_W@std@@QBE_W_W@Z */
2457 /* ?tolower@?$ctype@_W@std@@QEBA_W_W@Z */
2458 /* ?tolower@?$ctype@G@std@@QBEGG@Z */
2459 /* ?tolower@?$ctype@G@std@@QEBAGG@Z */
2460 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower_ch, 8)
2461 wchar_t __thiscall ctype_wchar_tolower_ch(const ctype_wchar *this, wchar_t ch)
2462 {
2463     TRACE("(%p %d)\n", this, ch);
2464     return call_ctype_wchar_do_tolower_ch(this, ch);
2465 }
2466
2467 /* ?tolower@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2468 /* ?tolower@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2469 /* ?tolower@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2470 /* ?tolower@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2471 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower, 12)
2472 const wchar_t* __thiscall ctype_wchar_tolower(const ctype_wchar *this,
2473         wchar_t *first, const wchar_t *last)
2474 {
2475     TRACE("(%p %p %p)\n", this, first, last);
2476     return call_ctype_wchar_do_tolower(this, first, last);
2477 }
2478
2479 /* _Towupper */
2480 wchar_t __cdecl _Towupper(wchar_t ch, const _Ctypevec *ctype)
2481 {
2482     TRACE("(%d %p)\n", ch, ctype);
2483     return toupperW(ch);
2484 }
2485
2486 /* ?do_toupper@?$ctype@_W@std@@MBE_W_W@Z */
2487 /* ?do_toupper@?$ctype@_W@std@@MEBA_W_W@Z */
2488 /* ?do_toupper@?$ctype@G@std@@MBEGG@Z */
2489 /* ?do_toupper@?$ctype@G@std@@MEBAGG@Z */
2490 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper_ch, 8)
2491 #define call_ctype_wchar_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 32, \
2492         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
2493 wchar_t __thiscall ctype_wchar_do_toupper_ch(const ctype_wchar *this, wchar_t ch)
2494 {
2495     return _Towupper(ch, &this->ctype);
2496 }
2497
2498 /* ?do_toupper@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
2499 /* ?do_toupper@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
2500 /* ?do_toupper@?$ctype@G@std@@MBEPBGPAGPBG@Z */
2501 /* ?do_toupper@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
2502 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper, 12)
2503 #define call_ctype_wchar_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 28, \
2504         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
2505         (this, first, last))
2506 const wchar_t* __thiscall ctype_wchar_do_toupper(const ctype_wchar *this,
2507         wchar_t *first, const wchar_t *last)
2508 {
2509     TRACE("(%p %p %p)\n", this, first, last);
2510     for(; first<last; first++)
2511         *first = _Towupper(*first, &this->ctype);
2512     return last;
2513 }
2514
2515 /* ?toupper@?$ctype@_W@std@@QBE_W_W@Z */
2516 /* ?toupper@?$ctype@_W@std@@QEBA_W_W@Z */
2517 /* ?toupper@?$ctype@G@std@@QBEGG@Z */
2518 /* ?toupper@?$ctype@G@std@@QEBAGG@Z */
2519 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper_ch, 8)
2520 wchar_t __thiscall ctype_wchar_toupper_ch(const ctype_wchar *this, wchar_t ch)
2521 {
2522     TRACE("(%p %d)\n", this, ch);
2523     return call_ctype_wchar_do_toupper_ch(this, ch);
2524 }
2525
2526 /* ?toupper@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
2527 /* ?toupper@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
2528 /* ?toupper@?$ctype@G@std@@QBEPBGPAGPBG@Z */
2529 /* ?toupper@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
2530 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper, 12)
2531 const wchar_t* __thiscall ctype_wchar_toupper(const ctype_wchar *this,
2532         wchar_t *first, const wchar_t *last)
2533 {
2534     TRACE("(%p %p %p)\n", this, first, last);
2535     return call_ctype_wchar_do_toupper(this, first, last);
2536 }
2537
2538 /* _Getwctypes */
2539 const wchar_t* __cdecl _Getwctypes(const wchar_t *first, const wchar_t *last,
2540         short *mask, const _Ctypevec *ctype)
2541 {
2542     TRACE("(%p %p %p %p)\n", first, last, mask, ctype);
2543     GetStringTypeW(CT_CTYPE1, first, last-first, (WORD*)mask);
2544     return last;
2545 }
2546
2547 /* _Getwctype */
2548 short __cdecl _Getwctype(wchar_t ch, const _Ctypevec *ctype)
2549 {
2550     short mask = 0;
2551     _Getwctypes(&ch, &ch+1, &mask, ctype);
2552     return mask;
2553 }
2554
2555 /* ?do_is@?$ctype@_W@std@@MBE_NF_W@Z */
2556 /* ?do_is@?$ctype@_W@std@@MEBA_NF_W@Z */
2557 /* ?do_is@?$ctype@G@std@@MBE_NFG@Z */
2558 /* ?do_is@?$ctype@G@std@@MEBA_NFG@Z */
2559 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is_ch, 12)
2560 #define call_ctype_wchar_do_is_ch(this, mask, ch) CALL_VTBL_FUNC(this, 8, \
2561         MSVCP_bool, (const ctype_wchar*, short, wchar_t), (this, mask, ch))
2562 MSVCP_bool __thiscall ctype_wchar_do_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2563 {
2564     TRACE("(%p %x %d)\n", this, mask, ch);
2565     return (_Getwctype(ch, &this->ctype) & mask) != 0;
2566 }
2567
2568 /* ?do_is@?$ctype@_W@std@@MBEPB_WPB_W0PAF@Z */
2569 /* ?do_is@?$ctype@_W@std@@MEBAPEB_WPEB_W0PEAF@Z */
2570 /* ?do_is@?$ctype@G@std@@MBEPBGPBG0PAF@Z */
2571 /* ?do_is@?$ctype@G@std@@MEBAPEBGPEBG0PEAF@Z */
2572 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is, 16)
2573 #define call_ctype_wchar_do_is(this, first, last, dest) CALL_VTBL_FUNC(this, 4, \
2574         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, short*), \
2575         (this, first, last, dest))
2576 const wchar_t* __thiscall ctype_wchar_do_is(const ctype_wchar *this,
2577         const wchar_t *first, const wchar_t *last, short *dest)
2578 {
2579     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2580     return _Getwctypes(first, last, dest, &this->ctype);
2581 }
2582
2583 /* ?is@?$ctype@_W@std@@QBE_NF_W@Z */
2584 /* ?is@?$ctype@_W@std@@QEBA_NF_W@Z */
2585 /* ?is@?$ctype@G@std@@QBE_NFG@Z */
2586 /* ?is@?$ctype@G@std@@QEBA_NFG@Z */
2587 DEFINE_THISCALL_WRAPPER(ctype_wchar_is_ch, 12)
2588 MSVCP_bool __thiscall ctype_wchar_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2589 {
2590     TRACE("(%p %x %d)\n", this, mask, ch);
2591     return call_ctype_wchar_do_is_ch(this, mask, ch);
2592 }
2593
2594 /* ?is@?$ctype@_W@std@@QBEPB_WPB_W0PAF@Z */
2595 /* ?is@?$ctype@_W@std@@QEBAPEB_WPEB_W0PEAF@Z */
2596 /* ?is@?$ctype@G@std@@QBEPBGPBG0PAF@Z */
2597 /* ?is@?$ctype@G@std@@QEBAPEBGPEBG0PEAF@Z */
2598 DEFINE_THISCALL_WRAPPER(ctype_wchar_is, 16)
2599 const wchar_t* __thiscall ctype_wchar_is(const ctype_wchar *this,
2600         const wchar_t *first, const wchar_t *last, short *dest)
2601 {
2602     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2603     return call_ctype_wchar_do_is(this, first, last, dest);
2604 }
2605
2606 /* ?do_scan_is@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2607 /* ?do_scan_is@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2608 /* ?do_scan_is@?$ctype@G@std@@MBEPBGFPBG0@Z */
2609 /* ?do_scan_is@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2610 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_is, 16)
2611 #define call_ctype_wchar_do_scan_is(this, mask, first, last) CALL_VTBL_FUNC(this, 12, \
2612         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2613         (this, mask, first, last))
2614 const wchar_t* __thiscall ctype_wchar_do_scan_is(const ctype_wchar *this,
2615         short mask, const wchar_t *first, const wchar_t *last)
2616 {
2617     TRACE("(%p %d %p %p)\n", this, mask, first, last);
2618     for(; first<last; first++)
2619         if(!ctype_wchar_is_ch(this, mask, *first))
2620             break;
2621     return first;
2622 }
2623
2624 /* ?scan_is@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2625 /* ?scan_is@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2626 /* ?scan_is@?$ctype@G@std@@QBEPBGFPBG0@Z */
2627 /* ?scan_is@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2628 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_is, 16)
2629 const wchar_t* __thiscall ctype_wchar_scan_is(const ctype_wchar *this,
2630         short mask, const wchar_t *first, const wchar_t *last)
2631 {
2632     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2633     return call_ctype_wchar_do_scan_is(this, mask, first, last);
2634 }
2635
2636 /* ?do_scan_not@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2637 /* ?do_scan_not@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2638 /* ?do_scan_not@?$ctype@G@std@@MBEPBGFPBG0@Z */
2639 /* ?do_scan_not@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2640 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_not, 16)
2641 #define call_ctype_wchar_do_scan_not(this, mask, first, last) CALL_VTBL_FUNC(this, 16, \
2642         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2643         (this, mask, first, last))
2644 const wchar_t* __thiscall ctype_wchar_do_scan_not(const ctype_wchar *this,
2645         short mask, const wchar_t *first, const wchar_t *last)
2646 {
2647     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2648     for(; first<last; first++)
2649         if(ctype_wchar_is_ch(this, mask, *first))
2650             break;
2651     return first;
2652 }
2653
2654 /* ?scan_not@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2655 /* ?scan_not@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2656 /* ?scan_not@?$ctype@G@std@@QBEPBGFPBG0@Z */
2657 /* ?scan_not@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2658 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_not, 16)
2659 const wchar_t* __thiscall ctype_wchar_scan_not(const ctype_wchar *this,
2660         short mask, const wchar_t *first, const wchar_t *last)
2661 {
2662     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2663     return call_ctype_wchar_do_scan_not(this, mask, first, last);
2664 }
2665
2666 /* ??_7codecvt_base@std@@6B@ */
2667 extern const vtable_ptr MSVCP_codecvt_base_vtable;
2668
2669 /* ??0codecvt_base@std@@QAE@I@Z */
2670 /* ??0codecvt_base@std@@QEAA@_K@Z */
2671 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor_refs, 8)
2672 codecvt_base* __thiscall codecvt_base_ctor_refs(codecvt_base *this, MSVCP_size_t refs)
2673 {
2674     TRACE("(%p %lu)\n", this, refs);
2675     locale_facet_ctor_refs(&this->facet, refs);
2676     this->facet.vtable = &MSVCP_codecvt_base_vtable;
2677     return this;
2678 }
2679
2680 /* ??_Fcodecvt_base@std@@QAEXXZ */
2681 /* ??_Fcodecvt_base@std@@QEAAXXZ */
2682 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor, 4)
2683 codecvt_base* __thiscall codecvt_base_ctor(codecvt_base *this)
2684 {
2685     return codecvt_base_ctor_refs(this, 0);
2686 }
2687
2688 /* ??1codecvt_base@std@@UAE@XZ */
2689 /* ??1codecvt_base@std@@UEAA@XZ */
2690 DEFINE_THISCALL_WRAPPER(codecvt_base_dtor, 4)
2691 void __thiscall codecvt_base_dtor(codecvt_base *this)
2692 {
2693     TRACE("(%p)\n", this);
2694     locale_facet_dtor(&this->facet);
2695 }
2696
2697 DEFINE_THISCALL_WRAPPER(codecvt_base_vector_dtor, 8)
2698 codecvt_base* __thiscall codecvt_base_vector_dtor(codecvt_base *this, unsigned int flags)
2699 {
2700     TRACE("(%p %x)\n", this, flags);
2701     if(flags & 2) {
2702         /* we have an array, with the number of elements stored before the first object */
2703         INT_PTR i, *ptr = (INT_PTR *)this-1;
2704
2705         for(i=*ptr-1; i>=0; i--)
2706             codecvt_base_dtor(this+i);
2707         MSVCRT_operator_delete(ptr);
2708     } else {
2709         codecvt_base_dtor(this);
2710         if(flags & 1)
2711             MSVCRT_operator_delete(this);
2712     }
2713
2714     return this;
2715 }
2716
2717 /* ?do_always_noconv@codecvt_base@std@@MBE_NXZ */
2718 /* ?do_always_noconv@codecvt_base@std@@MEBA_NXZ */
2719 #define call_codecvt_base_do_always_noconv(this) CALL_VTBL_FUNC(this, 4, \
2720         MSVCP_bool, (const codecvt_base*), (this))
2721 DEFINE_THISCALL_WRAPPER(codecvt_base_do_always_noconv, 4)
2722 MSVCP_bool __thiscall codecvt_base_do_always_noconv(const codecvt_base *this)
2723 {
2724     TRACE("(%p)\n", this);
2725     return TRUE;
2726 }
2727
2728 /* ?always_noconv@codecvt_base@std@@QBE_NXZ */
2729 /* ?always_noconv@codecvt_base@std@@QEBA_NXZ */
2730 DEFINE_THISCALL_WRAPPER(codecvt_base_always_noconv, 4)
2731 MSVCP_bool __thiscall codecvt_base_always_noconv(const codecvt_base *this)
2732 {
2733     TRACE("(%p)\n", this);
2734     return call_codecvt_base_do_always_noconv(this);
2735 }
2736
2737 /* ?do_max_length@codecvt_base@std@@MBEHXZ */
2738 /* ?do_max_length@codecvt_base@std@@MEBAHXZ */
2739 #define call_codecvt_base_do_max_length(this) CALL_VTBL_FUNC(this, 8, \
2740         int, (const codecvt_base*), (this))
2741 DEFINE_THISCALL_WRAPPER(codecvt_base_do_max_length, 4)
2742 int __thiscall codecvt_base_do_max_length(const codecvt_base *this)
2743 {
2744     TRACE("(%p)\n", this);
2745     return 1;
2746 }
2747
2748 /* ?max_length@codecvt_base@std@@QBEHXZ */
2749 /* ?max_length@codecvt_base@std@@QEBAHXZ */
2750 DEFINE_THISCALL_WRAPPER(codecvt_base_max_length, 4)
2751 int __thiscall codecvt_base_max_length(const codecvt_base *this)
2752 {
2753     TRACE("(%p)\n", this);
2754     return call_codecvt_base_do_max_length(this);
2755 }
2756
2757 /* ?do_encoding@codecvt_base@std@@MBEHXZ */
2758 /* ?do_encoding@codecvt_base@std@@MEBAHXZ */
2759 #define call_codecvt_base_do_encoding(this) CALL_VTBL_FUNC(this, 12, \
2760         int, (const codecvt_base*), (this))
2761 DEFINE_THISCALL_WRAPPER(codecvt_base_do_encoding, 4)
2762 int __thiscall codecvt_base_do_encoding(const codecvt_base *this)
2763 {
2764     TRACE("(%p)\n", this);
2765     return 1;
2766 }
2767
2768 /* ?encoding@codecvt_base@std@@QBEHXZ */
2769 /* ?encoding@codecvt_base@std@@QEBAHXZ */
2770 DEFINE_THISCALL_WRAPPER(codecvt_base_encoding, 4)
2771 int __thiscall codecvt_base_encoding(const codecvt_base *this)
2772 {
2773     TRACE("(%p)\n", this);
2774     return call_codecvt_base_do_encoding(this);
2775 }
2776
2777 /* ?id@?$codecvt@DDH@std@@2V0locale@2@A */
2778 locale_id codecvt_char_id = {0};
2779
2780 /* ??_7?$codecvt@DDH@std@@6B@ */
2781 extern const vtable_ptr MSVCP_codecvt_char_vtable;
2782
2783 /* ?_Init@?$codecvt@DDH@std@@IAEXABV_Locinfo@2@@Z */
2784 /* ?_Init@?$codecvt@DDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2785 DEFINE_THISCALL_WRAPPER(codecvt_char__Init, 8)
2786 void __thiscall codecvt_char__Init(codecvt_char *this, const _Locinfo *locinfo)
2787 {
2788     TRACE("(%p %p)\n", this, locinfo);
2789 }
2790
2791 /* ??0?$codecvt@DDH@std@@QAE@ABV_Locinfo@1@I@Z */
2792 /* ??0?$codecvt@DDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2793 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_locinfo, 12)
2794 codecvt_char* __thiscall codecvt_char_ctor_locinfo(codecvt_char *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2795 {
2796     TRACE("(%p %p %lu)\n", this, locinfo, refs);
2797     codecvt_base_ctor_refs(&this->base, refs);
2798     this->base.facet.vtable = &MSVCP_codecvt_char_vtable;
2799     return this;
2800 }
2801
2802 /* ??0?$codecvt@DDH@std@@QAE@I@Z */
2803 /* ??0?$codecvt@DDH@std@@QEAA@_K@Z */
2804 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_refs, 8)
2805 codecvt_char* __thiscall codecvt_char_ctor_refs(codecvt_char *this, MSVCP_size_t refs)
2806 {
2807     return codecvt_char_ctor_locinfo(this, NULL, refs);
2808 }
2809
2810 /* ??_F?$codecvt@DDH@std@@QAEXXZ */
2811 /* ??_F?$codecvt@DDH@std@@QEAAXXZ */
2812 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor, 4)
2813 codecvt_char* __thiscall codecvt_char_ctor(codecvt_char *this)
2814 {
2815     return codecvt_char_ctor_locinfo(this, NULL, 0);
2816 }
2817
2818 /* ??1?$codecvt@DDH@std@@MAE@XZ */
2819 /* ??1?$codecvt@DDH@std@@MEAA@XZ */
2820 DEFINE_THISCALL_WRAPPER(codecvt_char_dtor, 4)
2821 void __thiscall codecvt_char_dtor(codecvt_char *this)
2822 {
2823     TRACE("(%p)\n", this);
2824     codecvt_base_dtor(&this->base);
2825 }
2826
2827 DEFINE_THISCALL_WRAPPER(codecvt_char_vector_dtor, 8)
2828 codecvt_char* __thiscall codecvt_char_vector_dtor(codecvt_char *this, unsigned int flags)
2829 {
2830     TRACE("(%p %x)\n", this, flags);
2831     if(flags & 2) {
2832         /* we have an array, with the number of elements stored before the first object */
2833         INT_PTR i, *ptr = (INT_PTR *)this-1;
2834
2835         for(i=*ptr-1; i>=0; i--)
2836             codecvt_char_dtor(this+i);
2837         MSVCRT_operator_delete(ptr);
2838     } else {
2839         codecvt_char_dtor(this);
2840         if(flags & 1)
2841             MSVCRT_operator_delete(this);
2842     }
2843
2844     return this;
2845 }
2846
2847 /* ?_Getcat@?$codecvt@DDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2848 /* ?_Getcat@?$codecvt@DDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2849 MSVCP_size_t __cdecl codecvt_char__Getcat(const locale_facet **facet, const locale *loc)
2850 {
2851     TRACE("(%p %p)\n", facet, loc);
2852
2853     if(facet && !*facet) {
2854         *facet = MSVCRT_operator_new(sizeof(codecvt_char));
2855         if(!*facet) {
2856             ERR("Out of memory\n");
2857             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2858             return 0;
2859         }
2860         codecvt_char_ctor((codecvt_char*)*facet);
2861     }
2862
2863     return LC_CTYPE;
2864 }
2865
2866 codecvt_char* codecvt_char_use_facet(const locale *loc)
2867 {
2868     static codecvt_char *obj = NULL;
2869
2870     _Lockit lock;
2871     const locale_facet *fac;
2872
2873     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2874     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_char_id));
2875     if(fac) {
2876         _Lockit_dtor(&lock);
2877         return (codecvt_char*)fac;
2878     }
2879
2880     if(obj) {
2881         _Lockit_dtor(&lock);
2882         return obj;
2883     }
2884
2885     codecvt_char__Getcat(&fac, loc);
2886     obj = (codecvt_char*)fac;
2887     locale_facet__Incref(&obj->base.facet);
2888     locale_facet_register(&obj->base.facet);
2889     _Lockit_dtor(&lock);
2890
2891     return obj;
2892 }
2893
2894 /* ?do_in@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2895 /* ?do_in@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2896 #define call_codecvt_char_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2897     CALL_VTBL_FUNC(this, 16, int, \
2898             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2899             (this, state, from, from_end, from_next, to, to_end, to_next))
2900 DEFINE_THISCALL_WRAPPER(codecvt_char_do_in, 32)
2901 int __thiscall codecvt_char_do_in(const codecvt_char *this, int *state,
2902         const char *from, const char *from_end, const char **from_next,
2903         char *to, char *to_end, char **to_next)
2904 {
2905     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2906             from_next, to, to_end, to_next);
2907     *from_next = from;
2908     *to_next = to;
2909     return CODECVT_noconv;
2910 }
2911
2912 /* ?in@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2913 /* ?in@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2914 DEFINE_THISCALL_WRAPPER(codecvt_char_in, 32)
2915 int __thiscall codecvt_char_in(const codecvt_char *this, int *state,
2916         const char *from, const char *from_end, const char **from_next,
2917         char *to, char *to_end, char **to_next)
2918 {
2919     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2920             from_next, to, to_end, to_next);
2921     return call_codecvt_char_do_in(this, state, from, from_end, from_next,
2922             to, to_end, to_next);
2923 }
2924
2925 /* ?do_out@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2926 /* ?do_out@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2927 #define call_codecvt_char_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2928     CALL_VTBL_FUNC(this, 20, int, \
2929             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2930             (this, state, from, from_end, from_next, to, to_end, to_next))
2931 DEFINE_THISCALL_WRAPPER(codecvt_char_do_out, 32)
2932 int __thiscall codecvt_char_do_out(const codecvt_char *this, int *state,
2933         const char *from, const char *from_end, const char **from_next,
2934         char *to, char *to_end, char **to_next)
2935 {
2936     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2937             from_end, from_next, to, to_end, to_next);
2938     *from_next = from;
2939     *to_next = to;
2940     return CODECVT_noconv;
2941 }
2942
2943 /* ?out@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2944 /* ?out@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2945 DEFINE_THISCALL_WRAPPER(codecvt_char_out, 32)
2946 int __thiscall codecvt_char_out(const codecvt_char *this, int *state,
2947         const char *from, const char *from_end, const char **from_next,
2948         char *to, char *to_end, char **to_next)
2949 {
2950     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2951             from_next, to, to_end, to_next);
2952     return call_codecvt_char_do_out(this, state, from, from_end, from_next,
2953             to, to_end, to_next);
2954 }
2955
2956 /* ?do_unshift@?$codecvt@DDH@std@@MBEHAAHPAD1AAPAD@Z */
2957 /* ?do_unshift@?$codecvt@DDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2958 #define call_codecvt_char_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2959         int, (const codecvt_char*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2960 DEFINE_THISCALL_WRAPPER(codecvt_char_do_unshift, 20)
2961 int __thiscall codecvt_char_do_unshift(const codecvt_char *this,
2962         int *state, char *to, char *to_end, char **to_next)
2963 {
2964     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2965     *to_next = to;
2966     return CODECVT_noconv;
2967 }
2968
2969 /* ?unshift@?$codecvt@DDH@std@@QBEHAAHPAD1AAPAD@Z */
2970 /* ?unshift@?$codecvt@DDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2971 DEFINE_THISCALL_WRAPPER(codecvt_char_unshift, 20)
2972 int __thiscall codecvt_char_unshift(const codecvt_char *this,
2973         int *state, char *to, char *to_end, char **to_next)
2974 {
2975     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2976     return call_codecvt_char_do_unshift(this, state, to, to_end, to_next);
2977 }
2978
2979 /* ?do_length@?$codecvt@DDH@std@@MBEHABHPBD1I@Z */
2980 /* ?do_length@?$codecvt@DDH@std@@MEBAHAEBHPEBD1_K@Z */
2981 #define call_codecvt_char_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2982         int, (const codecvt_char*, const int*, const char*, const char*, MSVCP_size_t), \
2983         (this, state, from, from_end, max))
2984 DEFINE_THISCALL_WRAPPER(codecvt_char_do_length, 20)
2985 int __thiscall codecvt_char_do_length(const codecvt_char *this, const int *state,
2986         const char *from, const char *from_end, MSVCP_size_t max)
2987 {
2988     TRACE("(%p %p %p %p %lu)\n", this, state, from, from_end, max);
2989     return (from_end-from > max ? max : from_end-from);
2990 }
2991
2992 /* ?length@?$codecvt@DDH@std@@QBEHABHPBD1I@Z */
2993 /* ?length@?$codecvt@DDH@std@@QEBAHAEBHPEBD1_K@Z */
2994 DEFINE_THISCALL_WRAPPER(codecvt_char_length, 20)
2995 int __thiscall codecvt_char_length(const codecvt_char *this, const int *state,
2996         const char *from, const char *from_end, MSVCP_size_t max)
2997 {
2998     TRACE("(%p %p %p %p %lu)\n", this, state, from, from_end, max);
2999     return call_codecvt_char_do_length(this, state, from, from_end, max);
3000 }
3001
3002 /* ?id@?$codecvt@_WDH@std@@2V0locale@2@A */
3003 locale_id codecvt_wchar_id = {0};
3004 /* ?id@?$codecvt@GDH@std@@2V0locale@2@A */
3005 locale_id codecvt_short_id = {0};
3006
3007 /* ??_7?$codecvt@_WDH@std@@6B@ */
3008 extern const vtable_ptr MSVCP_codecvt_wchar_vtable;
3009 /* ??_7?$codecvt@GDH@std@@6B@ */
3010 extern const vtable_ptr MSVCP_codecvt_short_vtable;
3011
3012 /* ?_Init@?$codecvt@GDH@std@@IAEXABV_Locinfo@2@@Z */
3013 /* ?_Init@?$codecvt@GDH@std@@IEAAXAEBV_Locinfo@2@@Z */
3014 /* ?_Init@?$codecvt@_WDH@std@@IAEXABV_Locinfo@2@@Z */
3015 /* ?_Init@?$codecvt@_WDH@std@@IEAAXAEBV_Locinfo@2@@Z */
3016 DEFINE_THISCALL_WRAPPER(codecvt_wchar__Init, 8)
3017 void __thiscall codecvt_wchar__Init(codecvt_wchar *this, const _Locinfo *locinfo)
3018 {
3019     TRACE("(%p %p)\n", this, locinfo);
3020     _Locinfo__Getcvt(locinfo, &this->cvt);
3021 }
3022
3023 /* ??0?$codecvt@_WDH@std@@QAE@ABV_Locinfo@1@I@Z */
3024 /* ??0?$codecvt@_WDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3025 DEFINE_THISCALL_WRAPPER(codecvt_wchar_ctor_locinfo, 12)
3026 codecvt_wchar* __thiscall codecvt_wchar_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
3027 {
3028     TRACE("(%p %p %ld)\n", this, locinfo, refs);
3029
3030     codecvt_base_ctor_refs(&this->base, refs);
3031     this->base.facet.vtable = &MSVCP_codecvt_wchar_vtable;
3032
3033     codecvt_wchar__Init(this, locinfo);
3034     return this;
3035 }
3036
3037 /* ??0?$codecvt@GDH@std@@QAE@ABV_Locinfo@1@I@Z */
3038 /* ??0?$codecvt@GDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3039 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_locinfo, 12)
3040 codecvt_wchar* __thiscall codecvt_short_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
3041 {
3042     TRACE("(%p %p %ld)\n", this, locinfo, refs);
3043
3044     codecvt_wchar_ctor_locinfo(this, locinfo, refs);
3045     this->base.facet.vtable = &MSVCP_codecvt_short_vtable;
3046     return this;
3047 }
3048
3049 /* ??0?$codecvt@_WDH@std@@QAE@I@Z */
3050 /* ??0?$codecvt@_WDH@std@@QEAA@_K@Z */
3051 DEFINE_THISCALL_WRAPPER(codecvt_wchar_ctor_refs, 8)
3052 codecvt_wchar* __thiscall codecvt_wchar_ctor_refs(codecvt_wchar *this, MSVCP_size_t refs)
3053 {
3054     _Locinfo locinfo;
3055
3056     TRACE("(%p %ld)\n", this, refs);
3057
3058     _Locinfo_ctor(&locinfo);
3059     codecvt_wchar_ctor_locinfo(this, &locinfo, refs);
3060     _Locinfo_dtor(&locinfo);
3061     return this;
3062 }
3063
3064 /* ??0?$codecvt@GDH@std@@QAE@I@Z */
3065 /* ??0?$codecvt@GDH@std@@QEAA@_K@Z */
3066 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_refs, 8)
3067 codecvt_wchar* __thiscall codecvt_short_ctor_refs(codecvt_wchar *this, MSVCP_size_t refs)
3068 {
3069     _Locinfo locinfo;
3070
3071     TRACE("(%p %ld)\n", this, refs);
3072
3073     _Locinfo_ctor(&locinfo);
3074     codecvt_short_ctor_locinfo(this, &locinfo, refs);
3075     _Locinfo_dtor(&locinfo);
3076     return this;
3077 }
3078
3079 /* ??0?$codecvt@GDH@std@@IAE@PBDI@Z */
3080 /* ??0?$codecvt@GDH@std@@IEAA@PEBD_K@Z */
3081 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_name, 12)
3082 codecvt_wchar* __thiscall codecvt_short_ctor_name(codecvt_wchar *this, const char *name, MSVCP_size_t refs)
3083 {
3084     _Locinfo locinfo;
3085
3086     TRACE("(%p %s %ld)\n", this, name, refs);
3087
3088     _Locinfo_ctor_cstr(&locinfo, name);
3089     codecvt_short_ctor_locinfo(this, &locinfo, refs);
3090     _Locinfo_dtor(&locinfo);
3091     return this;
3092 }
3093
3094 /* ??_F?$codecvt@_WDH@std@@QAEXXZ */
3095 /* ??_F?$codecvt@_WDH@std@@QEAAXXZ */
3096 DEFINE_THISCALL_WRAPPER(codecvt_wchar_ctor, 4)
3097 codecvt_wchar* __thiscall codecvt_wchar_ctor(codecvt_wchar *this)
3098 {
3099     return codecvt_wchar_ctor_refs(this, 0);
3100 }
3101
3102 /* ??_F?$codecvt@GDH@std@@QAEXXZ */
3103 /* ??_F?$codecvt@GDH@std@@QEAAXXZ */
3104 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor, 4)
3105 codecvt_wchar* __thiscall codecvt_short_ctor(codecvt_wchar *this)
3106 {
3107     return codecvt_short_ctor_refs(this, 0);
3108 }
3109
3110 /* ??1?$codecvt@GDH@std@@MAE@XZ */
3111 /* ??1?$codecvt@GDH@std@@MEAA@XZ */
3112 /* ??1?$codecvt@_WDH@std@@MAE@XZ */
3113 /* ??1?$codecvt@_WDH@std@@MEAA@XZ */
3114 DEFINE_THISCALL_WRAPPER(codecvt_wchar_dtor, 4)
3115 void __thiscall codecvt_wchar_dtor(codecvt_wchar *this)
3116 {
3117     TRACE("(%p)\n", this);
3118     codecvt_base_dtor(&this->base);
3119 }
3120
3121 DEFINE_THISCALL_WRAPPER(codecvt_wchar_vector_dtor, 8)
3122 codecvt_wchar* __thiscall codecvt_wchar_vector_dtor(codecvt_wchar *this, unsigned int flags)
3123 {
3124     TRACE("(%p %x)\n", this, flags);
3125     if(flags & 2) {
3126         /* we have an array, with the number of elements stored before the first object */
3127         INT_PTR i, *ptr = (INT_PTR *)this-1;
3128
3129         for(i=*ptr-1; i>=0; i--)
3130             codecvt_wchar_dtor(this+i);
3131         MSVCRT_operator_delete(ptr);
3132     } else {
3133         codecvt_wchar_dtor(this);
3134         if(flags & 1)
3135             MSVCRT_operator_delete(this);
3136     }
3137
3138     return this;
3139 }
3140
3141 /* ?_Getcat@?$codecvt@_WDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3142 /* ?_Getcat@?$codecvt@_WDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3143 MSVCP_size_t __cdecl codecvt_wchar__Getcat(const locale_facet **facet, const locale *loc)
3144 {
3145     TRACE("(%p %p)\n", facet, loc);
3146
3147     if(facet && !*facet) {
3148         _Locinfo locinfo;
3149
3150         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
3151         if(!*facet) {
3152             ERR("Out of memory\n");
3153             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3154             return 0;
3155         }
3156
3157         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
3158         codecvt_wchar_ctor_locinfo((codecvt_wchar*)*facet, &locinfo, 0);
3159         _Locinfo_dtor(&locinfo);
3160     }
3161
3162     return LC_CTYPE;
3163 }
3164
3165 codecvt_wchar* codecvt_wchar_use_facet(const locale *loc)
3166 {
3167     static codecvt_wchar *obj = NULL;
3168
3169     _Lockit lock;
3170     const locale_facet *fac;
3171
3172     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3173     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_wchar_id));
3174     if(fac) {
3175         _Lockit_dtor(&lock);
3176         return (codecvt_wchar*)fac;
3177     }
3178
3179     if(obj) {
3180         _Lockit_dtor(&lock);
3181         return obj;
3182     }
3183
3184     codecvt_wchar__Getcat(&fac, loc);
3185     obj = (codecvt_wchar*)fac;
3186     locale_facet__Incref(&obj->base.facet);
3187     locale_facet_register(&obj->base.facet);
3188     _Lockit_dtor(&lock);
3189
3190     return obj;
3191 }
3192
3193 /* ?_Getcat@?$codecvt@GDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3194 /* ?_Getcat@?$codecvt@GDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3195 MSVCP_size_t __cdecl codecvt_short__Getcat(const locale_facet **facet, const locale *loc)
3196 {
3197     TRACE("(%p %p)\n", facet, loc);
3198
3199     if(facet && !*facet) {
3200         _Locinfo locinfo;
3201
3202         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
3203         if(!*facet) {
3204             ERR("Out of memory\n");
3205             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3206             return 0;
3207         }
3208
3209         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
3210         codecvt_short_ctor((codecvt_wchar*)*facet);
3211         _Locinfo_dtor(&locinfo);
3212     }
3213
3214     return LC_CTYPE;
3215 }
3216
3217 codecvt_wchar* codecvt_short_use_facet(const locale *loc)
3218 {
3219     static codecvt_wchar *obj = NULL;
3220
3221     _Lockit lock;
3222     const locale_facet *fac;
3223
3224     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3225     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_short_id));
3226     if(fac) {
3227         _Lockit_dtor(&lock);
3228         return (codecvt_wchar*)fac;
3229     }
3230
3231     if(obj) {
3232         _Lockit_dtor(&lock);
3233         return obj;
3234     }
3235
3236     codecvt_short__Getcat(&fac, loc);
3237     obj = (codecvt_wchar*)fac;
3238     locale_facet__Incref(&obj->base.facet);
3239     locale_facet_register(&obj->base.facet);
3240     _Lockit_dtor(&lock);
3241
3242     return obj;
3243 }
3244
3245 /* ?_Id_func@?$codecvt@_WDH@std@@SAAAVid@locale@2@XZ */
3246 /* ?_Id_func@?$codecvt@_WDH@std@@SAAEAVid@locale@2@XZ */
3247 locale_id* __cdecl codecvt_wchar__Id_func(void)
3248 {
3249     TRACE("()\n");
3250     return &codecvt_wchar_id;
3251 }
3252
3253 /* ?_Id_func@?$codecvt@GDH@std@@SAAAVid@locale@2@XZ */
3254 /* ?_Id_func@?$codecvt@GDH@std@@SAAEAVid@locale@2@XZ */
3255 locale_id* __cdecl codecvt_short__Id_func(void)
3256 {
3257     TRACE("()\n");
3258     return &codecvt_short_id;
3259 }
3260
3261 /* ?do_always_noconv@?$codecvt@GDH@std@@MBE_NXZ */
3262 /* ?do_always_noconv@?$codecvt@GDH@std@@MEBA_NXZ */
3263 /* ?do_always_noconv@?$codecvt@_WDH@std@@MBE_NXZ */
3264 /* ?do_always_noconv@?$codecvt@_WDH@std@@MEBA_NXZ */
3265 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_always_noconv, 4)
3266 MSVCP_bool __thiscall codecvt_wchar_do_always_noconv(const codecvt_wchar *this)
3267 {
3268     TRACE("(%p)\n", this);
3269     return FALSE;
3270 }
3271
3272 /* ?do_max_length@?$codecvt@GDH@std@@MBEHXZ */
3273 /* ?do_max_length@?$codecvt@GDH@std@@MEBAHXZ */
3274 /* ?do_max_length@?$codecvt@_WDH@std@@MBEHXZ */
3275 /* ?do_max_length@?$codecvt@_WDH@std@@MEBAHXZ */
3276 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_max_length, 4)
3277 int __thiscall codecvt_wchar_do_max_length(const codecvt_wchar *this)
3278 {
3279     TRACE("(%p)\n", this);
3280     return MB_LEN_MAX;
3281 }
3282
3283 /* ?do_in@?$codecvt@GDH@std@@MBEHAAHPBD1AAPBDPAG3AAPAG@Z */
3284 /* ?do_in@?$codecvt@GDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
3285 /* ?do_in@?$codecvt@_WDH@std@@MBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
3286 /* ?do_in@?$codecvt@_WDH@std@@MEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
3287 #define call_codecvt_wchar_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
3288     CALL_VTBL_FUNC(this, 16, int, \
3289             (const codecvt_wchar*, int*, const char*, const char*, const char**, wchar_t*, wchar_t*, wchar_t**), \
3290             (this, state, from, from_end, from_next, to, to_end, to_next))
3291 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_in, 32)
3292 int __thiscall codecvt_wchar_do_in(const codecvt_wchar *this, int *state,
3293         const char *from, const char *from_end, const char **from_next,
3294         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
3295 {
3296     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
3297             from_end, from_next, to, to_end, to_next);
3298
3299     *from_next = from;
3300     *to_next = to;
3301
3302     while(*from_next!=from_end && *to_next!=to_end) {
3303         switch(_Mbrtowc(*to_next, *from_next, from_end-*from_next, state, &this->cvt)) {
3304         case -2:
3305             *from_next = from_end;
3306             return CODECVT_partial;
3307         case -1:
3308             return CODECVT_error;
3309         case 2:
3310             (*from_next)++;
3311             /* fall through */
3312         case 0:
3313         case 1:
3314             (*from_next)++;
3315             (*to_next)++;
3316         }
3317     }
3318
3319     return CODECVT_ok;
3320 }
3321
3322 /* ?in@?$codecvt@GDH@std@@QBEHAAHPBD1AAPBDPAG3AAPAG@Z */
3323 /* ?in@?$codecvt@GDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
3324 /* ?in@?$codecvt@_WDH@std@@QBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
3325 /* ?in@?$codecvt@_WDH@std@@QEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
3326 DEFINE_THISCALL_WRAPPER(codecvt_wchar_in, 32)
3327 int __thiscall codecvt_wchar_in(const codecvt_wchar *this, int *state,
3328         const char *from, const char *from_end, const char **from_next,
3329         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
3330 {
3331     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
3332             from_end, from_next, to, to_end, to_next);
3333     return call_codecvt_wchar_do_in(this, state, from,
3334             from_end, from_next, to, to_end, to_next);
3335 }
3336
3337 /* ?do_out@?$codecvt@GDH@std@@MBEHAAHPBG1AAPBGPAD3AAPAD@Z */
3338 /* ?do_out@?$codecvt@GDH@std@@MEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
3339 /* ?do_out@?$codecvt@_WDH@std@@MBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
3340 /* ?do_out@?$codecvt@_WDH@std@@MEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
3341 #define call_codecvt_wchar_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
3342     CALL_VTBL_FUNC(this, 20, int, \
3343             (const codecvt_wchar*, int*, const wchar_t*, const wchar_t*, const wchar_t**, char*, char*, char**), \
3344             (this, state, from, from_end, from_next, to, to_end, to_next))
3345 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_out, 32)
3346 int __thiscall codecvt_wchar_do_out(const codecvt_wchar *this, int *state,
3347         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
3348         char *to, char *to_end, char **to_next)
3349 {
3350     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
3351             from_end, from_next, to, to_end, to_next);
3352
3353     *from_next = from;
3354     *to_next = to;
3355
3356     while(*from_next!=from_end && *to_next!=to_end) {
3357         int old_state = *state, size;
3358         char buf[MB_LEN_MAX];
3359
3360         switch((size = _Wcrtomb(buf, **from_next, state, &this->cvt))) {
3361         case -1:
3362             return CODECVT_error;
3363         default:
3364             if(size > from_end-*from_next) {
3365                 *state = old_state;
3366                 return CODECVT_partial;
3367             }
3368
3369             (*from_next)++;
3370             memcpy_s(*to_next, to_end-*to_next, buf, size);
3371             (*to_next) += size;
3372         }
3373     }
3374
3375     return CODECVT_ok;
3376 }
3377
3378 /* ?out@?$codecvt@GDH@std@@QBEHAAHPBG1AAPBGPAD3AAPAD@Z */
3379 /* ?out@?$codecvt@GDH@std@@QEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
3380 /* ?out@?$codecvt@_WDH@std@@QBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
3381 /* ?out@?$codecvt@_WDH@std@@QEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
3382 DEFINE_THISCALL_WRAPPER(codecvt_wchar_out, 32)
3383 int __thiscall codecvt_wchar_out(const codecvt_wchar *this, int *state,
3384         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
3385         char *to, char *to_end, char **to_next)
3386 {
3387     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
3388             from_end, from_next, to, to_end, to_next);
3389     return call_codecvt_wchar_do_out(this, state, from,
3390             from_end, from_next, to, to_end, to_next);
3391 }
3392
3393 /* ?do_unshift@?$codecvt@GDH@std@@MBEHAAHPAD1AAPAD@Z */
3394 /* ?do_unshift@?$codecvt@GDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
3395 /* ?do_unshift@?$codecvt@_WDH@std@@MBEHAAHPAD1AAPAD@Z */
3396 /* ?do_unshift@?$codecvt@_WDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
3397 #define call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
3398         int, (const codecvt_wchar*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
3399 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_unshift, 20)
3400 int __thiscall codecvt_wchar_do_unshift(const codecvt_wchar *this,
3401         int *state, char *to, char *to_end, char **to_next)
3402 {
3403     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
3404     if(*state)
3405         WARN("unexpected state: %x\n", *state);
3406
3407     *to_next = to;
3408     return CODECVT_ok;
3409 }
3410
3411 /* ?unshift@?$codecvt@GDH@std@@QBEHAAHPAD1AAPAD@Z */
3412 /* ?unshift@?$codecvt@GDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
3413 /* ?unshift@?$codecvt@_WDH@std@@QBEHAAHPAD1AAPAD@Z */
3414 /* ?unshift@?$codecvt@_WDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
3415 DEFINE_THISCALL_WRAPPER(codecvt_wchar_unshift, 20)
3416 int __thiscall codecvt_wchar_unshift(const codecvt_wchar *this,
3417         int *state, char *to, char *to_end, char **to_next)
3418 {
3419     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
3420     return call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next);
3421 }
3422
3423 /* ?do_length@?$codecvt@GDH@std@@MBEHABHPBD1I@Z */
3424 /* ?do_length@?$codecvt@GDH@std@@MEBAHAEBHPEBD1_K@Z */
3425 /* ?do_length@?$codecvt@_WDH@std@@MBEHABHPBD1I@Z */
3426 /* ?do_length@?$codecvt@_WDH@std@@MEBAHAEBHPEBD1_K@Z */
3427 #define call_codecvt_wchar_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
3428         int, (const codecvt_wchar*, const int*, const char*, const char*, MSVCP_size_t), \
3429         (this, state, from, from_end, max))
3430 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_length, 20)
3431 int __thiscall codecvt_wchar_do_length(const codecvt_wchar *this, const int *state,
3432         const char *from, const char *from_end, MSVCP_size_t max)
3433 {
3434     int tmp_state = *state, ret=0;
3435
3436     TRACE("(%p %p %p %p %ld)\n", this, state, from, from_end, max);
3437
3438     while(ret<max && from!=from_end) {
3439         switch(_Mbrtowc(NULL, from, from_end-from, &tmp_state, &this->cvt)) {
3440         case -2:
3441         case -1:
3442             return ret;
3443         case 2:
3444             from++;
3445             /* fall through */
3446         case 0:
3447         case 1:
3448             from++;
3449             ret++;
3450         }
3451     }
3452
3453     return ret;
3454 }
3455
3456 /* ?length@?$codecvt@GDH@std@@QBEHABHPBD1I@Z */
3457 /* ?length@?$codecvt@GDH@std@@QEBAHAEBHPEBD1_K@Z */
3458 /* ?length@?$codecvt@_WDH@std@@QBEHABHPBD1I@Z */
3459 /* ?length@?$codecvt@_WDH@std@@QEBAHAEBHPEBD1_K@Z */
3460 DEFINE_THISCALL_WRAPPER(codecvt_wchar_length, 20)
3461 int __thiscall codecvt_wchar_length(const codecvt_wchar *this, const int *state,
3462         const char *from, const char *from_end, MSVCP_size_t max)
3463 {
3464     TRACE("(%p %p %p %p %ld)\n", this, state, from, from_end, max);
3465     return call_codecvt_wchar_do_length(this, state, from, from_end, max);
3466 }
3467
3468 /* ?id@?$numpunct@D@std@@2V0locale@2@A */
3469 locale_id numpunct_char_id = {0};
3470
3471 /* ??_7?$numpunct@D@std@@6B@ */
3472 extern const vtable_ptr MSVCP_numpunct_char_vtable;
3473
3474 /* ?_Init@?$numpunct@D@std@@IAEXABV_Locinfo@2@_N@Z */
3475 /* ?_Init@?$numpunct@D@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3476 DEFINE_THISCALL_WRAPPER(numpunct_char__Init, 12)
3477 void __thiscall numpunct_char__Init(numpunct_char *this, const _Locinfo *locinfo, MSVCP_bool isdef)
3478 {
3479     int len;
3480
3481     TRACE("(%p %p %d)\n", this, locinfo, isdef);
3482
3483     len = strlen(_Locinfo__Getfalse(locinfo))+1;
3484     this->false_name = MSVCRT_operator_new(len);
3485     if(this->false_name)
3486         memcpy((char*)this->false_name, _Locinfo__Getfalse(locinfo), len);
3487
3488     len = strlen(_Locinfo__Gettrue(locinfo))+1;
3489     this->true_name = MSVCRT_operator_new(len);
3490     if(this->true_name)
3491         memcpy((char*)this->true_name, _Locinfo__Gettrue(locinfo), len);
3492
3493     if(isdef) {
3494         this->grouping = MSVCRT_operator_new(1);
3495         if(this->grouping)
3496             *(char*)this->grouping = 0;
3497
3498         this->dp = '.';
3499         this->sep = ',';
3500     } else {
3501         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
3502
3503         len = strlen(lc->grouping)+1;
3504         this->grouping = MSVCRT_operator_new(len);
3505         if(this->grouping)
3506             memcpy((char*)this->grouping, lc->grouping, len);
3507
3508         this->dp = lc->decimal_point[0];
3509         this->sep = lc->thousands_sep[0];
3510     }
3511
3512     if(!this->false_name || !this->true_name || !this->grouping) {
3513         MSVCRT_operator_delete((char*)this->grouping);
3514         MSVCRT_operator_delete((char*)this->false_name);
3515         MSVCRT_operator_delete((char*)this->true_name);
3516
3517         ERR("Out of memory\n");
3518         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3519     }
3520 }
3521
3522 /* ?_Tidy@?$numpunct@D@std@@AAEXXZ */
3523 /* ?_Tidy@?$numpunct@D@std@@AEAAXXZ */
3524 DEFINE_THISCALL_WRAPPER(numpunct_char__Tidy, 4)
3525 void __thiscall numpunct_char__Tidy(numpunct_char *this)
3526 {
3527     TRACE("(%p)\n", this);
3528
3529     MSVCRT_operator_delete((char*)this->grouping);
3530     MSVCRT_operator_delete((char*)this->false_name);
3531     MSVCRT_operator_delete((char*)this->true_name);
3532 }
3533
3534 /* ??0?$numpunct@D@std@@QAE@ABV_Locinfo@1@I_N@Z */
3535 /* ??0?$numpunct@D@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3536 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_locinfo, 16)
3537 numpunct_char* __thiscall numpunct_char_ctor_locinfo(numpunct_char *this,
3538         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3539 {
3540     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3541     locale_facet_ctor_refs(&this->facet, refs);
3542     this->facet.vtable = &MSVCP_numpunct_char_vtable;
3543     numpunct_char__Init(this, locinfo, usedef);
3544     return this;
3545 }
3546
3547 /* ??0?$numpunct@D@std@@IAE@PBDI_N@Z */
3548 /* ??0?$numpunct@D@std@@IEAA@PEBD_K_N@Z */
3549 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_name, 16)
3550 numpunct_char* __thiscall numpunct_char_ctor_name(numpunct_char *this,
3551         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3552 {
3553     _Locinfo locinfo;
3554
3555     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3556     locale_facet_ctor_refs(&this->facet, refs);
3557     this->facet.vtable = &MSVCP_numpunct_char_vtable;
3558
3559     _Locinfo_ctor_cstr(&locinfo, name);
3560     numpunct_char__Init(this, &locinfo, usedef);
3561     _Locinfo_dtor(&locinfo);
3562     return this;
3563 }
3564
3565 /* ??0?$numpunct@D@std@@QAE@I@Z */
3566 /* ??0?$numpunct@D@std@@QEAA@_K@Z */
3567 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor_refs, 8)
3568 numpunct_char* __thiscall numpunct_char_ctor_refs(numpunct_char *this, MSVCP_size_t refs)
3569 {
3570     TRACE("(%p %lu)\n", this, refs);
3571     return numpunct_char_ctor_name(this, "C", refs, FALSE);
3572 }
3573
3574 /* ??_F?$numpunct@D@std@@QAEXXZ */
3575 /* ??_F?$numpunct@D@std@@QEAAXXZ */
3576 DEFINE_THISCALL_WRAPPER(numpunct_char_ctor, 4)
3577 numpunct_char* __thiscall numpunct_char_ctor(numpunct_char *this)
3578 {
3579     return numpunct_char_ctor_refs(this, 0);
3580 }
3581
3582 /* ??1?$numpunct@D@std@@MAE@XZ */
3583 /* ??1?$numpunct@D@std@@MEAA@XZ */
3584 DEFINE_THISCALL_WRAPPER(numpunct_char_dtor, 4)
3585 void __thiscall numpunct_char_dtor(numpunct_char *this)
3586 {
3587     TRACE("(%p)\n", this);
3588     numpunct_char__Tidy(this);
3589 }
3590
3591 DEFINE_THISCALL_WRAPPER(numpunct_char_vector_dtor, 8)
3592 numpunct_char* __thiscall numpunct_char_vector_dtor(numpunct_char *this, unsigned int flags)
3593 {
3594     TRACE("(%p %x)\n", this, flags);
3595     if(flags & 2) {
3596         /* we have an array, with the number of elements stored before the first object */
3597         INT_PTR i, *ptr = (INT_PTR *)this-1;
3598
3599         for(i=*ptr-1; i>=0; i--)
3600             numpunct_char_dtor(this+i);
3601         MSVCRT_operator_delete(ptr);
3602     } else {
3603         numpunct_char_dtor(this);
3604         if(flags & 1)
3605             MSVCRT_operator_delete(this);
3606     }
3607
3608     return this;
3609 }
3610
3611 /* ?_Getcat@?$numpunct@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3612 /* ?_Getcat@?$numpunct@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3613 MSVCP_size_t __cdecl numpunct_char__Getcat(const locale_facet **facet, const locale *loc)
3614 {
3615     TRACE("(%p %p)\n", facet, loc);
3616
3617     if(facet && !*facet) {
3618         *facet = MSVCRT_operator_new(sizeof(numpunct_char));
3619         if(!*facet) {
3620             ERR("Out of memory\n");
3621             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3622             return 0;
3623         }
3624         numpunct_char_ctor_name((numpunct_char*)*facet,
3625                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3626     }
3627
3628     return LC_NUMERIC;
3629 }
3630
3631 static numpunct_char* numpunct_char_use_facet(const locale *loc)
3632 {
3633     static numpunct_char *obj = NULL;
3634
3635     _Lockit lock;
3636     const locale_facet *fac;
3637
3638     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3639     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_char_id));
3640     if(fac) {
3641         _Lockit_dtor(&lock);
3642         return (numpunct_char*)fac;
3643     }
3644
3645     if(obj) {
3646         _Lockit_dtor(&lock);
3647         return obj;
3648     }
3649
3650     numpunct_char__Getcat(&fac, loc);
3651     obj = (numpunct_char*)fac;
3652     locale_facet__Incref(&obj->facet);
3653     locale_facet_register(&obj->facet);
3654     _Lockit_dtor(&lock);
3655
3656     return obj;
3657 }
3658
3659 /* ?do_decimal_point@?$numpunct@D@std@@MBEDXZ */
3660 /* ?do_decimal_point@?$numpunct@D@std@@MEBADXZ */
3661 DEFINE_THISCALL_WRAPPER(numpunct_char_do_decimal_point, 4)
3662 #define call_numpunct_char_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3663         char, (const numpunct_char *this), (this))
3664 char __thiscall numpunct_char_do_decimal_point(const numpunct_char *this)
3665 {
3666     TRACE("(%p)\n", this);
3667     return this->dp;
3668 }
3669
3670 /* ?decimal_point@?$numpunct@D@std@@QBEDXZ */
3671 /* ?decimal_point@?$numpunct@D@std@@QEBADXZ */
3672 DEFINE_THISCALL_WRAPPER(numpunct_char_decimal_point, 4)
3673 char __thiscall numpunct_char_decimal_point(const numpunct_char *this)
3674 {
3675     TRACE("(%p)\n", this);
3676     return call_numpunct_char_do_decimal_point(this);
3677 }
3678
3679 /* ?do_thousands_sep@?$numpunct@D@std@@MBEDXZ */
3680 /* ?do_thousands_sep@?$numpunct@D@std@@MEBADXZ */
3681 DEFINE_THISCALL_WRAPPER(numpunct_char_do_thousands_sep, 4)
3682 #define call_numpunct_char_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3683         char, (const numpunct_char*), (this))
3684 char __thiscall numpunct_char_do_thousands_sep(const numpunct_char *this)
3685 {
3686     TRACE("(%p)\n", this);
3687     return this->sep;
3688 }
3689
3690 /* ?thousands_sep@?$numpunct@D@std@@QBEDXZ */
3691 /* ?thousands_sep@?$numpunct@D@std@@QEBADXZ */
3692 DEFINE_THISCALL_WRAPPER(numpunct_char_thousands_sep, 4)
3693 char __thiscall numpunct_char_thousands_sep(const numpunct_char *this)
3694 {
3695     TRACE("(%p)\n", this);
3696     return call_numpunct_char_do_thousands_sep(this);
3697 }
3698
3699 /* ?do_grouping@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3700 /* ?do_grouping@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3701 DEFINE_THISCALL_WRAPPER(numpunct_char_do_grouping, 8)
3702 #define call_numpunct_char_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3703         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3704 basic_string_char* __thiscall numpunct_char_do_grouping(
3705         const numpunct_char *this, basic_string_char *ret)
3706 {
3707     TRACE("(%p)\n", this);
3708     return MSVCP_basic_string_char_ctor_cstr(ret, this->grouping);
3709 }
3710
3711 /* ?grouping@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3712 /* ?grouping@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3713 DEFINE_THISCALL_WRAPPER(numpunct_char_grouping, 8)
3714 basic_string_char* __thiscall numpunct_char_grouping(const numpunct_char *this, basic_string_char *ret)
3715 {
3716     TRACE("(%p)\n", this);
3717     return call_numpunct_char_do_grouping(this, ret);
3718 }
3719
3720 /* ?do_falsename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3721 /* ?do_falsename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3722 DEFINE_THISCALL_WRAPPER(numpunct_char_do_falsename, 8)
3723 #define call_numpunct_char_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3724         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3725 basic_string_char* __thiscall numpunct_char_do_falsename(
3726         const numpunct_char *this, basic_string_char *ret)
3727 {
3728     TRACE("(%p)\n", this);
3729     return MSVCP_basic_string_char_ctor_cstr(ret, this->false_name);
3730 }
3731
3732 /* ?falsename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3733 /* ?falsename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3734 DEFINE_THISCALL_WRAPPER(numpunct_char_falsename, 8)
3735 basic_string_char* __thiscall numpunct_char_falsename(const numpunct_char *this, basic_string_char *ret)
3736 {
3737     TRACE("(%p)\n", this);
3738     return call_numpunct_char_do_falsename(this, ret);
3739 }
3740
3741 /* ?do_truename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3742 /* ?do_truename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3743 DEFINE_THISCALL_WRAPPER(numpunct_char_do_truename, 8)
3744 #define call_numpunct_char_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3745         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3746 basic_string_char* __thiscall numpunct_char_do_truename(
3747         const numpunct_char *this, basic_string_char *ret)
3748 {
3749     TRACE("(%p)\n", this);
3750     return MSVCP_basic_string_char_ctor_cstr(ret, this->true_name);
3751 }
3752
3753 /* ?truename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3754 /* ?truename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3755 DEFINE_THISCALL_WRAPPER(numpunct_char_truename, 8)
3756 basic_string_char* __thiscall numpunct_char_truename(const numpunct_char *this, basic_string_char *ret)
3757 {
3758     TRACE("(%p)\n", this);
3759     return call_numpunct_char_do_truename(this, ret);
3760 }
3761
3762 /* ?id@?$numpunct@_W@std@@2V0locale@2@A */
3763 locale_id numpunct_wchar_id = {0};
3764 /* ?id@?$numpunct@G@std@@2V0locale@2@A */
3765 locale_id numpunct_short_id = {0};
3766
3767 /* ??_7?$numpunct@_W@std@@6B@ */
3768 extern const vtable_ptr MSVCP_numpunct_wchar_vtable;
3769 /* ??_7?$numpunct@G@std@@6B@ */
3770 extern const vtable_ptr MSVCP_numpunct_short_vtable;
3771
3772 /* ?_Init@?$numpunct@_W@std@@IAEXABV_Locinfo@2@_N@Z */
3773 /* ?_Init@?$numpunct@_W@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3774 /* ?_Init@?$numpunct@G@std@@IAEXABV_Locinfo@2@_N@Z */
3775 /* ?_Init@?$numpunct@G@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3776 DEFINE_THISCALL_WRAPPER(numpunct_wchar__Init, 12)
3777 void __thiscall numpunct_wchar__Init(numpunct_wchar *this,
3778         const _Locinfo *locinfo, MSVCP_bool isdef)
3779 {
3780     const char *to_convert;
3781     _Cvtvec cvt;
3782     int len;
3783
3784     TRACE("(%p %p %d)\n", this, locinfo, isdef);
3785
3786     _Locinfo__Getcvt(locinfo, &cvt);
3787
3788     to_convert = _Locinfo__Getfalse(locinfo);
3789     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3790     this->false_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3791     if(this->false_name)
3792         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3793                 (wchar_t*)this->false_name, len);
3794
3795     to_convert = _Locinfo__Gettrue(locinfo);
3796     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3797     this->true_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3798     if(this->true_name)
3799         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3800                 (wchar_t*)this->true_name, len);
3801
3802     if(isdef) {
3803         this->grouping = MSVCRT_operator_new(1);
3804         if(this->grouping)
3805             *(char*)this->grouping = 0;
3806
3807         this->dp = '.';
3808         this->sep = ',';
3809     } else {
3810         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
3811
3812         len = strlen(lc->grouping)+1;
3813         this->grouping = MSVCRT_operator_new(len);
3814         if(this->grouping)
3815             memcpy((char*)this->grouping, lc->grouping, len);
3816
3817         this->dp = lc->decimal_point[0];
3818         this->sep = lc->thousands_sep[0];
3819     }
3820
3821     if(!this->false_name || !this->true_name || !this->grouping) {
3822         MSVCRT_operator_delete((char*)this->grouping);
3823         MSVCRT_operator_delete((wchar_t*)this->false_name);
3824         MSVCRT_operator_delete((wchar_t*)this->true_name);
3825
3826         ERR("Out of memory\n");
3827         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3828     }
3829 }
3830
3831 /* ?_Tidy@?$numpunct@_W@std@@AAEXXZ */
3832 /* ?_Tidy@?$numpunct@_W@std@@AEAAXXZ */
3833 /* ?_Tidy@?$numpunct@G@std@@AAEXXZ */
3834 /* ?_Tidy@?$numpunct@G@std@@AEAAXXZ */
3835 DEFINE_THISCALL_WRAPPER(numpunct_wchar__Tidy, 4)
3836 void __thiscall numpunct_wchar__Tidy(numpunct_wchar *this)
3837 {
3838     TRACE("(%p)\n", this);
3839
3840     MSVCRT_operator_delete((char*)this->grouping);
3841     MSVCRT_operator_delete((wchar_t*)this->false_name);
3842     MSVCRT_operator_delete((wchar_t*)this->true_name);
3843 }
3844
3845 /* ??0?$numpunct@_W@std@@QAE@ABV_Locinfo@1@I_N@Z */
3846 /* ??0?$numpunct@_W@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3847 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor_locinfo, 16)
3848 numpunct_wchar* __thiscall numpunct_wchar_ctor_locinfo(numpunct_wchar *this,
3849         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3850 {
3851     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3852     locale_facet_ctor_refs(&this->facet, refs);
3853     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3854     numpunct_wchar__Init(this, locinfo, usedef);
3855     return this;
3856 }
3857
3858 /* ??0?$numpunct@G@std@@QAE@ABV_Locinfo@1@I_N@Z */
3859 /* ??0?$numpunct@G@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3860 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_locinfo, 16)
3861 numpunct_wchar* __thiscall numpunct_short_ctor_locinfo(numpunct_wchar *this,
3862         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3863 {
3864     numpunct_wchar_ctor_locinfo(this, locinfo, refs, usedef);
3865     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3866     return this;
3867 }
3868
3869 /* ??0?$numpunct@_W@std@@IAE@PBDI_N@Z */
3870 /* ??0?$numpunct@_W@std@@IEAA@PEBD_K_N@Z */
3871 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor_name, 16)
3872 numpunct_wchar* __thiscall numpunct_wchar_ctor_name(numpunct_wchar *this,
3873         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3874 {
3875     _Locinfo locinfo;
3876
3877     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3878     locale_facet_ctor_refs(&this->facet, refs);
3879     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3880
3881     _Locinfo_ctor_cstr(&locinfo, name);
3882     numpunct_wchar__Init(this, &locinfo, usedef);
3883     _Locinfo_dtor(&locinfo);
3884     return this;
3885 }
3886
3887 /* ??0?$numpunct@G@std@@IAE@PBDI_N@Z */
3888 /* ??0?$numpunct@G@std@@IEAA@PEBD_K_N@Z */
3889     DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_name, 16)
3890 numpunct_wchar* __thiscall numpunct_short_ctor_name(numpunct_wchar *this,
3891         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3892 {
3893     numpunct_wchar_ctor_name(this, name, refs, usedef);
3894     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3895     return this;
3896 }
3897
3898 /* ??0?$numpunct@_W@std@@QAE@I@Z */
3899 /* ??0?$numpunct@_W@std@@QEAA@_K@Z */
3900     DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor_refs, 8)
3901 numpunct_wchar* __thiscall numpunct_wchar_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
3902 {
3903     TRACE("(%p %lu)\n", this, refs);
3904     return numpunct_wchar_ctor_name(this, "C", refs, FALSE);
3905 }
3906
3907 /* ??0?$numpunct@G@std@@QAE@I@Z */
3908 /* ??0?$numpunct@G@std@@QEAA@_K@Z */
3909 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor_refs, 8)
3910 numpunct_wchar* __thiscall numpunct_short_ctor_refs(numpunct_wchar *this, MSVCP_size_t refs)
3911 {
3912     numpunct_wchar_ctor_refs(this, refs);
3913     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3914     return this;
3915 }
3916
3917 /* ??_F?$numpunct@_W@std@@QAEXXZ */
3918 /* ??_F?$numpunct@_W@std@@QEAAXXZ */
3919 DEFINE_THISCALL_WRAPPER(numpunct_wchar_ctor, 4)
3920 numpunct_wchar* __thiscall numpunct_wchar_ctor(numpunct_wchar *this)
3921 {
3922     return numpunct_wchar_ctor_refs(this, 0);
3923 }
3924
3925 /* ??_F?$numpunct@G@std@@QAEXXZ */
3926 /* ??_F?$numpunct@G@std@@QEAAXXZ */
3927 DEFINE_THISCALL_WRAPPER(numpunct_short_ctor, 4)
3928 numpunct_wchar* __thiscall numpunct_short_ctor(numpunct_wchar *this)
3929 {
3930     return numpunct_short_ctor_refs(this, 0);
3931 }
3932
3933 /* ??1?$numpunct@_W@std@@MAE@XZ */
3934 /* ??1?$numpunct@_W@std@@MEAA@XZ */
3935 /* ??1?$numpunct@G@std@@MAE@XZ */
3936 /* ??1?$numpunct@G@std@@MEAA@XZ */
3937 DEFINE_THISCALL_WRAPPER(numpunct_wchar_dtor, 4)
3938 void __thiscall numpunct_wchar_dtor(numpunct_wchar *this)
3939 {
3940     TRACE("(%p)\n", this);
3941     numpunct_wchar__Tidy(this);
3942 }
3943
3944 DEFINE_THISCALL_WRAPPER(numpunct_wchar_vector_dtor, 8)
3945 numpunct_wchar* __thiscall numpunct_wchar_vector_dtor(numpunct_wchar *this, unsigned int flags)
3946 {
3947     TRACE("(%p %x)\n", this, flags);
3948     if(flags & 2) {
3949         /* we have an array, with the number of elements stored before the first object */
3950         INT_PTR i, *ptr = (INT_PTR *)this-1;
3951
3952         for(i=*ptr-1; i>=0; i--)
3953             numpunct_wchar_dtor(this+i);
3954         MSVCRT_operator_delete(ptr);
3955     } else {
3956         numpunct_wchar_dtor(this);
3957         if(flags & 1)
3958             MSVCRT_operator_delete(this);
3959     }
3960
3961     return this;
3962 }
3963
3964 /* ?_Getcat@?$numpunct@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3965 /* ?_Getcat@?$numpunct@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3966 MSVCP_size_t __cdecl numpunct_wchar__Getcat(const locale_facet **facet, const locale *loc)
3967 {
3968     TRACE("(%p %p)\n", facet, loc);
3969
3970     if(facet && !*facet) {
3971         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3972         if(!*facet) {
3973             ERR("Out of memory\n");
3974             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3975             return 0;
3976         }
3977         numpunct_wchar_ctor_name((numpunct_wchar*)*facet,
3978                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
3979     }
3980
3981     return LC_NUMERIC;
3982 }
3983
3984 static numpunct_wchar* numpunct_wchar_use_facet(const locale *loc)
3985 {
3986     static numpunct_wchar *obj = NULL;
3987
3988     _Lockit lock;
3989     const locale_facet *fac;
3990
3991     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3992     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_wchar_id));
3993     if(fac) {
3994         _Lockit_dtor(&lock);
3995         return (numpunct_wchar*)fac;
3996     }
3997
3998     if(obj) {
3999         _Lockit_dtor(&lock);
4000         return obj;
4001     }
4002
4003     numpunct_wchar__Getcat(&fac, loc);
4004     obj = (numpunct_wchar*)fac;
4005     locale_facet__Incref(&obj->facet);
4006     locale_facet_register(&obj->facet);
4007     _Lockit_dtor(&lock);
4008
4009     return obj;
4010 }
4011
4012 /* ?_Getcat@?$numpunct@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
4013 /* ?_Getcat@?$numpunct@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
4014 MSVCP_size_t __cdecl numpunct_short__Getcat(const locale_facet **facet, const locale *loc)
4015 {
4016     TRACE("(%p %p)\n", facet, loc);
4017
4018     if(facet && !*facet) {
4019         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
4020         if(!*facet) {
4021             ERR("Out of memory\n");
4022             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
4023             return 0;
4024         }
4025         numpunct_short_ctor_name((numpunct_wchar*)*facet,
4026                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0, TRUE);
4027     }
4028
4029     return LC_NUMERIC;
4030 }
4031
4032 static numpunct_wchar* numpunct_short_use_facet(const locale *loc)
4033 {
4034     static numpunct_wchar *obj = NULL;
4035
4036     _Lockit lock;
4037     const locale_facet *fac;
4038
4039     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
4040     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_short_id));
4041     if(fac) {
4042         _Lockit_dtor(&lock);
4043         return (numpunct_wchar*)fac;
4044     }
4045
4046     if(obj) {
4047         _Lockit_dtor(&lock);
4048         return obj;
4049     }
4050
4051     numpunct_short__Getcat(&fac, loc);
4052     obj = (numpunct_wchar*)fac;
4053     locale_facet__Incref(&obj->facet);
4054     locale_facet_register(&obj->facet);
4055     _Lockit_dtor(&lock);
4056
4057     return obj;
4058 }
4059
4060 /* ?do_decimal_point@?$numpunct@_W@std@@MBE_WXZ */
4061 /* ?do_decimal_point@?$numpunct@_W@std@@MEBA_WXZ */
4062 /* ?do_decimal_point@?$numpunct@G@std@@MBEGXZ */
4063 /* ?do_decimal_point@?$numpunct@G@std@@MEBAGXZ */
4064 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_decimal_point, 4)
4065 #define call_numpunct_wchar_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
4066         wchar_t, (const numpunct_wchar *this), (this))
4067 wchar_t __thiscall numpunct_wchar_do_decimal_point(const numpunct_wchar *this)
4068 {
4069     TRACE("(%p)\n", this);
4070     return this->dp;
4071 }
4072
4073 /* ?decimal_point@?$numpunct@_W@std@@QBE_WXZ */
4074 /* ?decimal_point@?$numpunct@_W@std@@QEBA_WXZ */
4075 /* ?decimal_point@?$numpunct@G@std@@QBEGXZ */
4076 /* ?decimal_point@?$numpunct@G@std@@QEBAGXZ */
4077 DEFINE_THISCALL_WRAPPER(numpunct_wchar_decimal_point, 4)
4078 wchar_t __thiscall numpunct_wchar_decimal_point(const numpunct_wchar *this)
4079 {
4080     TRACE("(%p)\n", this);
4081     return call_numpunct_wchar_do_decimal_point(this);
4082 }
4083
4084 /* ?do_thousands_sep@?$numpunct@_W@std@@MBE_WXZ */
4085 /* ?do_thousands_sep@?$numpunct@_W@std@@MEBA_WXZ */
4086 /* ?do_thousands_sep@?$numpunct@G@std@@MBEGXZ */
4087 /* ?do_thousands_sep@?$numpunct@G@std@@MEBAGXZ */
4088 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_thousands_sep, 4)
4089 #define call_numpunct_wchar_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
4090         wchar_t, (const numpunct_wchar *this), (this))
4091 wchar_t __thiscall numpunct_wchar_do_thousands_sep(const numpunct_wchar *this)
4092 {
4093     TRACE("(%p)\n", this);
4094     return this->sep;
4095 }
4096
4097 /* ?thousands_sep@?$numpunct@_W@std@@QBE_WXZ */
4098 /* ?thousands_sep@?$numpunct@_W@std@@QEBA_WXZ */
4099 /* ?thousands_sep@?$numpunct@G@std@@QBEGXZ */
4100 /* ?thousands_sep@?$numpunct@G@std@@QEBAGXZ */
4101 DEFINE_THISCALL_WRAPPER(numpunct_wchar_thousands_sep, 4)
4102 wchar_t __thiscall numpunct_wchar_thousands_sep(const numpunct_wchar *this)
4103 {
4104     TRACE("(%p)\n", this);
4105     return call_numpunct_wchar_do_thousands_sep(this);
4106 }
4107
4108 /* ?do_grouping@?$numpunct@_W@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4109 /* ?do_grouping@?$numpunct@_W@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4110 /* ?do_grouping@?$numpunct@G@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4111 /* ?do_grouping@?$numpunct@G@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4112 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_grouping, 8)
4113 #define call_numpunct_wchar_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
4114         basic_string_char*, (const numpunct_wchar*, basic_string_char*), (this, ret))
4115 basic_string_char* __thiscall numpunct_wchar_do_grouping(const numpunct_wchar *this, basic_string_char *ret)
4116 {
4117     TRACE("(%p)\n", this);
4118     return MSVCP_basic_string_char_ctor_cstr(ret, this->grouping);
4119 }
4120
4121 /* ?grouping@?$numpunct@_W@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4122 /* ?grouping@?$numpunct@_W@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4123 /* ?grouping@?$numpunct@G@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4124 /* ?grouping@?$numpunct@G@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
4125 DEFINE_THISCALL_WRAPPER(numpunct_wchar_grouping, 8)
4126 basic_string_char* __thiscall numpunct_wchar_grouping(const numpunct_wchar *this, basic_string_char *ret)
4127 {
4128     TRACE("(%p)\n", this);
4129     return call_numpunct_wchar_do_grouping(this, ret);
4130 }
4131
4132 /* ?do_falsename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4133 /* ?do_falsename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4134 /* ?do_falsename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4135 /* ?do_falsename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4136 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_falsename, 8)
4137 #define call_numpunct_wchar_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
4138         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
4139 basic_string_wchar* __thiscall numpunct_wchar_do_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
4140 {
4141     TRACE("(%p)\n", this);
4142     return MSVCP_basic_string_wchar_ctor_cstr(ret, this->false_name);
4143 }
4144
4145 /* ?falsename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4146 /* ?falsename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4147 /* ?falsename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4148 /* ?falsename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4149 DEFINE_THISCALL_WRAPPER(numpunct_wchar_falsename, 8)
4150 basic_string_wchar* __thiscall numpunct_wchar_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
4151 {
4152     TRACE("(%p)\n", this);
4153     return call_numpunct_wchar_do_falsename(this, ret);
4154 }
4155
4156 /* ?do_truename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4157 /* ?do_truename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4158 /* ?do_truename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4159 /* ?do_truename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4160 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_truename, 8)
4161 #define call_numpunct_wchar_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
4162         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
4163 basic_string_wchar* __thiscall numpunct_wchar_do_truename(const numpunct_wchar *this, basic_string_wchar *ret)
4164 {
4165     TRACE("(%p)\n", this);
4166     return MSVCP_basic_string_wchar_ctor_cstr(ret, this->true_name);
4167 }
4168
4169 /* ?truename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4170 /* ?truename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
4171 /* ?truename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4172 /* ?truename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
4173 DEFINE_THISCALL_WRAPPER(numpunct_wchar_truename, 8)
4174 basic_string_wchar* __thiscall numpunct_wchar_truename(const numpunct_wchar *this, basic_string_wchar *ret)
4175 {
4176     TRACE("(%p)\n", this);
4177     return call_numpunct_wchar_do_truename(this, ret);
4178 }
4179
4180 double __cdecl _Stod(const char *buf, char **buf_end, LONG exp)
4181 {
4182     double ret = strtod(buf, buf_end);
4183
4184     if(exp)
4185         ret *= pow(10, exp);
4186     return ret;
4187 }
4188
4189 double __cdecl _Stodx(const char *buf, char **buf_end, LONG exp, int *err)
4190 {
4191     double ret;
4192
4193     *err = *_errno();
4194     *_errno() = 0;
4195     ret = _Stod(buf, buf_end, exp);
4196     if(*_errno()) {
4197         *err = *_errno();
4198     }else {
4199         *_errno() = *err;
4200         *err = 0;
4201     }
4202     return ret;
4203 }
4204
4205 float __cdecl _Stof(const char *buf, char **buf_end, LONG exp)
4206 {
4207     return _Stod(buf, buf_end, exp);
4208 }
4209
4210 float __cdecl _Stofx(const char *buf, char **buf_end, LONG exp, int *err)
4211 {
4212     return _Stodx(buf, buf_end, exp, err);
4213 }
4214
4215 __int64 __cdecl _Stoll(const char *buf, char **buf_end, int base)
4216 {
4217     return _strtoi64(buf, buf_end, base);
4218 }
4219
4220 __int64 __cdecl _Stollx(const char *buf, char **buf_end, int base, int *err)
4221 {
4222     __int64 ret;
4223
4224     *err = *_errno();
4225     *_errno() = 0;
4226     ret = _strtoi64(buf, buf_end, base);
4227     if(*_errno()) {
4228         *err = *_errno();
4229     }else {
4230         *_errno() = *err;
4231         *err = 0;
4232     }
4233     return ret;
4234 }
4235
4236 LONG __cdecl _Stolx(const char *buf, char **buf_end, int base, int *err)
4237 {
4238     __int64 i = _Stollx(buf, buf_end, base, err);
4239     if(!*err && i!=(__int64)((LONG)i))
4240         *err = ERANGE;
4241     return i;
4242 }
4243
4244 unsigned __int64 __cdecl _Stoull(const char *buf, char **buf_end, int base)
4245 {
4246     return _strtoui64(buf, buf_end, base);
4247 }
4248
4249 unsigned __int64 __cdecl _Stoullx(const char *buf, char **buf_end, int base, int *err)
4250 {
4251     unsigned __int64 ret;
4252
4253     *err = *_errno();
4254     *_errno() = 0;
4255     ret = _strtoui64(buf, buf_end, base);
4256     if(*_errno()) {
4257         *err = *_errno();
4258     }else {
4259         *_errno() = *err;
4260         *err = 0;
4261     }
4262     return ret;
4263 }
4264
4265 ULONG __cdecl _Stoul(const char *buf, char **buf_end, int base)
4266 {
4267     int err;
4268     unsigned __int64 i = _Stoullx(buf[0]=='-' ? buf+1 : buf, buf_end, base, &err);
4269     if(!err && i!=(unsigned __int64)((ULONG)i))
4270         *_errno() = ERANGE;
4271     return buf[0]=='-' ? -i : i;
4272 }
4273
4274 ULONG __cdecl _Stoulx(const char *buf, char **buf_end, int base, int *err)
4275 {
4276     unsigned __int64 i = _Stoullx(buf[0]=='-' ? buf+1 : buf, buf_end, base, err);
4277     if(!*err && i!=(unsigned __int64)((ULONG)i))
4278         *err = ERANGE;
4279     return buf[0]=='-' ? -i : i;
4280 }
4281
4282 /* ?id@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
4283 locale_id num_get_wchar_id = {0};
4284 /* ?id@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
4285 locale_id num_get_short_id = {0};
4286
4287 /* ??_7?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
4288 extern const vtable_ptr MSVCP_num_get_wchar_vtable;
4289 /* ??_7?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
4290 extern const vtable_ptr MSVCP_num_get_short_vtable;
4291
4292 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
4293 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
4294 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
4295 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
4296 DEFINE_THISCALL_WRAPPER(num_get_wchar__Init, 8)
4297 void __thiscall num_get_wchar__Init(num_get *this, const _Locinfo *locinfo)
4298 {
4299     TRACE("(%p %p)\n", this, locinfo);
4300     _Locinfo__Getcvt(locinfo, &this->cvt);
4301 }
4302
4303 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
4304 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
4305 DEFINE_THISCALL_WRAPPER(num_get_wchar_ctor_locinfo, 12)
4306 num_get* __thiscall num_get_wchar_ctor_locinfo(num_get *this,
4307         const _Locinfo *locinfo, MSVCP_size_t refs)
4308 {
4309     TRACE("(%p %p %lu)\n", this, locinfo, refs);
4310
4311     locale_facet_ctor_refs(&this->facet, refs);
4312     this->facet.vtable = &MSVCP_num_get_wchar_vtable;
4313
4314     num_get_wchar__Init(this, locinfo);
4315     return this;
4316 }
4317
4318 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
4319 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
4320 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_locinfo, 12)
4321 num_get* __thiscall num_get_short_ctor_locinfo(num_get *this,
4322         const _Locinfo *locinfo, MSVCP_size_t refs)
4323 {
4324     num_get_wchar_ctor_locinfo(this, locinfo, refs);
4325     this->facet.vtable = &MSVCP_num_get_short_vtable;
4326     return this;
4327 }
4328
4329 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
4330 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
4331 DEFINE_THISCALL_WRAPPER(num_get_wchar_ctor_refs, 8)
4332 num_get* __thiscall num_get_wchar_ctor_refs(num_get *this, MSVCP_size_t refs)
4333 {
4334     _Locinfo locinfo;
4335
4336     TRACE("(%p %lu)\n", this, refs);
4337
4338     _Locinfo_ctor(&locinfo);
4339     num_get_wchar_ctor_locinfo(this, &locinfo, refs);
4340     _Locinfo_dtor(&locinfo);
4341     return this;
4342 }
4343
4344 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
4345 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
4346 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_refs, 8)
4347 num_get* __thiscall num_get_short_ctor_refs(num_get *this, MSVCP_size_t refs)
4348 {
4349     num_get_wchar_ctor_refs(this, refs);
4350     this->facet.vtable = &MSVCP_num_get_short_vtable;
4351     return this;
4352 }
4353
4354 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
4355 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
4356 DEFINE_THISCALL_WRAPPER(num_get_wchar_ctor, 4)
4357 num_get* __thiscall num_get_wchar_ctor(num_get *this)
4358 {
4359     return num_get_wchar_ctor_refs(this, 0);
4360 }
4361
4362 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
4363 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
4364 DEFINE_THISCALL_WRAPPER(num_get_short_ctor, 4)
4365 num_get* __thiscall num_get_short_ctor(num_get *this)
4366 {
4367     return num_get_short_ctor_refs(this, 0);
4368 }
4369
4370 /* ??1?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
4371 /* ??1?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
4372 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
4373 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
4374 DEFINE_THISCALL_WRAPPER(num_get_wchar_dtor, 4)
4375 void __thiscall num_get_wchar_dtor(num_get *this)
4376 {
4377     TRACE("(%p)\n", this);
4378     locale_facet_dtor(&this->facet);
4379 }
4380
4381 DEFINE_THISCALL_WRAPPER(num_get_wchar_vector_dtor, 8)
4382 num_get* __thiscall num_get_wchar_vector_dtor(num_get *this, unsigned int flags)
4383 {
4384     TRACE("(%p %x)\n", this, flags);
4385     if(flags & 2) {
4386         /* we have an array, with the number of elements stored before the first object */
4387         INT_PTR i, *ptr = (INT_PTR *)this-1;
4388
4389         for(i=*ptr-1; i>=0; i--)
4390             num_get_wchar_dtor(this+i);
4391         MSVCRT_operator_delete(ptr);
4392     } else {
4393         num_get_wchar_dtor(this);
4394         if(flags & 1)
4395             MSVCRT_operator_delete(this);
4396     }
4397
4398     return this;
4399 }
4400
4401 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
4402 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
4403 MSVCP_size_t __cdecl num_get_wchar__Getcat(const locale_facet **facet, const locale *loc)
4404 {
4405     TRACE("(%p %p)\n", facet, loc);
4406
4407     if(facet && !*facet) {
4408         _Locinfo locinfo;
4409
4410         *facet = MSVCRT_operator_new(sizeof(num_get));
4411         if(!*facet) {
4412             ERR("Out of memory\n");
4413             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
4414             return 0;
4415         }
4416
4417         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
4418         num_get_wchar_ctor_locinfo((num_get*)*facet, &locinfo, 0);
4419         _Locinfo_dtor(&locinfo);
4420     }
4421
4422     return LC_NUMERIC;
4423 }
4424
4425 num_get* num_get_wchar_use_facet(const locale *loc)
4426 {
4427         static num_get *obj = NULL;
4428
4429         _Lockit lock;
4430         const locale_facet *fac;
4431
4432         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
4433         fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_wchar_id));
4434         if(fac) {
4435             _Lockit_dtor(&lock);
4436             return (num_get*)fac;
4437         }
4438
4439         if(obj) {
4440             _Lockit_dtor(&lock);
4441             return obj;
4442         }
4443
4444         num_get_wchar__Getcat(&fac, loc);
4445         obj = (num_get*)fac;
4446         locale_facet__Incref(&obj->facet);
4447         locale_facet_register(&obj->facet);
4448         _Lockit_dtor(&lock);
4449
4450         return obj;
4451 }
4452
4453 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
4454 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
4455 MSVCP_size_t __cdecl num_get_short__Getcat(const locale_facet **facet, const locale *loc)
4456 {
4457     if(facet && !*facet) {
4458         num_get_wchar__Getcat(facet, loc);
4459         (*(locale_facet**)facet)->vtable = &MSVCP_num_get_short_vtable;
4460     }
4461
4462     return LC_NUMERIC;
4463 }
4464
4465 num_get* num_get_short_use_facet(const locale *loc)
4466 {
4467     static num_get *obj = NULL;
4468
4469     _Lockit lock;
4470     const locale_facet *fac;
4471
4472     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
4473     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_short_id));
4474     if(fac) {
4475         _Lockit_dtor(&lock);
4476         return (num_get*)fac;
4477     }
4478
4479     if(obj) {
4480         _Lockit_dtor(&lock);
4481         return obj;
4482     }
4483
4484     num_get_short__Getcat(&fac, loc);
4485     obj = (num_get*)fac;
4486     locale_facet__Incref(&obj->facet);
4487     locale_facet_register(&obj->facet);
4488     _Lockit_dtor(&lock);
4489
4490     return obj;
4491 }
4492
4493 static inline wchar_t mb_to_wc(char ch, const _Cvtvec *cvt)
4494 {
4495     int state = 0;
4496     wchar_t ret;
4497
4498     return _Mbrtowc(&ret, &ch, 1, &state, cvt) == 1 ? ret : 0;
4499 }
4500
4501 static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4502         istreambuf_iterator_wchar *last, const locale *loc, numpunct_wchar *numpunct)
4503 {
4504     basic_string_char grouping_bstr;
4505     basic_string_char groups_found;
4506     int i, groups_no = 0, cur_group = 0, exp = 0;
4507     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
4508     wchar_t sep, digits[11], *digits_pos;
4509     const char *grouping, *groups;
4510     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
4511
4512     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
4513
4514     for(i=0; i<10; i++)
4515         digits[i] = mb_to_wc('0'+i, &this->cvt);
4516     digits[10] = 0;
4517
4518     numpunct_wchar_grouping(numpunct, &grouping_bstr);
4519     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
4520     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : 0;
4521
4522     if(sep)
4523         MSVCP_basic_string_char_ctor(&groups_found);
4524
4525     istreambuf_iterator_wchar_val(first);
4526     /* get sign */
4527     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4528         *dest++ = '-';
4529         istreambuf_iterator_wchar_inc(first);
4530     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4531         *dest++ = '+';
4532         istreambuf_iterator_wchar_inc(first);
4533     }
4534
4535     /* read possibly grouped numbers before decimal */
4536     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4537         if(!(digits_pos = wcschr(digits, first->val))) {
4538             if(sep && first->val==sep) {
4539                 if(!groups_no) break; /* empty group - stop parsing */
4540                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4541                 groups_no = 0;
4542                 ++cur_group;
4543             }else {
4544                 break;
4545             }
4546         }else {
4547             got_digit = TRUE; /* found a digit, zero or non-zero */
4548             /* write digit to dest if not a leading zero (to not waste dest buffer) */
4549             if(!got_nonzero && first->val == digits[0])
4550             {
4551                 ++groups_no;
4552                 continue;
4553             }
4554             got_nonzero = TRUE;
4555             if(dest < num_end)
4556                 *dest++ = '0'+digits_pos-digits;
4557             else
4558                 exp++; /* too many digits, just multiply by 10 */
4559             if(sep && groups_no<CHAR_MAX)
4560                 ++groups_no;
4561         }
4562     }
4563
4564     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
4565     if(got_digit && !got_nonzero)
4566         *dest++ = '0';
4567
4568     /* get decimal, if any */
4569     if(first->strbuf && first->val==numpunct_wchar_decimal_point(numpunct)) {
4570         if(dest < num_end)
4571             *dest++ = *localeconv()->decimal_point;
4572         istreambuf_iterator_wchar_inc(first);
4573     }
4574
4575     /* read non-grouped after decimal */
4576     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4577         if(!(digits_pos = wcschr(digits, first->val)))
4578             break;
4579         else if(dest<num_end) {
4580             got_digit = TRUE;
4581             *dest++ = '0'+digits_pos-digits;
4582         }
4583     }
4584
4585     /* read exponent, if any */
4586     if(first->strbuf && (first->val==mb_to_wc('e', &this->cvt) || first->val==mb_to_wc('E', &this->cvt))) {
4587         *dest++ = 'e';
4588         istreambuf_iterator_wchar_inc(first);
4589
4590         if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4591             *dest++ = '-';
4592             istreambuf_iterator_wchar_inc(first);
4593         }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4594             *dest++ = '+';
4595             istreambuf_iterator_wchar_inc(first);
4596         }
4597
4598         got_digit = got_nonzero = FALSE;
4599         error = TRUE;
4600         /* skip any leading zeroes */
4601         for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first))
4602             error = FALSE;
4603
4604         for(; first->strbuf && (digits_pos = wcschr(digits, first->val)); istreambuf_iterator_wchar_inc(first)) {
4605             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
4606             error = FALSE;
4607             if(dest<exp_end)
4608                 *dest++ = '0'+digits_pos-digits;
4609         }
4610
4611         /* if just found zeroes for exponent, use that */
4612         if(got_digit && !got_nonzero)
4613         {
4614             error = FALSE;
4615             if(dest<exp_end)
4616                 *dest++ = '0';
4617         }
4618     }
4619
4620     if(sep && groups_no)
4621         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4622
4623     if(!cur_group) /* no groups, skip loop */
4624         cur_group--;
4625     else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group])
4626         error = TRUE; /* trailing empty */
4627
4628     for(; cur_group>=0 && !error; cur_group--) {
4629         if(*grouping == CHAR_MAX) {
4630             if(cur_group)
4631                 error = TRUE;
4632             break;
4633         }else if((cur_group && *grouping!=groups[cur_group])
4634                 || (!cur_group && *grouping<groups[cur_group])) {
4635             error = TRUE;
4636             break;
4637         }else if(grouping[1]) {
4638             grouping++;
4639         }
4640     }
4641     MSVCP_basic_string_char_dtor(&grouping_bstr);
4642     if(sep)
4643         MSVCP_basic_string_char_dtor(&groups_found);
4644
4645     if(error) {
4646         *dest_beg = '\0';
4647         return 0;
4648     }
4649     *dest++ = '\0';
4650     return exp;
4651 }
4652
4653 /* ?_Getffld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1ABVlocale@2@@Z */
4654 /* ?_Getffld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1AEBVlocale@2@@Z */
4655 int __cdecl num_get_wchar__Getffld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4656     istreambuf_iterator_wchar *last, const locale *loc)
4657 {
4658     return num_get__Getffld(this, dest, first, last, loc, numpunct_wchar_use_facet(loc));
4659 }
4660
4661 /* ?_Getffld@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@1ABVlocale@2@@Z */
4662 /* ?_Getffld@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@1AEBVlocale@2@@Z */
4663 int __cdecl num_get_short__Getffld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4664     istreambuf_iterator_wchar *last, const locale *loc)
4665 {
4666     return num_get__Getffld(this, dest, first, last, loc, numpunct_short_use_facet(loc));
4667 }
4668
4669 /* ?_Getffldx@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1AAVios_base@2@PAH@Z */
4670 /* ?_Getffldx@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1AEAVios_base@2@PEAH@Z */
4671 /* ?_Getffldx@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@1AAVios_base@2@PAH@Z */
4672 /* ?_Getffldx@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@1AEAVios_base@2@PEAH@Z */
4673 int __cdecl num_get_wchar__Getffldx(num_get *this, char *dest, istreambuf_iterator_wchar *first,
4674     istreambuf_iterator_wchar *last, ios_base *ios, int *phexexp)
4675 {
4676     FIXME("(%p %p %p %p %p) stub\n", dest, first, last, ios, phexexp);
4677     return -1;
4678 }
4679
4680 static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4681     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc, numpunct_wchar *numpunct)
4682 {
4683     wchar_t digits[23], *digits_pos, sep;
4684     basic_string_char grouping_bstr;
4685     basic_string_char groups_found;
4686     int i, basefield, base, groups_no = 0, cur_group = 0;
4687     char *dest_beg = dest, *dest_end = dest+24;
4688     const char *grouping, *groups;
4689     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
4690
4691     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
4692
4693     for(i=0; i<10; i++)
4694         digits[i] = mb_to_wc('0'+i, &this->cvt);
4695     for(i=0; i<6; i++) {
4696         digits[10+i] = mb_to_wc('a'+i, &this->cvt);
4697         digits[16+i] = mb_to_wc('A'+i, &this->cvt);
4698     }
4699
4700     numpunct_wchar_grouping(numpunct, &grouping_bstr);
4701     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
4702     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
4703
4704     basefield = fmtflags & FMTFLAG_basefield;
4705     if(basefield == FMTFLAG_oct)
4706         base = 8;
4707     else if(basefield == FMTFLAG_hex)
4708         base = 22; /* equal to the size of digits buffer */
4709     else if(!basefield)
4710         base = 0;
4711     else
4712         base = 10;
4713
4714     istreambuf_iterator_wchar_val(first);
4715     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4716         *dest++ = '-';
4717         istreambuf_iterator_wchar_inc(first);
4718     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4719         *dest++ = '+';
4720         istreambuf_iterator_wchar_inc(first);
4721     }
4722
4723     if(first->strbuf && first->val==digits[0]) {
4724         found_zero = TRUE;
4725         istreambuf_iterator_wchar_inc(first);
4726         if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) {
4727             if(!base || base == 22) {
4728                 found_zero = FALSE;
4729                 istreambuf_iterator_wchar_inc(first);
4730                 base = 22;
4731             }else {
4732                 base = 10;
4733             }
4734         }else {
4735             error = FALSE;
4736             if(!base) base = 8;
4737         }
4738     }else {
4739         if(!base) base = 10;
4740     }
4741     digits[base] = 0;
4742
4743     if(sep) {
4744         MSVCP_basic_string_char_ctor(&groups_found);
4745         if(found_zero) ++groups_no;
4746     }
4747
4748     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4749         if(!(digits_pos = wcschr(digits, first->val))) {
4750             if(sep && first->val==sep) {
4751                 if(!groups_no) break; /* empty group - stop parsing */
4752                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4753                 groups_no = 0;
4754                 ++cur_group;
4755             }else {
4756                 break;
4757             }
4758         }else {
4759             error = FALSE;
4760             if(dest_empty && first->val == digits[0]) {
4761                 found_zero = TRUE;
4762                 ++groups_no;
4763                 continue;
4764             }
4765             dest_empty = FALSE;
4766             /* skip digits that can't be copied to dest buffer, other
4767              * functions are responsible for detecting overflows */
4768             if(dest < dest_end)
4769                 *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits :
4770                         (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 :
4771                          'A'+digits_pos-digits-16));
4772             if(sep && groups_no<CHAR_MAX)
4773                 ++groups_no;
4774         }
4775     }
4776
4777     if(sep && groups_no)
4778         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4779
4780     if(!cur_group) { /* no groups, skip loop */
4781         cur_group--;
4782     }else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group]) {
4783         error = TRUE; /* trailing empty */
4784         found_zero = FALSE;
4785     }
4786
4787     for(; cur_group>=0 && !error; cur_group--) {
4788         if(*grouping == CHAR_MAX) {
4789             if(cur_group)
4790                 error = TRUE;
4791             break;
4792         }else if((cur_group && *grouping!=groups[cur_group])
4793                 || (!cur_group && *grouping<groups[cur_group])) {
4794             error = TRUE;
4795             break;
4796         }else if(grouping[1]) {
4797             grouping++;
4798         }
4799     }
4800
4801     MSVCP_basic_string_char_dtor(&grouping_bstr);
4802     if(sep)
4803         MSVCP_basic_string_char_dtor(&groups_found);
4804
4805     if(error) {
4806         if (found_zero)
4807             *dest++ = '0';
4808         else
4809             dest = dest_beg;
4810     }else if(dest_empty)
4811         *dest++ = '0';
4812     *dest = '\0';
4813
4814     return (base==22 ? 16 : base);
4815 }
4816
4817 /* ?_Getifld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1HABVlocale@2@@Z */
4818 /* ?_Getifld@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@1HAEBVlocale@2@@Z */
4819 int __cdecl num_get_wchar__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4820     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc)
4821 {
4822     return num_get__Getifld(this, dest, first, last,
4823             fmtflags, loc, numpunct_wchar_use_facet(loc));
4824 }
4825
4826 /* ?_Getifld@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@1HABVlocale@2@@Z */
4827 /* ?_Getifld@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@1HAEBVlocale@2@@Z */
4828 int __cdecl num_get_short__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4829     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc)
4830 {
4831     return num_get__Getifld(this, dest, first, last,
4832             fmtflags, loc, numpunct_short_use_facet(loc));
4833 }
4834
4835 /* ?_Hexdig@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABEH_W000@Z */
4836 /* ?_Hexdig@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAH_W000@Z */
4837 /* ?_Hexdig@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABEHGGGG@Z */
4838 /* ?_Hexdig@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAHGGGG@Z */
4839 DEFINE_THISCALL_WRAPPER(MSVCP_num_get_wchar__Hexdig, 20)
4840 int __thiscall MSVCP_num_get_wchar__Hexdig(num_get *this, wchar_t dig, wchar_t e0, wchar_t al, wchar_t au)
4841 {
4842     FIXME("(%p %c %c %c %c) stub\n", this, dig, e0, al, au);
4843     return -1;
4844 }
4845
4846 static istreambuf_iterator_wchar* num_get_do_get_void(const num_get *this,
4847         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4848         istreambuf_iterator_wchar last, ios_base *base, int *state,
4849         void **pval, numpunct_wchar *numpunct)
4850 {
4851     unsigned __int64 v;
4852     char tmp[25], *end;
4853     int err;
4854
4855     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4856
4857     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4858                 &last, FMTFLAG_hex, base->loc, numpunct), &err);
4859     if(v!=(unsigned __int64)((INT_PTR)v))
4860         *state |= IOSTATE_failbit;
4861     else if(end!=tmp && !err)
4862         *pval = (void*)((INT_PTR)v);
4863     else
4864         *state |= IOSTATE_failbit;
4865
4866     if(!first.strbuf)
4867         *state |= IOSTATE_eofbit;
4868
4869     *ret = first;
4870     return ret;
4871 }
4872
4873 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4874 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4875 #define call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_wchar*, \
4876         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, void**), \
4877         (this, ret, first, last, base, state, pval))
4878 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_void,36)
4879 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4880     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4881 {
4882     return num_get_do_get_void(this, ret, first, last, base,
4883             state, pval, numpunct_wchar_use_facet(base->loc));
4884 }
4885
4886 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4887 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4888 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_void,36)
4889 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4890     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4891 {
4892     return num_get_do_get_void(this, ret, first, last, base,
4893             state, pval, numpunct_short_use_facet(base->loc));
4894 }
4895
4896 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4897 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4898 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
4899 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
4900 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_void,36)
4901 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4902     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4903 {
4904     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4905     return call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval);
4906 }
4907
4908 static istreambuf_iterator_wchar* num_get_do_get_double(const num_get *this,
4909         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4910         istreambuf_iterator_wchar last, ios_base *base, int *state,
4911         double *pval, numpunct_wchar *numpunct)
4912 {
4913     double v;
4914     char tmp[32], *end;
4915     int err;
4916
4917     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4918
4919     v = _Stodx(tmp, &end, num_get__Getffld(this, tmp, &first, &last, base->loc, numpunct), &err);
4920     if(end!=tmp && !err)
4921         *pval = v;
4922     else
4923         *state |= IOSTATE_failbit;
4924
4925     if(!first.strbuf)
4926         *state |= IOSTATE_eofbit;
4927
4928     *ret = first;
4929     return ret;
4930 }
4931
4932 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4933 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4934 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4935 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4936 #define call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_wchar*, \
4937         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4938         (this, ret, first, last, base, state, pval))
4939 #define call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_wchar*, \
4940         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4941         (this, ret, first, last, base, state, pval))
4942 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_double,36)
4943 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4944     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4945 {
4946     return num_get_do_get_double(this, ret, first, last, base,
4947             state, pval, numpunct_wchar_use_facet(base->loc));
4948 }
4949
4950 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4951 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4952 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4953 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4954 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_double,36)
4955 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4956     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4957 {
4958     return num_get_do_get_double(this, ret, first, last, base,
4959             state, pval, numpunct_short_use_facet(base->loc));
4960 }
4961
4962 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4963 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4964 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
4965 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
4966 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ldouble,36)
4967 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ldouble(const num_get *this, istreambuf_iterator_wchar *ret,
4968         istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4969 {
4970     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4971     return call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval);
4972 }
4973
4974 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4975 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4976 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
4977 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
4978 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_double,36)
4979 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4980     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4981 {
4982     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4983     return call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval);
4984 }
4985
4986 static istreambuf_iterator_wchar* num_get_do_get_float(const num_get *this,
4987         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4988         istreambuf_iterator_wchar last, ios_base *base, int *state,
4989         float *pval, numpunct_wchar *numpunct)
4990 {
4991     float v;
4992     char tmp[32], *end;
4993     int err;
4994
4995     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4996
4997     v = _Stofx(tmp, &end, num_get__Getffld(this, tmp, &first,
4998                 &last, base->loc, numpunct), &err);
4999     if(end!=tmp && !err)
5000         *pval = v;
5001     else
5002         *state |= IOSTATE_failbit;
5003
5004     if(!first.strbuf)
5005         *state |= IOSTATE_eofbit;
5006
5007     *ret = first;
5008     return ret;
5009 }
5010
5011 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5012 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5013 #define call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_wchar*, \
5014         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, float*), \
5015         (this, ret, first, last, base, state, pval))
5016 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_float,36)
5017 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
5018     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
5019 {
5020     return num_get_do_get_float(this, ret, first, last, base,
5021             state, pval, numpunct_wchar_use_facet(base->loc));
5022 }
5023
5024 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5025 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5026 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_float,36)
5027 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
5028     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
5029 {
5030     return num_get_do_get_float(this, ret, first, last, base,
5031             state, pval, numpunct_short_use_facet(base->loc));
5032 }
5033
5034 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5035 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5036 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
5037 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
5038 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_float,36)
5039 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
5040     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
5041 {
5042     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5043     return call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval);
5044 }
5045
5046 static istreambuf_iterator_wchar* num_get_do_get_uint64(const num_get *this,
5047         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
5048         istreambuf_iterator_wchar last, ios_base *base, int *state,
5049         ULONGLONG *pval, numpunct_wchar *numpunct)
5050 {
5051     unsigned __int64 v;
5052     char tmp[25], *end;
5053     int err;
5054
5055     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5056
5057     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
5058                 &last, base->fmtfl, base->loc, numpunct), &err);
5059     if(end!=tmp && !err)
5060         *pval = v;
5061     else
5062         *state |= IOSTATE_failbit;
5063
5064     if(!first.strbuf)
5065         *state |= IOSTATE_eofbit;
5066
5067     *ret = first;
5068     return ret;
5069 }
5070
5071 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5072 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5073 #define call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_wchar*, \
5074         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONGLONG*), \
5075         (this, ret, first, last, base, state, pval))
5076 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint64,36)
5077 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
5078     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
5079 {
5080     return num_get_do_get_uint64(this, ret, first, last, base,
5081             state, pval, numpunct_wchar_use_facet(base->loc));
5082 }
5083
5084 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5085 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5086 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint64,36)
5087 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
5088     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
5089 {
5090     return num_get_do_get_uint64(this, ret, first, last, base,
5091             state, pval, numpunct_short_use_facet(base->loc));
5092 }
5093
5094 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5095 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5096 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
5097 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
5098 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint64,36)
5099 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
5100     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
5101 {
5102     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5103     return call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval);
5104 }
5105
5106 static istreambuf_iterator_wchar* num_get_do_get_int64(const num_get *this,
5107         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
5108         istreambuf_iterator_wchar last, ios_base *base, int *state,
5109         LONGLONG *pval, numpunct_wchar *numpunct)
5110 {
5111     __int64 v;
5112     char tmp[25], *end;
5113     int err;
5114
5115     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5116
5117     v = _Stollx(tmp, &end, num_get__Getifld(this, tmp, &first,
5118                 &last, base->fmtfl, base->loc, numpunct), &err);
5119     if(end!=tmp && !err)
5120         *pval = v;
5121     else
5122         *state |= IOSTATE_failbit;
5123
5124     if(!first.strbuf)
5125         *state |= IOSTATE_eofbit;
5126
5127     *ret = first;
5128     return ret;
5129 }
5130
5131 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5132 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5133 #define call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_wchar*, \
5134         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONGLONG*), \
5135         (this, ret, first, last, base, state, pval))
5136 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_int64,36)
5137 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
5138     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
5139 {
5140     return num_get_do_get_int64(this, ret, first, last, base,
5141             state, pval, numpunct_wchar_use_facet(base->loc));
5142 }
5143
5144 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5145 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5146 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_int64,36)
5147 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
5148     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
5149 {
5150     return num_get_do_get_int64(this, ret, first, last, base,
5151             state, pval, numpunct_short_use_facet(base->loc));
5152 }
5153
5154 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5155 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5156 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
5157 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
5158 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_int64,36)
5159 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
5160     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
5161 {
5162     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5163     return call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval);
5164 }
5165
5166 static istreambuf_iterator_wchar* num_get_do_get_ulong(const num_get *this,
5167         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
5168         istreambuf_iterator_wchar last, ios_base *base, int *state,
5169         ULONG *pval, numpunct_wchar *numpunct)
5170 {
5171     ULONG v;
5172     char tmp[25], *end;
5173     int err;
5174
5175     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5176
5177     v = _Stoulx(tmp, &end, num_get__Getifld(this, tmp, &first,
5178                 &last, base->fmtfl, base->loc, numpunct), &err);
5179     if(end!=tmp && !err)
5180         *pval = v;
5181     else
5182         *state |= IOSTATE_failbit;
5183
5184     if(!first.strbuf)
5185         *state |= IOSTATE_eofbit;
5186
5187     *ret = first;
5188     return ret;
5189 }
5190
5191 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5192 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5193 #define call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_wchar*, \
5194         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONG*), \
5195         (this, ret, first, last, base, state, pval))
5196 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ulong,36)
5197 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
5198     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
5199 {
5200     return num_get_do_get_ulong(this, ret, first, last, base,
5201             state, pval, numpunct_wchar_use_facet(base->loc));
5202 }
5203
5204 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5205 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5206 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ulong,36)
5207 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
5208     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
5209 {
5210     return num_get_do_get_ulong(this, ret, first, last, base,
5211             state, pval, numpunct_short_use_facet(base->loc));
5212 }
5213
5214 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5215 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5216 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
5217 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
5218 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ulong,36)
5219 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
5220     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
5221 {
5222     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5223     return call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
5224 }
5225
5226 static istreambuf_iterator_wchar* num_get_do_get_long(const num_get *this,
5227         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
5228         istreambuf_iterator_wchar last, ios_base *base, int *state,
5229         LONG *pval, numpunct_wchar *numpunct)
5230 {
5231     LONG v;
5232     char tmp[25], *end;
5233     int err;
5234
5235     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5236
5237     v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
5238                 &last, base->fmtfl, base->loc, numpunct), &err);
5239     if(end!=tmp && !err)
5240         *pval = v;
5241     else
5242         *state |= IOSTATE_failbit;
5243
5244     if(!first.strbuf)
5245         *state |= IOSTATE_eofbit;
5246
5247     *ret = first;
5248     return ret;
5249 }
5250
5251 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5252 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5253 #define call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_wchar*, \
5254         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONG*), \
5255         (this, ret, first, last, base, state, pval))
5256 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_long,36)
5257 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
5258     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
5259 {
5260     return num_get_do_get_long(this, ret, first, last, base,
5261             state, pval, numpunct_wchar_use_facet(base->loc));
5262 }
5263
5264 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5265 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5266 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_long,36)
5267 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
5268     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
5269 {
5270     return num_get_do_get_long(this, ret, first, last, base,
5271         state, pval, numpunct_short_use_facet(base->loc));
5272 }
5273
5274 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5275 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5276 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
5277 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
5278 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_long,36)
5279 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
5280     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
5281 {
5282     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5283     return call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval);
5284 }
5285
5286 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5287 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5288 #define call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_wchar*, \
5289         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned int*), \
5290         (this, ret, first, last, base, state, pval))
5291 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint,36)
5292 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
5293     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
5294 {
5295     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5296     return num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
5297 }
5298
5299 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5300 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5301 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint,36)
5302 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
5303     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
5304 {
5305     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5306     return num_get_short_do_get_ulong(this, ret, first, last, base, state, pval);
5307 }
5308
5309 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5310 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5311 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
5312 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
5313 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint,36)
5314 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
5315     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
5316 {
5317     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5318     return call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval);
5319 }
5320
5321 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5322 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5323 #define call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_wchar*, \
5324         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned short*), \
5325         (this, ret, first, last, base, state, pval))
5326 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ushort,36)
5327 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
5328     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
5329 {
5330     ULONG v;
5331     char tmp[25], *beg, *end;
5332     int err, b;
5333
5334     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5335
5336     b = num_get_wchar__Getifld(this, tmp,
5337             &first, &last, base->fmtfl, base->loc);
5338     beg = tmp + (tmp[0]=='-' ? 1 : 0);
5339     v = _Stoulx(beg, &end, b, &err);
5340
5341     if(v != (ULONG)((unsigned short)v))
5342         *state |= IOSTATE_failbit;
5343     else if(end!=beg && !err)
5344         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
5345     else
5346         *state |= IOSTATE_failbit;
5347
5348     if(!first.strbuf)
5349         *state |= IOSTATE_eofbit;
5350
5351     *ret = first;
5352     return ret;
5353 }
5354
5355 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5356 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5357 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ushort,36)
5358 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
5359     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
5360 {
5361     FIXME("(%p %p %p %p %p) stub\n", this, ret, base, state, pval);
5362     return ret;
5363 }
5364
5365 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
5366 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5367 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAAG@ */
5368 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
5369 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ushort,36)
5370 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
5371     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
5372 {
5373     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5374     return call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval);
5375 }
5376
5377 static istreambuf_iterator_wchar* num_get_do_get_bool(const num_get *this,
5378         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
5379         istreambuf_iterator_wchar last, ios_base *base, int *state,
5380         MSVCP_bool *pval, numpunct_wchar *numpunct)
5381 {
5382     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5383
5384     if(base->fmtfl & FMTFLAG_boolalpha) {
5385         basic_string_wchar false_bstr, true_bstr;
5386         const wchar_t *pfalse, *ptrue;
5387
5388         numpunct_wchar_falsename(numpunct, &false_bstr);
5389         numpunct_wchar_truename(numpunct, &true_bstr);
5390         pfalse = MSVCP_basic_string_wchar_c_str(&false_bstr);
5391         ptrue = MSVCP_basic_string_wchar_c_str(&true_bstr);
5392
5393         for(istreambuf_iterator_wchar_val(&first); first.strbuf;
5394                 istreambuf_iterator_wchar_inc(&first)) {
5395             if(pfalse && *pfalse && first.val!=*pfalse)
5396                 pfalse = NULL;
5397             if(ptrue && *ptrue && first.val!=*ptrue)
5398                 ptrue = NULL;
5399
5400             if(pfalse && *pfalse && ptrue && !*ptrue)
5401                 ptrue = NULL;
5402             if(ptrue && *ptrue && pfalse && !*pfalse)
5403                 pfalse = NULL;
5404
5405             if(pfalse)
5406                 pfalse++;
5407             if(ptrue)
5408                 ptrue++;
5409
5410             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
5411                 break;
5412         }
5413
5414         if(ptrue)
5415             *pval = TRUE;
5416         else if(pfalse)
5417             *pval = FALSE;
5418         else
5419             *state |= IOSTATE_failbit;
5420
5421         MSVCP_basic_string_wchar_dtor(&false_bstr);
5422         MSVCP_basic_string_wchar_dtor(&true_bstr);
5423     }else {
5424         char tmp[25], *end;
5425         int err;
5426         LONG v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
5427                     &last, base->fmtfl, base->loc, numpunct), &err);
5428
5429         if(end!=tmp && err==0 && (v==0 || v==1))
5430             *pval = v;
5431         else
5432             *state |= IOSTATE_failbit;
5433     }
5434
5435     if(!first.strbuf)
5436         *state |= IOSTATE_eofbit;
5437     memcpy(ret, &first, sizeof(first));
5438     return ret;
5439 }
5440
5441 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5442 /* ?do_get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5443 #define call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_wchar*, \
5444         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, MSVCP_bool*), \
5445         (this, ret, first, last, base, state, pval))
5446 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_bool,36)
5447 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
5448     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
5449 {
5450     return num_get_do_get_bool(this, ret, first, last, base,
5451             state, pval, numpunct_wchar_use_facet(base->loc));
5452 }
5453
5454 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5455 /* ?do_get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5456 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_bool,36)
5457 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
5458     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
5459 {
5460     return num_get_do_get_bool(this, ret, first, last, base,
5461             state, pval, numpunct_short_use_facet(base->loc));
5462 }
5463
5464 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5465 /* ?get@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5466 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
5467 /* ?get@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@GU?$char_traits@G@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
5468 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_bool,36)
5469 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
5470     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
5471 {
5472     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5473     return call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval);
5474 }
5475
5476 /* ?id@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
5477 locale_id num_get_char_id = {0};
5478
5479 /* ??_7?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
5480 extern const vtable_ptr MSVCP_num_get_char_vtable;
5481
5482 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
5483 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
5484 DEFINE_THISCALL_WRAPPER(num_get_char__Init, 8)
5485 void __thiscall num_get_char__Init(num_get *this, const _Locinfo *locinfo)
5486 {
5487     TRACE("(%p %p)\n", this, locinfo);
5488     _Locinfo__Getcvt(locinfo, &this->cvt);
5489 }
5490
5491 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
5492 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
5493 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_locinfo, 12)
5494 num_get* __thiscall num_get_char_ctor_locinfo(num_get *this,
5495         const _Locinfo *locinfo, MSVCP_size_t refs)
5496 {
5497     TRACE("(%p %p %lu)\n", this, locinfo, refs);
5498
5499     locale_facet_ctor_refs(&this->facet, refs);
5500     this->facet.vtable = &MSVCP_num_get_char_vtable;
5501
5502     num_get_char__Init(this, locinfo);
5503     return this;
5504 }
5505
5506 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
5507 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
5508 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_refs, 8)
5509 num_get* __thiscall num_get_char_ctor_refs(num_get *this, MSVCP_size_t refs)
5510 {
5511     _Locinfo locinfo;
5512
5513     TRACE("(%p %lu)\n", this, refs);
5514
5515     _Locinfo_ctor(&locinfo);
5516     num_get_char_ctor_locinfo(this, &locinfo, refs);
5517     _Locinfo_dtor(&locinfo);
5518     return this;
5519 }
5520
5521 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
5522 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
5523 DEFINE_THISCALL_WRAPPER(num_get_char_ctor, 4)
5524 num_get* __thiscall num_get_char_ctor(num_get *this)
5525 {
5526     return num_get_char_ctor_refs(this, 0);
5527 }
5528
5529 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
5530 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
5531 DEFINE_THISCALL_WRAPPER(num_get_char_dtor, 4)
5532 void __thiscall num_get_char_dtor(num_get *this)
5533 {
5534     TRACE("(%p)\n", this);
5535     locale_facet_dtor(&this->facet);
5536 }
5537
5538 DEFINE_THISCALL_WRAPPER(num_get_char_vector_dtor, 8)
5539 num_get* __thiscall num_get_char_vector_dtor(num_get *this, unsigned int flags)
5540 {
5541     TRACE("(%p %x)\n", this, flags);
5542     if(flags & 2) {
5543         /* we have an array, with the number of elements stored before the first object */
5544         INT_PTR i, *ptr = (INT_PTR *)this-1;
5545
5546         for(i=*ptr-1; i>=0; i--)
5547             num_get_char_dtor(this+i);
5548         MSVCRT_operator_delete(ptr);
5549     } else {
5550         num_get_char_dtor(this);
5551         if(flags & 1)
5552             MSVCRT_operator_delete(this);
5553     }
5554
5555     return this;
5556 }
5557
5558 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
5559 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
5560 MSVCP_size_t __cdecl num_get_char__Getcat(const locale_facet **facet, const locale *loc)
5561 {
5562     TRACE("(%p %p)\n", facet, loc);
5563
5564     if(facet && !*facet) {
5565         _Locinfo locinfo;
5566
5567         *facet = MSVCRT_operator_new(sizeof(num_get));
5568         if(!*facet) {
5569             ERR("Out of memory\n");
5570             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
5571             return 0;
5572         }
5573
5574         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
5575         num_get_char_ctor_locinfo((num_get*)*facet, &locinfo, 0);
5576         _Locinfo_dtor(&locinfo);
5577     }
5578
5579     return LC_NUMERIC;
5580 }
5581
5582 num_get* num_get_char_use_facet(const locale *loc)
5583 {
5584     static num_get *obj = NULL;
5585
5586     _Lockit lock;
5587     const locale_facet *fac;
5588
5589     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
5590     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_char_id));
5591     if(fac) {
5592         _Lockit_dtor(&lock);
5593         return (num_get*)fac;
5594     }
5595
5596     if(obj) {
5597         _Lockit_dtor(&lock);
5598         return obj;
5599     }
5600
5601     num_get_char__Getcat(&fac, loc);
5602     obj = (num_get*)fac;
5603     locale_facet__Incref(&obj->facet);
5604     locale_facet_register(&obj->facet);
5605     _Lockit_dtor(&lock);
5606
5607     return obj;
5608 }
5609
5610 /* ?_Getffld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1ABVlocale@2@@Z */
5611 /* ?_Getffld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1AEBVlocale@2@@Z */
5612 /* Copies number to dest buffer, validates grouping and skips separators.
5613  * Updates first so it points past the number, all digits are skipped.
5614  * Returns how exponent needs to changed.
5615  * Size of dest buffer is not specified, assuming it's not smaller than 32:
5616  * strlen(+0.e+) + 22(digits) + 4(expontent) + 1(nullbyte)
5617  */
5618 int __cdecl num_get_char__Getffld(const num_get *this, char *dest, istreambuf_iterator_char *first,
5619         istreambuf_iterator_char *last, const locale *loc)
5620 {
5621     numpunct_char *numpunct = numpunct_char_use_facet(loc);
5622     basic_string_char grouping_bstr;
5623     basic_string_char groups_found;
5624     int groups_no = 0, cur_group = 0, exp = 0;
5625     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31, sep;
5626     const char *grouping, *groups;
5627     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
5628
5629     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
5630
5631     numpunct_char_grouping(numpunct, &grouping_bstr);
5632     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
5633     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5634
5635     if(sep)
5636         MSVCP_basic_string_char_ctor(&groups_found);
5637
5638     istreambuf_iterator_char_val(first);
5639     /* get sign */
5640     if(first->strbuf && (first->val=='-' || first->val=='+')) {
5641         *dest++ = first->val;
5642         istreambuf_iterator_char_inc(first);
5643     }
5644
5645     /* read possibly grouped numbers before decimal */
5646     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
5647         if(first->val<'0' || first->val>'9') {
5648             if(sep && first->val==sep) {
5649                 if(!groups_no) break; /* empty group - stop parsing */
5650                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5651                 groups_no = 0;
5652                 ++cur_group;
5653             }else {
5654                 break;
5655             }
5656         }else {
5657             got_digit = TRUE; /* found a digit, zero or non-zero */
5658             /* write digit to dest if not a leading zero (to not waste dest buffer) */
5659             if(!got_nonzero && first->val == '0')
5660             {
5661                 ++groups_no;
5662                 continue;
5663             }
5664             got_nonzero = TRUE;
5665             if(dest < num_end)
5666                 *dest++ = first->val;
5667             else
5668                 exp++; /* too many digits, just multiply by 10 */
5669             if(sep && groups_no<CHAR_MAX)
5670                 ++groups_no;
5671         }
5672     }
5673
5674     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
5675     if(got_digit && !got_nonzero)
5676         *dest++ = '0';
5677
5678     /* get decimal, if any */
5679     if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
5680         if(dest < num_end)
5681             *dest++ = *localeconv()->decimal_point;
5682         istreambuf_iterator_char_inc(first);
5683     }
5684
5685     /* read non-grouped after decimal */
5686     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
5687         if(first->val<'0' || first->val>'9')
5688             break;
5689         else if(dest<num_end) {
5690             got_digit = TRUE;
5691             *dest++ = first->val;
5692         }
5693     }
5694
5695     /* read exponent, if any */
5696     if(first->strbuf && (first->val=='e' || first->val=='E')) {
5697         *dest++ = first->val;
5698         istreambuf_iterator_char_inc(first);
5699
5700         if(first->strbuf && (first->val=='-' || first->val=='+')) {
5701             *dest++ = first->val;
5702             istreambuf_iterator_char_inc(first);
5703         }
5704
5705         got_digit = got_nonzero = FALSE;
5706         error = TRUE;
5707         /* skip any leading zeroes */
5708         for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
5709             got_digit = TRUE;
5710
5711         for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
5712             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
5713             error = FALSE;
5714             if(dest<exp_end)
5715                 *dest++ = first->val;
5716         }
5717
5718         /* if just found zeroes for exponent, use that */
5719         if(got_digit && !got_nonzero)
5720         {
5721             error = FALSE;
5722             if(dest<exp_end)
5723                 *dest++ = '0';
5724         }
5725     }
5726
5727     if(sep && groups_no)
5728         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5729
5730     if(!cur_group) /* no groups, skip loop */
5731         cur_group--;
5732     else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group])
5733         error = TRUE; /* trailing empty */
5734
5735     for(; cur_group>=0 && !error; cur_group--) {
5736         if(*grouping == CHAR_MAX) {
5737             if(cur_group)
5738                 error = TRUE;
5739             break;
5740         }else if((cur_group && *grouping!=groups[cur_group])
5741                 || (!cur_group && *grouping<groups[cur_group])) {
5742             error = TRUE;
5743             break;
5744         }else if(grouping[1]) {
5745             grouping++;
5746         }
5747     }
5748     MSVCP_basic_string_char_dtor(&grouping_bstr);
5749     if(sep)
5750         MSVCP_basic_string_char_dtor(&groups_found);
5751
5752     if(error) {
5753         *dest_beg = '\0';
5754         return 0;
5755     }
5756     *dest++ = '\0';
5757     return exp;
5758 }
5759
5760 /* ?_Getffldx@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1AAVios_base@2@PAH@Z */
5761 /* ?_Getffldx@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1AEAVios_base@2@PEAH@Z */
5762 int __cdecl num_get_char__Getffldx(const num_get *this, char *dest, istreambuf_iterator_char *first,
5763     istreambuf_iterator_char *last, ios_base *ios, int *phexexp)
5764 {
5765     FIXME("(%p %p %p %p %p) stub\n", dest, first, last, ios, phexexp);
5766     return -1;
5767 }
5768
5769 /* ?_Getifld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAHPADAAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1HABVlocale@2@@Z */
5770 /* ?_Getifld@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHPEADAEAV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@1HAEBVlocale@2@@Z */
5771 /* Copies number to dest buffer, validates grouping and skips separators.
5772  * Updates first so it points past the number, all digits are skipped.
5773  * Returns number base (8, 10 or 16).
5774  * Size of dest buffer is not specified, assuming it's not smaller than 25:
5775  * 22(8^22>2^64)+1(detect overflows)+1(sign)+1(nullbyte) = 25
5776  */
5777 int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_iterator_char *first,
5778         istreambuf_iterator_char *last, int fmtflags, const locale *loc)
5779 {
5780     static const char digits[] = "0123456789abcdefABCDEF";
5781
5782     numpunct_char *numpunct = numpunct_char_use_facet(loc);
5783     basic_string_char grouping_bstr;
5784     basic_string_char groups_found;
5785     int basefield, base, groups_no = 0, cur_group = 0;
5786     char *dest_beg = dest, *dest_end = dest+24, sep;
5787     const char *grouping, *groups;
5788     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
5789
5790     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
5791
5792     numpunct_char_grouping(numpunct, &grouping_bstr);
5793     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
5794     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5795
5796     basefield = fmtflags & FMTFLAG_basefield;
5797     if(basefield == FMTFLAG_oct)
5798         base = 8;
5799     else if(basefield == FMTFLAG_hex)
5800         base = 22; /* equal to the size of digits buffer */
5801     else if(!basefield)
5802         base = 0;
5803     else
5804         base = 10;
5805
5806     istreambuf_iterator_char_val(first);
5807     if(first->strbuf && (first->val=='-' || first->val=='+')) {
5808         *dest++ = first->val;
5809         istreambuf_iterator_char_inc(first);
5810     }
5811
5812     if(first->strbuf && first->val=='0') {
5813         found_zero = TRUE;
5814         istreambuf_iterator_char_inc(first);
5815         if(first->strbuf && (first->val=='x' || first->val=='X')) {
5816             if(!base || base == 22) {
5817                 found_zero = FALSE;
5818                 istreambuf_iterator_char_inc(first);
5819                 base = 22;
5820             }else {
5821                 base = 10;
5822             }
5823         }else {
5824             error = FALSE;
5825             if(!base) base = 8;
5826         }
5827     }else {
5828         if (!base) base = 10;
5829     }
5830
5831     if(sep)
5832     {
5833         MSVCP_basic_string_char_ctor(&groups_found);
5834         if(found_zero) ++groups_no;
5835     }
5836
5837     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
5838         if(!memchr(digits, first->val, base)) {
5839             if(sep && first->val==sep) {
5840                 if(!groups_no) break; /* empty group - stop parsing */
5841                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5842                 groups_no = 0;
5843                 ++cur_group;
5844             }else {
5845                 break;
5846             }
5847         }else {
5848             error = FALSE;
5849             if(dest_empty && first->val == '0')
5850             {
5851                 found_zero = TRUE;
5852                 ++groups_no;
5853                 continue;
5854             }
5855             dest_empty = FALSE;
5856             /* skip digits that can't be copied to dest buffer, other
5857              * functions are responsible for detecting overflows */
5858             if(dest < dest_end)
5859                 *dest++ = first->val;
5860             if(sep && groups_no<CHAR_MAX)
5861                 ++groups_no;
5862         }
5863     }
5864
5865     if(sep && groups_no)
5866         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5867
5868     if(!cur_group) { /* no groups, skip loop */
5869         cur_group--;
5870     }else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group]) {
5871         error = TRUE; /* trailing empty */
5872         found_zero = FALSE;
5873     }
5874
5875     for(; cur_group>=0 && !error; cur_group--) {
5876         if(*grouping == CHAR_MAX) {
5877             if(cur_group)
5878                 error = TRUE;
5879             break;
5880         }else if((cur_group && *grouping!=groups[cur_group])
5881                 || (!cur_group && *grouping<groups[cur_group])) {
5882             error = TRUE;
5883             break;
5884         }else if(grouping[1]) {
5885             grouping++;
5886         }
5887     }
5888
5889     MSVCP_basic_string_char_dtor(&grouping_bstr);
5890     if(sep)
5891         MSVCP_basic_string_char_dtor(&groups_found);
5892
5893     if(error) {
5894         if (found_zero)
5895             *dest++ = '0';
5896         else
5897             dest = dest_beg;
5898     }else if(dest_empty)
5899         *dest++ = '0';
5900     *dest = '\0';
5901
5902     return (base==22 ? 16 : base);
5903 }
5904
5905 /* ?_Hexdig@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABEHD000@Z */
5906 /* ?_Hexdig@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHD000@Z */
5907 DEFINE_THISCALL_WRAPPER(MSVCP_num_get_char__Hexdig, 20)
5908 int __thiscall MSVCP_num_get_char__Hexdig(num_get *this, char dig, char e0, char al, char au)
5909 {
5910     FIXME("(%p %c %c %c %c) stub\n", this, dig, e0, al, au);
5911     return -1;
5912 }
5913
5914 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
5915 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
5916 #define call_num_get_char_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_char*, \
5917         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, void**), \
5918         (this, ret, first, last, base, state, pval))
5919 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_void,36)
5920 istreambuf_iterator_char *__thiscall num_get_char_do_get_void(const num_get *this, istreambuf_iterator_char *ret,
5921     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5922 {
5923     unsigned __int64 v;
5924     char tmp[25], *end;
5925     int err;
5926
5927     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5928
5929     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5930                 &first, &last, FMTFLAG_hex, base->loc), &err);
5931     if(v!=(unsigned __int64)((INT_PTR)v))
5932         *state |= IOSTATE_failbit;
5933     else if(end!=tmp && !err)
5934         *pval = (void*)((INT_PTR)v);
5935     else
5936         *state |= IOSTATE_failbit;
5937
5938     if(!first.strbuf)
5939         *state |= IOSTATE_eofbit;
5940
5941     *ret = first;
5942     return ret;
5943 }
5944
5945 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAPAX@Z */
5946 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAPEAX@Z */
5947 DEFINE_THISCALL_WRAPPER(num_get_char_get_void,36)
5948 istreambuf_iterator_char *__thiscall num_get_char_get_void(const num_get *this, istreambuf_iterator_char *ret,
5949     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5950 {
5951     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5952     return call_num_get_char_do_get_void(this, ret, first, last, base, state, pval);
5953 }
5954
5955 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
5956 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
5957 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
5958 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
5959 #define call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_char*, \
5960         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5961         (this, ret, first, last, base, state, pval))
5962 #define call_num_get_char_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_char*, \
5963         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5964         (this, ret, first, last, base, state, pval))
5965 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_double,36)
5966 istreambuf_iterator_char *__thiscall num_get_char_do_get_double(const num_get *this, istreambuf_iterator_char *ret,
5967     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5968 {
5969     double v;
5970     char tmp[32], *end;
5971     int err;
5972
5973     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5974
5975     v = _Stodx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, base->loc), &err);
5976     if(end!=tmp && !err)
5977         *pval = v;
5978     else
5979         *state |= IOSTATE_failbit;
5980
5981     if(!first.strbuf)
5982         *state |= IOSTATE_eofbit;
5983
5984     *ret = first;
5985     return ret;
5986 }
5987
5988 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAO@Z */
5989 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAO@Z */
5990 DEFINE_THISCALL_WRAPPER(num_get_char_get_ldouble,36)
5991 istreambuf_iterator_char *__thiscall num_get_char_get_ldouble(const num_get *this, istreambuf_iterator_char *ret,
5992         istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5993 {
5994     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5995     return call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval);
5996 }
5997
5998 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAN@Z */
5999 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAN@Z */
6000 DEFINE_THISCALL_WRAPPER(num_get_char_get_double,36)
6001 istreambuf_iterator_char *__thiscall num_get_char_get_double(const num_get *this, istreambuf_iterator_char *ret,
6002     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
6003 {
6004     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6005     return call_num_get_char_do_get_double(this, ret, first, last, base, state, pval);
6006 }
6007
6008 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
6009 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
6010 #define call_num_get_char_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_char*, \
6011         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, float*), \
6012         (this, ret, first, last, base, state, pval))
6013 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_float,36)
6014 istreambuf_iterator_char *__thiscall num_get_char_do_get_float(const num_get *this, istreambuf_iterator_char *ret,
6015     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
6016 {
6017     float v;
6018     char tmp[32], *end;
6019     int err;
6020
6021     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6022
6023     v = _Stofx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, base->loc), &err);
6024     if(end!=tmp && !err)
6025         *pval = v;
6026     else
6027         *state |= IOSTATE_failbit;
6028
6029     if(!first.strbuf)
6030         *state |= IOSTATE_eofbit;
6031
6032     *ret = first;
6033     return ret;
6034 }
6035
6036 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z */
6037 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAM@Z */
6038 DEFINE_THISCALL_WRAPPER(num_get_char_get_float,36)
6039 istreambuf_iterator_char *__thiscall num_get_char_get_float(const num_get *this, istreambuf_iterator_char *ret,
6040     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
6041 {
6042     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6043     return call_num_get_char_do_get_float(this, ret, first, last, base, state, pval);
6044 }
6045
6046 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
6047 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
6048 #define call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_char*, \
6049         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONGLONG*), \
6050         (this, ret, first, last, base, state, pval))
6051 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint64,36)
6052 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
6053     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
6054 {
6055     unsigned __int64 v;
6056     char tmp[25], *end;
6057     int err;
6058
6059     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6060
6061     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
6062                 &first, &last, base->fmtfl, base->loc), &err);
6063     if(end!=tmp && !err)
6064         *pval = v;
6065     else
6066         *state |= IOSTATE_failbit;
6067
6068     if(!first.strbuf)
6069         *state |= IOSTATE_eofbit;
6070
6071     *ret = first;
6072     return ret;
6073 }
6074
6075 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_K@Z */
6076 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_K@Z */
6077 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint64,36)
6078 istreambuf_iterator_char *__thiscall num_get_char_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
6079     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
6080 {
6081     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6082     return call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval);
6083 }
6084
6085 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
6086 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
6087 #define call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_char*, \
6088         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONGLONG*), \
6089         (this, ret, first, last, base, state, pval))
6090 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_int64,36)
6091 istreambuf_iterator_char *__thiscall num_get_char_do_get_int64(const num_get *this, istreambuf_iterator_char *ret,
6092     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
6093 {
6094     __int64 v;
6095     char tmp[25], *end;
6096     int err;
6097
6098     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6099
6100     v = _Stollx(tmp, &end, num_get_char__Getifld(this, tmp,
6101                 &first, &last, base->fmtfl, base->loc), &err);
6102     if(end!=tmp && !err)
6103         *pval = v;
6104     else
6105         *state |= IOSTATE_failbit;
6106
6107     if(!first.strbuf)
6108         *state |= IOSTATE_eofbit;
6109
6110     *ret = first;
6111     return ret;
6112 }
6113
6114 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_J@Z */
6115 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_J@Z */
6116 DEFINE_THISCALL_WRAPPER(num_get_char_get_int64,36)
6117 istreambuf_iterator_char *__thiscall num_get_char_get_int64(const num_get *this, istreambuf_iterator_char *ret,
6118     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
6119 {
6120     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6121     return call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval);
6122 }
6123
6124 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
6125 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
6126 #define call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_char*, \
6127         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONG*), \
6128         (this, ret, first, last, base, state, pval))
6129 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ulong,36)
6130 istreambuf_iterator_char *__thiscall num_get_char_do_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
6131     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
6132 {
6133     ULONG v;
6134     char tmp[25], *end;
6135     int err;
6136
6137     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6138
6139     v = _Stoulx(tmp, &end, num_get_char__Getifld(this, tmp,
6140                 &first, &last, base->fmtfl, base->loc), &err);
6141     if(end!=tmp && !err)
6142         *pval = v;
6143     else
6144         *state |= IOSTATE_failbit;
6145
6146     if(!first.strbuf)
6147         *state |= IOSTATE_eofbit;
6148
6149     *ret = first;
6150     return ret;
6151 }
6152
6153 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z */
6154 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAK@Z */
6155 DEFINE_THISCALL_WRAPPER(num_get_char_get_ulong,36)
6156 istreambuf_iterator_char *__thiscall num_get_char_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
6157     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
6158 {
6159     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6160     return call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
6161 }
6162
6163 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
6164 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
6165 #define call_num_get_char_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_char*, \
6166         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONG*), \
6167         (this, ret, first, last, base, state, pval))
6168 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_long,36)
6169 istreambuf_iterator_char *__thiscall num_get_char_do_get_long(const num_get *this, istreambuf_iterator_char *ret,
6170     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
6171 {
6172     LONG v;
6173     char tmp[25], *end;
6174     int err;
6175
6176     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6177
6178     v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
6179                 &first, &last, base->fmtfl, base->loc), &err);
6180     if(end!=tmp && !err)
6181         *pval = v;
6182     else
6183         *state |= IOSTATE_failbit;
6184
6185     if(!first.strbuf)
6186         *state |= IOSTATE_eofbit;
6187
6188     *ret = first;
6189     return ret;
6190 }
6191
6192 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z */
6193 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAJ@Z */
6194 DEFINE_THISCALL_WRAPPER(num_get_char_get_long,36)
6195 istreambuf_iterator_char *__thiscall num_get_char_get_long(const num_get *this, istreambuf_iterator_char *ret,
6196     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
6197 {
6198     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6199     return call_num_get_char_do_get_long(this, ret, first, last, base, state, pval);
6200 }
6201
6202 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
6203 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
6204 #define call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_char*, \
6205         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned int*), \
6206         (this, ret, first, last, base, state, pval))
6207 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint,36)
6208 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint(const num_get *this, istreambuf_iterator_char *ret,
6209     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
6210 {
6211     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6212     return num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
6213 }
6214
6215 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAI@Z */
6216 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAI@Z */
6217 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint,36)
6218 istreambuf_iterator_char *__thiscall num_get_char_get_uint(const num_get *this, istreambuf_iterator_char *ret,
6219     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
6220 {
6221     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6222     return call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval);
6223 }
6224
6225 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
6226 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
6227 #define call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_char*, \
6228         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned short*), \
6229         (this, ret, first, last, base, state, pval))
6230 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ushort,36)
6231 istreambuf_iterator_char *__thiscall num_get_char_do_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
6232     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
6233 {
6234     ULONG v;
6235     char tmp[25], *beg, *end;
6236     int err, b;
6237
6238     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6239
6240     b = num_get_char__Getifld(this, tmp,
6241             &first, &last, base->fmtfl, base->loc);
6242     beg = tmp + (tmp[0]=='-' ? 1 : 0);
6243     v = _Stoulx(beg, &end, b, &err);
6244
6245     if(v != (ULONG)((unsigned short)v))
6246         *state |= IOSTATE_failbit;
6247     else if(end!=beg && !err)
6248         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
6249     else
6250         *state |= IOSTATE_failbit;
6251
6252     if(!first.strbuf)
6253         *state |= IOSTATE_eofbit;
6254
6255     *ret = first;
6256     return ret;
6257 }
6258
6259 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAG@Z */
6260 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEAG@Z */
6261 DEFINE_THISCALL_WRAPPER(num_get_char_get_ushort,36)
6262 istreambuf_iterator_char *__thiscall num_get_char_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
6263     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
6264 {
6265     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6266     return call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval);
6267 }
6268
6269 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
6270 /* ?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
6271 #define call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_char*, \
6272         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, MSVCP_bool*), \
6273         (this, ret, first, last, base, state, pval))
6274 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_bool,36)
6275 istreambuf_iterator_char *__thiscall num_get_char_do_get_bool(const num_get *this, istreambuf_iterator_char *ret,
6276     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
6277 {
6278     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6279
6280     if(base->fmtfl & FMTFLAG_boolalpha) {
6281         numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
6282         basic_string_char false_bstr, true_bstr;
6283         const char *pfalse, *ptrue;
6284
6285         numpunct_char_falsename(numpunct, &false_bstr);
6286         numpunct_char_truename(numpunct, &true_bstr);
6287         pfalse = MSVCP_basic_string_char_c_str(&false_bstr);
6288         ptrue = MSVCP_basic_string_char_c_str(&true_bstr);
6289
6290         for(istreambuf_iterator_char_val(&first); first.strbuf;
6291                 istreambuf_iterator_char_inc(&first)) {
6292             if(pfalse && *pfalse && first.val!=*pfalse)
6293                 pfalse = NULL;
6294             if(ptrue && *ptrue && first.val!=*ptrue)
6295                 ptrue = NULL;
6296
6297             if(pfalse && *pfalse && ptrue && !*ptrue)
6298                 ptrue = NULL;
6299             if(ptrue && *ptrue && pfalse && !*pfalse)
6300                 pfalse = NULL;
6301
6302             if(pfalse)
6303                 pfalse++;
6304             if(ptrue)
6305                 ptrue++;
6306
6307             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
6308                 break;
6309         }
6310
6311         if(ptrue)
6312             *pval = TRUE;
6313         else if(pfalse)
6314             *pval = FALSE;
6315         else
6316             *state |= IOSTATE_failbit;
6317
6318         MSVCP_basic_string_char_dtor(&false_bstr);
6319         MSVCP_basic_string_char_dtor(&true_bstr);
6320     }else {
6321         char tmp[25], *end;
6322         int err;
6323         LONG v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
6324                     &first, &last, base->fmtfl, base->loc), &err);
6325
6326         if(end!=tmp && err==0 && (v==0 || v==1))
6327             *pval = v;
6328         else
6329             *state |= IOSTATE_failbit;
6330     }
6331
6332     if(!first.strbuf)
6333         *state |= IOSTATE_eofbit;
6334     memcpy(ret, &first, sizeof(first));
6335     return ret;
6336 }
6337
6338 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAA_N@Z */
6339 /* ?get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AEAVios_base@2@AEAHAEA_N@Z */
6340 DEFINE_THISCALL_WRAPPER(num_get_char_get_bool,36)
6341 istreambuf_iterator_char *__thiscall num_get_char_get_bool(const num_get *this, istreambuf_iterator_char *ret,
6342     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
6343 {
6344     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
6345     return call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval);
6346 }
6347
6348 /* ?id@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
6349 locale_id num_put_char_id = {0};
6350
6351 /* num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
6352 extern const vtable_ptr MSVCP_num_put_char_vtable;
6353
6354 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
6355 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
6356 DEFINE_THISCALL_WRAPPER(num_put_char__Init, 8)
6357 void __thiscall num_put_char__Init(num_put *this, const _Locinfo *locinfo)
6358 {
6359     TRACE("(%p %p)\n", this, locinfo);
6360     _Locinfo__Getcvt(locinfo, &this->cvt);
6361 }
6362
6363 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6364 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6365 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_locinfo, 12)
6366 num_put* __thiscall num_put_char_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6367 {
6368     TRACE("(%p %p %ld)\n", this, locinfo, refs);
6369
6370     locale_facet_ctor_refs(&this->facet, refs);
6371     this->facet.vtable = &MSVCP_num_put_char_vtable;
6372
6373     num_put_char__Init(this, locinfo);
6374     return this;
6375 }
6376
6377 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
6378 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
6379 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_refs, 8)
6380 num_put* __thiscall num_put_char_ctor_refs(num_put *this, MSVCP_size_t refs)
6381 {
6382      _Locinfo locinfo;
6383
6384      TRACE("(%p %lu)\n", this, refs);
6385
6386      _Locinfo_ctor(&locinfo);
6387      num_put_char_ctor_locinfo(this, &locinfo, refs);
6388      _Locinfo_dtor(&locinfo);
6389      return this;
6390 }
6391
6392 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
6393 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
6394 DEFINE_THISCALL_WRAPPER(num_put_char_ctor, 4)
6395 num_put* __thiscall num_put_char_ctor(num_put *this)
6396 {
6397     return num_put_char_ctor_refs(this, 0);
6398 }
6399
6400 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
6401 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
6402 DEFINE_THISCALL_WRAPPER(num_put_char_dtor, 4)
6403 void __thiscall num_put_char_dtor(num_put *this)
6404 {
6405     TRACE("(%p)\n", this);
6406     locale_facet_dtor(&this->facet);
6407 }
6408
6409 DEFINE_THISCALL_WRAPPER(num_put_char_vector_dtor, 8)
6410 num_put* __thiscall num_put_char_vector_dtor(num_put *this, unsigned int flags)
6411 {
6412     TRACE("(%p %x)\n", this, flags);
6413     if(flags & 2) {
6414         /* we have an array, with the number of elements stored before the first object */
6415         INT_PTR i, *ptr = (INT_PTR *)this-1;
6416
6417         for(i=*ptr-1; i>=0; i--)
6418             num_put_char_dtor(this+i);
6419         MSVCRT_operator_delete(ptr);
6420     } else {
6421         num_put_char_dtor(this);
6422         if(flags & 1)
6423             MSVCRT_operator_delete(this);
6424     }
6425
6426     return this;
6427 }
6428
6429 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6430 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6431 MSVCP_size_t __cdecl num_put_char__Getcat(const locale_facet **facet, const locale *loc)
6432 {
6433     TRACE("(%p %p)\n", facet, loc);
6434
6435     if(facet && !*facet) {
6436         _Locinfo locinfo;
6437
6438         *facet = MSVCRT_operator_new(sizeof(num_put));
6439         if(!*facet) {
6440             ERR("Out of memory\n");
6441             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6442             return 0;
6443         }
6444
6445         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
6446         num_put_char_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6447         _Locinfo_dtor(&locinfo);
6448     }
6449
6450     return LC_NUMERIC;
6451 }
6452
6453 num_put* num_put_char_use_facet(const locale *loc)
6454 {
6455     static num_put *obj = NULL;
6456
6457     _Lockit lock;
6458     const locale_facet *fac;
6459
6460     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6461     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_char_id));
6462     if(fac) {
6463         _Lockit_dtor(&lock);
6464         return (num_put*)fac;
6465     }
6466
6467     if(obj) {
6468         _Lockit_dtor(&lock);
6469         return obj;
6470     }
6471
6472     num_put_char__Getcat(&fac, loc);
6473     obj = (num_put*)fac;
6474     locale_facet__Incref(&obj->facet);
6475     locale_facet_register(&obj->facet);
6476     _Lockit_dtor(&lock);
6477
6478     return obj;
6479 }
6480
6481 /* ?_Put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PBDI@Z */
6482 /* ?_Put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PEBD_K@Z */
6483 ostreambuf_iterator_char* __cdecl num_put_char__Put(const num_put *this, ostreambuf_iterator_char *ret,
6484         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count)
6485 {
6486     TRACE("(%p %p %p %ld)\n", this, ret, ptr, count);
6487
6488     for(; count>0; count--)
6489         ostreambuf_iterator_char_put(&dest, *ptr++);
6490
6491     *ret = dest;
6492     return ret;
6493 }
6494
6495 /* ?_Putc@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PBDI@Z */
6496 /* ?_Putc@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PEBD_K@Z */
6497 ostreambuf_iterator_char* __cdecl num_put_char__Putc(const num_put *this, ostreambuf_iterator_char *ret,
6498         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count)
6499 {
6500     TRACE("(%p %p %p %ld)\n", this, ret, ptr, count);
6501
6502     for(; count>0; count--)
6503         ostreambuf_iterator_char_put(&dest, *ptr++);
6504
6505     *ret = dest;
6506     return ret;
6507 }
6508
6509 /* ?_Putgrouped@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PBDID@Z */
6510 /* ?_Putgrouped@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@PEBD_KD@Z */
6511 ostreambuf_iterator_char* __cdecl num_put_char__Putgrouped(const num_put *this, ostreambuf_iterator_char *ret,
6512         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count, char delim)
6513 {
6514     FIXME("(%p %p %p %ld %d) stub\n", this, ret, ptr, count, delim);
6515     return NULL;
6516 }
6517
6518 /* ?_Rep@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@DI@Z */
6519 /* ?_Rep@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@D_K@Z */
6520 ostreambuf_iterator_char* __cdecl num_put_char__Rep(const num_put *this, ostreambuf_iterator_char *ret,
6521         ostreambuf_iterator_char dest, char c, MSVCP_size_t count)
6522 {
6523     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
6524
6525     for(; count>0; count--)
6526         ostreambuf_iterator_char_put(&dest, c);
6527
6528     *ret = dest;
6529     return ret;
6530 }
6531
6532 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADDH@Z */
6533 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6534 char* __cdecl num_put_char__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
6535 {
6536     int type = fmtfl & FMTFLAG_floatfield;
6537     char *p = fmt;
6538
6539     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
6540
6541     *p++ = '%';
6542     if(fmtfl & FMTFLAG_showpos)
6543         *p++ = '+';
6544     if(fmtfl & FMTFLAG_showbase)
6545         *p++ = '#';
6546     *p++ = '.';
6547     *p++ = '*';
6548     if(spec)
6549         *p++ = spec;
6550
6551     if(type == FMTFLAG_fixed)
6552         *p++ = 'f';
6553     else if(type == FMTFLAG_scientific)
6554         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
6555     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
6556         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
6557     else
6558         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
6559
6560     *p++ = '\0';
6561     return fmt;
6562 }
6563
6564 /* ?_Fput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBDIIII@Z */
6565 /* ?_Fput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBD_K333@Z */
6566 ostreambuf_iterator_char* __cdecl num_put_char__Fput(const num_put *this, ostreambuf_iterator_char *ret,
6567         ostreambuf_iterator_char dest, ios_base *base, char fill, const char *buf, MSVCP_size_t bef_point,
6568         MSVCP_size_t aft_point, MSVCP_size_t trailing, MSVCP_size_t count)
6569 {
6570     FIXME("(%p %p %p %d %p %ld %ld %ld %ld) stub\n", this, ret, base,
6571             fill, buf, bef_point, aft_point, trailing, count);
6572     return NULL;
6573 }
6574
6575 /* TODO: This function should be removed when num_put_char__Fput is implemented */
6576 static ostreambuf_iterator_char* num_put_char_fput(const num_put *this, ostreambuf_iterator_char *ret,
6577         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
6578 {
6579     numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
6580     basic_string_char grouping_bstr;
6581     const char *grouping;
6582     char *p, sep = *localeconv()->decimal_point;
6583     int cur_group = 0, group_size = 0;
6584     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6585     MSVCP_size_t pad;
6586
6587     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6588
6589     /* Change decimal point */
6590     for(p=buf; p<buf+count; p++) {
6591         if(*p == sep) {
6592             *p = numpunct_char_decimal_point(numpunct);
6593             break;
6594         }
6595     }
6596     p--;
6597
6598     /* Add separators to number */
6599     numpunct_char_grouping(numpunct, &grouping_bstr);
6600     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
6601     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
6602
6603     for(; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
6604         group_size++;
6605         if(group_size == grouping[cur_group]) {
6606             group_size = 0;
6607             if(grouping[cur_group+1])
6608                 cur_group++;
6609
6610             memmove(p+1, p, buf+count-p);
6611             *p = sep;
6612             count++;
6613         }
6614     }
6615     MSVCP_basic_string_char_dtor(&grouping_bstr);
6616
6617     /* Display number with padding */
6618     if(count >= base->wide)
6619         pad = 0;
6620     else
6621         pad = base->wide-count;
6622     base->wide = 0;
6623
6624     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6625         num_put_char__Putc(this, &dest, dest, buf, 1);
6626         buf++;
6627     }
6628     if(adjustfield != FMTFLAG_left) {
6629         num_put_char__Rep(this, ret, dest, fill, pad);
6630         pad = 0;
6631     }
6632     num_put_char__Putc(this, &dest, dest, buf, count);
6633     return num_put_char__Rep(this, ret, dest, fill, pad);
6634 }
6635
6636 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADPBDH@Z */
6637 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6638 char* __cdecl num_put_char__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
6639 {
6640     int base = fmtfl & FMTFLAG_basefield;
6641     char *p = fmt;
6642
6643     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
6644
6645     *p++ = '%';
6646     if(fmtfl & FMTFLAG_showpos)
6647         *p++ = '+';
6648     if(fmtfl & FMTFLAG_showbase)
6649         *p++ = '#';
6650
6651     *p++ = *spec++;
6652     if(*spec == 'l')
6653         *p++ = *spec++;
6654
6655     if(base == FMTFLAG_oct)
6656         *p++ = 'o';
6657     else if(base == FMTFLAG_hex)
6658         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
6659     else
6660         *p++ = *spec;
6661
6662     *p++ = '\0';
6663     return fmt;
6664 }
6665
6666 /* ?_Iput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPADI@Z */
6667 /* ?_Iput@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEAD_K@Z */
6668 ostreambuf_iterator_char* __cdecl num_put_char__Iput(const num_put *this, ostreambuf_iterator_char *ret,
6669         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
6670 {
6671     numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
6672     basic_string_char grouping_bstr;
6673     const char *grouping;
6674     char *p, sep;
6675     int cur_group = 0, group_size = 0;
6676     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6677     MSVCP_size_t pad;
6678
6679     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6680
6681     /* Add separators to number */
6682     numpunct_char_grouping(numpunct, &grouping_bstr);
6683     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
6684     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
6685
6686     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
6687         group_size++;
6688         if(group_size == grouping[cur_group]) {
6689             group_size = 0;
6690             if(grouping[cur_group+1])
6691                 cur_group++;
6692
6693             memmove(p+1, p, buf+count-p);
6694             *p = sep;
6695             count++;
6696         }
6697     }
6698     MSVCP_basic_string_char_dtor(&grouping_bstr);
6699
6700     /* Display number with padding */
6701     if(count >= base->wide)
6702         pad = 0;
6703     else
6704         pad = base->wide-count;
6705     base->wide = 0;
6706
6707     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6708         num_put_char__Putc(this, &dest, dest, buf, 1);
6709         buf++;
6710     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
6711         num_put_char__Putc(this, &dest, dest, buf, 2);
6712         buf += 2;
6713     }
6714     if(adjustfield != FMTFLAG_left) {
6715         num_put_char__Rep(this, ret, dest, fill, pad);
6716         pad = 0;
6717     }
6718     num_put_char__Putc(this, &dest, dest, buf, count);
6719     return num_put_char__Rep(this, ret, dest, fill, pad);
6720 }
6721
6722 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DJ@Z */
6723 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DJ@Z */
6724 #define call_num_put_char_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_char*, \
6725         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, LONG), \
6726         (this, ret, dest, base, fill, v))
6727 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_long, 28)
6728 ostreambuf_iterator_char* __thiscall num_put_char_do_put_long(const num_put *this, ostreambuf_iterator_char *ret,
6729         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
6730 {
6731     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6732     char fmt[7]; /* strlen("%+#lld")+1 */
6733
6734     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6735
6736     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6737             sprintf(tmp, num_put_char__Ifmt(this, fmt, "ld", base->fmtfl), v));
6738 }
6739
6740 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DJ@Z */
6741 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DJ@Z */
6742 DEFINE_THISCALL_WRAPPER(num_put_char_put_long, 28)
6743 ostreambuf_iterator_char* __thiscall num_put_char_put_long(const num_put *this, ostreambuf_iterator_char *ret,
6744         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
6745 {
6746     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6747     return call_num_put_char_do_put_long(this, ret, dest, base, fill, v);
6748 }
6749
6750 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DK@Z */
6751 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DK@Z */
6752 #define call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_char*, \
6753         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, ULONG), \
6754         (this, ret, dest, base, fill, v))
6755 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ulong, 28)
6756 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
6757         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
6758 {
6759     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6760     char fmt[7]; /* strlen("%+#lld")+1 */
6761
6762     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6763
6764     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6765             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lu", base->fmtfl), v));
6766 }
6767
6768 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DK@Z */
6769 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DK@Z */
6770 DEFINE_THISCALL_WRAPPER(num_put_char_put_ulong, 28)
6771 ostreambuf_iterator_char* __thiscall num_put_char_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
6772         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
6773 {
6774     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6775     return call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v);
6776 }
6777
6778 static inline streamsize get_precision(const ios_base *base)
6779 {
6780     return base->prec <= 0 && !(base->fmtfl & FMTFLAG_fixed) ? 6 : base->prec;
6781 }
6782
6783 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */
6784 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DN@Z */
6785 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DO@Z */
6786 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DO@Z */
6787 #define call_num_put_char_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_char*, \
6788         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
6789         (this, ret, dest, base, fill, v))
6790 #define call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_char*, \
6791         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
6792         (this, ret, dest, base, fill, v))
6793 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_double, 32)
6794 ostreambuf_iterator_char* __thiscall num_put_char_do_put_double(const num_put *this, ostreambuf_iterator_char *ret,
6795         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
6796 {
6797     char *tmp;
6798     char fmt[8]; /* strlen("%+#.*lg")+1 */
6799     int size;
6800     streamsize prec;
6801
6802     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6803
6804     num_put_char__Ffmt(this, fmt, '\0', base->fmtfl);
6805     prec = get_precision(base);
6806     size = _scprintf(fmt, prec, v);
6807
6808     /* TODO: don't use dynamic allocation */
6809     tmp = MSVCRT_operator_new(size*2);
6810     if(!tmp) {
6811         ERR("Out of memory\n");
6812         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6813     }
6814     num_put_char_fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v));
6815     MSVCRT_operator_delete(tmp);
6816     return ret;
6817 }
6818
6819 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DN@Z */
6820 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DN@Z */
6821 DEFINE_THISCALL_WRAPPER(num_put_char_put_double, 32)
6822 ostreambuf_iterator_char* __thiscall num_put_char_put_double(const num_put *this, ostreambuf_iterator_char *ret,
6823         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
6824 {
6825     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6826     return call_num_put_char_do_put_double(this, ret, dest, base, fill, v);
6827 }
6828
6829 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DO@Z */
6830 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DO@Z */
6831 DEFINE_THISCALL_WRAPPER(num_put_char_put_ldouble, 32)
6832 ostreambuf_iterator_char* __thiscall num_put_char_put_ldouble(const num_put *this, ostreambuf_iterator_char *ret,
6833         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
6834 {
6835     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6836     return call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v);
6837 }
6838
6839 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBX@Z */
6840 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBX@Z */
6841 #define call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_char*, \
6842         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, const void*), \
6843         (this, ret, dest, base, fill, v))
6844 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ptr, 28)
6845 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
6846         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
6847 {
6848     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6849
6850     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6851
6852     return num_put_char__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6853 }
6854
6855 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBX@Z */
6856 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBX@Z */
6857 DEFINE_THISCALL_WRAPPER(num_put_char_put_ptr, 28)
6858 ostreambuf_iterator_char* __thiscall num_put_char_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
6859         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
6860 {
6861     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6862     return call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v);
6863 }
6864
6865 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_J@Z */
6866 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_J@Z */
6867 #define call_num_put_char_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_char*, \
6868         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, __int64), \
6869         (this, ret, dest, base, fill, v))
6870 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_int64, 32)
6871 ostreambuf_iterator_char* __thiscall num_put_char_do_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6872         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6873 {
6874     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6875     char fmt[7]; /* strlen("%+#lld")+1 */
6876
6877     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6878
6879     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6880             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lld", base->fmtfl), v));
6881 }
6882
6883 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_J@Z */
6884 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_J@Z */
6885 DEFINE_THISCALL_WRAPPER(num_put_char_put_int64, 32)
6886 ostreambuf_iterator_char* __thiscall num_put_char_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6887         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6888 {
6889     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6890     return call_num_put_char_do_put_int64(this, ret, dest, base, fill, v);
6891 }
6892
6893 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_K@Z */
6894 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_K@Z */
6895 #define call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_char*, \
6896         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, unsigned __int64), \
6897         (this, ret, dest, base, fill, v))
6898 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_uint64, 32)
6899 ostreambuf_iterator_char* __thiscall num_put_char_do_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6900         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6901 {
6902     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6903     char fmt[7]; /* strlen("%+#lld")+1 */
6904
6905     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6906
6907     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6908             sprintf(tmp, num_put_char__Ifmt(this, fmt, "llu", base->fmtfl), v));
6909 }
6910
6911 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_K@Z */
6912 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_K@Z */
6913 DEFINE_THISCALL_WRAPPER(num_put_char_put_uint64, 32)
6914 ostreambuf_iterator_char* __thiscall num_put_char_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6915         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6916 {
6917     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6918     return call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v);
6919 }
6920
6921 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_N@Z */
6922 /* ?do_put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_N@Z */
6923 #define call_num_put_char_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_char*, \
6924         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, MSVCP_bool), \
6925         (this, ret, dest, base, fill, v))
6926 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_bool, 28)
6927 ostreambuf_iterator_char* __thiscall num_put_char_do_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6928         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6929 {
6930     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6931
6932     if(base->fmtfl & FMTFLAG_boolalpha) {
6933         numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
6934         basic_string_char str;
6935         MSVCP_size_t pad, len;
6936
6937         if(v)
6938             numpunct_char_truename(numpunct, &str);
6939         else
6940             numpunct_char_falsename(numpunct, &str);
6941
6942         len = MSVCP_basic_string_char_length(&str);
6943         pad = (len>base->wide ? 0 : base->wide-len);
6944         base->wide = 0;
6945
6946         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6947             num_put_char__Rep(this, &dest, dest, fill, pad);
6948             pad = 0;
6949         }
6950         num_put_char__Putc(this, &dest, dest, MSVCP_basic_string_char_c_str(&str), len);
6951         MSVCP_basic_string_char_dtor(&str);
6952         return num_put_char__Rep(this, ret, dest, fill, pad);
6953     }
6954
6955     return num_put_char_put_long(this, ret, dest, base, fill, v);
6956 }
6957
6958 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@D_N@Z */
6959 /* ?put@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@D_N@Z */
6960 DEFINE_THISCALL_WRAPPER(num_put_char_put_bool, 28)
6961 ostreambuf_iterator_char* __thiscall num_put_char_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6962         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6963 {
6964     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6965     return call_num_put_char_do_put_bool(this, ret, dest, base, fill, v);
6966 }
6967
6968 /* ?id@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
6969 locale_id num_put_wchar_id = {0};
6970 /* ?id@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
6971 locale_id num_put_short_id = {0};
6972
6973 /* num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
6974 extern const vtable_ptr MSVCP_num_put_wchar_vtable;
6975 /* num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
6976 extern const vtable_ptr MSVCP_num_put_short_vtable;
6977
6978 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
6979 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
6980 DEFINE_THISCALL_WRAPPER(num_put_wchar__Init, 8)
6981 void __thiscall num_put_wchar__Init(num_put *this, const _Locinfo *locinfo)
6982 {
6983     TRACE("(%p %p)\n", this, locinfo);
6984     _Locinfo__Getcvt(locinfo, &this->cvt);
6985 }
6986
6987 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6988 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6989 DEFINE_THISCALL_WRAPPER(num_put_wchar_ctor_locinfo, 12)
6990 num_put* __thiscall num_put_wchar_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6991 {
6992     TRACE("(%p %p %ld)\n", this, locinfo, refs);
6993
6994     locale_facet_ctor_refs(&this->facet, refs);
6995     this->facet.vtable = &MSVCP_num_put_wchar_vtable;
6996
6997     num_put_wchar__Init(this, locinfo);
6998     return this;
6999 }
7000
7001 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
7002 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
7003 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_locinfo, 12)
7004 num_put* __thiscall num_put_short_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
7005 {
7006     num_put_wchar_ctor_locinfo(this, locinfo, refs);
7007     this->facet.vtable = &MSVCP_num_put_short_vtable;
7008     return this;
7009 }
7010
7011 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
7012 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
7013 DEFINE_THISCALL_WRAPPER(num_put_wchar_ctor_refs, 8)
7014 num_put* __thiscall num_put_wchar_ctor_refs(num_put *this, MSVCP_size_t refs)
7015 {
7016     _Locinfo locinfo;
7017
7018     TRACE("(%p %lu)\n", this, refs);
7019
7020     _Locinfo_ctor(&locinfo);
7021     num_put_wchar_ctor_locinfo(this, &locinfo, refs);
7022     _Locinfo_dtor(&locinfo);
7023     return this;
7024 }
7025
7026 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
7027 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
7028 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_refs, 8)
7029 num_put* __thiscall num_put_short_ctor_refs(num_put *this, MSVCP_size_t refs)
7030 {
7031     num_put_wchar_ctor_refs(this, refs);
7032     this->facet.vtable = &MSVCP_num_put_short_vtable;
7033     return this;
7034 }
7035
7036 /* ??_F?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
7037 /* ??_F?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
7038 DEFINE_THISCALL_WRAPPER(num_put_wchar_ctor, 4)
7039 num_put* __thiscall num_put_wchar_ctor(num_put *this)
7040 {
7041     return num_put_wchar_ctor_refs(this, 0);
7042 }
7043
7044 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAEXXZ */
7045 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAAXXZ */
7046 DEFINE_THISCALL_WRAPPER(num_put_short_ctor, 4)
7047 num_put* __thiscall num_put_short_ctor(num_put *this)
7048 {
7049     return num_put_short_ctor_refs(this, 0);
7050 }
7051
7052 /* ??1?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
7053 /* ??1?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
7054 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
7055 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
7056 DEFINE_THISCALL_WRAPPER(num_put_wchar_dtor, 4)
7057 void __thiscall num_put_wchar_dtor(num_put *this)
7058 {
7059     TRACE("(%p)\n", this);
7060     locale_facet_dtor(&this->facet);
7061 }
7062
7063 DEFINE_THISCALL_WRAPPER(num_put_wchar_vector_dtor, 8)
7064 num_put* __thiscall num_put_wchar_vector_dtor(num_put *this, unsigned int flags)
7065 {
7066     TRACE("(%p %x)\n", this, flags);
7067     if(flags & 2) {
7068         /* we have an array, with the number of elements stored before the first object */
7069         INT_PTR i, *ptr = (INT_PTR *)this-1;
7070
7071         for(i=*ptr-1; i>=0; i--)
7072             num_put_wchar_dtor(this+i);
7073         MSVCRT_operator_delete(ptr);
7074     } else {
7075         num_put_wchar_dtor(this);
7076         if(flags & 1)
7077             MSVCRT_operator_delete(this);
7078     }
7079
7080     return this;
7081 }
7082
7083 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
7084 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
7085 MSVCP_size_t __cdecl num_put_wchar__Getcat(const locale_facet **facet, const locale *loc)
7086 {
7087     TRACE("(%p %p)\n", facet, loc);
7088
7089     if(facet && !*facet) {
7090         _Locinfo locinfo;
7091
7092         *facet = MSVCRT_operator_new(sizeof(num_put));
7093         if(!*facet) {
7094             ERR("Out of memory\n");
7095             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7096             return 0;
7097         }
7098
7099         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
7100         num_put_wchar_ctor_locinfo((num_put*)*facet, &locinfo, 0);
7101         _Locinfo_dtor(&locinfo);
7102     }
7103
7104     return LC_NUMERIC;
7105 }
7106
7107 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
7108 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
7109 MSVCP_size_t __cdecl num_put_short__Getcat(const locale_facet **facet, const locale *loc)
7110 {
7111     TRACE("(%p %p)\n", facet, loc);
7112
7113     if(facet && !*facet) {
7114         _Locinfo locinfo;
7115
7116         *facet = MSVCRT_operator_new(sizeof(num_put));
7117         if(!*facet) {
7118             ERR("Out of memory\n");
7119             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7120             return 0;
7121         }
7122
7123         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
7124         num_put_short_ctor_locinfo((num_put*)*facet, &locinfo, 0);
7125         _Locinfo_dtor(&locinfo);
7126     }
7127
7128     return LC_NUMERIC;
7129 }
7130
7131 num_put* num_put_wchar_use_facet(const locale *loc)
7132 {
7133     static num_put *obj = NULL;
7134
7135     _Lockit lock;
7136     const locale_facet *fac;
7137
7138     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7139     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_wchar_id));
7140     if(fac) {
7141         _Lockit_dtor(&lock);
7142         return (num_put*)fac;
7143     }
7144
7145     if(obj) {
7146         _Lockit_dtor(&lock);
7147         return obj;
7148     }
7149
7150     num_put_wchar__Getcat(&fac, loc);
7151     obj = (num_put*)fac;
7152     locale_facet__Incref(&obj->facet);
7153     locale_facet_register(&obj->facet);
7154     _Lockit_dtor(&lock);
7155
7156     return obj;
7157 }
7158
7159 num_put* num_put_short_use_facet(const locale *loc)
7160 {
7161     static num_put *obj = NULL;
7162
7163     _Lockit lock;
7164     const locale_facet *fac;
7165
7166     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7167     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_short_id));
7168     if(fac) {
7169         _Lockit_dtor(&lock);
7170         return (num_put*)fac;
7171     }
7172
7173     if(obj) {
7174         _Lockit_dtor(&lock);
7175         return obj;
7176     }
7177
7178     num_put_short__Getcat(&fac, loc);
7179     obj = (num_put*)fac;
7180     locale_facet__Incref(&obj->facet);
7181     locale_facet_register(&obj->facet);
7182     _Lockit_dtor(&lock);
7183
7184     return obj;
7185 }
7186
7187 /* ?_Put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PB_WI@Z */
7188 /* ?_Put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEB_W_K@Z */
7189 /* ?_Put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBGI@Z */
7190 /* ?_Put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBG_K@Z */
7191 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Put(const num_put *this, ostreambuf_iterator_wchar *ret,
7192         ostreambuf_iterator_wchar dest, const wchar_t *ptr, MSVCP_size_t count)
7193 {
7194     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_wn(ptr, count), count);
7195
7196     for(; count>0; count--)
7197         ostreambuf_iterator_wchar_put(&dest, *ptr++);
7198
7199     *ret = dest;
7200     return ret;
7201 }
7202
7203 /* ?_Putc@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PBDI@Z */
7204 /* ?_Putc@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEBD_K@Z */
7205 /* ?_Putc@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBDI@Z */
7206 /* ?_Putc@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBD_K@Z */
7207 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Putc(const num_put *this, ostreambuf_iterator_wchar *ret,
7208         ostreambuf_iterator_wchar dest, const char *ptr, MSVCP_size_t count)
7209 {
7210     int state = 0;
7211     wchar_t ch;
7212
7213     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_an(ptr, count), count);
7214
7215     for(; count>0; count--) {
7216         if(_Mbrtowc(&ch, ptr++, 1, &state, &this->cvt) == 1)
7217             ostreambuf_iterator_wchar_put(&dest, ch);
7218     }
7219
7220     *ret = dest;
7221     return ret;
7222 }
7223
7224 /* ?_Putgrouped@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PBDI_W@Z */
7225 /* ?_Putgrouped@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@PEBD_K_W@Z */
7226 /* ?_Putgrouped@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PBDIG@Z */
7227 /* ?_Putgrouped@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@PEBD_KG@Z */
7228 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Putgrouped(const num_put *this, ostreambuf_iterator_wchar *ret,
7229         ostreambuf_iterator_wchar dest, const char *ptr, MSVCP_size_t count, wchar_t delim)
7230 {
7231     FIXME("(%p %p %p %ld %d) stub\n", this, ret, ptr, count, delim);
7232     return NULL;
7233 }
7234
7235 /* ?_Rep@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@_WI@Z */
7236 /* ?_Rep@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@_W_K@Z */
7237 /* ?_Rep@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@GI@Z */
7238 /* ?_Rep@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@G_K@Z */
7239 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Rep(const num_put *this, ostreambuf_iterator_wchar *ret,
7240         ostreambuf_iterator_wchar dest, wchar_t c, MSVCP_size_t count)
7241 {
7242     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
7243
7244     for(; count>0; count--)
7245         ostreambuf_iterator_wchar_put(&dest, c);
7246
7247     *ret = dest;
7248     return ret;
7249 }
7250
7251 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADDH@Z */
7252 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADDH@Z */
7253 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADDH@Z */
7254 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADDH@Z */
7255 char* __cdecl num_put_wchar__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
7256 {
7257     int type = fmtfl & FMTFLAG_floatfield;
7258     char *p = fmt;
7259
7260     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
7261
7262     *p++ = '%';
7263     if(fmtfl & FMTFLAG_showpos)
7264         *p++ = '+';
7265     if(fmtfl & FMTFLAG_showbase)
7266         *p++ = '#';
7267     *p++ = '.';
7268     *p++ = '*';
7269     if(spec)
7270         *p++ = spec;
7271
7272     if(type == FMTFLAG_fixed)
7273         *p++ = 'f';
7274     else if(type == FMTFLAG_scientific)
7275         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
7276     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
7277         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
7278     else
7279         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
7280
7281     *p++ = '\0';
7282     return fmt;
7283 }
7284
7285 /* ?_Fput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBDIIII@Z */
7286 /* ?_Fput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBD_K444@Z */
7287 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Fput(const num_put *this, ostreambuf_iterator_wchar *ret,
7288         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const char *buf, MSVCP_size_t bef_point,
7289         MSVCP_size_t aft_point, MSVCP_size_t trailing, MSVCP_size_t count)
7290 {
7291     FIXME("(%p %p %p %d %p %ld %ld %ld %ld) stub\n", this, ret, base,
7292             fill, buf, bef_point, aft_point, trailing, count);
7293     return NULL;
7294 }
7295
7296 /* ?_Fput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBDIIII@Z */
7297 /* ?_Fput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBD_K333@Z */
7298 ostreambuf_iterator_wchar* __cdecl num_put_short__Fput(const num_put *this, ostreambuf_iterator_wchar *ret,
7299         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const char *buf, MSVCP_size_t bef_point,
7300         MSVCP_size_t aft_point, MSVCP_size_t trailing, MSVCP_size_t count)
7301 {
7302     FIXME("(%p %p %p %d %p %ld %ld %ld %ld) stub\n", this, ret, base,
7303             fill, buf, bef_point, aft_point, trailing, count);
7304     return NULL;
7305 }
7306
7307 /* TODO: This function should be removed when num_put_wchar__Fput is implemented */
7308 static ostreambuf_iterator_wchar* num_put__fput(const num_put *this, ostreambuf_iterator_wchar *ret,
7309         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
7310         MSVCP_size_t count, numpunct_wchar *numpunct)
7311 {
7312     basic_string_char grouping_bstr;
7313     const char *grouping;
7314     char *p, dec_point = *localeconv()->decimal_point;
7315     wchar_t sep;
7316     int cur_group = 0, group_size = 0;
7317     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
7318     MSVCP_size_t i, pad;
7319
7320     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
7321
7322     for(p=buf; p<buf+count; p++) {
7323         if(*p == dec_point)
7324             break;
7325     }
7326     p--;
7327
7328     /* Add separators to number */
7329     numpunct_wchar_grouping(numpunct, &grouping_bstr);
7330     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
7331     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
7332
7333     for(; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
7334         group_size++;
7335         if(group_size == grouping[cur_group]) {
7336             group_size = 0;
7337             if(grouping[cur_group+1])
7338                 cur_group++;
7339
7340             memmove(p+1, p, buf+count-p);
7341             *p = '\0'; /* mark thousands separator positions */
7342             count++;
7343         }
7344     }
7345     MSVCP_basic_string_char_dtor(&grouping_bstr);
7346
7347     /* Display number with padding */
7348     if(count >= base->wide)
7349         pad = 0;
7350     else
7351         pad = base->wide-count;
7352     base->wide = 0;
7353
7354     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
7355         num_put_wchar__Putc(this, &dest, dest, buf, 1);
7356         buf++;
7357     }
7358     if(adjustfield != FMTFLAG_left) {
7359         num_put_wchar__Rep(this, ret, dest, fill, pad);
7360         pad = 0;
7361     }
7362
7363     for(i=0; i<count; i++) {
7364         if(buf[i] == dec_point)
7365             num_put_wchar__Rep(this, &dest, dest, numpunct_wchar_decimal_point(numpunct), 1);
7366         else if(!buf[i])
7367             num_put_wchar__Rep(this, &dest, dest, sep, 1);
7368         else
7369             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
7370     }
7371
7372     return num_put_wchar__Rep(this, ret, dest, fill, pad);
7373 }
7374
7375 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADPBDH@Z */
7376 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
7377 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADPBDH@Z */
7378 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
7379 char* __cdecl num_put_wchar__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
7380 {
7381     int base = fmtfl & FMTFLAG_basefield;
7382     char *p = fmt;
7383
7384     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
7385
7386     *p++ = '%';
7387     if(fmtfl & FMTFLAG_showpos)
7388         *p++ = '+';
7389     if(fmtfl & FMTFLAG_showbase)
7390         *p++ = '#';
7391
7392     *p++ = *spec++;
7393     if(*spec == 'l')
7394         *p++ = *spec++;
7395
7396     if(base == FMTFLAG_oct)
7397         *p++ = 'o';
7398     else if(base == FMTFLAG_hex)
7399         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
7400     else
7401         *p++ = *spec;
7402
7403     *p++ = '\0';
7404     return fmt;
7405 }
7406
7407 static ostreambuf_iterator_wchar* num_put__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
7408         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
7409         MSVCP_size_t count, numpunct_wchar *numpunct)
7410 {
7411     basic_string_char grouping_bstr;
7412     const char *grouping;
7413     char *p;
7414     wchar_t sep;
7415     int cur_group = 0, group_size = 0;
7416     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
7417     MSVCP_size_t i, pad;
7418
7419     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
7420
7421     /* Add separators to number */
7422     numpunct_wchar_grouping(numpunct, &grouping_bstr);
7423     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
7424     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
7425
7426     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
7427         group_size++;
7428         if(group_size == grouping[cur_group]) {
7429             group_size = 0;
7430             if(grouping[cur_group+1])
7431                 cur_group++;
7432
7433             memmove(p+1, p, buf+count-p);
7434             *p = '\0'; /* mark thousands separator positions */
7435             count++;
7436         }
7437     }
7438     MSVCP_basic_string_char_dtor(&grouping_bstr);
7439
7440     /* Display number with padding */
7441     if(count >= base->wide)
7442         pad = 0;
7443     else
7444         pad = base->wide-count;
7445     base->wide = 0;
7446
7447     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
7448         num_put_wchar__Putc(this, &dest, dest, buf, 1);
7449         buf++;
7450     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
7451         num_put_wchar__Putc(this, &dest, dest, buf, 2);
7452         buf += 2;
7453     }
7454     if(adjustfield != FMTFLAG_left) {
7455         num_put_wchar__Rep(this, ret, dest, fill, pad);
7456         pad = 0;
7457     }
7458
7459     for(i=0; i<count; i++) {
7460         if(!buf[i])
7461             num_put_wchar__Rep(this, &dest, dest, sep, 1);
7462         else
7463             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
7464     }
7465
7466     return num_put_wchar__Rep(this, ret, dest, fill, pad);
7467 }
7468
7469 /* ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPADI@Z */
7470 /* ?_Iput@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEAD_K@Z */
7471 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
7472         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
7473 {
7474     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_wchar_use_facet(base->loc));
7475 }
7476
7477 /* ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPADI@Z */
7478 /* ?_Iput@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEAD_K@Z */
7479 ostreambuf_iterator_wchar* __cdecl num_put_short__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
7480         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
7481 {
7482     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_short_use_facet(base->loc));
7483 }
7484
7485 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WJ@Z */
7486 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WJ@Z */
7487 #define call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_wchar*, \
7488         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, LONG), \
7489         (this, ret, dest, base, fill, v))
7490 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_long, 28)
7491 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
7492         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
7493 {
7494     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7495     char fmt[7]; /* strlen("%+#lld")+1 */
7496
7497     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7498
7499     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
7500             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
7501 }
7502
7503 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GJ@Z */
7504 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GJ@Z */
7505 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_long, 28)
7506 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
7507         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
7508 {
7509     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7510     char fmt[7]; /* strlen("%+#lld")+1 */
7511
7512     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7513
7514     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
7515             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
7516 }
7517
7518 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WJ@Z */
7519 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WJ@Z */
7520 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GJ@Z */
7521 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GJ@Z */
7522 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_long, 28)
7523 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
7524         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
7525 {
7526     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7527     return call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v);
7528 }
7529
7530 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WK@Z */
7531 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WK@Z */
7532 #define call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_wchar*, \
7533         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, ULONG), \
7534         (this, ret, dest, base, fill, v))
7535 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ulong, 28)
7536 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
7537         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
7538 {
7539     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7540     char fmt[7]; /* strlen("%+#lld")+1 */
7541
7542     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7543
7544     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
7545             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
7546 }
7547
7548 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GK@Z */
7549 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GK@Z */
7550 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ulong, 28)
7551 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
7552         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
7553 {
7554     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7555     char fmt[7]; /* strlen("%+#lld")+1 */
7556
7557     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7558
7559     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
7560             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
7561 }
7562
7563 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WK@Z */
7564 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WK@Z */
7565 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GK@Z */
7566 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GK@Z */
7567 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ulong, 28)
7568 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
7569         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
7570 {
7571     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7572     return call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v);
7573 }
7574
7575 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WN@Z */
7576 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WN@Z */
7577 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WO@Z */
7578 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WO@Z */
7579 #define call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_wchar*, \
7580         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
7581         (this, ret, dest, base, fill, v))
7582 #define call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_wchar*, \
7583         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
7584         (this, ret, dest, base, fill, v))
7585 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_double, 32)
7586 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
7587         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
7588 {
7589     char *tmp;
7590     char fmt[8]; /* strlen("%+#.*lg")+1 */
7591     int size;
7592     streamsize prec;
7593
7594     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
7595
7596     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
7597     prec = get_precision(base);
7598     size = _scprintf(fmt, prec, v);
7599
7600     /* TODO: don't use dynamic allocation */
7601     tmp = MSVCRT_operator_new(size*2);
7602     if(!tmp) {
7603         ERR("Out of memory\n");
7604         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7605     }
7606     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v),
7607             numpunct_wchar_use_facet(base->loc));
7608     MSVCRT_operator_delete(tmp);
7609     return ret;
7610 }
7611
7612 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GN@Z */
7613 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GN@Z */
7614 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GO@Z */
7615 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GO@Z */
7616 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_double, 32)
7617 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
7618         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
7619 {
7620     char *tmp;
7621     char fmt[8]; /* strlen("%+#.*lg")+1 */
7622     int size;
7623     streamsize prec;
7624
7625     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
7626
7627     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
7628     prec = get_precision(base);
7629     size = _scprintf(fmt, prec, v);
7630
7631     /* TODO: don't use dynamic allocation */
7632     tmp = MSVCRT_operator_new(size*2);
7633     if(!tmp) {
7634         ERR("Out of memory\n");
7635         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7636     }
7637     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v),
7638             numpunct_short_use_facet(base->loc));
7639     MSVCRT_operator_delete(tmp);
7640     return ret;
7641 }
7642
7643 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WN@Z */
7644 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WN@Z */
7645 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GN@Z */
7646 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GN@Z */
7647 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_double, 32)
7648 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
7649         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
7650 {
7651     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
7652     return call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v);
7653 }
7654
7655 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WO@Z */
7656 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WO@Z */
7657 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GO@Z */
7658 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GO@Z */
7659 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ldouble, 32)
7660 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ldouble(const num_put *this, ostreambuf_iterator_wchar *ret,
7661         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
7662 {
7663     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
7664     return call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v);
7665 }
7666
7667 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBX@Z */
7668 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBX@Z */
7669 #define call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_wchar*, \
7670         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, const void*), \
7671         (this, ret, dest, base, fill, v))
7672 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ptr, 28)
7673 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
7674         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
7675 {
7676     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
7677
7678     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
7679
7680     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
7681 }
7682
7683 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBX@Z */
7684 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBX@Z */
7685 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ptr, 28)
7686 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
7687         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
7688 {
7689     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
7690
7691     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
7692
7693     return num_put_short__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
7694 }
7695
7696 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBX@Z */
7697 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBX@Z */
7698 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBX@Z */
7699 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBX@Z */
7700 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ptr, 28)
7701 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
7702         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
7703 {
7704     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
7705     return call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v);
7706 }
7707
7708 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_J@Z */
7709 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_J@Z */
7710 #define call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_wchar*, \
7711         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, __int64), \
7712         (this, ret, dest, base, fill, v))
7713 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_int64, 32)
7714 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
7715         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
7716 {
7717     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7718     char fmt[7]; /* strlen("%+#lld")+1 */
7719
7720     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7721
7722     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
7723             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
7724 }
7725
7726 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_J@Z */
7727 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_J@Z */
7728 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_int64, 32)
7729 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
7730         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
7731 {
7732     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7733     char fmt[7]; /* strlen("%+#lld")+1 */
7734
7735     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7736
7737     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
7738             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
7739 }
7740
7741 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_J@Z */
7742 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_J@Z */
7743 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_J@Z */
7744 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_J@Z */
7745 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_int64, 32)
7746 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
7747         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
7748 {
7749     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7750     return call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v);
7751 }
7752
7753 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_K@Z */
7754 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_K@Z */
7755 #define call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_wchar*, \
7756         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, unsigned __int64), \
7757         (this, ret, dest, base, fill, v))
7758 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_uint64, 32)
7759 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
7760         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
7761 {
7762     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7763     char fmt[7]; /* strlen("%+#lld")+1 */
7764
7765     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7766
7767     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
7768             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
7769 }
7770
7771 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_K@Z */
7772 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_K@Z */
7773 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_uint64, 32)
7774 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
7775         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
7776 {
7777     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7778     char fmt[7]; /* strlen("%+#lld")+1 */
7779
7780     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7781
7782     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
7783             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
7784 }
7785
7786 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_K@Z */
7787 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_K@Z */
7788 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_K@Z */
7789 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_K@Z */
7790 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_uint64, 32)
7791 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
7792         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
7793 {
7794     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7795     return call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v);
7796 }
7797
7798 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_N@Z */
7799 /* ?do_put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_N@Z */
7800 #define call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_wchar*, \
7801         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, MSVCP_bool), \
7802         (this, ret, dest, base, fill, v))
7803 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_bool, 28)
7804 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
7805         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
7806 {
7807     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7808
7809     if(base->fmtfl & FMTFLAG_boolalpha) {
7810         numpunct_wchar *numpunct = numpunct_wchar_use_facet(base->loc);
7811         basic_string_wchar str;
7812         MSVCP_size_t pad, len;
7813
7814         if(v)
7815             numpunct_wchar_truename(numpunct, &str);
7816         else
7817             numpunct_wchar_falsename(numpunct, &str);
7818
7819         len = MSVCP_basic_string_wchar_length(&str);
7820         pad = (len>base->wide ? 0 : base->wide-len);
7821         base->wide = 0;
7822
7823         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
7824             num_put_wchar__Rep(this, &dest, dest, fill, pad);
7825             pad = 0;
7826         }
7827         num_put_wchar__Put(this, &dest, dest, MSVCP_basic_string_wchar_c_str(&str), len);
7828         MSVCP_basic_string_wchar_dtor(&str);
7829         return num_put_wchar__Rep(this, ret, dest, fill, pad);
7830     }
7831
7832     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
7833 }
7834
7835 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_N@Z */
7836 /* ?do_put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_N@Z */
7837 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_bool, 28)
7838 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
7839         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
7840 {
7841     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7842
7843     if(base->fmtfl & FMTFLAG_boolalpha) {
7844         numpunct_wchar *numpunct = numpunct_short_use_facet(base->loc);
7845         basic_string_wchar str;
7846         MSVCP_size_t pad, len;
7847
7848         if(v)
7849             numpunct_wchar_truename(numpunct, &str);
7850         else
7851             numpunct_wchar_falsename(numpunct, &str);
7852
7853         len = MSVCP_basic_string_wchar_length(&str);
7854         pad = (len>base->wide ? 0 : base->wide-len);
7855         base->wide = 0;
7856
7857         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
7858             num_put_wchar__Rep(this, &dest, dest, fill, pad);
7859             pad = 0;
7860         }
7861         num_put_wchar__Put(this, &dest, dest, MSVCP_basic_string_wchar_c_str(&str), len);
7862         MSVCP_basic_string_wchar_dtor(&str);
7863         return num_put_wchar__Rep(this, ret, dest, fill, pad);
7864     }
7865
7866     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
7867 }
7868
7869 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_W_N@Z */
7870 /* ?put@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_W_N@Z */
7871 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@G_N@Z */
7872 /* ?put@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@G_N@Z */
7873 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_bool, 28)
7874 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
7875         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
7876 {
7877     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7878     return call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v);
7879 }
7880
7881 /* ?id@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
7882 locale_id time_put_char_id = {0};
7883
7884 /* ??_7?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
7885 extern const vtable_ptr MSVCP_time_put_char_vtable;
7886
7887 /* ?_Init@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
7888 /* ?_Init@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
7889 DEFINE_THISCALL_WRAPPER(time_put_char__Init, 8)
7890 void __thiscall time_put_char__Init(time_put *this, const _Locinfo *locinfo)
7891 {
7892     TRACE("(%p %p)\n", this, locinfo);
7893     _Locinfo__Gettnames(locinfo, &this->time);
7894     _Locinfo__Getcvt(locinfo, &this->cvt);
7895 }
7896
7897 /* ??0?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
7898 /* ??0?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
7899 DEFINE_THISCALL_WRAPPER(time_put_char_ctor_locinfo, 12)
7900 time_put* __thiscall time_put_char_ctor_locinfo(time_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
7901 {
7902     TRACE("(%p %p %lu)\n", this, locinfo, refs);
7903     locale_facet_ctor_refs(&this->facet, refs);
7904     this->facet.vtable = &MSVCP_time_put_char_vtable;
7905     time_put_char__Init(this, locinfo);
7906     return this;
7907 }
7908
7909 /* ??0?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
7910 /* ??0?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
7911 DEFINE_THISCALL_WRAPPER(time_put_char_ctor_refs, 8)
7912 time_put* __thiscall time_put_char_ctor_refs(time_put *this, MSVCP_size_t refs)
7913 {
7914     _Locinfo locinfo;
7915
7916     TRACE("(%p %lu)\n", this, refs);
7917
7918     _Locinfo_ctor(&locinfo);
7919     time_put_char_ctor_locinfo(this, &locinfo, refs);
7920     _Locinfo_dtor(&locinfo);
7921     return this;
7922 }
7923
7924 /* ??_F?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
7925 /* ??_F?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
7926 DEFINE_THISCALL_WRAPPER(time_put_char_ctor, 4)
7927 time_put* __thiscall time_put_char_ctor(time_put *this)
7928 {
7929     return time_put_char_ctor_refs(this, 0);
7930 }
7931
7932 /* ??1?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
7933 /* ??1?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
7934 DEFINE_THISCALL_WRAPPER(time_put_char_dtor, 4)
7935 void __thiscall time_put_char_dtor(time_put *this)
7936 {
7937     TRACE("(%p)\n", this);
7938     _Timevec_dtor(&this->time);
7939 }
7940
7941 DEFINE_THISCALL_WRAPPER(time_put_char_vector_dtor, 8)
7942 time_put* __thiscall time_put_char_vector_dtor(time_put *this, unsigned int flags)
7943 {
7944     TRACE("(%p %x)\n", this, flags);
7945     if(flags & 2) {
7946         /* we have an array, with the number of elements stored before the first object */
7947         INT_PTR i, *ptr = (INT_PTR *)this-1;
7948
7949         for(i=*ptr-1; i>=0; i--)
7950             time_put_char_dtor(this+i);
7951         MSVCRT_operator_delete(ptr);
7952     } else {
7953         time_put_char_dtor(this);
7954         if(flags & 1)
7955             MSVCRT_operator_delete(this);
7956     }
7957
7958     return this;
7959 }
7960
7961 /* ?_Getcat@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
7962 /* ?_Getcat@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
7963 MSVCP_size_t __cdecl time_put_char__Getcat(const locale_facet **facet, const locale *loc)
7964 {
7965     TRACE("(%p %p)\n", facet, loc);
7966
7967     if(facet && !*facet) {
7968         _Locinfo locinfo;
7969
7970         *facet = MSVCRT_operator_new(sizeof(time_put));
7971         if(!*facet) {
7972             ERR("Out of memory\n");
7973             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7974             return 0;
7975         }
7976
7977         _Locinfo_ctor_cstr(&locinfo, MSVCP_basic_string_char_c_str(&loc->ptr->name));
7978         time_put_char_ctor_locinfo((time_put*)*facet, &locinfo, 0);
7979         _Locinfo_dtor(&locinfo);
7980     }
7981
7982     return LC_TIME;
7983 }
7984
7985 static time_put* time_put_char_use_facet(const locale *loc)
7986 {
7987     static time_put *obj = NULL;
7988
7989     _Lockit lock;
7990     const locale_facet *fac;
7991
7992     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7993     fac = locale__Getfacet(loc, locale_id_operator_size_t(&time_put_char_id));
7994     if(fac) {
7995         _Lockit_dtor(&lock);
7996         return (time_put*)fac;
7997     }
7998
7999     if(obj) {
8000         _Lockit_dtor(&lock);
8001         return obj;
8002     }
8003
8004     time_put_char__Getcat(&fac, loc);
8005     obj = (time_put*)fac;
8006     locale_facet__Incref(&obj->facet);
8007     locale_facet_register(&obj->facet);
8008     _Lockit_dtor(&lock);
8009
8010     return obj;
8011 }
8012
8013 /* ?do_put@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBUtm@@DD@Z */
8014 /* ?do_put@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBUtm@@DD@Z */
8015 DEFINE_THISCALL_WRAPPER(time_put_char_do_put, 36)
8016 #define call_time_put_char_do_put(this, ret, dest, base, fill, t, spec, mod) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_char*, \
8017         (const time_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, const struct tm*, char, char), \
8018         (this, ret, dest, base, fill, t, spec, mod))
8019 ostreambuf_iterator_char* __thiscall time_put_char_do_put(const time_put *this, ostreambuf_iterator_char *ret,
8020         ostreambuf_iterator_char dest, ios_base *base, char fill, const struct tm *t, char spec, char mod)
8021 {
8022     char buf[64], fmt[4], *p = fmt;
8023     MSVCP_size_t i, len;
8024
8025     TRACE("(%p %p %p %c %p %c %c)\n", this, ret, base, fill, t, spec, mod);
8026
8027     *p++ = '%';
8028     if(mod)
8029         *p++ = mod;
8030     *p++ = spec;
8031     *p++ = 0;
8032
8033     len = _Strftime(buf, sizeof(buf), fmt, t, this->time.timeptr);
8034     for(i=0; i<len; i++)
8035         ostreambuf_iterator_char_put(&dest, buf[i]);
8036
8037     *ret = dest;
8038     return ret;
8039 }
8040
8041 /* ?put@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBUtm@@DD@Z */
8042 /* ?put@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBUtm@@DD@Z */
8043 DEFINE_THISCALL_WRAPPER(time_put_char_put, 36)
8044 ostreambuf_iterator_char* __thiscall time_put_char_put(const time_put *this, ostreambuf_iterator_char *ret,
8045         ostreambuf_iterator_char dest, ios_base *base, char fill, const struct tm *t, char spec, char mod)
8046 {
8047     TRACE("(%p %p %p %c %p %c %c)\n", this, ret, base, fill, t, spec, mod);
8048     return call_time_put_char_do_put(this, ret, dest, base, fill, t, spec, mod);
8049 }
8050
8051 /* ?put@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AAVios_base@2@DPBUtm@@PBD3@Z */
8052 /* ?put@?$time_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@DU?$char_traits@D@std@@@2@V32@AEAVios_base@2@DPEBUtm@@PEBD3@Z */
8053 DEFINE_THISCALL_WRAPPER(time_put_char_put_format, 36)
8054 ostreambuf_iterator_char* __thiscall time_put_char_put_format(const time_put *this, ostreambuf_iterator_char *ret,
8055         ostreambuf_iterator_char dest, ios_base *base, char fill, const struct tm *t, const char *pat, const char *pat_end)
8056 {
8057     TRACE("(%p %p %p %c %p %s)\n", this, ret, base, fill, t, debugstr_an(pat, pat_end-pat));
8058
8059     while(pat < pat_end) {
8060         if(*pat != '%') {
8061             ostreambuf_iterator_char_put(&dest, *pat++);
8062         }else if(++pat == pat_end) {
8063             ostreambuf_iterator_char_put(&dest, '%');
8064         }else if(*pat=='#' && pat+1==pat_end) {
8065             ostreambuf_iterator_char_put(&dest, '%');
8066             ostreambuf_iterator_char_put(&dest, *pat++);
8067         }else {
8068             char mod;
8069
8070             if(*pat == '#') {
8071                 mod = '#';
8072                 pat++;
8073             }else {
8074                 mod = 0;
8075             }
8076
8077             time_put_char_put(this, &dest, dest, base, fill, t, *pat++, mod);
8078         }
8079     }
8080
8081     *ret = dest;
8082     return ret;
8083 }
8084
8085 /* ?id@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
8086 locale_id time_put_wchar_id = {0};
8087 /* ?id@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
8088 locale_id time_put_short_id = {0};
8089
8090 /* ??_7?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
8091 extern const vtable_ptr MSVCP_time_put_wchar_vtable;
8092 /* ??_7?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
8093 extern const vtable_ptr MSVCP_time_put_short_vtable;
8094
8095 /* ?_Init@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
8096 /* ?_Init@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
8097 /* ?_Init@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
8098 /* ?_Init@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
8099 DEFINE_THISCALL_WRAPPER(time_put_wchar__Init, 8)
8100 void __thiscall time_put_wchar__Init(time_put *this, const _Locinfo *locinfo)
8101 {
8102     TRACE("(%p %p)\n", this, locinfo);
8103     _Locinfo__Gettnames(locinfo, &this->time);
8104     _Locinfo__Getcvt(locinfo, &this->cvt);
8105 }
8106
8107 /* ??0?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
8108 /* ??0?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
8109 DEFINE_THISCALL_WRAPPER(time_put_wchar_ctor_locinfo, 12)
8110 time_put* __thiscall time_put_wchar_ctor_locinfo(time_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
8111 {
8112     TRACE("(%p %p %lu)\n", this, locinfo, refs);
8113     locale_facet_ctor_refs(&this->facet, refs);
8114     this->facet.vtable = &MSVCP_time_put_wchar_vtable;
8115     time_put_wchar__Init(this, locinfo);
8116     return this;
8117 }
8118
8119 /* ??0?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
8120 /* ??0?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
8121 DEFINE_THISCALL_WRAPPER(time_put_short_ctor_locinfo, 12)
8122 time_put* __thiscall time_put_short_ctor_locinfo(time_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
8123 {
8124     time_put_wchar_ctor_locinfo(this, locinfo, refs);
8125     this->facet.vtable = &MSVCP_time_put_short_vtable;
8126     return this;
8127 }
8128
8129 /* ??0?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAE@PBDI@Z */
8130 /* ??0?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAA@PEBD_K@Z */
8131 DEFINE_THISCALL_WRAPPER(time_put_wchar_ctor_name, 12)
8132 time_put* __thiscall time_put_wchar_ctor_name(time_put *this, const char *name, MSVCP_size_t refs)
8133 {
8134     _Locinfo locinfo;
8135
8136     TRACE("(%p %s %lu)\n", this, debugstr_a(name), refs);
8137
8138     _Locinfo_ctor_cstr(&locinfo, name);
8139     time_put_wchar_ctor_locinfo(this, &locinfo, refs);
8140     _Locinfo_dtor(&locinfo);
8141     return this;
8142 }
8143
8144 /* ??0?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IAE@PBDI@Z */
8145 /* ??0?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IEAA@PEBD_K@Z */
8146 DEFINE_THISCALL_WRAPPER(time_put_short_ctor_name, 12)
8147 time_put* __thiscall time_put_short_ctor_name(time_put *this, const char *name, MSVCP_size_t refs)
8148 {
8149     time_put_wchar_ctor_name(this, name, refs);
8150     this->facet.vtable = &MSVCP_time_put_short_vtable;
8151     return this;
8152 }
8153
8154 /* ??0?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
8155 /* ??0?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
8156 DEFINE_THISCALL_WRAPPER(time_put_wchar_ctor_refs, 8)
8157 time_put* __thiscall time_put_wchar_ctor_refs(time_put *this, MSVCP_size_t refs)
8158 {
8159     _Locinfo locinfo;
8160
8161     TRACE("(%p %lu)\n", this, refs);
8162
8163     _Locinfo_ctor(&locinfo);
8164     time_put_wchar_ctor_locinfo(this, &locinfo, refs);
8165     _Locinfo_dtor(&locinfo);
8166     return this;
8167 }
8168
8169 /* ??0?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
8170 /* ??0?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
8171 DEFINE_THISCALL_WRAPPER(time_put_short_ctor_refs, 8)
8172 time_put* __thiscall time_put_short_ctor_refs(time_put *this, MSVCP_size_t refs)
8173 {
8174     time_put_wchar_ctor_refs(this, refs);
8175     this->facet.vtable = &MSVCP_time_put_short_vtable;
8176     return this;
8177 }
8178
8179 /* ??_F?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
8180 /* ??_F?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
8181 DEFINE_THISCALL_WRAPPER(time_put_wchar_ctor, 4)
8182 time_put* __thiscall time_put_wchar_ctor(time_put *this)
8183 {
8184     return time_put_wchar_ctor_refs(this, 0);
8185 }
8186
8187 /* ??_F?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAEXXZ */
8188 /* ??_F?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAAXXZ */
8189 DEFINE_THISCALL_WRAPPER(time_put_short_ctor, 4)
8190 time_put* __thiscall time_put_short_ctor(time_put *this)
8191 {
8192     time_put_wchar_ctor(this);
8193     this->facet.vtable = &MSVCP_time_put_short_vtable;
8194     return this;
8195 }
8196
8197 /* ??1?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
8198 /* ??1?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
8199 /* ??1?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
8200 /* ??1?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
8201 DEFINE_THISCALL_WRAPPER(time_put_wchar_dtor, 4)
8202 void __thiscall time_put_wchar_dtor(time_put *this)
8203 {
8204     TRACE("(%p)\n", this);
8205     _Timevec_dtor(&this->time);
8206 }
8207
8208 DEFINE_THISCALL_WRAPPER(time_put_wchar_vector_dtor, 8)
8209 time_put* __thiscall time_put_wchar_vector_dtor(time_put *this, unsigned int flags)
8210 {
8211     TRACE("(%p %x)\n", this, flags);
8212     if(flags & 2) {
8213         /* we have an array, with the number of elements stored before the first object */
8214         INT_PTR i, *ptr = (INT_PTR *)this-1;
8215
8216         for(i=*ptr-1; i>=0; i--)
8217             time_put_wchar_dtor(this+i);
8218         MSVCRT_operator_delete(ptr);
8219     } else {
8220         time_put_wchar_dtor(this);
8221         if(flags & 1)
8222             MSVCRT_operator_delete(this);
8223     }
8224
8225     return this;
8226 }
8227
8228 /* ?_Getcat@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
8229 /* ?_Getcat@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
8230 MSVCP_size_t __cdecl time_put_wchar__Getcat(const locale_facet **facet, const locale *loc)
8231 {
8232     TRACE("(%p %p)\n", facet, loc);
8233
8234     if(facet && !*facet) {
8235         *facet = MSVCRT_operator_new(sizeof(time_put));
8236         if(!*facet) {
8237             ERR("Out of memory\n");
8238             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8239             return 0;
8240         }
8241         time_put_wchar_ctor_name((time_put*)*facet,
8242                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
8243     }
8244
8245     return LC_TIME;
8246 }
8247
8248 static time_put* time_put_wchar_use_facet(const locale *loc)
8249 {
8250     static time_put *obj = NULL;
8251
8252     _Lockit lock;
8253     const locale_facet *fac;
8254
8255     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
8256     fac = locale__Getfacet(loc, locale_id_operator_size_t(&time_put_wchar_id));
8257     if(fac) {
8258         _Lockit_dtor(&lock);
8259         return (time_put*)fac;
8260     }
8261
8262     if(obj) {
8263         _Lockit_dtor(&lock);
8264         return obj;
8265     }
8266
8267     time_put_wchar__Getcat(&fac, loc);
8268     obj = (time_put*)fac;
8269     locale_facet__Incref(&obj->facet);
8270     locale_facet_register(&obj->facet);
8271     _Lockit_dtor(&lock);
8272
8273     return obj;
8274 }
8275
8276 /* ?_Getcat@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
8277 /* ?_Getcat@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
8278 MSVCP_size_t __cdecl time_put_short__Getcat(const locale_facet **facet, const locale *loc)
8279 {
8280     TRACE("(%p %p)\n", facet, loc);
8281
8282     if(facet && !*facet) {
8283         *facet = MSVCRT_operator_new(sizeof(time_put));
8284         if(!*facet) {
8285             ERR("Out of memory\n");
8286             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8287             return 0;
8288         }
8289         time_put_short_ctor_name((time_put*)*facet,
8290                 MSVCP_basic_string_char_c_str(&loc->ptr->name), 0);
8291     }
8292
8293     return LC_TIME;
8294 }
8295
8296 static time_put* time_put_short_use_facet(const locale *loc)
8297 {
8298     static time_put *obj = NULL;
8299
8300     _Lockit lock;
8301     const locale_facet *fac;
8302
8303     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
8304     fac = locale__Getfacet(loc, locale_id_operator_size_t(&time_put_short_id));
8305     if(fac) {
8306         _Lockit_dtor(&lock);
8307         return (time_put*)fac;
8308     }
8309
8310     if(obj) {
8311         _Lockit_dtor(&lock);
8312         return obj;
8313     }
8314
8315     time_put_short__Getcat(&fac, loc);
8316     obj = (time_put*)fac;
8317     locale_facet__Incref(&obj->facet);
8318     locale_facet_register(&obj->facet);
8319     _Lockit_dtor(&lock);
8320
8321     return obj;
8322 }
8323
8324 /* ?do_put@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBUtm@@DD@Z */
8325 /* ?do_put@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBUtm@@DD@Z */
8326 /* ?do_put@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBUtm@@DD@Z */
8327 /* ?do_put@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBUtm@@DD@Z */
8328 DEFINE_THISCALL_WRAPPER(time_put_wchar_do_put, 36)
8329 #define call_time_put_wchar_do_put(this, ret, dest, base, fill, t, spec, mod) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_wchar*, \
8330         (const time_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, const struct tm*, char, char), \
8331         (this, ret, dest, base, fill, t, spec, mod))
8332 ostreambuf_iterator_wchar* __thiscall time_put_wchar_do_put(const time_put *this,
8333         ostreambuf_iterator_wchar *ret, ostreambuf_iterator_wchar dest, ios_base *base,
8334         wchar_t fill, const struct tm *t, char spec, char mod)
8335 {
8336     char buf[64], fmt[4], *p = fmt;
8337     MSVCP_size_t i, len;
8338     wchar_t c;
8339
8340     TRACE("(%p %p %p %c %p %c %c)\n", this, ret, base, fill, t, spec, mod);
8341
8342     *p++ = '%';
8343     if(mod)
8344         *p++ = mod;
8345     *p++ = spec;
8346     *p++ = 0;
8347
8348     len = _Strftime(buf, sizeof(buf), fmt, t, this->time.timeptr);
8349     for(i=0; i<len; i++) {
8350         c = mb_to_wc(buf[i], &this->cvt);
8351         ostreambuf_iterator_wchar_put(&dest, c);
8352     }
8353
8354     *ret = dest;
8355     return ret;
8356 }
8357
8358 /* ?put@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBUtm@@DD@Z */
8359 /* ?put@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBUtm@@DD@Z */
8360 /* ?put@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBUtm@@DD@Z */
8361 /* ?put@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBUtm@@DD@Z */
8362 DEFINE_THISCALL_WRAPPER(time_put_wchar_put, 36)
8363 ostreambuf_iterator_wchar* __thiscall time_put_wchar_put(const time_put *this,
8364         ostreambuf_iterator_wchar *ret, ostreambuf_iterator_wchar dest, ios_base *base,
8365         wchar_t fill, const struct tm *t, char spec, char mod)
8366 {
8367     TRACE("(%p %p %p %c %p %c %c)\n", this, ret, base, fill, t, spec, mod);
8368     return call_time_put_wchar_do_put(this, ret, dest, base, fill, t, spec, mod);
8369 }
8370
8371 /* ?put@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AAVios_base@2@GPBUtm@@PBG3@Z */
8372 /* ?put@?$time_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@GU?$char_traits@G@std@@@2@V32@AEAVios_base@2@GPEBUtm@@PEBG3@Z */
8373 /* ?put@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QBE?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AAVios_base@2@_WPBUtm@@PB_W4@Z */
8374 /* ?put@?$time_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEBA?AV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@2@V32@AEAVios_base@2@_WPEBUtm@@PEB_W4@Z */
8375 DEFINE_THISCALL_WRAPPER(time_put_wchar_put_format, 36)
8376 ostreambuf_iterator_wchar* __thiscall time_put_wchar_put_format(const time_put *this,
8377         ostreambuf_iterator_wchar *ret, ostreambuf_iterator_wchar dest, ios_base *base,
8378         wchar_t fill, const struct tm *t, const wchar_t *pat, const wchar_t *pat_end)
8379 {
8380     wchar_t percent = mb_to_wc('%', &this->cvt);
8381     char c[MB_LEN_MAX];
8382
8383     TRACE("(%p %p %p %c %p %s)\n", this, ret, base, fill, t, debugstr_wn(pat, pat_end-pat));
8384
8385     while(pat < pat_end) {
8386         if(*pat != percent) {
8387             ostreambuf_iterator_wchar_put(&dest, *pat++);
8388         }else if(++pat == pat_end) {
8389             ostreambuf_iterator_wchar_put(&dest, percent);
8390         }else if(!_Wcrtomb(c, *pat, NULL, &this->cvt) || (*c=='#' && pat+1==pat_end)) {
8391             ostreambuf_iterator_wchar_put(&dest, percent);
8392             ostreambuf_iterator_wchar_put(&dest, *pat++);
8393         }else {
8394             if(*c == '#') {
8395                 if(!_Wcrtomb(c, *pat++, NULL, &this->cvt)) {
8396                     ostreambuf_iterator_wchar_put(&dest, percent);
8397                     ostreambuf_iterator_wchar_put(&dest, *(pat-1));
8398                     ostreambuf_iterator_wchar_put(&dest, *pat);
8399                 }else {
8400                     time_put_wchar_put(this, &dest, dest, base, fill, t, *c, '#');
8401                 }
8402             }else {
8403                 time_put_wchar_put(this, &dest, dest, base, fill, t, *c, 0);
8404             }
8405         }
8406     }
8407
8408     *ret = dest;
8409     return ret;
8410 }
8411
8412 /* ??0_Locimp@locale@std@@AAE@_N@Z */
8413 /* ??0_Locimp@locale@std@@AEAA@_N@Z */
8414 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor_transparent, 8)
8415 locale__Locimp* __thiscall locale__Locimp_ctor_transparent(locale__Locimp *this, MSVCP_bool transparent)
8416 {
8417     TRACE("(%p %d)\n", this, transparent);
8418
8419     memset(this, 0, sizeof(locale__Locimp));
8420     locale_facet_ctor_refs(&this->facet, 1);
8421     this->transparent = transparent;
8422     MSVCP_basic_string_char_ctor_cstr(&this->name, "*");
8423     return this;
8424 }
8425
8426 /* ??_F_Locimp@locale@std@@QAEXXZ */
8427 /* ??_F_Locimp@locale@std@@QEAAXXZ */
8428 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor, 4)
8429 locale__Locimp* __thiscall locale__Locimp_ctor(locale__Locimp *this)
8430 {
8431     return locale__Locimp_ctor_transparent(this, FALSE);
8432 }
8433
8434 /* ??0_Locimp@locale@std@@AAE@ABV012@@Z */
8435 /* ??0_Locimp@locale@std@@AEAA@AEBV012@@Z */
8436 DEFINE_THISCALL_WRAPPER(locale__Locimp_copy_ctor, 8)
8437 locale__Locimp* __thiscall locale__Locimp_copy_ctor(locale__Locimp *this, const locale__Locimp *copy)
8438 {
8439     _Lockit lock;
8440     MSVCP_size_t i;
8441
8442     TRACE("(%p %p)\n", this, copy);
8443
8444     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
8445     memcpy(this, copy, sizeof(locale__Locimp));
8446     locale_facet_ctor_refs(&this->facet, 1);
8447     if(copy->facetvec) {
8448         this->facetvec = MSVCRT_operator_new(copy->facet_cnt*sizeof(locale_facet*));
8449         if(!this->facetvec) {
8450             _Lockit_dtor(&lock);
8451             ERR("Out of memory\n");
8452             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8453             return NULL;
8454         }
8455         for(i=0; i<this->facet_cnt; i++)
8456         {
8457             this->facetvec[i] = copy->facetvec[i];
8458             if(this->facetvec[i])
8459                 locale_facet__Incref(this->facetvec[i]);
8460         }
8461     }
8462     MSVCP_basic_string_char_copy_ctor(&this->name, &copy->name);
8463     _Lockit_dtor(&lock);
8464     return this;
8465 }
8466
8467 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPAV123@ABV123@@Z */
8468 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPEAV123@AEBV123@@Z */
8469 locale__Locimp* __cdecl locale__Locimp__Locimp_ctor(locale__Locimp *this, const locale__Locimp *copy)
8470 {
8471     return locale__Locimp_copy_ctor(this, copy);
8472 }
8473
8474 /* ??1_Locimp@locale@std@@MAE@XZ */
8475 /* ??1_Locimp@locale@std@@MEAA@XZ */
8476 DEFINE_THISCALL_WRAPPER(locale__Locimp_dtor, 4)
8477 void __thiscall locale__Locimp_dtor(locale__Locimp *this)
8478 {
8479     MSVCP_size_t i;
8480
8481     TRACE("(%p)\n", this);
8482
8483     locale_facet_dtor(&this->facet);
8484     for(i=0; i<this->facet_cnt; i++)
8485         if(this->facetvec[i] && locale_facet__Decref(this->facetvec[i]))
8486             call_locale_facet_vector_dtor(this->facetvec[i], 1);
8487
8488     MSVCRT_operator_delete(this->facetvec);
8489     MSVCP_basic_string_char_dtor(&this->name);
8490 }
8491
8492 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPAV123@@Z */
8493 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPEAV123@@Z */
8494 void __cdecl locale__Locimp__Locimp_dtor(locale__Locimp *this)
8495 {
8496     locale__Locimp_dtor(this);
8497 }
8498
8499 DEFINE_THISCALL_WRAPPER(locale__Locimp_vector_dtor, 8)
8500 locale__Locimp* __thiscall locale__Locimp_vector_dtor(locale__Locimp *this, unsigned int flags)
8501 {
8502     TRACE("(%p %x)\n", this, flags);
8503     if(flags & 2) {
8504         /* we have an array, with the number of elements stored before the first object */
8505         INT_PTR i, *ptr = (INT_PTR *)this-1;
8506
8507         for(i=*ptr-1; i>=0; i--)
8508             locale__Locimp_dtor(this+i);
8509         MSVCRT_operator_delete(ptr);
8510     } else {
8511         locale__Locimp_dtor(this);
8512         if(flags & 1)
8513             MSVCRT_operator_delete(this);
8514     }
8515
8516     return this;
8517 }
8518
8519 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z */
8520 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z */
8521 void __cdecl locale__Locimp__Locimp_Addfac(locale__Locimp *locimp, locale_facet *facet, MSVCP_size_t id)
8522 {
8523     _Lockit lock;
8524
8525     TRACE("(%p %p %lu)\n", locimp, facet, id);
8526
8527     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
8528     if(id >= locimp->facet_cnt) {
8529         MSVCP_size_t new_size = id+1;
8530         locale_facet **new_facetvec;
8531
8532         if(new_size < locale_id__Id_cnt+1)
8533             new_size = locale_id__Id_cnt+1;
8534
8535         new_facetvec = MSVCRT_operator_new(sizeof(locale_facet*)*new_size);
8536         if(!new_facetvec) {
8537             _Lockit_dtor(&lock);
8538             ERR("Out of memory\n");
8539             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8540             return;
8541         }
8542
8543         memset(new_facetvec, 0, sizeof(locale_facet*)*new_size);
8544         memcpy(new_facetvec, locimp->facetvec, sizeof(locale_facet*)*locimp->facet_cnt);
8545         MSVCRT_operator_delete(locimp->facetvec);
8546         locimp->facetvec = new_facetvec;
8547         locimp->facet_cnt = new_size;
8548     }
8549
8550     if(locimp->facetvec[id] && locale_facet__Decref(locimp->facetvec[id]))
8551         call_locale_facet_vector_dtor(locimp->facetvec[id], 1);
8552
8553     locimp->facetvec[id] = facet;
8554     if(facet)
8555         locale_facet__Incref(facet);
8556     _Lockit_dtor(&lock);
8557 }
8558
8559 /* ?_Addfac@_Locimp@locale@std@@AAEXPAVfacet@23@I@Z */
8560 /* ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z */
8561 DEFINE_THISCALL_WRAPPER(locale__Locimp__Addfac, 12)
8562 void __thiscall locale__Locimp__Addfac(locale__Locimp *this, locale_facet *facet, MSVCP_size_t id)
8563 {
8564     locale__Locimp__Locimp_Addfac(this, facet, id);
8565 }
8566
8567 /* ?_Clocptr_func@_Locimp@locale@std@@CAAAPAV123@XZ */
8568 /* ?_Clocptr_func@_Locimp@locale@std@@CAAEAPEAV123@XZ */
8569 locale__Locimp** __cdecl locale__Locimp__Clocptr_func(void)
8570 {
8571     FIXME("stub\n");
8572     return NULL;
8573 }
8574
8575 /* ?_Makeushloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
8576 /* ?_Makeushloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
8577 /* List of missing facets:
8578  * messages, money_get, money_put, moneypunct, moneypunct, time_get
8579  */
8580 void __cdecl locale__Locimp__Makeushloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
8581 {
8582     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
8583
8584     if(cat & (1<<(ctype_short__Getcat(NULL, NULL)-1))) {
8585         ctype_wchar *ctype;
8586
8587         if(loc) {
8588             ctype = ctype_short_use_facet(loc);
8589         }else {
8590             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
8591             if(!ctype) {
8592                 ERR("Out of memory\n");
8593                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8594             }
8595             ctype_short_ctor_locinfo(ctype, locinfo, 0);
8596         }
8597         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_short_id));
8598     }
8599
8600     if(cat & (1<<(num_get_short__Getcat(NULL, NULL)-1))) {
8601         num_get *numget;
8602
8603         if(loc) {
8604             numget = num_get_short_use_facet(loc);
8605         }else {
8606             numget = MSVCRT_operator_new(sizeof(num_get));
8607             if(!numget) {
8608                 ERR("Out of memory\n");
8609                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8610             }
8611             num_get_short_ctor_locinfo(numget, locinfo, 0);
8612         }
8613         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_short_id));
8614     }
8615
8616     if(cat & (1<<(num_put_short__Getcat(NULL, NULL)-1))) {
8617         num_put *numput;
8618
8619         if(loc) {
8620             numput = num_put_short_use_facet(loc);
8621         }else {
8622             numput = MSVCRT_operator_new(sizeof(num_put));
8623             if(!numput) {
8624                 ERR("Out of memory\n");
8625                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8626             }
8627             num_put_short_ctor_locinfo(numput, locinfo, 0);
8628         }
8629         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_short_id));
8630     }
8631
8632     if(cat & (1<<(numpunct_short__Getcat(NULL, NULL)-1))) {
8633         numpunct_wchar *numpunct;
8634
8635         if(loc) {
8636             numpunct = numpunct_short_use_facet(loc);
8637         }else {
8638             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
8639             if(!numpunct) {
8640                 ERR("Out of memory\n");
8641                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8642             }
8643             numpunct_short_ctor_locinfo(numpunct, locinfo, 0, FALSE);
8644         }
8645         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_short_id));
8646     }
8647
8648     if(cat & (1<<(collate_short__Getcat(NULL, NULL)-1))) {
8649         collate *c;
8650
8651         if(loc) {
8652             c = collate_short_use_facet(loc);
8653         }else {
8654             c = MSVCRT_operator_new(sizeof(collate));
8655             if(!c) {
8656                 ERR("Out of memory\n");
8657                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8658             }
8659             collate_short_ctor_locinfo(c, locinfo, 0);
8660         }
8661         locale__Locimp__Addfac(locimp, &c->facet, locale_id_operator_size_t(&collate_short_id));
8662     }
8663
8664      if(cat & (1<<(time_put_short__Getcat(NULL, NULL)-1))) {
8665          time_put *t;
8666
8667          if(loc) {
8668              t = time_put_short_use_facet(loc);
8669          }else {
8670              t = MSVCRT_operator_new(sizeof(time_put));
8671              if(!t) {
8672                  ERR("Out of memory\n");
8673                  throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8674              }
8675              time_put_short_ctor_locinfo(t, locinfo, 0);
8676          }
8677          locale__Locimp__Addfac(locimp, &t->facet, locale_id_operator_size_t(&time_put_short_id));
8678      }
8679
8680     if(cat & (1<<(codecvt_short__Getcat(NULL, NULL)-1))) {
8681         codecvt_wchar *codecvt;
8682
8683         if(loc) {
8684             codecvt = codecvt_short_use_facet(loc);
8685         }else {
8686             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
8687             if(!codecvt) {
8688                 ERR("Out of memory\n");
8689                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8690             }
8691             codecvt_short_ctor_locinfo(codecvt, locinfo, 0);
8692         }
8693         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_short_id));
8694     }
8695 }
8696
8697 /* ?_Makewloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
8698 /* ?_Makewloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
8699 /* List of missing facets:
8700  * messages, money_get, money_put, moneypunct, moneypunct, time_get
8701  */
8702 void __cdecl locale__Locimp__Makewloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
8703 {
8704     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
8705
8706     if(cat & (1<<(ctype_wchar__Getcat(NULL, NULL)-1))) {
8707         ctype_wchar *ctype;
8708
8709         if(loc) {
8710             ctype = ctype_wchar_use_facet(loc);
8711         }else {
8712             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
8713             if(!ctype) {
8714                 ERR("Out of memory\n");
8715                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8716             }
8717             ctype_wchar_ctor_locinfo(ctype, locinfo, 0);
8718         }
8719         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_wchar_id));
8720     }
8721
8722     if(cat & (1<<(num_get_wchar__Getcat(NULL, NULL)-1))) {
8723         num_get *numget;
8724
8725         if(loc) {
8726             numget = num_get_wchar_use_facet(loc);
8727         }else {
8728             numget = MSVCRT_operator_new(sizeof(num_get));
8729             if(!numget) {
8730                 ERR("Out of memory\n");
8731                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8732             }
8733             num_get_wchar_ctor_locinfo(numget, locinfo, 0);
8734         }
8735         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_wchar_id));
8736     }
8737
8738     if(cat & (1<<(num_put_wchar__Getcat(NULL, NULL)-1))) {
8739         num_put *numput;
8740
8741         if(loc) {
8742             numput = num_put_wchar_use_facet(loc);
8743         }else {
8744             numput = MSVCRT_operator_new(sizeof(num_put));
8745             if(!numput) {
8746                 ERR("Out of memory\n");
8747                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8748             }
8749             num_put_wchar_ctor_locinfo(numput, locinfo, 0);
8750         }
8751         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_wchar_id));
8752     }
8753
8754     if(cat & (1<<(numpunct_wchar__Getcat(NULL, NULL)-1))) {
8755         numpunct_wchar *numpunct;
8756
8757         if(loc) {
8758             numpunct = numpunct_wchar_use_facet(loc);
8759         }else {
8760             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
8761             if(!numpunct) {
8762                 ERR("Out of memory\n");
8763                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8764             }
8765             numpunct_wchar_ctor_locinfo(numpunct, locinfo, 0, FALSE);
8766         }
8767         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_wchar_id));
8768     }
8769
8770     if(cat & (1<<(collate_wchar__Getcat(NULL, NULL)-1))) {
8771         collate *c;
8772
8773         if(loc) {
8774             c = collate_wchar_use_facet(loc);
8775         }else {
8776             c = MSVCRT_operator_new(sizeof(collate));
8777             if(!c) {
8778                 ERR("Out of memory\n");
8779                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8780             }
8781             collate_wchar_ctor_locinfo(c, locinfo, 0);
8782         }
8783         locale__Locimp__Addfac(locimp, &c->facet, locale_id_operator_size_t(&collate_wchar_id));
8784     }
8785
8786     if(cat & (1<<(time_put_wchar__Getcat(NULL, NULL)-1))) {
8787         time_put *t;
8788
8789         if(loc) {
8790             t = time_put_wchar_use_facet(loc);
8791         }else {
8792             t = MSVCRT_operator_new(sizeof(time_put));
8793             if(!t) {
8794                 ERR("Out of memory\n");
8795                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8796             }
8797             time_put_wchar_ctor_locinfo(t, locinfo, 0);
8798         }
8799         locale__Locimp__Addfac(locimp, &t->facet, locale_id_operator_size_t(&time_put_wchar_id));
8800     }
8801
8802     if(cat & (1<<(codecvt_wchar__Getcat(NULL, NULL)-1))) {
8803         codecvt_wchar *codecvt;
8804
8805         if(loc) {
8806             codecvt = codecvt_wchar_use_facet(loc);
8807         }else {
8808             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
8809             if(!codecvt) {
8810                 ERR("Out of memory\n");
8811                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8812             }
8813             codecvt_wchar_ctor_locinfo(codecvt, locinfo, 0);
8814         }
8815         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_wchar_id));
8816     }
8817 }
8818
8819 /* ?_Makexloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
8820 /* ?_Makexloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
8821 /* List of missing facets:
8822  * messages, money_get, money_put, moneypunct, moneypunct, time_get
8823  */
8824 void __cdecl locale__Locimp__Makexloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
8825 {
8826     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
8827
8828     if(cat & (1<<(ctype_char__Getcat(NULL, NULL)-1))) {
8829         ctype_char *ctype;
8830
8831         if(loc) {
8832             ctype = ctype_char_use_facet(loc);
8833         }else {
8834             ctype = MSVCRT_operator_new(sizeof(ctype_char));
8835             if(!ctype) {
8836                 ERR("Out of memory\n");
8837                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8838             }
8839             ctype_char_ctor_locinfo(ctype, locinfo, 0);
8840         }
8841         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_char_id));
8842     }
8843
8844     if(cat & (1<<(num_get_char__Getcat(NULL, NULL)-1))) {
8845         num_get *numget;
8846
8847         if(loc) {
8848             numget = num_get_char_use_facet(loc);
8849         }else {
8850             numget = MSVCRT_operator_new(sizeof(num_get));
8851             if(!numget) {
8852                 ERR("Out of memory\n");
8853                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8854             }
8855             num_get_char_ctor_locinfo(numget, locinfo, 0);
8856         }
8857         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_char_id));
8858     }
8859
8860     if(cat & (1<<(num_put_char__Getcat(NULL, NULL)-1))) {
8861         num_put *numput;
8862
8863         if(loc) {
8864             numput = num_put_char_use_facet(loc);
8865         }else {
8866             numput = MSVCRT_operator_new(sizeof(num_put));
8867             if(!numput) {
8868                 ERR("Out of memory\n");
8869                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8870             }
8871             num_put_char_ctor_locinfo(numput, locinfo, 0);
8872         }
8873         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_char_id));
8874     }
8875
8876     if(cat & (1<<(numpunct_char__Getcat(NULL, NULL)-1))) {
8877         numpunct_char *numpunct;
8878
8879         if(loc) {
8880             numpunct = numpunct_char_use_facet(loc);
8881         }else {
8882             numpunct = MSVCRT_operator_new(sizeof(numpunct_char));
8883             if(!numpunct) {
8884                 ERR("Out of memory\n");
8885                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8886             }
8887             numpunct_char_ctor_locinfo(numpunct, locinfo, 0, FALSE);
8888         }
8889         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_char_id));
8890     }
8891
8892     if(cat & (1<<(collate_char__Getcat(NULL, NULL)-1))) {
8893         collate *c;
8894
8895         if(loc) {
8896             c = collate_char_use_facet(loc);
8897         }else {
8898             c = MSVCRT_operator_new(sizeof(collate));
8899             if(!c) {
8900                 ERR("Out of memory\n");
8901                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8902             }
8903             collate_char_ctor_locinfo(c, locinfo, 0);
8904         }
8905         locale__Locimp__Addfac(locimp, &c->facet, locale_id_operator_size_t(&collate_char_id));
8906     }
8907
8908     if(cat & (1<<(time_put_char__Getcat(NULL, NULL)-1))) {
8909         time_put *t;
8910
8911         if(loc) {
8912             t = time_put_char_use_facet(loc);
8913         }else {
8914             t = MSVCRT_operator_new(sizeof(time_put));
8915             if(!t) {
8916                 ERR("Out of memory\n");
8917                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8918             }
8919             time_put_char_ctor_locinfo(t, locinfo, 0);
8920         }
8921         locale__Locimp__Addfac(locimp, &t->facet, locale_id_operator_size_t(&time_put_char_id));
8922     }
8923
8924     if(cat & (1<<(codecvt_char__Getcat(NULL, NULL)-1))) {
8925         codecvt_char *codecvt;
8926
8927         if(loc) {
8928             codecvt = codecvt_char_use_facet(loc);
8929         }else {
8930             codecvt = MSVCRT_operator_new(sizeof(codecvt_char));
8931             if(!codecvt) {
8932                 ERR("Out of memory\n");
8933                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8934             }
8935             codecvt_char_ctor_locinfo(codecvt, locinfo, 0);
8936         }
8937         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_char_id));
8938     }
8939 }
8940
8941 /* ?_Makeloc@_Locimp@locale@std@@CAPAV123@ABV_Locinfo@3@HPAV123@PBV23@@Z */
8942 /* ?_Makeloc@_Locimp@locale@std@@CAPEAV123@AEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
8943 locale__Locimp* __cdecl locale__Locimp__Makeloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
8944 {
8945     TRACE("(%p %d %p %p)\n", locinfo, cat, locimp, loc);
8946
8947     locale__Locimp__Makexloc(locinfo, cat, locimp, loc);
8948     locale__Locimp__Makewloc(locinfo, cat, locimp, loc);
8949     locale__Locimp__Makeushloc(locinfo, cat, locimp, loc);
8950
8951     locimp->catmask |= cat;
8952     MSVCP_basic_string_char_copy_ctor(&locimp->name, &locinfo->newlocname);
8953     return locimp;
8954 }
8955
8956 /* ??_7_Locimp@locale@std@@6B@ */
8957 const vtable_ptr MSVCP_locale__Locimp_vtable[] = {
8958     (vtable_ptr)THISCALL_NAME(locale__Locimp_vector_dtor)
8959 };
8960
8961 /* ??0locale@std@@AAE@PAV_Locimp@01@@Z */
8962 /* ??0locale@std@@AEAA@PEAV_Locimp@01@@Z */
8963 DEFINE_THISCALL_WRAPPER(locale_ctor_locimp, 8)
8964 locale* __thiscall locale_ctor_locimp(locale *this, locale__Locimp *locimp)
8965 {
8966     TRACE("(%p %p)\n", this, locimp);
8967     /* Don't change locimp reference counter */
8968     this->ptr = locimp;
8969     return this;
8970 }
8971
8972 /* ?_Init@locale@std@@CAPAV_Locimp@12@XZ */
8973 /* ?_Init@locale@std@@CAPEAV_Locimp@12@XZ */
8974 locale__Locimp* __cdecl locale__Init(void)
8975 {
8976     _Lockit lock;
8977
8978     TRACE("\n");
8979
8980     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
8981     if(global_locale) {
8982         _Lockit_dtor(&lock);
8983         return global_locale;
8984     }
8985
8986     global_locale = MSVCRT_operator_new(sizeof(locale__Locimp));
8987     if(!global_locale) {
8988         _Lockit_dtor(&lock);
8989         ERR("Out of memory\n");
8990         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
8991         return NULL;
8992     }
8993
8994     locale__Locimp_ctor(global_locale);
8995     global_locale->catmask = (1<<(LC_MAX+1))-1;
8996     MSVCP_basic_string_char_dtor(&global_locale->name);
8997     MSVCP_basic_string_char_ctor_cstr(&global_locale->name, "C");
8998
8999     locale__Locimp__Clocptr = global_locale;
9000     global_locale->facet.refs++;
9001     locale_ctor_locimp(&classic_locale, locale__Locimp__Clocptr);
9002     _Lockit_dtor(&lock);
9003
9004     return global_locale;
9005 }
9006
9007 /* ??0locale@std@@QAE@ABV01@0H@Z */
9008 /* ??0locale@std@@QEAA@AEBV01@0H@Z */
9009 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_locale, 16)
9010 locale* __thiscall locale_ctor_locale_locale(locale *this, const locale *loc, const locale *other, category cat)
9011 {
9012     _Locinfo locinfo;
9013
9014     TRACE("(%p %p %p %d)\n", this, loc, other, cat);
9015
9016     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
9017     if(!this->ptr) {
9018         ERR("Out of memory\n");
9019         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
9020     }
9021     locale__Locimp_copy_ctor(this->ptr, loc->ptr);
9022
9023     _Locinfo_ctor_cat_cstr(&locinfo, loc->ptr->catmask, MSVCP_basic_string_char_c_str(&loc->ptr->name));
9024     _Locinfo__Addcats(&locinfo, cat & other->ptr->catmask, MSVCP_basic_string_char_c_str(&other->ptr->name));
9025     locale__Locimp__Makeloc(&locinfo, cat, this->ptr, other);
9026     _Locinfo_dtor(&locinfo);
9027
9028     return this;
9029 }
9030
9031 /* ??0locale@std@@QAE@ABV01@@Z */
9032 /* ??0locale@std@@QEAA@AEBV01@@Z */
9033 DEFINE_THISCALL_WRAPPER(locale_copy_ctor, 8)
9034 locale* __thiscall locale_copy_ctor(locale *this, const locale *copy)
9035 {
9036     TRACE("(%p %p)\n", this, copy);
9037     this->ptr = copy->ptr;
9038     locale_facet__Incref(&this->ptr->facet);
9039     return this;
9040 }
9041
9042 /* ??0locale@std@@QAE@ABV01@PBDH@Z */
9043 /* ??0locale@std@@QEAA@AEBV01@PEBDH@Z */
9044 DEFINE_THISCALL_WRAPPER(locale_ctor_locale_cstr, 16)
9045 locale* __thiscall locale_ctor_locale_cstr(locale *this, const locale *loc, const char *locname, category cat)
9046 {
9047     FIXME("(%p %p %s %d) stub\n", this, loc, locname, cat);
9048     return NULL;
9049 }
9050
9051 /* ??0locale@std@@QAE@PBDH@Z */
9052 /* ??0locale@std@@QEAA@PEBDH@Z */
9053 DEFINE_THISCALL_WRAPPER(locale_ctor_cstr, 12)
9054 locale* __thiscall locale_ctor_cstr(locale *this, const char *locname, category cat)
9055 {
9056     _Locinfo locinfo;
9057
9058     TRACE("(%p %s %d)\n", this, locname, cat);
9059
9060     this->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
9061     if(!this->ptr) {
9062         ERR("Out of memory\n");
9063         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
9064     }
9065     locale__Locimp_ctor(this->ptr);
9066
9067     locale__Init();
9068
9069     _Locinfo_ctor_cat_cstr(&locinfo, cat, locname);
9070     if(!memcmp(MSVCP_basic_string_char_c_str(&locinfo.newlocname), "*", 2)) {
9071         _Locinfo_dtor(&locinfo);
9072         MSVCRT_operator_delete(this->ptr);
9073         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
9074     }
9075
9076     locale__Locimp__Makeloc(&locinfo, cat, this->ptr, NULL);
9077     _Locinfo_dtor(&locinfo);
9078
9079     return this;
9080 }
9081
9082 /* ??0locale@std@@QAE@W4_Uninitialized@1@@Z */
9083 /* ??0locale@std@@QEAA@W4_Uninitialized@1@@Z */
9084 DEFINE_THISCALL_WRAPPER(locale_ctor_uninitialized, 8)
9085 locale* __thiscall locale_ctor_uninitialized(locale *this, int uninitialized)
9086 {
9087     TRACE("(%p)\n", this);
9088     this->ptr = NULL;
9089     return this;
9090 }
9091
9092 /* ??0locale@std@@QAE@XZ */
9093 /* ??0locale@std@@QEAA@XZ */
9094 DEFINE_THISCALL_WRAPPER(locale_ctor, 4)
9095 locale* __thiscall locale_ctor(locale *this)
9096 {
9097     TRACE("(%p)\n", this);
9098     this->ptr = locale__Init();
9099     locale_facet__Incref(&this->ptr->facet);
9100     return this;
9101 }
9102
9103 /* ??1locale@std@@QAE@XZ */
9104 /* ??1locale@std@@QEAA@XZ */
9105 DEFINE_THISCALL_WRAPPER(locale_dtor, 4)
9106 void __thiscall locale_dtor(locale *this)
9107 {
9108     TRACE("(%p)\n", this);
9109     if(this->ptr && locale_facet__Decref(&this->ptr->facet))
9110     {
9111         locale__Locimp_dtor(this->ptr);
9112         MSVCRT_operator_delete(this->ptr);
9113     }
9114 }
9115
9116 /* ??4locale@std@@QAEAAV01@ABV01@@Z */
9117 /* ??4locale@std@@QEAAAEAV01@AEBV01@@Z */
9118 DEFINE_THISCALL_WRAPPER(locale_operator_assign, 8)
9119 locale* __thiscall locale_operator_assign(locale *this, const locale *loc)
9120 {
9121     FIXME("(%p %p) stub\n", this, loc);
9122     return NULL;
9123 }
9124
9125 /* ??8locale@std@@QBE_NABV01@@Z */
9126 /* ??8locale@std@@QEBA_NAEBV01@@Z */
9127 DEFINE_THISCALL_WRAPPER(locale_operator_equal, 8)
9128 MSVCP_bool __thiscall locale_operator_equal(const locale *this, const locale *loc)
9129 {
9130     FIXME("(%p %p) stub\n", this, loc);
9131     return 0;
9132 }
9133
9134 /* ??9locale@std@@QBE_NABV01@@Z */
9135 /* ??9locale@std@@QEBA_NAEBV01@@Z */
9136 DEFINE_THISCALL_WRAPPER(locale_operator_not_equal, 8)
9137 MSVCP_bool __thiscall locale_operator_not_equal(const locale *this, locale const *loc)
9138 {
9139     FIXME("(%p %p) stub\n", this, loc);
9140     return 0;
9141 }
9142
9143 /* ?_Addfac@locale@std@@QAEAAV12@PAVfacet@12@II@Z */
9144 /* ?_Addfac@locale@std@@QEAAAEAV12@PEAVfacet@12@_K1@Z */
9145 DEFINE_THISCALL_WRAPPER(locale__Addfac, 16)
9146 locale* __thiscall locale__Addfac(locale *this, locale_facet *facet, MSVCP_size_t id, MSVCP_size_t catmask)
9147 {
9148     TRACE("(%p %p %lu %lu)\n", this, facet, id, catmask);
9149
9150     if(this->ptr->facet.refs > 1) {
9151         locale__Locimp *new_ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
9152         if(!new_ptr) {
9153             ERR("Out of memory\n");
9154             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
9155             return NULL;
9156         }
9157         locale__Locimp_copy_ctor(new_ptr, this->ptr);
9158         locale_facet__Decref(&this->ptr->facet);
9159         this->ptr = new_ptr;
9160     }
9161
9162     locale__Locimp__Addfac(this->ptr, facet, id);
9163
9164     if(catmask) {
9165         MSVCP_basic_string_char_dtor(&this->ptr->name);
9166         MSVCP_basic_string_char_ctor_cstr(&this->ptr->name, "*");
9167     }
9168     return this;
9169 }
9170
9171 /* ?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z */
9172 /* ?_Getfacet@locale@std@@QEBAPEBVfacet@12@_K@Z */
9173 DEFINE_THISCALL_WRAPPER(locale__Getfacet, 8)
9174 const locale_facet* __thiscall locale__Getfacet(const locale *this, MSVCP_size_t id)
9175 {
9176     locale_facet *fac;
9177
9178     TRACE("(%p %lu)\n", this, id);
9179
9180     fac = id < this->ptr->facet_cnt ? this->ptr->facetvec[id] : NULL;
9181     if(fac || !this->ptr->transparent)
9182         return fac;
9183
9184     return id < global_locale->facet_cnt ? global_locale->facetvec[id] : NULL;
9185 }
9186
9187 /* ?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ */
9188 /* ?_Getgloballocale@locale@std@@CAPEAV_Locimp@12@XZ */
9189 locale__Locimp* __cdecl locale__Getgloballocale(void)
9190 {
9191     TRACE("\n");
9192     return global_locale;
9193 }
9194
9195 /* ?_Setgloballocale@locale@std@@CAXPAX@Z */
9196 /* ?_Setgloballocale@locale@std@@CAXPEAX@Z */
9197 void __cdecl locale__Setgloballocale(void *locimp)
9198 {
9199     TRACE("(%p)\n", locimp);
9200     global_locale = locimp;
9201 }
9202
9203 /* ?classic@locale@std@@SAABV12@XZ */
9204 /* ?classic@locale@std@@SAAEBV12@XZ */
9205 const locale* __cdecl locale_classic(void)
9206 {
9207     TRACE("\n");
9208     locale__Init();
9209     return &classic_locale;
9210 }
9211
9212 /* ?empty@locale@std@@SA?AV12@XZ */
9213 locale* __cdecl locale_empty(locale *ret)
9214 {
9215     TRACE("\n");
9216
9217     locale__Init();
9218
9219     ret->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
9220     if(!ret->ptr) {
9221         ERR("Out of memory\n");
9222         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
9223     }
9224     locale__Locimp_ctor_transparent(ret->ptr, TRUE);
9225     return ret;
9226 }
9227
9228 /* ?name@locale@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
9229 /* ?name@locale@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
9230 DEFINE_THISCALL_WRAPPER(locale_name, 8)
9231 basic_string_char* __thiscall locale_name(const locale *this, basic_string_char *ret)
9232 {
9233     TRACE( "(%p)\n", this);
9234     MSVCP_basic_string_char_copy_ctor(ret, &this->ptr->name);
9235     return ret;
9236 }
9237
9238 /* ?global@locale@std@@SA?AV12@ABV12@@Z */
9239 /* ?global@locale@std@@SA?AV12@AEBV12@@Z */
9240 locale* __cdecl locale_global(locale *ret, const locale *loc)
9241 {
9242     _Lockit lock;
9243     int i;
9244
9245     TRACE("(%p %p)\n", loc, ret);
9246
9247     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
9248     locale_ctor(ret);
9249
9250     if(loc->ptr != global_locale) {
9251         locale_facet__Decref(&global_locale->facet);
9252         global_locale = loc->ptr;
9253         locale_facet__Incref(&global_locale->facet);
9254
9255         for(i=LC_ALL+1; i<=LC_MAX; i++) {
9256             if((global_locale->catmask & (1<<(i-1))) == 0)
9257                 continue;
9258             setlocale(i, MSVCP_basic_string_char_c_str(&global_locale->name));
9259         }
9260     }
9261     _Lockit_dtor(&lock);
9262     return ret;
9263 }
9264
9265 /* wctrans */
9266 wctrans_t __cdecl wctrans(const char *property)
9267 {
9268     static const char str_tolower[] = "tolower";
9269     static const char str_toupper[] = "toupper";
9270
9271     if(!strcmp(property, str_tolower))
9272         return 2;
9273     if(!strcmp(property, str_toupper))
9274         return 1;
9275     return 0;
9276 }
9277
9278 /* towctrans */
9279 wint_t __cdecl towctrans(wint_t c, wctrans_t category)
9280 {
9281     if(category == 1)
9282         return towupper(c);
9283     return towlower(c);
9284 }
9285
9286 DEFINE_RTTI_DATA0(locale_facet, 0, ".?AVfacet@locale@std@@")
9287 DEFINE_RTTI_DATA1(collate_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@D@std@@")
9288 DEFINE_RTTI_DATA1(collate_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@_W@std@@")
9289 DEFINE_RTTI_DATA1(collate_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@G@std@@")
9290 DEFINE_RTTI_DATA1(ctype_base, 0, &locale_facet_rtti_base_descriptor, ".?AUctype_base@std@@")
9291 DEFINE_RTTI_DATA2(ctype_char, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@D@std@@")
9292 DEFINE_RTTI_DATA2(ctype_wchar, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@_W@std@@")
9293 DEFINE_RTTI_DATA2(ctype_short, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@G@std@@")
9294 DEFINE_RTTI_DATA1(codecvt_base, 0, &locale_facet_rtti_base_descriptor, ".?AVcodecvt_base@std@@")
9295 DEFINE_RTTI_DATA2(codecvt_char, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@DDH@std@@")
9296 DEFINE_RTTI_DATA2(codecvt_wchar, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@_WDH@std@@")
9297 DEFINE_RTTI_DATA2(codecvt_short, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@GDH@std@@")
9298 DEFINE_RTTI_DATA1(numpunct_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@D@std@@")
9299 DEFINE_RTTI_DATA1(numpunct_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@_W@std@@")
9300 DEFINE_RTTI_DATA1(numpunct_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@G@std@@")
9301 DEFINE_RTTI_DATA1(num_get_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@")
9302 DEFINE_RTTI_DATA1(num_get_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@")
9303 DEFINE_RTTI_DATA1(num_get_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@")
9304 DEFINE_RTTI_DATA1(num_put_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@")
9305 DEFINE_RTTI_DATA1(num_put_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@")
9306 DEFINE_RTTI_DATA1(num_put_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@")
9307 DEFINE_RTTI_DATA1(time_put_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@")
9308 DEFINE_RTTI_DATA1(time_put_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@")
9309 DEFINE_RTTI_DATA1(time_put_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@")
9310
9311 #ifndef __GNUC__
9312 void __asm_dummy_vtables(void) {
9313 #endif
9314     __ASM_VTABLE(locale_facet,
9315             VTABLE_ADD_FUNC(locale_facet_vector_dtor));
9316     __ASM_VTABLE(collate_char,
9317             VTABLE_ADD_FUNC(collate_char_vector_dtor)
9318             VTABLE_ADD_FUNC(collate_char_do_compare)
9319             VTABLE_ADD_FUNC(collate_char_do_transform)
9320             VTABLE_ADD_FUNC(collate_char_do_hash));
9321     __ASM_VTABLE(collate_wchar,
9322             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
9323             VTABLE_ADD_FUNC(collate_wchar_do_compare)
9324             VTABLE_ADD_FUNC(collate_wchar_do_transform)
9325             VTABLE_ADD_FUNC(collate_wchar_do_hash));
9326     __ASM_VTABLE(collate_short,
9327             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
9328             VTABLE_ADD_FUNC(collate_wchar_do_compare)
9329             VTABLE_ADD_FUNC(collate_wchar_do_transform)
9330             VTABLE_ADD_FUNC(collate_wchar_do_hash));
9331     __ASM_VTABLE(ctype_base,
9332             VTABLE_ADD_FUNC(ctype_base_vector_dtor));
9333     __ASM_VTABLE(ctype_char,
9334             VTABLE_ADD_FUNC(ctype_char_vector_dtor)
9335             VTABLE_ADD_FUNC(ctype_char_do_tolower)
9336             VTABLE_ADD_FUNC(ctype_char_do_tolower_ch)
9337             VTABLE_ADD_FUNC(ctype_char_do_toupper)
9338             VTABLE_ADD_FUNC(ctype_char_do_toupper_ch)
9339             VTABLE_ADD_FUNC(ctype_char_do_widen)
9340             VTABLE_ADD_FUNC(ctype_char_do_widen_ch)
9341             VTABLE_ADD_FUNC(ctype_char__Do_widen_s)
9342             VTABLE_ADD_FUNC(ctype_char_do_narrow)
9343             VTABLE_ADD_FUNC(ctype_char_do_narrow_ch)
9344             VTABLE_ADD_FUNC(ctype_char__Do_narrow_s));
9345     __ASM_VTABLE(ctype_wchar,
9346             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
9347             VTABLE_ADD_FUNC(ctype_wchar_do_is)
9348             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
9349             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
9350             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
9351             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
9352             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
9353             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
9354             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
9355             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
9356             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
9357             VTABLE_ADD_FUNC(ctype_wchar__Do_widen_s)
9358             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
9359             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch)
9360             VTABLE_ADD_FUNC(ctype_wchar__Do_narrow_s));
9361     __ASM_VTABLE(ctype_short,
9362             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
9363             VTABLE_ADD_FUNC(ctype_wchar_do_is)
9364             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
9365             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
9366             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
9367             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
9368             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
9369             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
9370             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
9371             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
9372             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
9373             VTABLE_ADD_FUNC(ctype_wchar__Do_widen_s)
9374             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
9375             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch)
9376             VTABLE_ADD_FUNC(ctype_wchar__Do_narrow_s));
9377     __ASM_VTABLE(codecvt_base,
9378             VTABLE_ADD_FUNC(codecvt_base_vector_dtor)
9379             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
9380             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
9381             VTABLE_ADD_FUNC(codecvt_base_do_encoding));
9382     __ASM_VTABLE(codecvt_char,
9383             VTABLE_ADD_FUNC(codecvt_char_vector_dtor)
9384             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
9385             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
9386             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
9387             VTABLE_ADD_FUNC(codecvt_char_do_in)
9388             VTABLE_ADD_FUNC(codecvt_char_do_out)
9389             VTABLE_ADD_FUNC(codecvt_char_do_unshift)
9390             VTABLE_ADD_FUNC(codecvt_char_do_length));
9391     __ASM_VTABLE(codecvt_wchar,
9392             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
9393             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
9394             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
9395             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
9396             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
9397             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
9398             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
9399             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
9400     __ASM_VTABLE(codecvt_short,
9401             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
9402             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
9403             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
9404             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
9405             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
9406             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
9407             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
9408             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
9409     __ASM_VTABLE(numpunct_char,
9410             VTABLE_ADD_FUNC(numpunct_char_vector_dtor)
9411             VTABLE_ADD_FUNC(numpunct_char_do_decimal_point)
9412             VTABLE_ADD_FUNC(numpunct_char_do_thousands_sep)
9413             VTABLE_ADD_FUNC(numpunct_char_do_grouping)
9414             VTABLE_ADD_FUNC(numpunct_char_do_falsename)
9415             VTABLE_ADD_FUNC(numpunct_char_do_truename));
9416     __ASM_VTABLE(numpunct_wchar,
9417             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
9418             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
9419             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
9420             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
9421             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
9422             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
9423     __ASM_VTABLE(numpunct_short,
9424             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
9425             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
9426             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
9427             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
9428             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
9429             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
9430     __ASM_VTABLE(num_get_char,
9431             VTABLE_ADD_FUNC(num_get_char_vector_dtor)
9432             VTABLE_ADD_FUNC(num_get_char_do_get_void)
9433             VTABLE_ADD_FUNC(num_get_char_do_get_double)
9434             VTABLE_ADD_FUNC(num_get_char_do_get_double)
9435             VTABLE_ADD_FUNC(num_get_char_do_get_float)
9436             VTABLE_ADD_FUNC(num_get_char_do_get_uint64)
9437             VTABLE_ADD_FUNC(num_get_char_do_get_int64)
9438             VTABLE_ADD_FUNC(num_get_char_do_get_ulong)
9439             VTABLE_ADD_FUNC(num_get_char_do_get_long)
9440             VTABLE_ADD_FUNC(num_get_char_do_get_uint)
9441             VTABLE_ADD_FUNC(num_get_char_do_get_ushort)
9442             VTABLE_ADD_FUNC(num_get_char_do_get_bool));
9443     __ASM_VTABLE(num_get_short,
9444             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
9445             VTABLE_ADD_FUNC(num_get_short_do_get_void)
9446             VTABLE_ADD_FUNC(num_get_short_do_get_double)
9447             VTABLE_ADD_FUNC(num_get_short_do_get_double)
9448             VTABLE_ADD_FUNC(num_get_short_do_get_float)
9449             VTABLE_ADD_FUNC(num_get_short_do_get_uint64)
9450             VTABLE_ADD_FUNC(num_get_short_do_get_int64)
9451             VTABLE_ADD_FUNC(num_get_short_do_get_ulong)
9452             VTABLE_ADD_FUNC(num_get_short_do_get_long)
9453             VTABLE_ADD_FUNC(num_get_short_do_get_uint)
9454             VTABLE_ADD_FUNC(num_get_short_do_get_ushort)
9455             VTABLE_ADD_FUNC(num_get_short_do_get_bool));
9456     __ASM_VTABLE(num_get_wchar,
9457             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
9458             VTABLE_ADD_FUNC(num_get_wchar_do_get_void)
9459             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
9460             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
9461             VTABLE_ADD_FUNC(num_get_wchar_do_get_float)
9462             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint64)
9463             VTABLE_ADD_FUNC(num_get_wchar_do_get_int64)
9464             VTABLE_ADD_FUNC(num_get_wchar_do_get_ulong)
9465             VTABLE_ADD_FUNC(num_get_wchar_do_get_long)
9466             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint)
9467             VTABLE_ADD_FUNC(num_get_wchar_do_get_ushort)
9468             VTABLE_ADD_FUNC(num_get_wchar_do_get_bool));
9469     __ASM_VTABLE(num_put_char,
9470             VTABLE_ADD_FUNC(num_put_char_vector_dtor)
9471             VTABLE_ADD_FUNC(num_put_char_do_put_ptr)
9472             VTABLE_ADD_FUNC(num_put_char_do_put_double)
9473             VTABLE_ADD_FUNC(num_put_char_do_put_double)
9474             VTABLE_ADD_FUNC(num_put_char_do_put_uint64)
9475             VTABLE_ADD_FUNC(num_put_char_do_put_int64)
9476             VTABLE_ADD_FUNC(num_put_char_do_put_ulong)
9477             VTABLE_ADD_FUNC(num_put_char_do_put_long)
9478             VTABLE_ADD_FUNC(num_put_char_do_put_bool));
9479     __ASM_VTABLE(num_put_wchar,
9480             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
9481             VTABLE_ADD_FUNC(num_put_wchar_do_put_ptr)
9482             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
9483             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
9484             VTABLE_ADD_FUNC(num_put_wchar_do_put_uint64)
9485             VTABLE_ADD_FUNC(num_put_wchar_do_put_int64)
9486             VTABLE_ADD_FUNC(num_put_wchar_do_put_ulong)
9487             VTABLE_ADD_FUNC(num_put_wchar_do_put_long)
9488             VTABLE_ADD_FUNC(num_put_wchar_do_put_bool));
9489     __ASM_VTABLE(num_put_short,
9490             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
9491             VTABLE_ADD_FUNC(num_put_short_do_put_ptr)
9492             VTABLE_ADD_FUNC(num_put_short_do_put_double)
9493             VTABLE_ADD_FUNC(num_put_short_do_put_double)
9494             VTABLE_ADD_FUNC(num_put_short_do_put_uint64)
9495             VTABLE_ADD_FUNC(num_put_short_do_put_int64)
9496             VTABLE_ADD_FUNC(num_put_short_do_put_ulong)
9497             VTABLE_ADD_FUNC(num_put_short_do_put_long)
9498             VTABLE_ADD_FUNC(num_put_short_do_put_bool));
9499     __ASM_VTABLE(time_put_char,
9500             VTABLE_ADD_FUNC(time_put_char_vector_dtor)
9501             VTABLE_ADD_FUNC(time_put_char_do_put));
9502     __ASM_VTABLE(time_put_wchar,
9503             VTABLE_ADD_FUNC(time_put_wchar_vector_dtor)
9504             VTABLE_ADD_FUNC(time_put_wchar_do_put));
9505     __ASM_VTABLE(time_put_short,
9506             VTABLE_ADD_FUNC(time_put_wchar_vector_dtor)
9507             VTABLE_ADD_FUNC(time_put_wchar_do_put));
9508 #ifndef __GNUC__
9509 }
9510 #endif
9511
9512 void init_locale(void *base)
9513 {
9514 #ifdef __x86_64__
9515     init_locale_facet_rtti(base);
9516     init_collate_char_rtti(base);
9517     init_collate_wchar_rtti(base);
9518     init_collate_short_rtti(base);
9519     init_ctype_base_rtti(base);
9520     init_ctype_char_rtti(base);
9521     init_ctype_wchar_rtti(base);
9522     init_ctype_short_rtti(base);
9523     init_codecvt_base_rtti(base);
9524     init_codecvt_char_rtti(base);
9525     init_codecvt_wchar_rtti(base);
9526     init_codecvt_short_rtti(base);
9527     init_numpunct_char_rtti(base);
9528     init_numpunct_wchar_rtti(base);
9529     init_numpunct_short_rtti(base);
9530     init_num_get_char_rtti(base);
9531     init_num_get_wchar_rtti(base);
9532     init_num_get_short_rtti(base);
9533     init_num_put_char_rtti(base);
9534     init_num_put_wchar_rtti(base);
9535     init_num_put_short_rtti(base);
9536     init_time_put_char_rtti(base);
9537     init_time_put_wchar_rtti(base);
9538     init_time_put_short_rtti(base);
9539 #endif
9540 }
9541
9542 void free_locale(void)
9543 {
9544     facets_elem *iter, *safe;
9545
9546     if(global_locale) {
9547         locale__Locimp_dtor(global_locale);
9548         locale_dtor(&classic_locale);
9549     }
9550
9551     LIST_FOR_EACH_ENTRY_SAFE(iter, safe, &lazy_facets, facets_elem, entry) {
9552         list_remove(&iter->entry);
9553         if(locale_facet__Decref(iter->fac))
9554             call_locale_facet_vector_dtor(iter->fac, 1);
9555         MSVCRT_operator_delete(iter);
9556     }
9557 }