d3dx9: Add support for D3DFMT_A32B32G32R32F.
[wine] / dlls / msvcp100 / 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 "msvcp.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
31 #include "wine/list.h"
32
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winnls.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
39
40 char* __cdecl _Getdays(void);
41 char* __cdecl _Getmonths(void);
42 void* __cdecl _Gettnames(void);
43 unsigned int __cdecl ___lc_codepage_func(void);
44 LCID* __cdecl ___lc_handle_func(void);
45 static const locale_facet* locale__Getfacet(const locale*, MSVCP_size_t);
46
47 typedef int category;
48
49 typedef struct {
50     MSVCP_size_t id;
51 } locale_id;
52
53 typedef struct _locale__Locimp {
54     locale_facet facet;
55     locale_facet **facetvec;
56     MSVCP_size_t facet_cnt;
57     category catmask;
58     MSVCP_bool transparent;
59     _Yarn_char name;
60 } locale__Locimp;
61
62 typedef struct {
63     void *timeptr;
64 } _Timevec;
65
66 typedef struct {
67     _Lockit lock;
68     _Yarn_char days;
69     _Yarn_char months;
70     _Yarn_char oldlocname;
71     _Yarn_char newlocname;
72 } _Locinfo;
73
74 typedef struct {
75     LCID handle;
76     unsigned page;
77 } _Collvec;
78
79 typedef struct {
80     locale_facet facet;
81     _Collvec coll;
82 } collate;
83
84 typedef struct {
85     locale_facet facet;
86     const char *grouping;
87     char dp;
88     char sep;
89     const char *false_name;
90     const char *true_name;
91 } numpunct_char;
92
93 typedef struct {
94     locale_facet facet;
95     const char *grouping;
96     wchar_t dp;
97     wchar_t sep;
98     const wchar_t *false_name;
99     const wchar_t *true_name;
100 } numpunct_wchar;
101
102 /* ?_Id_cnt@id@locale@std@@0HA */
103 int locale_id__Id_cnt = 0;
104
105 static locale__Locimp *global_locale;
106 static locale classic_locale;
107
108 /* ?_Clocptr@_Locimp@locale@std@@0PAV123@A */
109 /* ?_Clocptr@_Locimp@locale@std@@0PEAV123@EA */
110 locale__Locimp *locale__Locimp__Clocptr = NULL;
111
112 static char istreambuf_iterator_char_val(istreambuf_iterator_char *this)
113 {
114     if(this->strbuf && !this->got) {
115         int c = basic_streambuf_char_sgetc(this->strbuf);
116         if(c == EOF)
117             this->strbuf = NULL;
118         else
119             this->val = c;
120     }
121
122     this->got = TRUE;
123     return this->val;
124 }
125
126 static wchar_t istreambuf_iterator_wchar_val(istreambuf_iterator_wchar *this)
127 {
128     if(this->strbuf && !this->got) {
129         unsigned short c = basic_streambuf_wchar_sgetc(this->strbuf);
130         if(c == WEOF)
131             this->strbuf = NULL;
132         else
133             this->val = c;
134     }
135
136     this->got = TRUE;
137     return this->val;
138 }
139
140 static void istreambuf_iterator_char_inc(istreambuf_iterator_char *this)
141 {
142     if(!this->strbuf || basic_streambuf_char_sbumpc(this->strbuf)==EOF) {
143         this->strbuf = NULL;
144         this->got = TRUE;
145     }else {
146         this->got = FALSE;
147         istreambuf_iterator_char_val(this);
148     }
149 }
150
151 static void istreambuf_iterator_wchar_inc(istreambuf_iterator_wchar *this)
152 {
153     if(!this->strbuf || basic_streambuf_wchar_sbumpc(this->strbuf)==WEOF) {
154         this->strbuf = NULL;
155         this->got = TRUE;
156     }else {
157         this->got = FALSE;
158         istreambuf_iterator_wchar_val(this);
159     }
160 }
161
162 static void ostreambuf_iterator_char_put(ostreambuf_iterator_char *this, char ch)
163 {
164     if(this->failed || basic_streambuf_char_sputc(this->strbuf, ch)==EOF)
165         this->failed = TRUE;
166 }
167
168 static void ostreambuf_iterator_wchar_put(ostreambuf_iterator_wchar *this, wchar_t ch)
169 {
170     if(this->failed || basic_streambuf_wchar_sputc(this->strbuf, ch)==WEOF)
171         this->failed = TRUE;
172 }
173
174 /* ??1facet@locale@std@@UAE@XZ */
175 /* ??1facet@locale@std@@UEAA@XZ */
176 DEFINE_THISCALL_WRAPPER(locale_facet_dtor, 4)
177 void __thiscall locale_facet_dtor(locale_facet *this)
178 {
179     TRACE("(%p)\n", this);
180 }
181
182 DEFINE_THISCALL_WRAPPER(locale_facet_vector_dtor, 8)
183 #define call_locale_facet_vector_dtor(this, flags) CALL_VTBL_FUNC(this, 0, \
184         locale_facet*, (locale_facet*, unsigned int), (this, flags))
185 locale_facet* __thiscall locale_facet_vector_dtor(locale_facet *this, unsigned int flags)
186 {
187     TRACE("(%p %x)\n", this, flags);
188     if(flags & 2) {
189         /* we have an array, with the number of elements stored before the first object */
190         INT_PTR i, *ptr = (INT_PTR *)this-1;
191
192         for(i=*ptr-1; i>=0; i--)
193             locale_facet_dtor(this+i);
194         MSVCRT_operator_delete(ptr);
195     } else {
196         locale_facet_dtor(this);
197         if(flags & 1)
198             MSVCRT_operator_delete(this);
199     }
200
201     return this;
202 }
203
204 typedef struct
205 {
206     locale_facet *fac;
207     struct list entry;
208 } facets_elem;
209 static struct list lazy_facets = LIST_INIT(lazy_facets);
210
211 /* ?facet_Register@facet@locale@std@@CAXPAV123@@Z */
212 /* ?facet_Register@facet@locale@std@@CAXPEAV123@@Z */
213 static void locale_facet_register(locale_facet *add)
214 {
215     facets_elem *head = MSVCRT_operator_new(sizeof(*head));
216     if(!head) {
217         ERR("Out of memory\n");
218         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
219     }
220
221     head->fac = add;
222     list_add_head(&lazy_facets, &head->entry);
223 }
224
225 /* Not exported from msvcp90 */
226 /* ??_7facet@locale@std@@6B@ */
227 extern const vtable_ptr MSVCP_locale_facet_vtable;
228
229 /* ??0id@locale@std@@QAE@I@Z */
230 /* ??0id@locale@std@@QEAA@_K@Z */
231 DEFINE_THISCALL_WRAPPER(locale_id_ctor_id, 8)
232 locale_id* __thiscall locale_id_ctor_id(locale_id *this, MSVCP_size_t id)
233 {
234     TRACE("(%p %lu)\n", this, id);
235
236     this->id = id;
237     return this;
238 }
239
240 /* ??_Fid@locale@std@@QAEXXZ */
241 /* ??_Fid@locale@std@@QEAAXXZ */
242 DEFINE_THISCALL_WRAPPER(locale_id_ctor, 4)
243 locale_id* __thiscall locale_id_ctor(locale_id *this)
244 {
245     TRACE("(%p)\n", this);
246
247     this->id = 0;
248     return this;
249 }
250
251 /* ??Bid@locale@std@@QAEIXZ */
252 /* ??Bid@locale@std@@QEAA_KXZ */
253 DEFINE_THISCALL_WRAPPER(locale_id_operator_size_t, 4)
254 MSVCP_size_t __thiscall locale_id_operator_size_t(locale_id *this)
255 {
256     _Lockit lock;
257
258     TRACE("(%p)\n", this);
259
260     if(!this->id) {
261         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
262         this->id = ++locale_id__Id_cnt;
263         _Lockit_dtor(&lock);
264     }
265
266     return this->id;
267 }
268
269 /* ??_Ffacet@locale@std@@QAEXXZ */
270 /* ??_Ffacet@locale@std@@QEAAXXZ */
271 DEFINE_THISCALL_WRAPPER(locale_facet_ctor, 4)
272 locale_facet* __thiscall locale_facet_ctor(locale_facet *this)
273 {
274     TRACE("(%p)\n", this);
275     this->vtable = &MSVCP_locale_facet_vtable;
276     this->refs = 0;
277     return this;
278 }
279
280 /* ??0facet@locale@std@@IAE@I@Z */
281 /* ??0facet@locale@std@@IEAA@_K@Z */
282 DEFINE_THISCALL_WRAPPER(locale_facet_ctor_refs, 8)
283 locale_facet* __thiscall locale_facet_ctor_refs(locale_facet *this, MSVCP_size_t refs)
284 {
285     TRACE("(%p %lu)\n", this, refs);
286     this->vtable = &MSVCP_locale_facet_vtable;
287     this->refs = refs;
288     return this;
289 }
290
291 /* ?_Incref@facet@locale@std@@QAEXXZ */
292 /* ?_Incref@facet@locale@std@@QEAAXXZ */
293 DEFINE_THISCALL_WRAPPER(locale_facet__Incref, 4)
294 void __thiscall locale_facet__Incref(locale_facet *this)
295 {
296     _Lockit lock;
297
298     TRACE("(%p)\n", this);
299
300     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
301     this->refs++;
302     _Lockit_dtor(&lock);
303 }
304
305 /* ?_Decref@facet@locale@std@@QAEPAV123@XZ */
306 /* ?_Decref@facet@locale@std@@QEAAPEAV123@XZ */
307 DEFINE_THISCALL_WRAPPER(locale_facet__Decref, 4)
308 locale_facet* __thiscall locale_facet__Decref(locale_facet *this)
309 {
310     _Lockit lock;
311     locale_facet *ret;
312
313     TRACE("(%p)\n", this);
314
315     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
316     if(this->refs)
317         this->refs--;
318
319     ret = this->refs ? NULL : this;
320     _Lockit_dtor(&lock);
321
322     return ret;
323 }
324
325 /* ?_Getcat@facet@locale@std@@SAIPAPBV123@PBV23@@Z */
326 /* ?_Getcat@facet@locale@std@@SA_KPEAPEBV123@PEBV23@@Z */
327 MSVCP_size_t __cdecl locale_facet__Getcat(const locale_facet **facet, const locale *loc)
328 {
329     TRACE("(%p %p)\n", facet, loc);
330     return -1;
331 }
332
333 /* ??0_Timevec@std@@QAE@ABV01@@Z */
334 /* ??0_Timevec@std@@QEAA@AEBV01@@Z */
335 /* This copy constructor modifies copied object */
336 DEFINE_THISCALL_WRAPPER(_Timevec_copy_ctor, 8)
337 _Timevec* __thiscall _Timevec_copy_ctor(_Timevec *this, _Timevec *copy)
338 {
339     TRACE("(%p %p)\n", this, copy);
340     this->timeptr = copy->timeptr;
341     copy->timeptr = NULL;
342     return this;
343 }
344
345 /* ??0_Timevec@std@@QAE@PAX@Z */
346 /* ??0_Timevec@std@@QEAA@PEAX@Z */
347 DEFINE_THISCALL_WRAPPER(_Timevec_ctor_timeptr, 8)
348 _Timevec* __thiscall _Timevec_ctor_timeptr(_Timevec *this, void *timeptr)
349 {
350     TRACE("(%p %p)\n", this, timeptr);
351     this->timeptr = timeptr;
352     return this;
353 }
354
355 /* ??_F_Timevec@std@@QAEXXZ */
356 /* ??_F_Timevec@std@@QEAAXXZ */
357 DEFINE_THISCALL_WRAPPER(_Timevec_ctor, 4)
358 _Timevec* __thiscall _Timevec_ctor(_Timevec *this)
359 {
360     TRACE("(%p)\n", this);
361     this->timeptr = NULL;
362     return this;
363 }
364
365 /* ??1_Timevec@std@@QAE@XZ */
366 /* ??1_Timevec@std@@QEAA@XZ */
367 DEFINE_THISCALL_WRAPPER(_Timevec_dtor, 4)
368 void __thiscall _Timevec_dtor(_Timevec *this)
369 {
370     TRACE("(%p)\n", this);
371     free(this->timeptr);
372 }
373
374 /* ??4_Timevec@std@@QAEAAV01@ABV01@@Z */
375 /* ??4_Timevec@std@@QEAAAEAV01@AEBV01@@Z */
376 DEFINE_THISCALL_WRAPPER(_Timevec_op_assign, 8)
377 _Timevec* __thiscall _Timevec_op_assign(_Timevec *this, _Timevec *right)
378 {
379     TRACE("(%p %p)\n", this, right);
380     this->timeptr = right->timeptr;
381     right->timeptr = NULL;
382     return this;
383 }
384
385 /* ?_Getptr@_Timevec@std@@QBEPAXXZ */
386 /* ?_Getptr@_Timevec@std@@QEBAPEAXXZ */
387 DEFINE_THISCALL_WRAPPER(_Timevec__Getptr, 4)
388 void* __thiscall _Timevec__Getptr(_Timevec *this)
389 {
390     TRACE("(%p)\n", this);
391     return this->timeptr;
392 }
393
394 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@HPBD@Z */
395 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@HPEBD@Z */
396 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cat_cstr(_Locinfo *locinfo, int category, const char *locstr)
397 {
398     const char *locale = NULL;
399
400     /* This function is probably modifying more global objects */
401     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
402
403     if(!locstr)
404         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
405
406     _Lockit_ctor_locktype(&locinfo->lock, _LOCK_LOCALE);
407     _Yarn_char_ctor_cstr(&locinfo->days, NULL);
408     _Yarn_char_ctor_cstr(&locinfo->months, NULL);
409     _Yarn_char_ctor_cstr(&locinfo->oldlocname, setlocale(LC_ALL, NULL));
410
411     if(category)
412         locale = setlocale(LC_ALL, locstr);
413     else
414         locale = setlocale(LC_ALL, NULL);
415
416     if(locale)
417         _Yarn_char_ctor_cstr(&locinfo->newlocname, locale);
418     else
419         _Yarn_char_ctor_cstr(&locinfo->newlocname, "*");
420
421     return locinfo;
422 }
423
424 /* ??0_Locinfo@std@@QAE@HPBD@Z */
425 /* ??0_Locinfo@std@@QEAA@HPEBD@Z */
426 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cat_cstr, 12)
427 _Locinfo* __thiscall _Locinfo_ctor_cat_cstr(_Locinfo *this, int category, const char *locstr)
428 {
429     return _Locinfo__Locinfo_ctor_cat_cstr(this, category, locstr);
430 }
431
432 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPAV12@PBD@Z */
433 /* ?_Locinfo_ctor@_Locinfo@std@@SAXPEAV12@PEBD@Z */
434 _Locinfo* __cdecl _Locinfo__Locinfo_ctor_cstr(_Locinfo *locinfo, const char *locstr)
435 {
436     return _Locinfo__Locinfo_ctor_cat_cstr(locinfo, 1/*FIXME*/, locstr);
437 }
438
439 /* ??0_Locinfo@std@@QAE@PBD@Z */
440 /* ??0_Locinfo@std@@QEAA@PEBD@Z */
441 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor_cstr, 8)
442 _Locinfo* __thiscall _Locinfo_ctor_cstr(_Locinfo *this, const char *locstr)
443 {
444     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, locstr);
445 }
446
447 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPAV12@@Z */
448 /* ?_Locinfo_dtor@_Locinfo@std@@SAXPEAV12@@Z */
449 void __cdecl _Locinfo__Locinfo_dtor(_Locinfo *locinfo)
450 {
451     TRACE("(%p)\n", locinfo);
452
453     setlocale(LC_ALL, _Yarn_char_c_str(&locinfo->oldlocname));
454     _Yarn_char_dtor(&locinfo->days);
455     _Yarn_char_dtor(&locinfo->months);
456     _Yarn_char_dtor(&locinfo->oldlocname);
457     _Yarn_char_dtor(&locinfo->newlocname);
458     _Lockit_dtor(&locinfo->lock);
459 }
460
461 /* ??_F_Locinfo@std@@QAEXXZ */
462 /* ??_F_Locinfo@std@@QEAAXXZ */
463 DEFINE_THISCALL_WRAPPER(_Locinfo_ctor, 4)
464 _Locinfo* __thiscall _Locinfo_ctor(_Locinfo *this)
465 {
466     return _Locinfo__Locinfo_ctor_cat_cstr(this, 1/*FIXME*/, "C");
467 }
468
469 /* ??1_Locinfo@std@@QAE@XZ */
470 /* ??1_Locinfo@std@@QEAA@XZ */
471 DEFINE_THISCALL_WRAPPER(_Locinfo_dtor, 4)
472 void __thiscall _Locinfo_dtor(_Locinfo *this)
473 {
474     _Locinfo__Locinfo_dtor(this);
475 }
476
477 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAAV12@PAV12@HPBD@Z */
478 /* ?_Locinfo_Addcats@_Locinfo@std@@SAAEAV12@PEAV12@HPEBD@Z */
479 _Locinfo* __cdecl _Locinfo__Locinfo_Addcats(_Locinfo *locinfo, int category, const char *locstr)
480 {
481     const char *locale = NULL;
482
483     /* This function is probably modifying more global objects */
484     FIXME("(%p %d %s) semi-stub\n", locinfo, category, locstr);
485     if(!locstr)
486         throw_exception(EXCEPTION_RUNTIME_ERROR, "bad locale name");
487
488     _Yarn_char_dtor(&locinfo->newlocname);
489
490     if(category)
491         locale = setlocale(LC_ALL, locstr);
492     else
493         locale = setlocale(LC_ALL, NULL);
494
495     if(locale)
496         _Yarn_char_ctor_cstr(&locinfo->newlocname, locale);
497     else
498         _Yarn_char_ctor_cstr(&locinfo->newlocname, "*");
499
500     return locinfo;
501 }
502
503 /* ?_Addcats@_Locinfo@std@@QAEAAV12@HPBD@Z */
504 /* ?_Addcats@_Locinfo@std@@QEAAAEAV12@HPEBD@Z */
505 DEFINE_THISCALL_WRAPPER(_Locinfo__Addcats, 12)
506 _Locinfo* __thiscall _Locinfo__Addcats(_Locinfo *this, int category, const char *locstr)
507 {
508     return _Locinfo__Locinfo_Addcats(this, category, locstr);
509 }
510
511 /* _Getcoll */
512 ULONGLONG __cdecl _Getcoll(void)
513 {
514     union {
515         _Collvec collvec;
516         ULONGLONG ull;
517     } ret;
518     _locale_t locale = _get_current_locale();
519
520     TRACE("\n");
521
522     ret.collvec.page = locale->locinfo->lc_collate_cp;
523     ret.collvec.handle = locale->locinfo->lc_handle[LC_COLLATE];
524     _free_locale(locale);
525     return ret.ull;
526 }
527
528 /* ?_Getcoll@_Locinfo@std@@QBE?AU_Collvec@@XZ */
529 /* ?_Getcoll@_Locinfo@std@@QEBA?AU_Collvec@@XZ */
530 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcoll, 8)
531 _Collvec* __thiscall _Locinfo__Getcoll(const _Locinfo *this, _Collvec *ret)
532 {
533     ULONGLONG ull = _Getcoll();
534     memcpy(ret, &ull, sizeof(ull));
535     return ret;
536 }
537
538 /* _Getctype */
539 _Ctypevec* __cdecl _Getctype(_Ctypevec *ret)
540 {
541     _locale_t locale = _get_current_locale();
542     short *table;
543
544     TRACE("\n");
545
546     ret->page = locale->locinfo->lc_codepage;
547     ret->handle = locale->locinfo->lc_handle[LC_COLLATE];
548     ret->delfl = TRUE;
549     table = malloc(sizeof(short[256]));
550     if(!table) {
551         _free_locale(locale);
552         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
553     }
554     memcpy(table, locale->locinfo->pctype, sizeof(short[256]));
555     ret->table = table;
556     _free_locale(locale);
557     return ret;
558 }
559
560 /* ?_Getctype@_Locinfo@std@@QBE?AU_Ctypevec@@XZ */
561 /* ?_Getctype@_Locinfo@std@@QEBA?AU_Ctypevec@@XZ */
562 DEFINE_THISCALL_WRAPPER(_Locinfo__Getctype, 8)
563 _Ctypevec* __thiscall _Locinfo__Getctype(const _Locinfo *this, _Ctypevec *ret)
564 {
565     return _Getctype(ret);
566 }
567
568 /* _Getcvt */
569 ULONGLONG __cdecl _Getcvt(void)
570 {
571     _locale_t locale = _get_current_locale();
572     union {
573         _Cvtvec cvtvec;
574         ULONGLONG ull;
575     } ret;
576
577     TRACE("\n");
578
579     ret.cvtvec.page = locale->locinfo->lc_codepage;
580     ret.cvtvec.handle = locale->locinfo->lc_handle[LC_CTYPE];
581     _free_locale(locale);
582     return ret.ull;
583 }
584
585 /* ?_Getcvt@_Locinfo@std@@QBE?AU_Cvtvec@@XZ */
586 /* ?_Getcvt@_Locinfo@std@@QEBA?AU_Cvtvec@@XZ */
587 DEFINE_THISCALL_WRAPPER(_Locinfo__Getcvt, 8)
588 _Cvtvec* __thiscall _Locinfo__Getcvt(const _Locinfo *this, _Cvtvec *ret)
589 {
590     ULONGLONG ull = _Getcvt();
591     memcpy(ret, &ull, sizeof(ull));
592     return ret;
593 }
594
595 /* ?_Getdateorder@_Locinfo@std@@QBEHXZ */
596 /* ?_Getdateorder@_Locinfo@std@@QEBAHXZ */
597 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdateorder, 4)
598 int __thiscall _Locinfo__Getdateorder(const _Locinfo *this)
599 {
600     FIXME("(%p) stub\n", this);
601     return 0;
602 }
603
604 /* ?_Getdays@_Locinfo@std@@QBEPBDXZ */
605 /* ?_Getdays@_Locinfo@std@@QEBAPEBDXZ */
606 DEFINE_THISCALL_WRAPPER(_Locinfo__Getdays, 4)
607 const char* __thiscall _Locinfo__Getdays(_Locinfo *this)
608 {
609     char *days = _Getdays();
610
611     TRACE("(%p)\n", this);
612
613     if(days) {
614         _Yarn_char_dtor(&this->days);
615         _Yarn_char_ctor_cstr(&this->days, days);
616         free(days);
617     }
618
619     return this->days.str ? _Yarn_char_c_str(&this->days) :
620         ":Sun:Sunday:Mon:Monday:Tue:Tuesday:Wed:Wednesday:Thu:Thursday:Fri:Friday:Sat:Saturday";
621 }
622
623 /* ?_Getmonths@_Locinfo@std@@QBEPBDXZ */
624 /* ?_Getmonths@_Locinfo@std@@QEBAPEBDXZ */
625 DEFINE_THISCALL_WRAPPER(_Locinfo__Getmonths, 4)
626 const char* __thiscall _Locinfo__Getmonths(_Locinfo *this)
627 {
628     char *months = _Getmonths();
629
630     TRACE("(%p)\n", this);
631
632     if(months) {
633         _Yarn_char_dtor(&this->months);
634         _Yarn_char_ctor_cstr(&this->months, months);
635         free(months);
636     }
637
638     return this->months.str ? _Yarn_char_c_str(&this->months) :
639         ":Jan:January:Feb:February:Mar:March:Apr:April:May:May:Jun:June:Jul:July"
640         ":Aug:August:Sep:September:Oct:October:Nov:November:Dec:December";
641 }
642
643 /* ?_Getfalse@_Locinfo@std@@QBEPBDXZ */
644 /* ?_Getfalse@_Locinfo@std@@QEBAPEBDXZ */
645 DEFINE_THISCALL_WRAPPER(_Locinfo__Getfalse, 4)
646 const char* __thiscall _Locinfo__Getfalse(const _Locinfo *this)
647 {
648     TRACE("(%p)\n", this);
649     return "false";
650 }
651
652 /* ?_Gettrue@_Locinfo@std@@QBEPBDXZ */
653 /* ?_Gettrue@_Locinfo@std@@QEBAPEBDXZ */
654 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettrue, 4)
655 const char* __thiscall _Locinfo__Gettrue(const _Locinfo *this)
656 {
657     TRACE("(%p)\n", this);
658     return "true";
659 }
660
661 /* ?_Getlconv@_Locinfo@std@@QBEPBUlconv@@XZ */
662 /* ?_Getlconv@_Locinfo@std@@QEBAPEBUlconv@@XZ */
663 DEFINE_THISCALL_WRAPPER(_Locinfo__Getlconv, 4)
664 const struct lconv* __thiscall _Locinfo__Getlconv(const _Locinfo *this)
665 {
666     TRACE("(%p)\n", this);
667     return localeconv();
668 }
669
670 /* ?_Gettnames@_Locinfo@std@@QBE?AV_Timevec@2@XZ */
671 /* ?_Gettnames@_Locinfo@std@@QEBA?AV_Timevec@2@XZ */
672 DEFINE_THISCALL_WRAPPER(_Locinfo__Gettnames, 8)
673 _Timevec*__thiscall _Locinfo__Gettnames(const _Locinfo *this, _Timevec *ret)
674 {
675     TRACE("(%p)\n", this);
676
677     _Timevec_ctor_timeptr(ret, _Gettnames());
678     return ret;
679 }
680
681 /* ?id@?$collate@D@std@@2V0locale@2@A */
682 locale_id collate_char_id = {0};
683
684 /* ??_7?$collate@D@std@@6B@ */
685 extern const vtable_ptr MSVCP_collate_char_vtable;
686
687 /* ??1?$collate@D@std@@MAE@XZ */
688 /* ??1?$collate@D@std@@MEAA@XZ */
689 static void collate_char_dtor(collate *this)
690 {
691     TRACE("(%p)\n", this);
692 }
693
694 DEFINE_THISCALL_WRAPPER(collate_char_vector_dtor, 8)
695 collate* __thiscall collate_char_vector_dtor(collate *this, unsigned int flags)
696 {
697     TRACE("(%p %x)\n", this, flags);
698     if(flags & 2) {
699         /* we have an array, with the number of elements stored before the first object */
700         INT_PTR i, *ptr = (INT_PTR *)this-1;
701
702         for(i=*ptr-1; i>=0; i--)
703             collate_char_dtor(this+i);
704         MSVCRT_operator_delete(ptr);
705     } else {
706         collate_char_dtor(this);
707         if(flags & 1)
708             MSVCRT_operator_delete(this);
709     }
710
711     return this;
712 }
713
714 /* _Strcoll */
715 int __cdecl _Strcoll(const char *first1, const char *last1, const char *first2,
716         const char *last2, const _Collvec *coll)
717 {
718     LCID lcid;
719
720     TRACE("(%s %s)\n", debugstr_an(first1, last1-first1), debugstr_an(first2, last2-first2));
721
722     if(coll)
723         lcid = coll->handle;
724     else
725         lcid = ___lc_handle_func()[LC_COLLATE];
726     return CompareStringA(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
727 }
728
729 /* ?do_compare@?$collate@D@std@@MBEHPBD000@Z */
730 /* ?do_compare@?$collate@D@std@@MEBAHPEBD000@Z */
731 DEFINE_THISCALL_WRAPPER(collate_char_do_compare, 20)
732 #define call_collate_char_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
733         (const collate*, const char*, const char*, const char*, const char*), \
734         (this, first1, last1, first2, last2))
735 int __thiscall collate_char_do_compare(const collate *this, const char *first1,
736         const char *last1, const char *first2, const char *last2)
737 {
738     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
739     return _Strcoll(first1, last1, first2, last2, &this->coll);
740 }
741
742 /* ?do_hash@?$collate@D@std@@MBEJPBD0@Z */
743 /* ?do_hash@?$collate@D@std@@MEBAJPEBD0@Z */
744 DEFINE_THISCALL_WRAPPER(collate_char_do_hash, 12)
745 #define call_collate_char_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
746         (const collate*, const char*, const char*), (this, first, last))
747 LONG __thiscall collate_char_do_hash(const collate *this,
748         const char *first, const char *last)
749 {
750     ULONG ret = 0;
751
752     TRACE("(%p %p %p)\n", this, first, last);
753
754     for(; first<last; first++)
755         ret = (ret<<8 | ret>>24) + *first;
756     return ret;
757 }
758
759 /* ?do_transform@?$collate@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PBD0@Z */
760 /* ?do_transform@?$collate@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@PEBD0@Z */
761 DEFINE_THISCALL_WRAPPER(collate_char_do_transform, 16)
762 basic_string_char* __thiscall collate_char_do_transform(const collate *this,
763         basic_string_char *ret, const char *first, const char *last)
764 {
765     FIXME("(%p %p %p) stub\n", this, first, last);
766     return ret;
767 }
768
769 /* ?id@?$collate@_W@std@@2V0locale@2@A */
770 locale_id collate_wchar_id = {0};
771 /* ?id@?$collate@G@std@@2V0locale@2@A */
772 locale_id collate_short_id = {0};
773
774 /* ??_7?$collate@_W@std@@6B@ */
775 extern const vtable_ptr MSVCP_collate_wchar_vtable;
776 /* ??_7?$collate@G@std@@6B@ */
777 extern const vtable_ptr MSVCP_collate_short_vtable;
778
779 /* ??1?$collate@_W@std@@MAE@XZ */
780 /* ??1?$collate@_W@std@@MEAA@XZ */
781 /* ??1?$collate@G@std@@MAE@XZ */
782 /* ??1?$collate@G@std@@MEAA@XZ */
783 static void collate_wchar_dtor(collate *this)
784 {
785     TRACE("(%p)\n", this);
786 }
787
788 DEFINE_THISCALL_WRAPPER(collate_wchar_vector_dtor, 8)
789 collate* __thiscall collate_wchar_vector_dtor(collate *this, unsigned int flags)
790 {
791     TRACE("(%p %x)\n", this, flags);
792     if(flags & 2) {
793         /* we have an array, with the number of elements stored before the first object */
794         INT_PTR i, *ptr = (INT_PTR *)this-1;
795
796         for(i=*ptr-1; i>=0; i--)
797             collate_wchar_dtor(this+i);
798         MSVCRT_operator_delete(ptr);
799     } else {
800         collate_wchar_dtor(this);
801         if(flags & 1)
802             MSVCRT_operator_delete(this);
803     }
804
805     return this;
806 }
807
808 /* _Wcscoll */
809 int __cdecl _Wcscoll(const wchar_t *first1, const wchar_t *last1, const wchar_t *first2,
810         const wchar_t *last2, const _Collvec *coll)
811 {
812     LCID lcid;
813
814     TRACE("(%s %s)\n", debugstr_wn(first1, last1-first1), debugstr_wn(first2, last2-first2));
815
816     if(coll)
817         lcid = coll->handle;
818     else
819         lcid = ___lc_handle_func()[LC_COLLATE];
820     return CompareStringW(lcid, 0, first1, last1-first1, first2, last2-first2)-CSTR_EQUAL;
821 }
822
823 /* ?do_compare@?$collate@_W@std@@MBEHPB_W000@Z */
824 /* ?do_compare@?$collate@_W@std@@MEBAHPEB_W000@Z */
825 /* ?do_compare@?$collate@G@std@@MBEHPBG000@Z */
826 /* ?do_compare@?$collate@G@std@@MEBAHPEBG000@Z */
827 DEFINE_THISCALL_WRAPPER(collate_wchar_do_compare, 20)
828 #define call_collate_wchar_do_compare(this, first1, last1, first2, last2) CALL_VTBL_FUNC(this, 4, int, \
829         (const collate*, const wchar_t*, const wchar_t*, const wchar_t*, const wchar_t*), \
830         (this, first1, last1, first2, last2))
831 int __thiscall collate_wchar_do_compare(const collate *this, const wchar_t *first1,
832         const wchar_t *last1, const wchar_t *first2, const wchar_t *last2)
833 {
834     TRACE("(%p %p %p %p %p)\n", this, first1, last1, first2, last2);
835     return _Wcscoll(first1, last1, first2, last2, &this->coll);
836 }
837
838 /* ?do_hash@?$collate@_W@std@@MBEJPB_W0@Z */
839 /* ?do_hash@?$collate@_W@std@@MEBAJPEB_W0@Z */
840 /* ?do_hash@?$collate@G@std@@MBEJPBG0@Z */
841 /* ?do_hash@?$collate@G@std@@MEBAJPEBG0@Z */
842 DEFINE_THISCALL_WRAPPER(collate_wchar_do_hash, 12)
843 #define call_collate_wchar_do_hash(this, first, last) CALL_VTBL_FUNC(this, 12, LONG, \
844         (const collate*, const wchar_t*, const wchar_t*), (this, first, last))
845 LONG __thiscall collate_wchar_do_hash(const collate *this,
846         const wchar_t *first, const wchar_t *last)
847 {
848     ULONG ret = 0;
849
850     TRACE("(%p %p %p)\n", this, first, last);
851
852     for(; first<last; first++)
853         ret = (ret<<8 | ret>>24) + *first;
854     return ret;
855 }
856
857 /* ?do_transform@?$collate@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PB_W0@Z */
858 /* ?do_transform@?$collate@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@PEB_W0@Z */
859 /* ?do_transform@?$collate@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PBG0@Z */
860 /* ?do_transform@?$collate@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@PEBG0@Z */
861 DEFINE_THISCALL_WRAPPER(collate_wchar_do_transform, 16)
862 basic_string_wchar* __thiscall collate_wchar_do_transform(const collate *this,
863         basic_string_wchar *ret, const wchar_t *first, const wchar_t *last)
864 {
865     FIXME("(%p %p %p) stub\n", this, first, last);
866     return ret;
867 }
868
869 /* ??_7ctype_base@std@@6B@ */
870 extern const vtable_ptr MSVCP_ctype_base_vtable;
871
872 /* ??0ctype_base@std@@QAE@I@Z */
873 /* ??0ctype_base@std@@QEAA@_K@Z */
874 DEFINE_THISCALL_WRAPPER(ctype_base_ctor_refs, 8)
875 ctype_base* __thiscall ctype_base_ctor_refs(ctype_base *this, MSVCP_size_t refs)
876 {
877     TRACE("(%p %lu)\n", this, refs);
878     locale_facet_ctor_refs(&this->facet, refs);
879     this->facet.vtable = &MSVCP_ctype_base_vtable;
880     return this;
881 }
882
883 /* ??_Fctype_base@std@@QAEXXZ */
884 /* ??_Fctype_base@std@@QEAAXXZ */
885 DEFINE_THISCALL_WRAPPER(ctype_base_ctor, 4)
886 ctype_base* __thiscall ctype_base_ctor(ctype_base *this)
887 {
888     TRACE("(%p)\n", this);
889     locale_facet_ctor_refs(&this->facet, 0);
890     this->facet.vtable = &MSVCP_ctype_base_vtable;
891     return this;
892 }
893
894 /* ??1ctype_base@std@@UAE@XZ */
895 /* ??1ctype_base@std@@UEAA@XZ */
896 DEFINE_THISCALL_WRAPPER(ctype_base_dtor, 4)
897 void __thiscall ctype_base_dtor(ctype_base *this)
898 {
899     TRACE("(%p)\n", this);
900 }
901
902 DEFINE_THISCALL_WRAPPER(ctype_base_vector_dtor, 8)
903 ctype_base* __thiscall ctype_base_vector_dtor(ctype_base *this, unsigned int flags)
904 {
905     TRACE("(%p %x)\n", this, flags);
906     if(flags & 2) {
907         /* we have an array, with the number of elements stored before the first object */
908         INT_PTR i, *ptr = (INT_PTR *)this-1;
909
910         for(i=*ptr-1; i>=0; i--)
911             ctype_base_dtor(this+i);
912         MSVCRT_operator_delete(ptr);
913     } else {
914         ctype_base_dtor(this);
915         if(flags & 1)
916             MSVCRT_operator_delete(this);
917     }
918
919     return this;
920 }
921
922 /* ?id@?$ctype@D@std@@2V0locale@2@A */
923 locale_id ctype_char_id = {0};
924 /* ?table_size@?$ctype@D@std@@2IB */
925 /* ?table_size@?$ctype@D@std@@2_KB */
926 MSVCP_size_t ctype_char_table_size = 256;
927
928 /* ??_7?$ctype@D@std@@6B@ */
929 extern const vtable_ptr MSVCP_ctype_char_vtable;
930
931 /* ?_Init@?$ctype@D@std@@IAEXABV_Locinfo@2@@Z */
932 /* ?_Init@?$ctype@D@std@@IEAAXAEBV_Locinfo@2@@Z */
933 DEFINE_THISCALL_WRAPPER(ctype_char__Init, 8)
934 void __thiscall ctype_char__Init(ctype_char *this, const _Locinfo *locinfo)
935 {
936     TRACE("(%p %p)\n", this, locinfo);
937     _Locinfo__Getctype(locinfo, &this->ctype);
938 }
939
940 /* ?_Tidy@?$ctype@D@std@@IAEXXZ */
941 /* ?_Tidy@?$ctype@D@std@@IEAAXXZ */
942 DEFINE_THISCALL_WRAPPER(ctype_char__Tidy, 4)
943 void __thiscall ctype_char__Tidy(ctype_char *this)
944 {
945     TRACE("(%p)\n", this);
946
947     if(this->ctype.delfl)
948         free((short*)this->ctype.table);
949 }
950
951 /* ??0?$ctype@D@std@@QAE@ABV_Locinfo@1@I@Z */
952 /* ??0?$ctype@D@std@@QEAA@AEBV_Locinfo@1@_K@Z */
953 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_locinfo, 12)
954 ctype_char* __thiscall ctype_char_ctor_locinfo(ctype_char *this,
955         const _Locinfo *locinfo, MSVCP_size_t refs)
956 {
957     TRACE("(%p %p %lu)\n", this, locinfo, refs);
958     ctype_base_ctor_refs(&this->base, refs);
959     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
960     ctype_char__Init(this, locinfo);
961     return this;
962 }
963
964 /* ??0?$ctype@D@std@@QAE@PBF_NI@Z */
965 /* ??0?$ctype@D@std@@QEAA@PEBF_N_K@Z */
966 DEFINE_THISCALL_WRAPPER(ctype_char_ctor_table, 16)
967 ctype_char* __thiscall ctype_char_ctor_table(ctype_char *this,
968         const short *table, MSVCP_bool delete, MSVCP_size_t refs)
969 {
970     _Locinfo locinfo;
971
972     TRACE("(%p %p %d %lu)\n", this, table, delete, refs);
973
974     ctype_base_ctor_refs(&this->base, refs);
975     this->base.facet.vtable = &MSVCP_ctype_char_vtable;
976
977     _Locinfo_ctor(&locinfo);
978     ctype_char__Init(this, &locinfo);
979     _Locinfo_dtor(&locinfo);
980
981     if(table) {
982         ctype_char__Tidy(this);
983         this->ctype.table = table;
984         this->ctype.delfl = delete;
985     }
986     return this;
987 }
988
989 /* ??_F?$ctype@D@std@@QAEXXZ */
990 /* ??_F?$ctype@D@std@@QEAAXXZ */
991 DEFINE_THISCALL_WRAPPER(ctype_char_ctor, 4)
992 ctype_char* __thiscall ctype_char_ctor(ctype_char *this)
993 {
994     return ctype_char_ctor_table(this, NULL, FALSE, 0);
995 }
996
997 /* ??1?$ctype@D@std@@MAE@XZ */
998 /* ??1?$ctype@D@std@@MEAA@XZ */
999 DEFINE_THISCALL_WRAPPER(ctype_char_dtor, 4)
1000 void __thiscall ctype_char_dtor(ctype_char *this)
1001 {
1002     TRACE("(%p)\n", this);
1003     ctype_char__Tidy(this);
1004 }
1005
1006 DEFINE_THISCALL_WRAPPER(ctype_char_vector_dtor, 8)
1007 ctype_char* __thiscall ctype_char_vector_dtor(ctype_char *this, unsigned int flags)
1008 {
1009     TRACE("(%p %x)\n", this, flags);
1010     if(flags & 2) {
1011         /* we have an array, with the number of elements stored before the first object */
1012         INT_PTR i, *ptr = (INT_PTR *)this-1;
1013
1014         for(i=*ptr-1; i>=0; i--)
1015             ctype_char_dtor(this+i);
1016         MSVCRT_operator_delete(ptr);
1017     } else {
1018         ctype_char_dtor(this);
1019         if(flags & 1)
1020             MSVCRT_operator_delete(this);
1021     }
1022
1023     return this;
1024 }
1025
1026 /* ?do_narrow@?$ctype@D@std@@MBEDDD@Z */
1027 /* ?do_narrow@?$ctype@D@std@@MEBADDD@Z */
1028 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow_ch, 12)
1029 #define call_ctype_char_do_narrow_ch(this, ch, unused) CALL_VTBL_FUNC(this, 32, \
1030         char, (const ctype_char*, char, char), (this, ch, unused))
1031 char __thiscall ctype_char_do_narrow_ch(const ctype_char *this, char ch, char unused)
1032 {
1033     TRACE("(%p %c %c)\n", this, ch, unused);
1034     return ch;
1035 }
1036
1037 /* ?do_narrow@?$ctype@D@std@@MBEPBDPBD0DPAD@Z */
1038 /* ?do_narrow@?$ctype@D@std@@MEBAPEBDPEBD0DPEAD@Z */
1039 DEFINE_THISCALL_WRAPPER(ctype_char_do_narrow, 20)
1040 #define call_ctype_char_do_narrow(this, first, last, unused, dest) CALL_VTBL_FUNC(this, 28, \
1041         const char*, (const ctype_char*, const char*, const char*, char, char*), \
1042         (this, first, last, unused, dest))
1043 const char* __thiscall ctype_char_do_narrow(const ctype_char *this,
1044         const char *first, const char *last, char unused, char *dest)
1045 {
1046     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1047     memcpy(dest, first, last-first);
1048     return last;
1049 }
1050
1051 /* ?narrow@?$ctype@D@std@@QBEDDD@Z */
1052 /* ?narrow@?$ctype@D@std@@QEBADDD@Z */
1053 DEFINE_THISCALL_WRAPPER(ctype_char_narrow_ch, 12)
1054 char __thiscall ctype_char_narrow_ch(const ctype_char *this, char ch, char dflt)
1055 {
1056     TRACE("(%p %c %c)\n", this, ch, dflt);
1057     return call_ctype_char_do_narrow_ch(this, ch, dflt);
1058 }
1059
1060 /* ?narrow@?$ctype@D@std@@QBEPBDPBD0DPAD@Z */
1061 /* ?narrow@?$ctype@D@std@@QEBAPEBDPEBD0DPEAD@Z */
1062 DEFINE_THISCALL_WRAPPER(ctype_char_narrow, 20)
1063 const char* __thiscall ctype_char_narrow(const ctype_char *this,
1064         const char *first, const char *last, char dflt, char *dest)
1065 {
1066     TRACE("(%p %p %p %c %p)\n", this, first, last, dflt, dest);
1067     return call_ctype_char_do_narrow(this, first, last, dflt, dest);
1068 }
1069
1070 /* ?do_widen@?$ctype@D@std@@MBEDD@Z */
1071 /* ?do_widen@?$ctype@D@std@@MEBADD@Z */
1072 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen_ch, 8)
1073 #define call_ctype_char_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1074         char, (const ctype_char*, char), (this, ch))
1075 char __thiscall ctype_char_do_widen_ch(const ctype_char *this, char ch)
1076 {
1077     TRACE("(%p %c)\n", this, ch);
1078     return ch;
1079 }
1080
1081 /* ?do_widen@?$ctype@D@std@@MBEPBDPBD0PAD@Z */
1082 /* ?do_widen@?$ctype@D@std@@MEBAPEBDPEBD0PEAD@Z */
1083 DEFINE_THISCALL_WRAPPER(ctype_char_do_widen, 16)
1084 #define call_ctype_char_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 20, \
1085         const char*, (const ctype_char*, const char*, const char*, char*), \
1086         (this, first, last, dest))
1087 const char* __thiscall ctype_char_do_widen(const ctype_char *this,
1088         const char *first, const char *last, char *dest)
1089 {
1090     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1091     memcpy(dest, first, last-first);
1092     return last;
1093 }
1094
1095 /* ?widen@?$ctype@D@std@@QBEDD@Z */
1096 /* ?widen@?$ctype@D@std@@QEBADD@Z */
1097 DEFINE_THISCALL_WRAPPER(ctype_char_widen_ch, 8)
1098 char __thiscall ctype_char_widen_ch(const ctype_char *this, char ch)
1099 {
1100     TRACE("(%p %c)\n", this, ch);
1101     return call_ctype_char_do_widen_ch(this, ch);
1102 }
1103
1104 /* ?widen@?$ctype@D@std@@QBEPBDPBD0PAD@Z */
1105 /* ?widen@?$ctype@D@std@@QEBAPEBDPEBD0PEAD@Z */
1106 DEFINE_THISCALL_WRAPPER(ctype_char_widen, 16)
1107 const char* __thiscall ctype_char_widen(const ctype_char *this,
1108         const char *first, const char *last, char *dest)
1109 {
1110     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1111     return call_ctype_char_do_widen(this, first, last, dest);
1112 }
1113
1114 /* ?_Getcat@?$ctype@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1115 /* ?_Getcat@?$ctype@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1116 MSVCP_size_t __cdecl ctype_char__Getcat(const locale_facet **facet, const locale *loc)
1117 {
1118     TRACE("(%p %p)\n", facet, loc);
1119
1120     if(facet && !*facet) {
1121         _Locinfo locinfo;
1122
1123         *facet = MSVCRT_operator_new(sizeof(ctype_char));
1124         if(!*facet) {
1125             ERR("Out of memory\n");
1126             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1127             return 0;
1128         }
1129
1130         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
1131         ctype_char_ctor_locinfo((ctype_char*)*facet, &locinfo, 0);
1132         _Locinfo_dtor(&locinfo);
1133     }
1134
1135     return LC_CTYPE;
1136 }
1137
1138 ctype_char* ctype_char_use_facet(const locale *loc)
1139 {
1140     static ctype_char *obj = NULL;
1141
1142     _Lockit lock;
1143     const locale_facet *fac;
1144
1145     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1146     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_char_id));
1147     if(fac) {
1148         _Lockit_dtor(&lock);
1149         return (ctype_char*)fac;
1150     }
1151
1152     if(obj) {
1153         _Lockit_dtor(&lock);
1154         return obj;
1155     }
1156
1157     ctype_char__Getcat(&fac, loc);
1158     obj = (ctype_char*)fac;
1159     locale_facet__Incref(&obj->base.facet);
1160     locale_facet_register(&obj->base.facet);
1161     _Lockit_dtor(&lock);
1162
1163     return obj;
1164 }
1165
1166 /* _Tolower */
1167 int __cdecl _Tolower(int ch, const _Ctypevec *ctype)
1168 {
1169     unsigned int cp;
1170
1171     TRACE("%d %p\n", ch, ctype);
1172
1173     if(ctype)
1174         cp = ctype->page;
1175     else
1176         cp = ___lc_codepage_func();
1177
1178     /* Don't convert to unicode in case of C locale */
1179     if(!cp) {
1180         if(ch>='A' && ch<='Z')
1181             ch = ch-'A'+'a';
1182         return ch;
1183     } else {
1184         WCHAR wide, lower;
1185         char str[2];
1186         int size;
1187
1188         if(ch > 255) {
1189             str[0] = (ch>>8) & 255;
1190             str[1] = ch & 255;
1191             size = 2;
1192         } else {
1193             str[0] = ch & 255;
1194             size = 1;
1195         }
1196
1197         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1198             return ch;
1199
1200         lower = tolowerW(wide);
1201         if(lower == wide)
1202             return ch;
1203
1204         WideCharToMultiByte(cp, 0, &lower, 1, str, 2, NULL, NULL);
1205
1206         return str[0] + (str[1]<<8);
1207     }
1208 }
1209
1210 /* ?do_tolower@?$ctype@D@std@@MBEDD@Z */
1211 /* ?do_tolower@?$ctype@D@std@@MEBADD@Z */
1212 #define call_ctype_char_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 8, \
1213         char, (const ctype_char*, char), (this, ch))
1214 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower_ch, 8)
1215 char __thiscall ctype_char_do_tolower_ch(const ctype_char *this, char ch)
1216 {
1217     TRACE("(%p %c)\n", this, ch);
1218     return _Tolower(ch, &this->ctype);
1219 }
1220
1221 /* ?do_tolower@?$ctype@D@std@@MBEPBDPADPBD@Z */
1222 /* ?do_tolower@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1223 #define call_ctype_char_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 4, \
1224         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1225 DEFINE_THISCALL_WRAPPER(ctype_char_do_tolower, 12)
1226 const char* __thiscall ctype_char_do_tolower(const ctype_char *this, char *first, const char *last)
1227 {
1228     TRACE("(%p %p %p)\n", this, first, last);
1229     for(; first<last; first++)
1230         *first = _Tolower(*first, &this->ctype);
1231     return last;
1232 }
1233
1234 /* ?tolower@?$ctype@D@std@@QBEDD@Z */
1235 /* ?tolower@?$ctype@D@std@@QEBADD@Z */
1236 DEFINE_THISCALL_WRAPPER(ctype_char_tolower_ch, 8)
1237 char __thiscall ctype_char_tolower_ch(const ctype_char *this, char ch)
1238 {
1239     TRACE("(%p %c)\n", this, ch);
1240     return call_ctype_char_do_tolower_ch(this, ch);
1241 }
1242
1243 /* ?tolower@?$ctype@D@std@@QBEPBDPADPBD@Z */
1244 /* ?tolower@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1245 DEFINE_THISCALL_WRAPPER(ctype_char_tolower, 12)
1246 const char* __thiscall ctype_char_tolower(const ctype_char *this, char *first, const char *last)
1247 {
1248     TRACE("(%p %p %p)\n", this, first, last);
1249     return call_ctype_char_do_tolower(this, first, last);
1250 }
1251
1252 /* _Toupper */
1253 int __cdecl _Toupper(int ch, const _Ctypevec *ctype)
1254 {
1255     unsigned int cp;
1256
1257     TRACE("%d %p\n", ch, ctype);
1258
1259     if(ctype)
1260         cp = ctype->page;
1261     else
1262         cp = ___lc_codepage_func();
1263
1264     /* Don't convert to unicode in case of C locale */
1265     if(!cp) {
1266         if(ch>='a' && ch<='z')
1267             ch = ch-'a'+'A';
1268         return ch;
1269     } else {
1270         WCHAR wide, upper;
1271         char str[2];
1272         int size;
1273
1274         if(ch > 255) {
1275             str[0] = (ch>>8) & 255;
1276             str[1] = ch & 255;
1277             size = 2;
1278         } else {
1279             str[0] = ch & 255;
1280             size = 1;
1281         }
1282
1283         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, str, size, &wide, 1))
1284             return ch;
1285
1286         upper = toupperW(wide);
1287         if(upper == wide)
1288             return ch;
1289
1290         WideCharToMultiByte(cp, 0, &upper, 1, str, 2, NULL, NULL);
1291
1292         return str[0] + (str[1]<<8);
1293     }
1294 }
1295
1296 /* ?do_toupper@?$ctype@D@std@@MBEDD@Z */
1297 /* ?do_toupper@?$ctype@D@std@@MEBADD@Z */
1298 #define call_ctype_char_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 16, \
1299         char, (const ctype_char*, char), (this, ch))
1300 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper_ch, 8)
1301 char __thiscall ctype_char_do_toupper_ch(const ctype_char *this, char ch)
1302 {
1303     TRACE("(%p %c)\n", this, ch);
1304     return _Toupper(ch, &this->ctype);
1305 }
1306
1307 /* ?do_toupper@?$ctype@D@std@@MBEPBDPADPBD@Z */
1308 /* ?do_toupper@?$ctype@D@std@@MEBAPEBDPEADPEBD@Z */
1309 #define call_ctype_char_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 12, \
1310         const char*, (const ctype_char*, char*, const char*), (this, first, last))
1311 DEFINE_THISCALL_WRAPPER(ctype_char_do_toupper, 12)
1312 const char* __thiscall ctype_char_do_toupper(const ctype_char *this,
1313         char *first, const char *last)
1314 {
1315     TRACE("(%p %p %p)\n", this, first, last);
1316     for(; first<last; first++)
1317         *first = _Toupper(*first, &this->ctype);
1318     return last;
1319 }
1320
1321 /* ?toupper@?$ctype@D@std@@QBEDD@Z */
1322 /* ?toupper@?$ctype@D@std@@QEBADD@Z */
1323 DEFINE_THISCALL_WRAPPER(ctype_char_toupper_ch, 8)
1324 char __thiscall ctype_char_toupper_ch(const ctype_char *this, char ch)
1325 {
1326     TRACE("(%p %c)\n", this, ch);
1327     return call_ctype_char_do_toupper_ch(this, ch);
1328 }
1329
1330 /* ?toupper@?$ctype@D@std@@QBEPBDPADPBD@Z */
1331 /* ?toupper@?$ctype@D@std@@QEBAPEBDPEADPEBD@Z */
1332 DEFINE_THISCALL_WRAPPER(ctype_char_toupper, 12)
1333 const char* __thiscall ctype_char_toupper(const ctype_char *this, char *first, const char *last)
1334 {
1335     TRACE("(%p %p %p)\n", this, first, last);
1336     return call_ctype_char_do_toupper(this, first, last);
1337 }
1338
1339 /* ?is@?$ctype@D@std@@QBE_NFD@Z */
1340 /* ?is@?$ctype@D@std@@QEBA_NFD@Z */
1341 DEFINE_THISCALL_WRAPPER(ctype_char_is_ch, 12)
1342 MSVCP_bool __thiscall ctype_char_is_ch(const ctype_char *this, short mask, char ch)
1343 {
1344     TRACE("(%p %x %c)\n", this, mask, ch);
1345     return (this->ctype.table[(unsigned char)ch] & mask) != 0;
1346 }
1347
1348 /* ?is@?$ctype@D@std@@QBEPBDPBD0PAF@Z */
1349 /* ?is@?$ctype@D@std@@QEBAPEBDPEBD0PEAF@Z */
1350 DEFINE_THISCALL_WRAPPER(ctype_char_is, 16)
1351 const char* __thiscall ctype_char_is(const ctype_char *this, const char *first, const char *last, short *dest)
1352 {
1353     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1354     for(; first<last; first++)
1355         *dest++ = this->ctype.table[(unsigned char)*first];
1356     return last;
1357 }
1358
1359 /* ?scan_is@?$ctype@D@std@@QBEPBDFPBD0@Z */
1360 /* ?scan_is@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1361 DEFINE_THISCALL_WRAPPER(ctype_char_scan_is, 16)
1362 const char* __thiscall ctype_char_scan_is(const ctype_char *this, short mask, const char *first, const char *last)
1363 {
1364     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1365     for(; first<last; first++)
1366         if(!ctype_char_is_ch(this, mask, *first))
1367             break;
1368     return first;
1369 }
1370
1371 /* ?scan_not@?$ctype@D@std@@QBEPBDFPBD0@Z */
1372 /* ?scan_not@?$ctype@D@std@@QEBAPEBDFPEBD0@Z */
1373 DEFINE_THISCALL_WRAPPER(ctype_char_scan_not, 16)
1374 const char* __thiscall ctype_char_scan_not(const ctype_char *this, short mask, const char *first, const char *last)
1375 {
1376     TRACE("(%p %x %p %p)\n", this, mask, first, last);
1377     for(; first<last; first++)
1378         if(ctype_char_is_ch(this, mask, *first))
1379             break;
1380     return first;
1381 }
1382
1383 /* ?id@?$ctype@_W@std@@2V0locale@2@A */
1384 locale_id ctype_wchar_id = {0};
1385 /* ?id@?$ctype@G@std@@2V0locale@2@A */
1386 locale_id ctype_short_id = {0};
1387
1388 /* ??_7?$ctype@_W@std@@6B@ */
1389 extern const vtable_ptr MSVCP_ctype_wchar_vtable;
1390 /* ??_7?$ctype@G@std@@6B@ */
1391 extern const vtable_ptr MSVCP_ctype_short_vtable;
1392
1393 /* ?_Init@?$ctype@_W@std@@IAEXABV_Locinfo@2@@Z */
1394 /* ?_Init@?$ctype@_W@std@@IEAAXAEBV_Locinfo@2@@Z */
1395 /* ?_Init@?$ctype@G@std@@IAEXABV_Locinfo@2@@Z */
1396 /* ?_Init@?$ctype@G@std@@IEAAXAEBV_Locinfo@2@@Z */
1397 DEFINE_THISCALL_WRAPPER(ctype_wchar__Init, 8)
1398 void __thiscall ctype_wchar__Init(ctype_wchar *this, const _Locinfo *locinfo)
1399 {
1400     TRACE("(%p %p)\n", this, locinfo);
1401     _Locinfo__Getctype(locinfo, &this->ctype);
1402     _Locinfo__Getcvt(locinfo, &this->cvt);
1403 }
1404
1405 /* ??0?$ctype@_W@std@@QAE@ABV_Locinfo@1@I@Z */
1406 /* ??0?$ctype@_W@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1407 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_locinfo, 12)
1408 ctype_wchar* __thiscall ctype_wchar_ctor_locinfo(ctype_wchar *this,
1409         const _Locinfo *locinfo, MSVCP_size_t refs)
1410 {
1411     TRACE("(%p %p %lu)\n", this, locinfo, refs);
1412     ctype_base_ctor_refs(&this->base, refs);
1413     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1414     ctype_wchar__Init(this, locinfo);
1415     return this;
1416 }
1417
1418 /* ??0?$ctype@G@std@@QAE@ABV_Locinfo@1@I@Z */
1419 /* ??0?$ctype@G@std@@QEAA@AEBV_Locinfo@1@_K@Z */
1420 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_locinfo, 12)
1421 ctype_wchar* __thiscall ctype_short_ctor_locinfo(ctype_wchar *this,
1422         const _Locinfo *locinfo, MSVCP_size_t refs)
1423 {
1424     ctype_wchar *ret = ctype_wchar_ctor_locinfo(this, locinfo, refs);
1425     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1426     return ret;
1427 }
1428
1429 /* ??0?$ctype@_W@std@@QAE@I@Z */
1430 /* ??0?$ctype@_W@std@@QEAA@_K@Z */
1431 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor_refs, 8)
1432 ctype_wchar* __thiscall ctype_wchar_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1433 {
1434     _Locinfo locinfo;
1435
1436     TRACE("(%p %lu)\n", this, refs);
1437
1438     ctype_base_ctor_refs(&this->base, refs);
1439     this->base.facet.vtable = &MSVCP_ctype_wchar_vtable;
1440
1441     _Locinfo_ctor(&locinfo);
1442     ctype_wchar__Init(this, &locinfo);
1443     _Locinfo_dtor(&locinfo);
1444     return this;
1445 }
1446
1447 /* ??0?$ctype@G@std@@QAE@I@Z */
1448 /* ??0?$ctype@G@std@@QEAA@_K@Z */
1449 DEFINE_THISCALL_WRAPPER(ctype_short_ctor_refs, 8)
1450 ctype_wchar* __thiscall ctype_short_ctor_refs(ctype_wchar *this, MSVCP_size_t refs)
1451 {
1452     ctype_wchar *ret = ctype_wchar_ctor_refs(this, refs);
1453     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1454     return ret;
1455 }
1456
1457 /* ??_F?$ctype@_W@std@@QAEXXZ */
1458 /* ??_F?$ctype@_W@std@@QEAAXXZ */
1459 DEFINE_THISCALL_WRAPPER(ctype_wchar_ctor, 4)
1460 ctype_wchar* __thiscall ctype_wchar_ctor(ctype_wchar *this)
1461 {
1462     TRACE("(%p)\n", this);
1463     return ctype_short_ctor_refs(this, 0);
1464 }
1465
1466 /* ??_F?$ctype@G@std@@QAEXXZ */
1467 /* ??_F?$ctype@G@std@@QEAAXXZ */
1468 DEFINE_THISCALL_WRAPPER(ctype_short_ctor, 4)
1469 ctype_wchar* __thiscall ctype_short_ctor(ctype_wchar *this)
1470 {
1471     ctype_wchar *ret = ctype_wchar_ctor(this);
1472     this->base.facet.vtable = &MSVCP_ctype_short_vtable;
1473     return ret;
1474 }
1475
1476 /* ??1?$ctype@_W@std@@MAE@XZ */
1477 /* ??1?$ctype@_W@std@@MEAA@XZ */
1478 /* ??1?$ctype@G@std@@MAE@XZ */
1479 /* ??1?$ctype@G@std@@MEAA@XZ */
1480 DEFINE_THISCALL_WRAPPER(ctype_wchar_dtor, 4)
1481 void __thiscall ctype_wchar_dtor(ctype_wchar *this)
1482 {
1483     TRACE("(%p)\n", this);
1484     if(this->ctype.delfl)
1485         free((void*)this->ctype.table);
1486 }
1487
1488 DEFINE_THISCALL_WRAPPER(ctype_wchar_vector_dtor, 8)
1489 ctype_wchar* __thiscall ctype_wchar_vector_dtor(ctype_wchar *this, unsigned int flags)
1490 {
1491     TRACE("(%p %x)\n", this, flags);
1492     if(flags & 2) {
1493         /* we have an array, with the number of elements stored before the first object */
1494         INT_PTR i, *ptr = (INT_PTR *)this-1;
1495
1496         for(i=*ptr-1; i>=0; i--)
1497             ctype_wchar_dtor(this+i);
1498         MSVCRT_operator_delete(ptr);
1499     } else {
1500         ctype_wchar_dtor(this);
1501         if(flags & 1)
1502             MSVCRT_operator_delete(this);
1503     }
1504
1505     return this;
1506 }
1507
1508 /* _Wcrtomb */
1509 int __cdecl _Wcrtomb(char *s, wchar_t wch, int *state, const _Cvtvec *cvt)
1510 {
1511     int cp, size;
1512     BOOL def;
1513
1514     TRACE("%p %d %p %p\n", s, wch, state, cvt);
1515
1516     if(cvt)
1517         cp = cvt->page;
1518     else
1519         cp = ___lc_codepage_func();
1520
1521     if(!cp) {
1522         if(wch > 255) {
1523            *_errno() = EILSEQ;
1524            return -1;
1525         }
1526
1527         *s = wch & 255;
1528         return 1;
1529     }
1530
1531     size = WideCharToMultiByte(cp, 0, &wch, 1, s, MB_LEN_MAX, NULL, &def);
1532     if(!size || def) {
1533         *_errno() = EILSEQ;
1534         return -1;
1535     }
1536
1537     return size;
1538 }
1539
1540 /* ?_Donarrow@?$ctype@_W@std@@IBED_WD@Z */
1541 /* ?_Donarrow@?$ctype@_W@std@@IEBAD_WD@Z */
1542 /* ?_Donarrow@?$ctype@G@std@@IBEDGD@Z */
1543 /* ?_Donarrow@?$ctype@G@std@@IEBADGD@Z */
1544 DEFINE_THISCALL_WRAPPER(ctype_wchar__Donarrow, 12)
1545 char __thiscall ctype_wchar__Donarrow(const ctype_wchar *this, wchar_t ch, char dflt)
1546 {
1547     char buf[MB_LEN_MAX];
1548
1549     TRACE("(%p %d %d)\n", this, ch, dflt);
1550
1551     return _Wcrtomb(buf, ch, NULL, &this->cvt)==1 ? buf[0] : dflt;
1552 }
1553
1554 /* ?do_narrow@?$ctype@_W@std@@MBED_WD@Z */
1555 /* ?do_narrow@?$ctype@_W@std@@MEBAD_WD@Z */
1556 /* ?do_narrow@?$ctype@G@std@@MBEDGD@Z */
1557 /* ?do_narrow@?$ctype@G@std@@MEBADGD@Z */
1558 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow_ch, 12)
1559 #define call_ctype_wchar_do_narrow_ch(this, ch, dflt) CALL_VTBL_FUNC(this, 48, \
1560         char, (const ctype_wchar*, wchar_t, char), (this, ch, dflt))
1561 char __thiscall ctype_wchar_do_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1562 {
1563     return ctype_wchar__Donarrow(this, ch, dflt);
1564 }
1565
1566 /* ?do_narrow@?$ctype@_W@std@@MBEPB_WPB_W0DPAD@Z */
1567 /* ?do_narrow@?$ctype@_W@std@@MEBAPEB_WPEB_W0DPEAD@Z */
1568 /* ?do_narrow@?$ctype@G@std@@MBEPBGPBG0DPAD@Z */
1569 /* ?do_narrow@?$ctype@G@std@@MEBAPEBGPEBG0DPEAD@Z */
1570 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_narrow, 20)
1571 #define call_ctype_wchar_do_narrow(this, first, last, dflt, dest) CALL_VTBL_FUNC(this, 44, \
1572         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, char, char*), \
1573         (this, first, last, dflt, dest))
1574 const wchar_t* __thiscall ctype_wchar_do_narrow(const ctype_wchar *this,
1575         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1576 {
1577     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1578     for(; first<last; first++)
1579         *dest++ = ctype_wchar__Donarrow(this, *first, dflt);
1580     return last;
1581 }
1582
1583 /* ?narrow@?$ctype@_W@std@@QBED_WD@Z */
1584 /* ?narrow@?$ctype@_W@std@@QEBAD_WD@Z */
1585 /* ?narrow@?$ctype@G@std@@QBEDGD@Z */
1586 /* ?narrow@?$ctype@G@std@@QEBADGD@Z */
1587 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow_ch, 12)
1588 char __thiscall ctype_wchar_narrow_ch(const ctype_wchar *this, wchar_t ch, char dflt)
1589 {
1590     TRACE("(%p %d %d)\n", this, ch, dflt);
1591     return call_ctype_wchar_do_narrow_ch(this, ch, dflt);
1592 }
1593
1594 /* ?narrow@?$ctype@_W@std@@QBEPB_WPB_W0DPAD@Z */
1595 /* ?narrow@?$ctype@_W@std@@QEBAPEB_WPEB_W0DPEAD@Z */
1596 /* ?narrow@?$ctype@G@std@@QBEPBGPBG0DPAD@Z */
1597 /* ?narrow@?$ctype@G@std@@QEBAPEBGPEBG0DPEAD@Z */
1598 DEFINE_THISCALL_WRAPPER(ctype_wchar_narrow, 20)
1599 const wchar_t* __thiscall ctype_wchar_narrow(const ctype_wchar *this,
1600         const wchar_t *first, const wchar_t *last, char dflt, char *dest)
1601 {
1602     TRACE("(%p %p %p %d %p)\n", this, first, last, dflt, dest);
1603     return call_ctype_wchar_do_narrow(this, first, last, dflt, dest);
1604 }
1605
1606 /* _Mbrtowc */
1607 int __cdecl _Mbrtowc(wchar_t *out, const char *in, MSVCP_size_t len, int *state, const _Cvtvec *cvt)
1608 {
1609     int i, cp;
1610     CPINFO cp_info;
1611     BOOL is_lead;
1612
1613     TRACE("(%p %p %lu %p %p)\n", out, in, len, state, cvt);
1614
1615     if(!len)
1616         return 0;
1617
1618     if(cvt)
1619         cp = cvt->page;
1620     else
1621         cp = ___lc_codepage_func();
1622
1623     if(!cp) {
1624         if(out)
1625             *out = (unsigned char)*in;
1626
1627         *state = 0;
1628         return *in ? 1 : 0;
1629     }
1630
1631     if(*state) {
1632         ((char*)state)[1] = *in;
1633
1634         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, (char*)state, 2, out, out ? 1 : 0)) {
1635             *state = 0;
1636             *_errno() = EILSEQ;
1637             return -1;
1638         }
1639
1640         *state = 0;
1641         return 2;
1642     }
1643
1644     GetCPInfo(cp, &cp_info);
1645     is_lead = FALSE;
1646     for(i=0; i<MAX_LEADBYTES; i+=2) {
1647         if(!cp_info.LeadByte[i+1])
1648             break;
1649         if((unsigned char)*in>=cp_info.LeadByte[i] && (unsigned char)*in<=cp_info.LeadByte[i+1]) {
1650             is_lead = TRUE;
1651             break;
1652         }
1653     }
1654
1655     if(is_lead) {
1656         if(len == 1) {
1657             *state = (unsigned char)*in;
1658             return -2;
1659         }
1660
1661         if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 2, out, out ? 1 : 0)) {
1662             *_errno() = EILSEQ;
1663             return -1;
1664         }
1665         return 2;
1666     }
1667
1668     if(!MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, in, 1, out, out ? 1 : 0)) {
1669         *_errno() = EILSEQ;
1670         return -1;
1671     }
1672     return 1;
1673 }
1674
1675 /* ?_Dowiden@?$ctype@_W@std@@IBE_WD@Z */
1676 /* ?_Dowiden@?$ctype@_W@std@@IEBA_WD@Z */
1677 /* ?_Dowiden@?$ctype@G@std@@IBEGD@Z */
1678 /* ?_Dowiden@?$ctype@G@std@@IEBAGD@Z */
1679 DEFINE_THISCALL_WRAPPER(ctype_wchar__Dowiden, 8)
1680 wchar_t __thiscall ctype_wchar__Dowiden(const ctype_wchar *this, char ch)
1681 {
1682     wchar_t ret;
1683     int state = 0;
1684     TRACE("(%p %d)\n", this, ch);
1685     return _Mbrtowc(&ret, &ch, 1, &state, &this->cvt)<0 ? WEOF : ret;
1686 }
1687
1688 /* ?do_widen@?$ctype@_W@std@@MBE_WD@Z */
1689 /* ?do_widen@?$ctype@_W@std@@MEBA_WD@Z */
1690 /* ?do_widen@?$ctype@G@std@@MBEGD@Z */
1691 /* ?do_widen@?$ctype@G@std@@MEBAGD@Z */
1692 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen_ch, 8)
1693 #define call_ctype_wchar_do_widen_ch(this, ch) CALL_VTBL_FUNC(this, 40, \
1694         wchar_t, (const ctype_wchar*, char), (this, ch))
1695 wchar_t __thiscall ctype_wchar_do_widen_ch(const ctype_wchar *this, char ch)
1696 {
1697     return ctype_wchar__Dowiden(this, ch);
1698 }
1699
1700 /* ?do_widen@?$ctype@_W@std@@MBEPBDPBD0PA_W@Z */
1701 /* ?do_widen@?$ctype@_W@std@@MEBAPEBDPEBD0PEA_W@Z */
1702 /* ?do_widen@?$ctype@G@std@@MBEPBDPBD0PAG@Z */
1703 /* ?do_widen@?$ctype@G@std@@MEBAPEBDPEBD0PEAG@Z */
1704 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_widen, 16)
1705 #define call_ctype_wchar_do_widen(this, first, last, dest) CALL_VTBL_FUNC(this, 36, \
1706         const char*, (const ctype_wchar*, const char*, const char*, wchar_t*), \
1707         (this, first, last, dest))
1708 const char* __thiscall ctype_wchar_do_widen(const ctype_wchar *this,
1709         const char *first, const char *last, wchar_t *dest)
1710 {
1711     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1712     for(; first<last; first++)
1713         *dest++ = ctype_wchar__Dowiden(this, *first);
1714     return last;
1715 }
1716
1717 /* ?widen@?$ctype@_W@std@@QBE_WD@Z */
1718 /* ?widen@?$ctype@_W@std@@QEBA_WD@Z */
1719 /* ?widen@?$ctype@G@std@@QBEGD@Z */
1720 /* ?widen@?$ctype@G@std@@QEBAGD@Z */
1721 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen_ch, 8)
1722 wchar_t __thiscall ctype_wchar_widen_ch(const ctype_wchar *this, char ch)
1723 {
1724     TRACE("(%p %d)\n", this, ch);
1725     return call_ctype_wchar_do_widen_ch(this, ch);
1726 }
1727
1728 /* ?widen@?$ctype@_W@std@@QBEPBDPBD0PA_W@Z */
1729 /* ?widen@?$ctype@_W@std@@QEBAPEBDPEBD0PEA_W@Z */
1730 /* ?widen@?$ctype@G@std@@QBEPBDPBD0PAG@Z */
1731 /* ?widen@?$ctype@G@std@@QEBAPEBDPEBD0PEAG@Z */
1732 DEFINE_THISCALL_WRAPPER(ctype_wchar_widen, 16)
1733 const char* __thiscall ctype_wchar_widen(const ctype_wchar *this,
1734         const char *first, const char *last, wchar_t *dest)
1735 {
1736     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1737     return call_ctype_wchar_do_widen(this, first, last, dest);
1738 }
1739
1740 /* ?_Getcat@?$ctype@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1741 /* ?_Getcat@?$ctype@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1742 MSVCP_size_t __cdecl ctype_wchar__Getcat(const locale_facet **facet, const locale *loc)
1743 {
1744     TRACE("(%p %p)\n", facet, loc);
1745
1746     if(facet && !*facet) {
1747         _Locinfo locinfo;
1748
1749         *facet = MSVCRT_operator_new(sizeof(ctype_wchar));
1750         if(!*facet) {
1751             ERR("Out of memory\n");
1752             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
1753             return 0;
1754         }
1755
1756         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
1757         ctype_wchar_ctor_locinfo((ctype_wchar*)*facet, &locinfo, 0);
1758         _Locinfo_dtor(&locinfo);
1759     }
1760
1761     return LC_CTYPE;
1762 }
1763
1764 /* ?_Getcat@?$ctype@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
1765 /* ?_Getcat@?$ctype@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
1766 MSVCP_size_t __cdecl ctype_short__Getcat(const locale_facet **facet, const locale *loc)
1767 {
1768     if(facet && !*facet) {
1769         ctype_wchar__Getcat(facet, loc);
1770         (*(locale_facet**)facet)->vtable = &MSVCP_ctype_short_vtable;
1771     }
1772
1773     return LC_CTYPE;
1774 }
1775
1776 /* _Towlower */
1777 wchar_t __cdecl _Towlower(wchar_t ch, const _Ctypevec *ctype)
1778 {
1779     TRACE("(%d %p)\n", ch, ctype);
1780     return tolowerW(ch);
1781 }
1782
1783 ctype_wchar* ctype_wchar_use_facet(const locale *loc)
1784 {
1785     static ctype_wchar *obj = NULL;
1786
1787     _Lockit lock;
1788     const locale_facet *fac;
1789
1790     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1791     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_wchar_id));
1792     if(fac) {
1793         _Lockit_dtor(&lock);
1794         return (ctype_wchar*)fac;
1795     }
1796
1797     if(obj) {
1798         _Lockit_dtor(&lock);
1799         return obj;
1800     }
1801
1802     ctype_wchar__Getcat(&fac, loc);
1803     obj = (ctype_wchar*)fac;
1804     locale_facet__Incref(&obj->base.facet);
1805     locale_facet_register(&obj->base.facet);
1806     _Lockit_dtor(&lock);
1807
1808     return obj;
1809 }
1810
1811 static ctype_wchar* ctype_short_use_facet(const locale *loc)
1812 {
1813     static ctype_wchar *obj = NULL;
1814
1815     _Lockit lock;
1816     const locale_facet *fac;
1817
1818     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
1819     fac = locale__Getfacet(loc, locale_id_operator_size_t(&ctype_short_id));
1820     if(fac) {
1821         _Lockit_dtor(&lock);
1822         return (ctype_wchar*)fac;
1823     }
1824
1825     if(obj) {
1826         _Lockit_dtor(&lock);
1827         return obj;
1828     }
1829
1830     ctype_short__Getcat(&fac, loc);
1831     obj = (ctype_wchar*)fac;
1832     locale_facet__Incref(&obj->base.facet);
1833     locale_facet_register(&obj->base.facet);
1834     _Lockit_dtor(&lock);
1835
1836     return obj;
1837 }
1838
1839 /* ?do_tolower@?$ctype@_W@std@@MBE_W_W@Z */
1840 /* ?do_tolower@?$ctype@_W@std@@MEBA_W_W@Z */
1841 /* ?do_tolower@?$ctype@G@std@@MBEGG@Z */
1842 /* ?do_tolower@?$ctype@G@std@@MEBAGG@Z */
1843 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower_ch, 8)
1844 #define call_ctype_wchar_do_tolower_ch(this, ch) CALL_VTBL_FUNC(this, 24, \
1845         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
1846 wchar_t __thiscall ctype_wchar_do_tolower_ch(const ctype_wchar *this, wchar_t ch)
1847 {
1848     return _Towlower(ch, &this->ctype);
1849 }
1850
1851 /* ?do_tolower@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
1852 /* ?do_tolower@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
1853 /* ?do_tolower@?$ctype@G@std@@MBEPBGPAGPBG@Z */
1854 /* ?do_tolower@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
1855 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_tolower, 12)
1856 #define call_ctype_wchar_do_tolower(this, first, last) CALL_VTBL_FUNC(this, 20, \
1857         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
1858         (this, first, last))
1859 const wchar_t* __thiscall ctype_wchar_do_tolower(const ctype_wchar *this,
1860         wchar_t *first, const wchar_t *last)
1861 {
1862     TRACE("(%p %p %p)\n", this, first, last);
1863     for(; first<last; first++)
1864         *first = _Towlower(*first, &this->ctype);
1865     return last;
1866 }
1867
1868 /* ?tolower@?$ctype@_W@std@@QBE_W_W@Z */
1869 /* ?tolower@?$ctype@_W@std@@QEBA_W_W@Z */
1870 /* ?tolower@?$ctype@G@std@@QBEGG@Z */
1871 /* ?tolower@?$ctype@G@std@@QEBAGG@Z */
1872 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower_ch, 8)
1873 wchar_t __thiscall ctype_wchar_tolower_ch(const ctype_wchar *this, wchar_t ch)
1874 {
1875     TRACE("(%p %d)\n", this, ch);
1876     return call_ctype_wchar_do_tolower_ch(this, ch);
1877 }
1878
1879 /* ?tolower@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
1880 /* ?tolower@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
1881 /* ?tolower@?$ctype@G@std@@QBEPBGPAGPBG@Z */
1882 /* ?tolower@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
1883 DEFINE_THISCALL_WRAPPER(ctype_wchar_tolower, 12)
1884 const wchar_t* __thiscall ctype_wchar_tolower(const ctype_wchar *this,
1885         wchar_t *first, const wchar_t *last)
1886 {
1887     TRACE("(%p %p %p)\n", this, first, last);
1888     return call_ctype_wchar_do_tolower(this, first, last);
1889 }
1890
1891 /* _Towupper */
1892 wchar_t __cdecl _Towupper(wchar_t ch, const _Ctypevec *ctype)
1893 {
1894     TRACE("(%d %p)\n", ch, ctype);
1895     return toupperW(ch);
1896 }
1897
1898 /* ?do_toupper@?$ctype@_W@std@@MBE_W_W@Z */
1899 /* ?do_toupper@?$ctype@_W@std@@MEBA_W_W@Z */
1900 /* ?do_toupper@?$ctype@G@std@@MBEGG@Z */
1901 /* ?do_toupper@?$ctype@G@std@@MEBAGG@Z */
1902 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper_ch, 8)
1903 #define call_ctype_wchar_do_toupper_ch(this, ch) CALL_VTBL_FUNC(this, 32, \
1904         wchar_t, (const ctype_wchar*, wchar_t), (this, ch))
1905 wchar_t __thiscall ctype_wchar_do_toupper_ch(const ctype_wchar *this, wchar_t ch)
1906 {
1907     return _Towupper(ch, &this->ctype);
1908 }
1909
1910 /* ?do_toupper@?$ctype@_W@std@@MBEPB_WPA_WPB_W@Z */
1911 /* ?do_toupper@?$ctype@_W@std@@MEBAPEB_WPEA_WPEB_W@Z */
1912 /* ?do_toupper@?$ctype@G@std@@MBEPBGPAGPBG@Z */
1913 /* ?do_toupper@?$ctype@G@std@@MEBAPEBGPEAGPEBG@Z */
1914 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_toupper, 12)
1915 #define call_ctype_wchar_do_toupper(this, first, last) CALL_VTBL_FUNC(this, 28, \
1916         const wchar_t*, (const ctype_wchar*, wchar_t*, const wchar_t*), \
1917         (this, first, last))
1918 const wchar_t* __thiscall ctype_wchar_do_toupper(const ctype_wchar *this,
1919         wchar_t *first, const wchar_t *last)
1920 {
1921     TRACE("(%p %p %p)\n", this, first, last);
1922     for(; first<last; first++)
1923         *first = _Towupper(*first, &this->ctype);
1924     return last;
1925 }
1926
1927 /* ?toupper@?$ctype@_W@std@@QBE_W_W@Z */
1928 /* ?toupper@?$ctype@_W@std@@QEBA_W_W@Z */
1929 /* ?toupper@?$ctype@G@std@@QBEGG@Z */
1930 /* ?toupper@?$ctype@G@std@@QEBAGG@Z */
1931 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper_ch, 8)
1932 wchar_t __thiscall ctype_wchar_toupper_ch(const ctype_wchar *this, wchar_t ch)
1933 {
1934     TRACE("(%p %d)\n", this, ch);
1935     return call_ctype_wchar_do_toupper_ch(this, ch);
1936 }
1937
1938 /* ?toupper@?$ctype@_W@std@@QBEPB_WPA_WPB_W@Z */
1939 /* ?toupper@?$ctype@_W@std@@QEBAPEB_WPEA_WPEB_W@Z */
1940 /* ?toupper@?$ctype@G@std@@QBEPBGPAGPBG@Z */
1941 /* ?toupper@?$ctype@G@std@@QEBAPEBGPEAGPEBG@Z */
1942 DEFINE_THISCALL_WRAPPER(ctype_wchar_toupper, 12)
1943 const wchar_t* __thiscall ctype_wchar_toupper(const ctype_wchar *this,
1944         wchar_t *first, const wchar_t *last)
1945 {
1946     TRACE("(%p %p %p)\n", this, first, last);
1947     return call_ctype_wchar_do_toupper(this, first, last);
1948 }
1949
1950 /* _Getwctypes */
1951 const wchar_t* __cdecl _Getwctypes(const wchar_t *first, const wchar_t *last,
1952         short *mask, const _Ctypevec *ctype)
1953 {
1954     TRACE("(%p %p %p %p)\n", first, last, mask, ctype);
1955     GetStringTypeW(CT_CTYPE1, first, last-first, (WORD*)mask);
1956     return last;
1957 }
1958
1959 /* _Getwctype */
1960 short __cdecl _Getwctype(wchar_t ch, const _Ctypevec *ctype)
1961 {
1962     short mask = 0;
1963     _Getwctypes(&ch, &ch+1, &mask, ctype);
1964     return mask;
1965 }
1966
1967 /* ?do_is@?$ctype@_W@std@@MBE_NF_W@Z */
1968 /* ?do_is@?$ctype@_W@std@@MEBA_NF_W@Z */
1969 /* ?do_is@?$ctype@G@std@@MBE_NFG@Z */
1970 /* ?do_is@?$ctype@G@std@@MEBA_NFG@Z */
1971 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is_ch, 12)
1972 #define call_ctype_wchar_do_is_ch(this, mask, ch) CALL_VTBL_FUNC(this, 8, \
1973         MSVCP_bool, (const ctype_wchar*, short, wchar_t), (this, mask, ch))
1974 MSVCP_bool __thiscall ctype_wchar_do_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
1975 {
1976     TRACE("(%p %x %d)\n", this, mask, ch);
1977     return (_Getwctype(ch, &this->ctype) & mask) != 0;
1978 }
1979
1980 /* ?do_is@?$ctype@_W@std@@MBEPB_WPB_W0PAF@Z */
1981 /* ?do_is@?$ctype@_W@std@@MEBAPEB_WPEB_W0PEAF@Z */
1982 /* ?do_is@?$ctype@G@std@@MBEPBGPBG0PAF@Z */
1983 /* ?do_is@?$ctype@G@std@@MEBAPEBGPEBG0PEAF@Z */
1984 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_is, 16)
1985 #define call_ctype_wchar_do_is(this, first, last, dest) CALL_VTBL_FUNC(this, 4, \
1986         const wchar_t*, (const ctype_wchar*, const wchar_t*, const wchar_t*, short*), \
1987         (this, first, last, dest))
1988 const wchar_t* __thiscall ctype_wchar_do_is(const ctype_wchar *this,
1989         const wchar_t *first, const wchar_t *last, short *dest)
1990 {
1991     TRACE("(%p %p %p %p)\n", this, first, last, dest);
1992     return _Getwctypes(first, last, dest, &this->ctype);
1993 }
1994
1995 /* ?is@?$ctype@_W@std@@QBE_NF_W@Z */
1996 /* ?is@?$ctype@_W@std@@QEBA_NF_W@Z */
1997 /* ?is@?$ctype@G@std@@QBE_NFG@Z */
1998 /* ?is@?$ctype@G@std@@QEBA_NFG@Z */
1999 DEFINE_THISCALL_WRAPPER(ctype_wchar_is_ch, 12)
2000 MSVCP_bool __thiscall ctype_wchar_is_ch(const ctype_wchar *this, short mask, wchar_t ch)
2001 {
2002     TRACE("(%p %x %d)\n", this, mask, ch);
2003     return call_ctype_wchar_do_is_ch(this, mask, ch);
2004 }
2005
2006 /* ?is@?$ctype@_W@std@@QBEPB_WPB_W0PAF@Z */
2007 /* ?is@?$ctype@_W@std@@QEBAPEB_WPEB_W0PEAF@Z */
2008 /* ?is@?$ctype@G@std@@QBEPBGPBG0PAF@Z */
2009 /* ?is@?$ctype@G@std@@QEBAPEBGPEBG0PEAF@Z */
2010 DEFINE_THISCALL_WRAPPER(ctype_wchar_is, 16)
2011 const wchar_t* __thiscall ctype_wchar_is(const ctype_wchar *this,
2012         const wchar_t *first, const wchar_t *last, short *dest)
2013 {
2014     TRACE("(%p %p %p %p)\n", this, first, last, dest);
2015     return call_ctype_wchar_do_is(this, first, last, dest);
2016 }
2017
2018 /* ?do_scan_is@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2019 /* ?do_scan_is@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2020 /* ?do_scan_is@?$ctype@G@std@@MBEPBGFPBG0@Z */
2021 /* ?do_scan_is@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2022 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_is, 16)
2023 #define call_ctype_wchar_do_scan_is(this, mask, first, last) CALL_VTBL_FUNC(this, 12, \
2024         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2025         (this, mask, first, last))
2026 const wchar_t* __thiscall ctype_wchar_do_scan_is(const ctype_wchar *this,
2027         short mask, const wchar_t *first, const wchar_t *last)
2028 {
2029     TRACE("(%p %d %p %p)\n", this, mask, first, last);
2030     for(; first<last; first++)
2031         if(!ctype_wchar_is_ch(this, mask, *first))
2032             break;
2033     return first;
2034 }
2035
2036 /* ?scan_is@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2037 /* ?scan_is@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2038 /* ?scan_is@?$ctype@G@std@@QBEPBGFPBG0@Z */
2039 /* ?scan_is@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2040 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_is, 16)
2041 const wchar_t* __thiscall ctype_wchar_scan_is(const ctype_wchar *this,
2042         short mask, const wchar_t *first, const wchar_t *last)
2043 {
2044     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2045     return call_ctype_wchar_do_scan_is(this, mask, first, last);
2046 }
2047
2048 /* ?do_scan_not@?$ctype@_W@std@@MBEPB_WFPB_W0@Z */
2049 /* ?do_scan_not@?$ctype@_W@std@@MEBAPEB_WFPEB_W0@Z */
2050 /* ?do_scan_not@?$ctype@G@std@@MBEPBGFPBG0@Z */
2051 /* ?do_scan_not@?$ctype@G@std@@MEBAPEBGFPEBG0@Z */
2052 DEFINE_THISCALL_WRAPPER(ctype_wchar_do_scan_not, 16)
2053 #define call_ctype_wchar_do_scan_not(this, mask, first, last) CALL_VTBL_FUNC(this, 16, \
2054         const wchar_t*, (const ctype_wchar*, short, const wchar_t*, const wchar_t*), \
2055         (this, mask, first, last))
2056 const wchar_t* __thiscall ctype_wchar_do_scan_not(const ctype_wchar *this,
2057         short mask, const wchar_t *first, const wchar_t *last)
2058 {
2059     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2060     for(; first<last; first++)
2061         if(ctype_wchar_is_ch(this, mask, *first))
2062             break;
2063     return first;
2064 }
2065
2066 /* ?scan_not@?$ctype@_W@std@@QBEPB_WFPB_W0@Z */
2067 /* ?scan_not@?$ctype@_W@std@@QEBAPEB_WFPEB_W0@Z */
2068 /* ?scan_not@?$ctype@G@std@@QBEPBGFPBG0@Z */
2069 /* ?scan_not@?$ctype@G@std@@QEBAPEBGFPEBG0@Z */
2070 DEFINE_THISCALL_WRAPPER(ctype_wchar_scan_not, 16)
2071 const wchar_t* __thiscall ctype_wchar_scan_not(const ctype_wchar *this,
2072         short mask, const wchar_t *first, const wchar_t *last)
2073 {
2074     TRACE("(%p %x %p %p)\n", this, mask, first, last);
2075     return call_ctype_wchar_do_scan_not(this, mask, first, last);
2076 }
2077
2078 /* ??_7codecvt_base@std@@6B@ */
2079 extern const vtable_ptr MSVCP_codecvt_base_vtable;
2080
2081 /* ??0codecvt_base@std@@QAE@I@Z */
2082 /* ??0codecvt_base@std@@QEAA@_K@Z */
2083 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor_refs, 8)
2084 codecvt_base* __thiscall codecvt_base_ctor_refs(codecvt_base *this, MSVCP_size_t refs)
2085 {
2086     TRACE("(%p %lu)\n", this, refs);
2087     locale_facet_ctor_refs(&this->facet, refs);
2088     this->facet.vtable = &MSVCP_codecvt_base_vtable;
2089     return this;
2090 }
2091
2092 /* ??_Fcodecvt_base@std@@QAEXXZ */
2093 /* ??_Fcodecvt_base@std@@QEAAXXZ */
2094 DEFINE_THISCALL_WRAPPER(codecvt_base_ctor, 4)
2095 codecvt_base* __thiscall codecvt_base_ctor(codecvt_base *this)
2096 {
2097     return codecvt_base_ctor_refs(this, 0);
2098 }
2099
2100 /* ??1codecvt_base@std@@UAE@XZ */
2101 /* ??1codecvt_base@std@@UEAA@XZ */
2102 DEFINE_THISCALL_WRAPPER(codecvt_base_dtor, 4)
2103 void __thiscall codecvt_base_dtor(codecvt_base *this)
2104 {
2105     TRACE("(%p)\n", this);
2106     locale_facet_dtor(&this->facet);
2107 }
2108
2109 DEFINE_THISCALL_WRAPPER(codecvt_base_vector_dtor, 8)
2110 codecvt_base* __thiscall codecvt_base_vector_dtor(codecvt_base *this, unsigned int flags)
2111 {
2112     TRACE("(%p %x)\n", this, flags);
2113     if(flags & 2) {
2114         /* we have an array, with the number of elements stored before the first object */
2115         INT_PTR i, *ptr = (INT_PTR *)this-1;
2116
2117         for(i=*ptr-1; i>=0; i--)
2118             codecvt_base_dtor(this+i);
2119         MSVCRT_operator_delete(ptr);
2120     } else {
2121         codecvt_base_dtor(this);
2122         if(flags & 1)
2123             MSVCRT_operator_delete(this);
2124     }
2125
2126     return this;
2127 }
2128
2129 /* ?do_always_noconv@codecvt_base@std@@MBE_NXZ */
2130 /* ?do_always_noconv@codecvt_base@std@@MEBA_NXZ */
2131 #define call_codecvt_base_do_always_noconv(this) CALL_VTBL_FUNC(this, 4, \
2132         MSVCP_bool, (const codecvt_base*), (this))
2133 DEFINE_THISCALL_WRAPPER(codecvt_base_do_always_noconv, 4)
2134 MSVCP_bool __thiscall codecvt_base_do_always_noconv(const codecvt_base *this)
2135 {
2136     TRACE("(%p)\n", this);
2137     return TRUE;
2138 }
2139
2140 /* ?always_noconv@codecvt_base@std@@QBE_NXZ */
2141 /* ?always_noconv@codecvt_base@std@@QEBA_NXZ */
2142 DEFINE_THISCALL_WRAPPER(codecvt_base_always_noconv, 4)
2143 MSVCP_bool __thiscall codecvt_base_always_noconv(const codecvt_base *this)
2144 {
2145     TRACE("(%p)\n", this);
2146     return call_codecvt_base_do_always_noconv(this);
2147 }
2148
2149 /* ?do_max_length@codecvt_base@std@@MBEHXZ */
2150 /* ?do_max_length@codecvt_base@std@@MEBAHXZ */
2151 #define call_codecvt_base_do_max_length(this) CALL_VTBL_FUNC(this, 8, \
2152         int, (const codecvt_base*), (this))
2153 DEFINE_THISCALL_WRAPPER(codecvt_base_do_max_length, 4)
2154 int __thiscall codecvt_base_do_max_length(const codecvt_base *this)
2155 {
2156     TRACE("(%p)\n", this);
2157     return 1;
2158 }
2159
2160 /* ?max_length@codecvt_base@std@@QBEHXZ */
2161 /* ?max_length@codecvt_base@std@@QEBAHXZ */
2162 DEFINE_THISCALL_WRAPPER(codecvt_base_max_length, 4)
2163 int __thiscall codecvt_base_max_length(const codecvt_base *this)
2164 {
2165     TRACE("(%p)\n", this);
2166     return call_codecvt_base_do_max_length(this);
2167 }
2168
2169 /* ?do_encoding@codecvt_base@std@@MBEHXZ */
2170 /* ?do_encoding@codecvt_base@std@@MEBAHXZ */
2171 #define call_codecvt_base_do_encoding(this) CALL_VTBL_FUNC(this, 12, \
2172         int, (const codecvt_base*), (this))
2173 DEFINE_THISCALL_WRAPPER(codecvt_base_do_encoding, 4)
2174 int __thiscall codecvt_base_do_encoding(const codecvt_base *this)
2175 {
2176     TRACE("(%p)\n", this);
2177     return 1;
2178 }
2179
2180 /* ?encoding@codecvt_base@std@@QBEHXZ */
2181 /* ?encoding@codecvt_base@std@@QEBAHXZ */
2182 DEFINE_THISCALL_WRAPPER(codecvt_base_encoding, 4)
2183 int __thiscall codecvt_base_encoding(const codecvt_base *this)
2184 {
2185     TRACE("(%p)\n", this);
2186     return call_codecvt_base_do_encoding(this);
2187 }
2188
2189 /* ?id@?$codecvt@DDH@std@@2V0locale@2@A */
2190 locale_id codecvt_char_id = {0};
2191
2192 /* ??_7?$codecvt@DDH@std@@6B@ */
2193 extern const vtable_ptr MSVCP_codecvt_char_vtable;
2194
2195 /* ?_Init@?$codecvt@DDH@std@@IAEXABV_Locinfo@2@@Z */
2196 /* ?_Init@?$codecvt@DDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2197 DEFINE_THISCALL_WRAPPER(codecvt_char__Init, 8)
2198 void __thiscall codecvt_char__Init(codecvt_char *this, const _Locinfo *locinfo)
2199 {
2200     TRACE("(%p %p)\n", this, locinfo);
2201 }
2202
2203 /* ??0?$codecvt@DDH@std@@QAE@ABV_Locinfo@1@I@Z */
2204 /* ??0?$codecvt@DDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2205 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_locinfo, 12)
2206 codecvt_char* __thiscall codecvt_char_ctor_locinfo(codecvt_char *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2207 {
2208     TRACE("(%p %p %lu)\n", this, locinfo, refs);
2209     codecvt_base_ctor_refs(&this->base, refs);
2210     this->base.facet.vtable = &MSVCP_codecvt_char_vtable;
2211     return this;
2212 }
2213
2214 /* ??0?$codecvt@DDH@std@@QAE@I@Z */
2215 /* ??0?$codecvt@DDH@std@@QEAA@_K@Z */
2216 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor_refs, 8)
2217 codecvt_char* __thiscall codecvt_char_ctor_refs(codecvt_char *this, MSVCP_size_t refs)
2218 {
2219     return codecvt_char_ctor_locinfo(this, NULL, refs);
2220 }
2221
2222 /* ??_F?$codecvt@DDH@std@@QAEXXZ */
2223 /* ??_F?$codecvt@DDH@std@@QEAAXXZ */
2224 DEFINE_THISCALL_WRAPPER(codecvt_char_ctor, 4)
2225 codecvt_char* __thiscall codecvt_char_ctor(codecvt_char *this)
2226 {
2227     return codecvt_char_ctor_locinfo(this, NULL, 0);
2228 }
2229
2230 /* ??1?$codecvt@DDH@std@@MAE@XZ */
2231 /* ??1?$codecvt@DDH@std@@MEAA@XZ */
2232 DEFINE_THISCALL_WRAPPER(codecvt_char_dtor, 4)
2233 void __thiscall codecvt_char_dtor(codecvt_char *this)
2234 {
2235     TRACE("(%p)\n", this);
2236     codecvt_base_dtor(&this->base);
2237 }
2238
2239 DEFINE_THISCALL_WRAPPER(codecvt_char_vector_dtor, 8)
2240 codecvt_char* __thiscall codecvt_char_vector_dtor(codecvt_char *this, unsigned int flags)
2241 {
2242     TRACE("(%p %x)\n", this, flags);
2243     if(flags & 2) {
2244         /* we have an array, with the number of elements stored before the first object */
2245         INT_PTR i, *ptr = (INT_PTR *)this-1;
2246
2247         for(i=*ptr-1; i>=0; i--)
2248             codecvt_char_dtor(this+i);
2249         MSVCRT_operator_delete(ptr);
2250     } else {
2251         codecvt_char_dtor(this);
2252         if(flags & 1)
2253             MSVCRT_operator_delete(this);
2254     }
2255
2256     return this;
2257 }
2258
2259 /* ?_Getcat@?$codecvt@DDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2260 /* ?_Getcat@?$codecvt@DDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2261 MSVCP_size_t __cdecl codecvt_char__Getcat(const locale_facet **facet, const locale *loc)
2262 {
2263     TRACE("(%p %p)\n", facet, loc);
2264
2265     if(facet && !*facet) {
2266         *facet = MSVCRT_operator_new(sizeof(codecvt_char));
2267         if(!*facet) {
2268             ERR("Out of memory\n");
2269             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2270             return 0;
2271         }
2272         codecvt_char_ctor((codecvt_char*)*facet);
2273     }
2274
2275     return LC_CTYPE;
2276 }
2277
2278 codecvt_char* codecvt_char_use_facet(const locale *loc)
2279 {
2280     static codecvt_char *obj = NULL;
2281
2282     _Lockit lock;
2283     const locale_facet *fac;
2284
2285     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2286     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_char_id));
2287     if(fac) {
2288         _Lockit_dtor(&lock);
2289         return (codecvt_char*)fac;
2290     }
2291
2292     if(obj) {
2293         _Lockit_dtor(&lock);
2294         return obj;
2295     }
2296
2297     codecvt_char__Getcat(&fac, loc);
2298     obj = (codecvt_char*)fac;
2299     locale_facet__Incref(&obj->base.facet);
2300     locale_facet_register(&obj->base.facet);
2301     _Lockit_dtor(&lock);
2302
2303     return obj;
2304 }
2305
2306 /* ?do_in@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2307 /* ?do_in@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2308 #define call_codecvt_char_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2309     CALL_VTBL_FUNC(this, 16, int, \
2310             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2311             (this, state, from, from_end, from_next, to, to_end, to_next))
2312 DEFINE_THISCALL_WRAPPER(codecvt_char_do_in, 32)
2313 int __thiscall codecvt_char_do_in(const codecvt_char *this, int *state,
2314         const char *from, const char *from_end, const char **from_next,
2315         char *to, char *to_end, char **to_next)
2316 {
2317     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2318             from_next, to, to_end, to_next);
2319     *from_next = from;
2320     *to_next = to;
2321     return CODECVT_noconv;
2322 }
2323
2324 /* ?in@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2325 /* ?in@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2326 DEFINE_THISCALL_WRAPPER(codecvt_char_in, 32)
2327 int __thiscall codecvt_char_in(const codecvt_char *this, int *state,
2328         const char *from, const char *from_end, const char **from_next,
2329         char *to, char *to_end, char **to_next)
2330 {
2331     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2332             from_next, to, to_end, to_next);
2333     return call_codecvt_char_do_in(this, state, from, from_end, from_next,
2334             to, to_end, to_next);
2335 }
2336
2337 /* ?do_out@?$codecvt@DDH@std@@MBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2338 /* ?do_out@?$codecvt@DDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2339 #define call_codecvt_char_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2340     CALL_VTBL_FUNC(this, 20, int, \
2341             (const codecvt_char*, int*, const char*, const char*, const char**, char*, char*, char**), \
2342             (this, state, from, from_end, from_next, to, to_end, to_next))
2343 DEFINE_THISCALL_WRAPPER(codecvt_char_do_out, 32)
2344 int __thiscall codecvt_char_do_out(const codecvt_char *this, int *state,
2345         const char *from, const char *from_end, const char **from_next,
2346         char *to, char *to_end, char **to_next)
2347 {
2348     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2349             from_end, from_next, to, to_end, to_next);
2350     *from_next = from;
2351     *to_next = to;
2352     return CODECVT_noconv;
2353 }
2354
2355 /* ?out@?$codecvt@DDH@std@@QBEHAAHPBD1AAPBDPAD3AAPAD@Z */
2356 /* ?out@?$codecvt@DDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAD3AEAPEAD@Z */
2357 DEFINE_THISCALL_WRAPPER(codecvt_char_out, 32)
2358 int __thiscall codecvt_char_out(const codecvt_char *this, int *state,
2359         const char *from, const char *from_end, const char **from_next,
2360         char *to, char *to_end, char **to_next)
2361 {
2362     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from, from_end,
2363             from_next, to, to_end, to_next);
2364     return call_codecvt_char_do_out(this, state, from, from_end, from_next,
2365             to, to_end, to_next);
2366 }
2367
2368 /* ?do_unshift@?$codecvt@DDH@std@@MBEHAAHPAD1AAPAD@Z */
2369 /* ?do_unshift@?$codecvt@DDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2370 #define call_codecvt_char_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2371         int, (const codecvt_char*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2372 DEFINE_THISCALL_WRAPPER(codecvt_char_do_unshift, 20)
2373 int __thiscall codecvt_char_do_unshift(const codecvt_char *this,
2374         int *state, char *to, char *to_end, char **to_next)
2375 {
2376     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2377     *to_next = to;
2378     return CODECVT_noconv;
2379 }
2380
2381 /* ?unshift@?$codecvt@DDH@std@@QBEHAAHPAD1AAPAD@Z */
2382 /* ?unshift@?$codecvt@DDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2383 DEFINE_THISCALL_WRAPPER(codecvt_char_unshift, 20)
2384 int __thiscall codecvt_char_unshift(const codecvt_char *this,
2385         int *state, char *to, char *to_end, char **to_next)
2386 {
2387     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2388     return call_codecvt_char_do_unshift(this, state, to, to_end, to_next);
2389 }
2390
2391 /* ?do_length@?$codecvt@DDH@std@@MBEHABHPBD1I@Z */
2392 /* ?do_length@?$codecvt@DDH@std@@MEBAHAEBHPEBD1_K@Z */
2393 #define call_codecvt_char_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2394         int, (const codecvt_char*, const int*, const char*, const char*, MSVCP_size_t), \
2395         (this, state, from, from_end, max))
2396 DEFINE_THISCALL_WRAPPER(codecvt_char_do_length, 20)
2397 int __thiscall codecvt_char_do_length(const codecvt_char *this, const int *state,
2398         const char *from, const char *from_end, MSVCP_size_t max)
2399 {
2400     TRACE("(%p %p %p %p %lu)\n", this, state, from, from_end, max);
2401     return (from_end-from > max ? max : from_end-from);
2402 }
2403
2404 /* ?length@?$codecvt@DDH@std@@QBEHABHPBD1I@Z */
2405 /* ?length@?$codecvt@DDH@std@@QEBAHAEBHPEBD1_K@Z */
2406 DEFINE_THISCALL_WRAPPER(codecvt_char_length, 20)
2407 int __thiscall codecvt_char_length(const codecvt_char *this, const int *state,
2408         const char *from, const char *from_end, MSVCP_size_t max)
2409 {
2410     TRACE("(%p %p %p %p %lu)\n", this, state, from, from_end, max);
2411     return call_codecvt_char_do_length(this, state, from, from_end, max);
2412 }
2413
2414 /* ?id@?$codecvt@_WDH@std@@2V0locale@2@A */
2415 locale_id codecvt_wchar_id = {0};
2416 /* ?id@?$codecvt@GDH@std@@2V0locale@2@A */
2417 locale_id codecvt_short_id = {0};
2418
2419 /* ??_7?$codecvt@_WDH@std@@6B@ */
2420 extern const vtable_ptr MSVCP_codecvt_wchar_vtable;
2421 /* ??_7?$codecvt@GDH@std@@6B@ */
2422 extern const vtable_ptr MSVCP_codecvt_short_vtable;
2423
2424 /* ?_Init@?$codecvt@GDH@std@@IAEXABV_Locinfo@2@@Z */
2425 /* ?_Init@?$codecvt@GDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2426 /* ?_Init@?$codecvt@_WDH@std@@IAEXABV_Locinfo@2@@Z */
2427 /* ?_Init@?$codecvt@_WDH@std@@IEAAXAEBV_Locinfo@2@@Z */
2428 DEFINE_THISCALL_WRAPPER(codecvt_wchar__Init, 8)
2429 void __thiscall codecvt_wchar__Init(codecvt_wchar *this, const _Locinfo *locinfo)
2430 {
2431     TRACE("(%p %p)\n", this, locinfo);
2432     _Locinfo__Getcvt(locinfo, &this->cvt);
2433 }
2434
2435 /* ??0?$codecvt@_WDH@std@@QAE@ABV_Locinfo@1@I@Z */
2436 /* ??0?$codecvt@_WDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2437 DEFINE_THISCALL_WRAPPER(codecvt_wchar_ctor_locinfo, 12)
2438 codecvt_wchar* __thiscall codecvt_wchar_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2439 {
2440     TRACE("(%p %p %ld)\n", this, locinfo, refs);
2441
2442     codecvt_base_ctor_refs(&this->base, refs);
2443     this->base.facet.vtable = &MSVCP_codecvt_wchar_vtable;
2444
2445     codecvt_wchar__Init(this, locinfo);
2446     return this;
2447 }
2448
2449 /* ??0?$codecvt@GDH@std@@QAE@ABV_Locinfo@1@I@Z */
2450 /* ??0?$codecvt@GDH@std@@QEAA@AEBV_Locinfo@1@_K@Z */
2451 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_locinfo, 12)
2452 codecvt_wchar* __thiscall codecvt_short_ctor_locinfo(codecvt_wchar *this, const _Locinfo *locinfo, MSVCP_size_t refs)
2453 {
2454     TRACE("(%p %p %ld)\n", this, locinfo, refs);
2455
2456     codecvt_wchar_ctor_locinfo(this, locinfo, refs);
2457     this->base.facet.vtable = &MSVCP_codecvt_short_vtable;
2458     return this;
2459 }
2460
2461 /* ??0?$codecvt@_WDH@std@@QAE@I@Z */
2462 /* ??0?$codecvt@_WDH@std@@QEAA@_K@Z */
2463 DEFINE_THISCALL_WRAPPER(codecvt_wchar_ctor_refs, 8)
2464 codecvt_wchar* __thiscall codecvt_wchar_ctor_refs(codecvt_wchar *this, MSVCP_size_t refs)
2465 {
2466     _Locinfo locinfo;
2467
2468     TRACE("(%p %ld)\n", this, refs);
2469
2470     _Locinfo_ctor(&locinfo);
2471     codecvt_wchar_ctor_locinfo(this, &locinfo, refs);
2472     _Locinfo_dtor(&locinfo);
2473     return this;
2474 }
2475
2476 /* ??0?$codecvt@GDH@std@@QAE@I@Z */
2477 /* ??0?$codecvt@GDH@std@@QEAA@_K@Z */
2478 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor_refs, 8)
2479 codecvt_wchar* __thiscall codecvt_short_ctor_refs(codecvt_wchar *this, MSVCP_size_t refs)
2480 {
2481     _Locinfo locinfo;
2482
2483     TRACE("(%p %ld)\n", this, refs);
2484
2485     _Locinfo_ctor(&locinfo);
2486     codecvt_short_ctor_locinfo(this, &locinfo, refs);
2487     _Locinfo_dtor(&locinfo);
2488     return this;
2489 }
2490
2491 /* ??_F?$codecvt@_WDH@std@@QAEXXZ */
2492 /* ??_F?$codecvt@_WDH@std@@QEAAXXZ */
2493 DEFINE_THISCALL_WRAPPER(codecvt_wchar_ctor, 4)
2494 codecvt_wchar* __thiscall codecvt_wchar_ctor(codecvt_wchar *this)
2495 {
2496     return codecvt_wchar_ctor_refs(this, 0);
2497 }
2498
2499 /* ??_F?$codecvt@GDH@std@@QAEXXZ */
2500 /* ??_F?$codecvt@GDH@std@@QEAAXXZ */
2501 DEFINE_THISCALL_WRAPPER(codecvt_short_ctor, 4)
2502 codecvt_wchar* __thiscall codecvt_short_ctor(codecvt_wchar *this)
2503 {
2504     return codecvt_short_ctor_refs(this, 0);
2505 }
2506
2507 /* ??1?$codecvt@GDH@std@@MAE@XZ */
2508 /* ??1?$codecvt@GDH@std@@MEAA@XZ */
2509 /* ??1?$codecvt@_WDH@std@@MAE@XZ */
2510 /* ??1?$codecvt@_WDH@std@@MEAA@XZ */
2511 DEFINE_THISCALL_WRAPPER(codecvt_wchar_dtor, 4)
2512 void __thiscall codecvt_wchar_dtor(codecvt_wchar *this)
2513 {
2514     TRACE("(%p)\n", this);
2515     codecvt_base_dtor(&this->base);
2516 }
2517
2518 DEFINE_THISCALL_WRAPPER(codecvt_wchar_vector_dtor, 8)
2519 codecvt_wchar* __thiscall codecvt_wchar_vector_dtor(codecvt_wchar *this, unsigned int flags)
2520 {
2521     TRACE("(%p %x)\n", this, flags);
2522     if(flags & 2) {
2523         /* we have an array, with the number of elements stored before the first object */
2524         INT_PTR i, *ptr = (INT_PTR *)this-1;
2525
2526         for(i=*ptr-1; i>=0; i--)
2527             codecvt_wchar_dtor(this+i);
2528         MSVCRT_operator_delete(ptr);
2529     } else {
2530         codecvt_wchar_dtor(this);
2531         if(flags & 1)
2532             MSVCRT_operator_delete(this);
2533     }
2534
2535     return this;
2536 }
2537
2538 /* ?_Getcat@?$codecvt@_WDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2539 /* ?_Getcat@?$codecvt@_WDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2540 MSVCP_size_t __cdecl codecvt_wchar__Getcat(const locale_facet **facet, const locale *loc)
2541 {
2542     TRACE("(%p %p)\n", facet, loc);
2543
2544     if(facet && !*facet) {
2545         _Locinfo locinfo;
2546
2547         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
2548         if(!*facet) {
2549             ERR("Out of memory\n");
2550             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2551             return 0;
2552         }
2553
2554         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
2555         codecvt_wchar_ctor_locinfo((codecvt_wchar*)*facet, &locinfo, 0);
2556         _Locinfo_dtor(&locinfo);
2557     }
2558
2559     return LC_CTYPE;
2560 }
2561
2562 codecvt_wchar* codecvt_wchar_use_facet(const locale *loc)
2563 {
2564     static codecvt_wchar *obj = NULL;
2565
2566     _Lockit lock;
2567     const locale_facet *fac;
2568
2569     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2570     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_wchar_id));
2571     if(fac) {
2572         _Lockit_dtor(&lock);
2573         return (codecvt_wchar*)fac;
2574     }
2575
2576     if(obj) {
2577         _Lockit_dtor(&lock);
2578         return obj;
2579     }
2580
2581     codecvt_wchar__Getcat(&fac, loc);
2582     obj = (codecvt_wchar*)fac;
2583     locale_facet__Incref(&obj->base.facet);
2584     locale_facet_register(&obj->base.facet);
2585     _Lockit_dtor(&lock);
2586
2587     return obj;
2588 }
2589
2590 /* ?_Getcat@?$codecvt@GDH@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2591 /* ?_Getcat@?$codecvt@GDH@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2592 MSVCP_size_t __cdecl codecvt_short__Getcat(const locale_facet **facet, const locale *loc)
2593 {
2594     TRACE("(%p %p)\n", facet, loc);
2595
2596     if(facet && !*facet) {
2597         _Locinfo locinfo;
2598
2599         *facet = MSVCRT_operator_new(sizeof(codecvt_wchar));
2600         if(!*facet) {
2601             ERR("Out of memory\n");
2602             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2603             return 0;
2604         }
2605
2606         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
2607         codecvt_short_ctor((codecvt_wchar*)*facet);
2608         _Locinfo_dtor(&locinfo);
2609     }
2610
2611     return LC_CTYPE;
2612 }
2613
2614 codecvt_wchar* codecvt_short_use_facet(const locale *loc)
2615 {
2616     static codecvt_wchar *obj = NULL;
2617
2618     _Lockit lock;
2619     const locale_facet *fac;
2620
2621     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2622     fac = locale__Getfacet(loc, locale_id_operator_size_t(&codecvt_short_id));
2623     if(fac) {
2624         _Lockit_dtor(&lock);
2625         return (codecvt_wchar*)fac;
2626     }
2627
2628     if(obj) {
2629         _Lockit_dtor(&lock);
2630         return obj;
2631     }
2632
2633     codecvt_short__Getcat(&fac, loc);
2634     obj = (codecvt_wchar*)fac;
2635     locale_facet__Incref(&obj->base.facet);
2636     locale_facet_register(&obj->base.facet);
2637     _Lockit_dtor(&lock);
2638
2639     return obj;
2640 }
2641
2642 /* ?do_always_noconv@?$codecvt@GDH@std@@MBE_NXZ */
2643 /* ?do_always_noconv@?$codecvt@GDH@std@@MEBA_NXZ */
2644 /* ?do_always_noconv@?$codecvt@_WDH@std@@MBE_NXZ */
2645 /* ?do_always_noconv@?$codecvt@_WDH@std@@MEBA_NXZ */
2646 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_always_noconv, 4)
2647 MSVCP_bool __thiscall codecvt_wchar_do_always_noconv(const codecvt_wchar *this)
2648 {
2649     TRACE("(%p)\n", this);
2650     return FALSE;
2651 }
2652
2653 /* ?do_max_length@?$codecvt@GDH@std@@MBEHXZ */
2654 /* ?do_max_length@?$codecvt@GDH@std@@MEBAHXZ */
2655 /* ?do_max_length@?$codecvt@_WDH@std@@MBEHXZ */
2656 /* ?do_max_length@?$codecvt@_WDH@std@@MEBAHXZ */
2657 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_max_length, 4)
2658 int __thiscall codecvt_wchar_do_max_length(const codecvt_wchar *this)
2659 {
2660     TRACE("(%p)\n", this);
2661     return MB_LEN_MAX;
2662 }
2663
2664 /* ?do_in@?$codecvt@GDH@std@@MBEHAAHPBD1AAPBDPAG3AAPAG@Z */
2665 /* ?do_in@?$codecvt@GDH@std@@MEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
2666 /* ?do_in@?$codecvt@_WDH@std@@MBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
2667 /* ?do_in@?$codecvt@_WDH@std@@MEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
2668 #define call_codecvt_wchar_do_in(this, state, from, from_end, from_next, to, to_end, to_next) \
2669     CALL_VTBL_FUNC(this, 16, int, \
2670             (const codecvt_wchar*, int*, const char*, const char*, const char**, wchar_t*, wchar_t*, wchar_t**), \
2671             (this, state, from, from_end, from_next, to, to_end, to_next))
2672 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_in, 32)
2673 int __thiscall codecvt_wchar_do_in(const codecvt_wchar *this, int *state,
2674         const char *from, const char *from_end, const char **from_next,
2675         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
2676 {
2677     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2678             from_end, from_next, to, to_end, to_next);
2679
2680     *from_next = from;
2681     *to_next = to;
2682
2683     while(*from_next!=from_end && *to_next!=to_end) {
2684         switch(_Mbrtowc(*to_next, *from_next, from_end-*from_next, state, &this->cvt)) {
2685         case -2:
2686             *from_next = from_end;
2687             return CODECVT_partial;
2688         case -1:
2689             return CODECVT_error;
2690         case 2:
2691             (*from_next)++;
2692             /* fall through */
2693         case 0:
2694         case 1:
2695             (*from_next)++;
2696             (*to_next)++;
2697         }
2698     }
2699
2700     return CODECVT_ok;
2701 }
2702
2703 /* ?in@?$codecvt@GDH@std@@QBEHAAHPBD1AAPBDPAG3AAPAG@Z */
2704 /* ?in@?$codecvt@GDH@std@@QEBAHAEAHPEBD1AEAPEBDPEAG3AEAPEAG@Z */
2705 /* ?in@?$codecvt@_WDH@std@@QBEHAAHPBD1AAPBDPA_W3AAPA_W@Z */
2706 /* ?in@?$codecvt@_WDH@std@@QEBAHAEAHPEBD1AEAPEBDPEA_W3AEAPEA_W@Z */
2707 DEFINE_THISCALL_WRAPPER(codecvt_wchar_in, 32)
2708 int __thiscall codecvt_wchar_in(const codecvt_wchar *this, int *state,
2709         const char *from, const char *from_end, const char **from_next,
2710         wchar_t *to, wchar_t *to_end, wchar_t **to_next)
2711 {
2712     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2713             from_end, from_next, to, to_end, to_next);
2714     return call_codecvt_wchar_do_in(this, state, from,
2715             from_end, from_next, to, to_end, to_next);
2716 }
2717
2718 /* ?do_out@?$codecvt@GDH@std@@MBEHAAHPBG1AAPBGPAD3AAPAD@Z */
2719 /* ?do_out@?$codecvt@GDH@std@@MEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
2720 /* ?do_out@?$codecvt@_WDH@std@@MBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
2721 /* ?do_out@?$codecvt@_WDH@std@@MEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
2722 #define call_codecvt_wchar_do_out(this, state, from, from_end, from_next, to, to_end, to_next) \
2723     CALL_VTBL_FUNC(this, 20, int, \
2724             (const codecvt_wchar*, int*, const wchar_t*, const wchar_t*, const wchar_t**, char*, char*, char**), \
2725             (this, state, from, from_end, from_next, to, to_end, to_next))
2726 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_out, 32)
2727 int __thiscall codecvt_wchar_do_out(const codecvt_wchar *this, int *state,
2728         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
2729         char *to, char *to_end, char **to_next)
2730 {
2731     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2732             from_end, from_next, to, to_end, to_next);
2733
2734     *from_next = from;
2735     *to_next = to;
2736
2737     while(*from_next!=from_end && *to_next!=to_end) {
2738         int old_state = *state, size;
2739         char buf[MB_LEN_MAX];
2740
2741         switch((size = _Wcrtomb(buf, **from_next, state, &this->cvt))) {
2742         case -1:
2743             return CODECVT_error;
2744         default:
2745             if(size > from_end-*from_next) {
2746                 *state = old_state;
2747                 return CODECVT_partial;
2748             }
2749
2750             (*from_next)++;
2751             memcpy_s(*to_next, to_end-*to_next, buf, size);
2752             (*to_next) += size;
2753         }
2754     }
2755
2756     return CODECVT_ok;
2757 }
2758
2759 /* ?out@?$codecvt@GDH@std@@QBEHAAHPBG1AAPBGPAD3AAPAD@Z */
2760 /* ?out@?$codecvt@GDH@std@@QEBAHAEAHPEBG1AEAPEBGPEAD3AEAPEAD@Z */
2761 /* ?out@?$codecvt@_WDH@std@@QBEHAAHPB_W1AAPB_WPAD3AAPAD@Z */
2762 /* ?out@?$codecvt@_WDH@std@@QEBAHAEAHPEB_W1AEAPEB_WPEAD3AEAPEAD@Z */
2763 DEFINE_THISCALL_WRAPPER(codecvt_wchar_out, 32)
2764 int __thiscall codecvt_wchar_out(const codecvt_wchar *this, int *state,
2765         const wchar_t *from, const wchar_t *from_end, const wchar_t **from_next,
2766         char *to, char *to_end, char **to_next)
2767 {
2768     TRACE("(%p %p %p %p %p %p %p %p)\n", this, state, from,
2769             from_end, from_next, to, to_end, to_next);
2770     return call_codecvt_wchar_do_out(this, state, from,
2771             from_end, from_next, to, to_end, to_next);
2772 }
2773
2774 /* ?do_unshift@?$codecvt@GDH@std@@MBEHAAHPAD1AAPAD@Z */
2775 /* ?do_unshift@?$codecvt@GDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2776 /* ?do_unshift@?$codecvt@_WDH@std@@MBEHAAHPAD1AAPAD@Z */
2777 /* ?do_unshift@?$codecvt@_WDH@std@@MEBAHAEAHPEAD1AEAPEAD@Z */
2778 #define call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next) CALL_VTBL_FUNC(this, 24, \
2779         int, (const codecvt_wchar*, int*, char*, char*, char**), (this, state, to, to_end, to_next))
2780 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_unshift, 20)
2781 int __thiscall codecvt_wchar_do_unshift(const codecvt_wchar *this,
2782         int *state, char *to, char *to_end, char **to_next)
2783 {
2784     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2785     if(*state)
2786         WARN("unexpected state: %x\n", *state);
2787
2788     *to_next = to;
2789     return CODECVT_ok;
2790 }
2791
2792 /* ?unshift@?$codecvt@GDH@std@@QBEHAAHPAD1AAPAD@Z */
2793 /* ?unshift@?$codecvt@GDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2794 /* ?unshift@?$codecvt@_WDH@std@@QBEHAAHPAD1AAPAD@Z */
2795 /* ?unshift@?$codecvt@_WDH@std@@QEBAHAEAHPEAD1AEAPEAD@Z */
2796 DEFINE_THISCALL_WRAPPER(codecvt_wchar_unshift, 20)
2797 int __thiscall codecvt_wchar_unshift(const codecvt_wchar *this,
2798         int *state, char *to, char *to_end, char **to_next)
2799 {
2800     TRACE("(%p %p %p %p %p)\n", this, state, to, to_end, to_next);
2801     return call_codecvt_wchar_do_unshift(this, state, to, to_end, to_next);
2802 }
2803
2804 /* ?do_length@?$codecvt@GDH@std@@MBEHABHPBD1I@Z */
2805 /* ?do_length@?$codecvt@GDH@std@@MEBAHAEBHPEBD1_K@Z */
2806 /* ?do_length@?$codecvt@_WDH@std@@MBEHABHPBD1I@Z */
2807 /* ?do_length@?$codecvt@_WDH@std@@MEBAHAEBHPEBD1_K@Z */
2808 #define call_codecvt_wchar_do_length(this, state, from, from_end, max) CALL_VTBL_FUNC(this, 28, \
2809         int, (const codecvt_wchar*, const int*, const char*, const char*, MSVCP_size_t), \
2810         (this, state, from, from_end, max))
2811 DEFINE_THISCALL_WRAPPER(codecvt_wchar_do_length, 20)
2812 int __thiscall codecvt_wchar_do_length(const codecvt_wchar *this, const int *state,
2813         const char *from, const char *from_end, MSVCP_size_t max)
2814 {
2815     int tmp_state = *state, ret=0;
2816
2817     TRACE("(%p %p %p %p %ld)\n", this, state, from, from_end, max);
2818
2819     while(ret<max && from!=from_end) {
2820         switch(_Mbrtowc(NULL, from, from_end-from, &tmp_state, &this->cvt)) {
2821         case -2:
2822         case -1:
2823             return ret;
2824         case 2:
2825             from++;
2826             /* fall through */
2827         case 0:
2828         case 1:
2829             from++;
2830             ret++;
2831         }
2832     }
2833
2834     return ret;
2835 }
2836
2837 /* ?length@?$codecvt@GDH@std@@QBEHABHPBD1I@Z */
2838 /* ?length@?$codecvt@GDH@std@@QEBAHAEBHPEBD1_K@Z */
2839 /* ?length@?$codecvt@_WDH@std@@QBEHABHPBD1I@Z */
2840 /* ?length@?$codecvt@_WDH@std@@QEBAHAEBHPEBD1_K@Z */
2841 DEFINE_THISCALL_WRAPPER(codecvt_wchar_length, 20)
2842 int __thiscall codecvt_wchar_length(const codecvt_wchar *this, const int *state,
2843         const char *from, const char *from_end, MSVCP_size_t max)
2844 {
2845     TRACE("(%p %p %p %p %ld)\n", this, state, from, from_end, max);
2846     return call_codecvt_wchar_do_length(this, state, from, from_end, max);
2847 }
2848
2849 /* ?id@?$numpunct@D@std@@2V0locale@2@A */
2850 locale_id numpunct_char_id = {0};
2851
2852 /* ??_7?$numpunct@D@std@@6B@ */
2853 extern const vtable_ptr MSVCP_numpunct_char_vtable;
2854
2855 /* ?_Init@?$numpunct@D@std@@IAEXABV_Locinfo@2@_N@Z */
2856 /* ?_Init@?$numpunct@D@std@@IEAAXAEBV_Locinfo@2@_N@Z */
2857 static void numpunct_char__Init(numpunct_char *this, const _Locinfo *locinfo, MSVCP_bool isdef)
2858 {
2859     int len;
2860
2861     TRACE("(%p %p %d)\n", this, locinfo, isdef);
2862
2863     len = strlen(_Locinfo__Getfalse(locinfo))+1;
2864     this->false_name = MSVCRT_operator_new(len);
2865     if(this->false_name)
2866         memcpy((char*)this->false_name, _Locinfo__Getfalse(locinfo), len);
2867
2868     len = strlen(_Locinfo__Gettrue(locinfo))+1;
2869     this->true_name = MSVCRT_operator_new(len);
2870     if(this->true_name)
2871         memcpy((char*)this->true_name, _Locinfo__Gettrue(locinfo), len);
2872
2873     if(isdef) {
2874         this->grouping = MSVCRT_operator_new(1);
2875         if(this->grouping)
2876             *(char*)this->grouping = 0;
2877
2878         this->dp = '.';
2879         this->sep = ',';
2880     } else {
2881         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
2882
2883         len = strlen(lc->grouping)+1;
2884         this->grouping = MSVCRT_operator_new(len);
2885         if(this->grouping)
2886             memcpy((char*)this->grouping, lc->grouping, len);
2887
2888         this->dp = lc->decimal_point[0];
2889         this->sep = lc->thousands_sep[0];
2890     }
2891
2892     if(!this->false_name || !this->true_name || !this->grouping) {
2893         MSVCRT_operator_delete((char*)this->grouping);
2894         MSVCRT_operator_delete((char*)this->false_name);
2895         MSVCRT_operator_delete((char*)this->true_name);
2896
2897         ERR("Out of memory\n");
2898         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2899     }
2900 }
2901
2902 /* ?_Tidy@?$numpunct@D@std@@AAEXXZ */
2903 /* ?_Tidy@?$numpunct@D@std@@AEAAXXZ */
2904 static void numpunct_char__Tidy(numpunct_char *this)
2905 {
2906     TRACE("(%p)\n", this);
2907
2908     MSVCRT_operator_delete((char*)this->grouping);
2909     MSVCRT_operator_delete((char*)this->false_name);
2910     MSVCRT_operator_delete((char*)this->true_name);
2911 }
2912
2913 /* ??0?$numpunct@D@std@@QAE@ABV_Locinfo@1@I_N@Z */
2914 /* ??0?$numpunct@D@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
2915 static numpunct_char* numpunct_char_ctor_locinfo(numpunct_char *this,
2916         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
2917 {
2918     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
2919     locale_facet_ctor_refs(&this->facet, refs);
2920     this->facet.vtable = &MSVCP_numpunct_char_vtable;
2921     numpunct_char__Init(this, locinfo, usedef);
2922     return this;
2923 }
2924
2925 /* ??0?$numpunct@D@std@@IAE@PBDI_N@Z */
2926 /* ??0?$numpunct@D@std@@IEAA@PEBD_K_N@Z */
2927 static numpunct_char* numpunct_char_ctor_name(numpunct_char *this,
2928         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
2929 {
2930     _Locinfo locinfo;
2931
2932     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
2933     locale_facet_ctor_refs(&this->facet, refs);
2934     this->facet.vtable = &MSVCP_numpunct_char_vtable;
2935
2936     _Locinfo_ctor_cstr(&locinfo, name);
2937     numpunct_char__Init(this, &locinfo, usedef);
2938     _Locinfo_dtor(&locinfo);
2939     return this;
2940 }
2941
2942 /* ??1?$numpunct@D@std@@MAE@XZ */
2943 /* ??1?$numpunct@D@std@@MEAA@XZ */
2944 static void numpunct_char_dtor(numpunct_char *this)
2945 {
2946     TRACE("(%p)\n", this);
2947     numpunct_char__Tidy(this);
2948 }
2949
2950 DEFINE_THISCALL_WRAPPER(numpunct_char_vector_dtor, 8)
2951 numpunct_char* __thiscall numpunct_char_vector_dtor(numpunct_char *this, unsigned int flags)
2952 {
2953     TRACE("(%p %x)\n", this, flags);
2954     if(flags & 2) {
2955         /* we have an array, with the number of elements stored before the first object */
2956         INT_PTR i, *ptr = (INT_PTR *)this-1;
2957
2958         for(i=*ptr-1; i>=0; i--)
2959             numpunct_char_dtor(this+i);
2960         MSVCRT_operator_delete(ptr);
2961     } else {
2962         numpunct_char_dtor(this);
2963         if(flags & 1)
2964             MSVCRT_operator_delete(this);
2965     }
2966
2967     return this;
2968 }
2969
2970 /* ?_Getcat@?$numpunct@D@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
2971 /* ?_Getcat@?$numpunct@D@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
2972 static MSVCP_size_t numpunct_char__Getcat(const locale_facet **facet, const locale *loc)
2973 {
2974     TRACE("(%p %p)\n", facet, loc);
2975
2976     if(facet && !*facet) {
2977         *facet = MSVCRT_operator_new(sizeof(numpunct_char));
2978         if(!*facet) {
2979             ERR("Out of memory\n");
2980             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
2981             return 0;
2982         }
2983         numpunct_char_ctor_name((numpunct_char*)*facet,
2984                 _Yarn_char_c_str(&loc->ptr->name), 0, TRUE);
2985     }
2986
2987     return LC_NUMERIC;
2988 }
2989
2990 static numpunct_char* numpunct_char_use_facet(const locale *loc)
2991 {
2992     static numpunct_char *obj = NULL;
2993
2994     _Lockit lock;
2995     const locale_facet *fac;
2996
2997     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
2998     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_char_id));
2999     if(fac) {
3000         _Lockit_dtor(&lock);
3001         return (numpunct_char*)fac;
3002     }
3003
3004     if(obj) {
3005         _Lockit_dtor(&lock);
3006         return obj;
3007     }
3008
3009     numpunct_char__Getcat(&fac, loc);
3010     obj = (numpunct_char*)fac;
3011     locale_facet__Incref(&obj->facet);
3012     locale_facet_register(&obj->facet);
3013     _Lockit_dtor(&lock);
3014
3015     return obj;
3016 }
3017
3018 /* ?do_decimal_point@?$numpunct@D@std@@MBEDXZ */
3019 /* ?do_decimal_point@?$numpunct@D@std@@MEBADXZ */
3020 DEFINE_THISCALL_WRAPPER(numpunct_char_do_decimal_point, 4)
3021 #define call_numpunct_char_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3022         char, (const numpunct_char *this), (this))
3023 char __thiscall numpunct_char_do_decimal_point(const numpunct_char *this)
3024 {
3025     TRACE("(%p)\n", this);
3026     return this->dp;
3027 }
3028
3029 /* ?decimal_point@?$numpunct@D@std@@QBEDXZ */
3030 /* ?decimal_point@?$numpunct@D@std@@QEBADXZ */
3031 static char numpunct_char_decimal_point(const numpunct_char *this)
3032 {
3033     TRACE("(%p)\n", this);
3034     return call_numpunct_char_do_decimal_point(this);
3035 }
3036
3037 /* ?do_thousands_sep@?$numpunct@D@std@@MBEDXZ */
3038 /* ?do_thousands_sep@?$numpunct@D@std@@MEBADXZ */
3039 DEFINE_THISCALL_WRAPPER(numpunct_char_do_thousands_sep, 4)
3040 #define call_numpunct_char_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3041         char, (const numpunct_char*), (this))
3042 char __thiscall numpunct_char_do_thousands_sep(const numpunct_char *this)
3043 {
3044     TRACE("(%p)\n", this);
3045     return this->sep;
3046 }
3047
3048 /* ?thousands_sep@?$numpunct@D@std@@QBEDXZ */
3049 /* ?thousands_sep@?$numpunct@D@std@@QEBADXZ */
3050 static char numpunct_char_thousands_sep(const numpunct_char *this)
3051 {
3052     TRACE("(%p)\n", this);
3053     return call_numpunct_char_do_thousands_sep(this);
3054 }
3055
3056 /* ?do_grouping@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3057 /* ?do_grouping@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3058 DEFINE_THISCALL_WRAPPER(numpunct_char_do_grouping, 8)
3059 #define call_numpunct_char_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3060         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3061 basic_string_char* __thiscall numpunct_char_do_grouping(
3062         const numpunct_char *this, basic_string_char *ret)
3063 {
3064     TRACE("(%p)\n", this);
3065     return MSVCP_basic_string_char_ctor_cstr(ret, this->grouping);
3066 }
3067
3068 /* ?grouping@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3069 /* ?grouping@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3070 static basic_string_char* numpunct_char_grouping(const numpunct_char *this, basic_string_char *ret)
3071 {
3072     TRACE("(%p)\n", this);
3073     return call_numpunct_char_do_grouping(this, ret);
3074 }
3075
3076 /* ?do_falsename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3077 /* ?do_falsename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3078 DEFINE_THISCALL_WRAPPER(numpunct_char_do_falsename, 8)
3079 #define call_numpunct_char_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3080         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3081 basic_string_char* __thiscall numpunct_char_do_falsename(
3082         const numpunct_char *this, basic_string_char *ret)
3083 {
3084     TRACE("(%p)\n", this);
3085     return MSVCP_basic_string_char_ctor_cstr(ret, this->false_name);
3086 }
3087
3088 /* ?falsename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3089 /* ?falsename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3090 static basic_string_char* numpunct_char_falsename(const numpunct_char *this, basic_string_char *ret)
3091 {
3092     TRACE("(%p)\n", this);
3093     return call_numpunct_char_do_falsename(this, ret);
3094 }
3095
3096 /* ?do_truename@?$numpunct@D@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3097 /* ?do_truename@?$numpunct@D@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3098 DEFINE_THISCALL_WRAPPER(numpunct_char_do_truename, 8)
3099 #define call_numpunct_char_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3100         basic_string_char*, (const numpunct_char*, basic_string_char*), (this, ret))
3101 basic_string_char* __thiscall numpunct_char_do_truename(
3102         const numpunct_char *this, basic_string_char *ret)
3103 {
3104     TRACE("(%p)\n", this);
3105     return MSVCP_basic_string_char_ctor_cstr(ret, this->true_name);
3106 }
3107
3108 /* ?truename@?$numpunct@D@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3109 /* ?truename@?$numpunct@D@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3110 static basic_string_char* numpunct_char_truename(const numpunct_char *this, basic_string_char *ret)
3111 {
3112     TRACE("(%p)\n", this);
3113     return call_numpunct_char_do_truename(this, ret);
3114 }
3115
3116 /* ?id@?$numpunct@_W@std@@2V0locale@2@A */
3117 locale_id numpunct_wchar_id = {0};
3118 /* ?id@?$numpunct@G@std@@2V0locale@2@A */
3119 locale_id numpunct_short_id = {0};
3120
3121 /* ??_7?$numpunct@_W@std@@6B@ */
3122 extern const vtable_ptr MSVCP_numpunct_wchar_vtable;
3123 /* ??_7?$numpunct@G@std@@6B@ */
3124 extern const vtable_ptr MSVCP_numpunct_short_vtable;
3125
3126 /* ?_Init@?$numpunct@_W@std@@IAEXABV_Locinfo@2@_N@Z */
3127 /* ?_Init@?$numpunct@_W@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3128 /* ?_Init@?$numpunct@G@std@@IAEXABV_Locinfo@2@_N@Z */
3129 /* ?_Init@?$numpunct@G@std@@IEAAXAEBV_Locinfo@2@_N@Z */
3130 static void numpunct_wchar__Init(numpunct_wchar *this,
3131         const _Locinfo *locinfo, MSVCP_bool isdef)
3132 {
3133     const char *to_convert;
3134     _Cvtvec cvt;
3135     int len;
3136
3137     TRACE("(%p %p %d)\n", this, locinfo, isdef);
3138
3139     _Locinfo__Getcvt(locinfo, &cvt);
3140
3141     to_convert = _Locinfo__Getfalse(locinfo);
3142     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3143     this->false_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3144     if(this->false_name)
3145         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3146                 (wchar_t*)this->false_name, len);
3147
3148     to_convert = _Locinfo__Gettrue(locinfo);
3149     len = MultiByteToWideChar(cvt.page, 0, to_convert, -1, NULL, 0);
3150     this->true_name = MSVCRT_operator_new(len*sizeof(WCHAR));
3151     if(this->true_name)
3152         MultiByteToWideChar(cvt.page, 0, to_convert, -1,
3153                 (wchar_t*)this->true_name, len);
3154
3155     if(isdef) {
3156         this->grouping = MSVCRT_operator_new(1);
3157         if(this->grouping)
3158             *(char*)this->grouping = 0;
3159
3160         this->dp = '.';
3161         this->sep = ',';
3162     } else {
3163         const struct lconv *lc = _Locinfo__Getlconv(locinfo);
3164
3165         len = strlen(lc->grouping)+1;
3166         this->grouping = MSVCRT_operator_new(len);
3167         if(this->grouping)
3168             memcpy((char*)this->grouping, lc->grouping, len);
3169
3170         this->dp = lc->decimal_point[0];
3171         this->sep = lc->thousands_sep[0];
3172     }
3173
3174     if(!this->false_name || !this->true_name || !this->grouping) {
3175         MSVCRT_operator_delete((char*)this->grouping);
3176         MSVCRT_operator_delete((wchar_t*)this->false_name);
3177         MSVCRT_operator_delete((wchar_t*)this->true_name);
3178
3179         ERR("Out of memory\n");
3180         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3181     }
3182 }
3183
3184 /* ?_Tidy@?$numpunct@_W@std@@AAEXXZ */
3185 /* ?_Tidy@?$numpunct@_W@std@@AEAAXXZ */
3186 /* ?_Tidy@?$numpunct@G@std@@AAEXXZ */
3187 /* ?_Tidy@?$numpunct@G@std@@AEAAXXZ */
3188 static void numpunct_wchar__Tidy(numpunct_wchar *this)
3189 {
3190     TRACE("(%p)\n", this);
3191
3192     MSVCRT_operator_delete((char*)this->grouping);
3193     MSVCRT_operator_delete((wchar_t*)this->false_name);
3194     MSVCRT_operator_delete((wchar_t*)this->true_name);
3195 }
3196
3197 /* ??0?$numpunct@_W@std@@QAE@ABV_Locinfo@1@I_N@Z */
3198 /* ??0?$numpunct@_W@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3199 static numpunct_wchar* numpunct_wchar_ctor_locinfo(numpunct_wchar *this,
3200         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3201 {
3202     TRACE("(%p %p %lu %d)\n", this, locinfo, refs, usedef);
3203     locale_facet_ctor_refs(&this->facet, refs);
3204     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3205     numpunct_wchar__Init(this, locinfo, usedef);
3206     return this;
3207 }
3208
3209 /* ??0?$numpunct@G@std@@QAE@ABV_Locinfo@1@I_N@Z */
3210 /* ??0?$numpunct@G@std@@QEAA@AEBV_Locinfo@1@_K_N@Z */
3211 static numpunct_wchar* numpunct_short_ctor_locinfo(numpunct_wchar *this,
3212         const _Locinfo *locinfo, MSVCP_size_t refs, MSVCP_bool usedef)
3213 {
3214     numpunct_wchar_ctor_locinfo(this, locinfo, refs, usedef);
3215     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3216     return this;
3217 }
3218
3219 /* ??0?$numpunct@_W@std@@IAE@PBDI_N@Z */
3220 /* ??0?$numpunct@_W@std@@IEAA@PEBD_K_N@Z */
3221 static numpunct_wchar* numpunct_wchar_ctor_name(numpunct_wchar *this,
3222         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3223 {
3224     _Locinfo locinfo;
3225
3226     TRACE("(%p %s %lu %d)\n", this, debugstr_a(name), refs, usedef);
3227     locale_facet_ctor_refs(&this->facet, refs);
3228     this->facet.vtable = &MSVCP_numpunct_wchar_vtable;
3229
3230     _Locinfo_ctor_cstr(&locinfo, name);
3231     numpunct_wchar__Init(this, &locinfo, usedef);
3232     _Locinfo_dtor(&locinfo);
3233     return this;
3234 }
3235
3236 /* ??0?$numpunct@G@std@@IAE@PBDI_N@Z */
3237 /* ??0?$numpunct@G@std@@IEAA@PEBD_K_N@Z */
3238 static numpunct_wchar* numpunct_short_ctor_name(numpunct_wchar *this,
3239         const char *name, MSVCP_size_t refs, MSVCP_bool usedef)
3240 {
3241     numpunct_wchar_ctor_name(this, name, refs, usedef);
3242     this->facet.vtable = &MSVCP_numpunct_short_vtable;
3243     return this;
3244 }
3245
3246 /* ??1?$numpunct@_W@std@@MAE@XZ */
3247 /* ??1?$numpunct@_W@std@@MEAA@XZ */
3248 /* ??1?$numpunct@G@std@@MAE@XZ */
3249 /* ??1?$numpunct@G@std@@MEAA@XZ */
3250 static void numpunct_wchar_dtor(numpunct_wchar *this)
3251 {
3252     TRACE("(%p)\n", this);
3253     numpunct_wchar__Tidy(this);
3254 }
3255
3256 DEFINE_THISCALL_WRAPPER(numpunct_wchar_vector_dtor, 8)
3257 numpunct_wchar* __thiscall numpunct_wchar_vector_dtor(numpunct_wchar *this, unsigned int flags)
3258 {
3259     TRACE("(%p %x)\n", this, flags);
3260     if(flags & 2) {
3261         /* we have an array, with the number of elements stored before the first object */
3262         INT_PTR i, *ptr = (INT_PTR *)this-1;
3263
3264         for(i=*ptr-1; i>=0; i--)
3265             numpunct_wchar_dtor(this+i);
3266         MSVCRT_operator_delete(ptr);
3267     } else {
3268         numpunct_wchar_dtor(this);
3269         if(flags & 1)
3270             MSVCRT_operator_delete(this);
3271     }
3272
3273     return this;
3274 }
3275
3276 /* ?_Getcat@?$numpunct@_W@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3277 /* ?_Getcat@?$numpunct@_W@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3278 static MSVCP_size_t numpunct_wchar__Getcat(const locale_facet **facet, const locale *loc)
3279 {
3280     TRACE("(%p %p)\n", facet, loc);
3281
3282     if(facet && !*facet) {
3283         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3284         if(!*facet) {
3285             ERR("Out of memory\n");
3286             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3287             return 0;
3288         }
3289         numpunct_wchar_ctor_name((numpunct_wchar*)*facet,
3290                 _Yarn_char_c_str(&loc->ptr->name), 0, TRUE);
3291     }
3292
3293     return LC_NUMERIC;
3294 }
3295
3296 static numpunct_wchar* numpunct_wchar_use_facet(const locale *loc)
3297 {
3298     static numpunct_wchar *obj = NULL;
3299
3300     _Lockit lock;
3301     const locale_facet *fac;
3302
3303     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3304     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_wchar_id));
3305     if(fac) {
3306         _Lockit_dtor(&lock);
3307         return (numpunct_wchar*)fac;
3308     }
3309
3310     if(obj) {
3311         _Lockit_dtor(&lock);
3312         return obj;
3313     }
3314
3315     numpunct_wchar__Getcat(&fac, loc);
3316     obj = (numpunct_wchar*)fac;
3317     locale_facet__Incref(&obj->facet);
3318     locale_facet_register(&obj->facet);
3319     _Lockit_dtor(&lock);
3320
3321     return obj;
3322 }
3323
3324 /* ?_Getcat@?$numpunct@G@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3325 /* ?_Getcat@?$numpunct@G@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3326 static MSVCP_size_t numpunct_short__Getcat(const locale_facet **facet, const locale *loc)
3327 {
3328     TRACE("(%p %p)\n", facet, loc);
3329
3330     if(facet && !*facet) {
3331         *facet = MSVCRT_operator_new(sizeof(numpunct_wchar));
3332         if(!*facet) {
3333             ERR("Out of memory\n");
3334             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3335             return 0;
3336         }
3337         numpunct_short_ctor_name((numpunct_wchar*)*facet,
3338                 _Yarn_char_c_str(&loc->ptr->name), 0, TRUE);
3339     }
3340
3341     return LC_NUMERIC;
3342 }
3343
3344 static numpunct_wchar* numpunct_short_use_facet(const locale *loc)
3345 {
3346     static numpunct_wchar *obj = NULL;
3347
3348     _Lockit lock;
3349     const locale_facet *fac;
3350
3351     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3352     fac = locale__Getfacet(loc, locale_id_operator_size_t(&numpunct_short_id));
3353     if(fac) {
3354         _Lockit_dtor(&lock);
3355         return (numpunct_wchar*)fac;
3356     }
3357
3358     if(obj) {
3359         _Lockit_dtor(&lock);
3360         return obj;
3361     }
3362
3363     numpunct_short__Getcat(&fac, loc);
3364     obj = (numpunct_wchar*)fac;
3365     locale_facet__Incref(&obj->facet);
3366     locale_facet_register(&obj->facet);
3367     _Lockit_dtor(&lock);
3368
3369     return obj;
3370 }
3371
3372 /* ?do_decimal_point@?$numpunct@_W@std@@MBE_WXZ */
3373 /* ?do_decimal_point@?$numpunct@_W@std@@MEBA_WXZ */
3374 /* ?do_decimal_point@?$numpunct@G@std@@MBEGXZ */
3375 /* ?do_decimal_point@?$numpunct@G@std@@MEBAGXZ */
3376 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_decimal_point, 4)
3377 #define call_numpunct_wchar_do_decimal_point(this) CALL_VTBL_FUNC(this, 4, \
3378         wchar_t, (const numpunct_wchar *this), (this))
3379 wchar_t __thiscall numpunct_wchar_do_decimal_point(const numpunct_wchar *this)
3380 {
3381     TRACE("(%p)\n", this);
3382     return this->dp;
3383 }
3384
3385 /* ?decimal_point@?$numpunct@_W@std@@QBE_WXZ */
3386 /* ?decimal_point@?$numpunct@_W@std@@QEBA_WXZ */
3387 /* ?decimal_point@?$numpunct@G@std@@QBEGXZ */
3388 /* ?decimal_point@?$numpunct@G@std@@QEBAGXZ */
3389 static wchar_t numpunct_wchar_decimal_point(const numpunct_wchar *this)
3390 {
3391     TRACE("(%p)\n", this);
3392     return call_numpunct_wchar_do_decimal_point(this);
3393 }
3394
3395 /* ?do_thousands_sep@?$numpunct@_W@std@@MBE_WXZ */
3396 /* ?do_thousands_sep@?$numpunct@_W@std@@MEBA_WXZ */
3397 /* ?do_thousands_sep@?$numpunct@G@std@@MBEGXZ */
3398 /* ?do_thousands_sep@?$numpunct@G@std@@MEBAGXZ */
3399 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_thousands_sep, 4)
3400 #define call_numpunct_wchar_do_thousands_sep(this) CALL_VTBL_FUNC(this, 8, \
3401         wchar_t, (const numpunct_wchar *this), (this))
3402 wchar_t __thiscall numpunct_wchar_do_thousands_sep(const numpunct_wchar *this)
3403 {
3404     TRACE("(%p)\n", this);
3405     return this->sep;
3406 }
3407
3408 /* ?thousands_sep@?$numpunct@_W@std@@QBE_WXZ */
3409 /* ?thousands_sep@?$numpunct@_W@std@@QEBA_WXZ */
3410 /* ?thousands_sep@?$numpunct@G@std@@QBEGXZ */
3411 /* ?thousands_sep@?$numpunct@G@std@@QEBAGXZ */
3412 static wchar_t numpunct_wchar_thousands_sep(const numpunct_wchar *this)
3413 {
3414     TRACE("(%p)\n", this);
3415     return call_numpunct_wchar_do_thousands_sep(this);
3416 }
3417
3418 /* ?do_grouping@?$numpunct@_W@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3419 /* ?do_grouping@?$numpunct@_W@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3420 /* ?do_grouping@?$numpunct@G@std@@MBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3421 /* ?do_grouping@?$numpunct@G@std@@MEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3422 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_grouping, 8)
3423 #define call_numpunct_wchar_do_grouping(this, ret) CALL_VTBL_FUNC(this, 12, \
3424         basic_string_char*, (const numpunct_wchar*, basic_string_char*), (this, ret))
3425 basic_string_char* __thiscall numpunct_wchar_do_grouping(const numpunct_wchar *this, basic_string_char *ret)
3426 {
3427     TRACE("(%p)\n", this);
3428     return MSVCP_basic_string_char_ctor_cstr(ret, this->grouping);
3429 }
3430
3431 /* ?grouping@?$numpunct@_W@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3432 /* ?grouping@?$numpunct@_W@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3433 /* ?grouping@?$numpunct@G@std@@QBE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3434 /* ?grouping@?$numpunct@G@std@@QEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@XZ */
3435 static basic_string_char* numpunct_wchar_grouping(const numpunct_wchar *this, basic_string_char *ret)
3436 {
3437     TRACE("(%p)\n", this);
3438     return call_numpunct_wchar_do_grouping(this, ret);
3439 }
3440
3441 /* ?do_falsename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3442 /* ?do_falsename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3443 /* ?do_falsename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3444 /* ?do_falsename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3445 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_falsename, 8)
3446 #define call_numpunct_wchar_do_falsename(this, ret) CALL_VTBL_FUNC(this, 16, \
3447         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
3448 basic_string_wchar* __thiscall numpunct_wchar_do_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
3449 {
3450     TRACE("(%p)\n", this);
3451     return MSVCP_basic_string_wchar_ctor_cstr(ret, this->false_name);
3452 }
3453
3454 /* ?falsename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3455 /* ?falsename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3456 /* ?falsename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3457 /* ?falsename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3458 static basic_string_wchar* numpunct_wchar_falsename(const numpunct_wchar *this, basic_string_wchar *ret)
3459 {
3460     TRACE("(%p)\n", this);
3461     return call_numpunct_wchar_do_falsename(this, ret);
3462 }
3463
3464 /* ?do_truename@?$numpunct@_W@std@@MBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3465 /* ?do_truename@?$numpunct@_W@std@@MEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3466 /* ?do_truename@?$numpunct@G@std@@MBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3467 /* ?do_truename@?$numpunct@G@std@@MEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3468 DEFINE_THISCALL_WRAPPER(numpunct_wchar_do_truename, 8)
3469 #define call_numpunct_wchar_do_truename(this, ret) CALL_VTBL_FUNC(this, 20, \
3470         basic_string_wchar*, (const numpunct_wchar*, basic_string_wchar*), (this, ret))
3471 basic_string_wchar* __thiscall numpunct_wchar_do_truename(const numpunct_wchar *this, basic_string_wchar *ret)
3472 {
3473     TRACE("(%p)\n", this);
3474     return MSVCP_basic_string_wchar_ctor_cstr(ret, this->true_name);
3475 }
3476
3477 /* ?truename@?$numpunct@_W@std@@QBE?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3478 /* ?truename@?$numpunct@_W@std@@QEBA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@2@XZ */
3479 /* ?truename@?$numpunct@G@std@@QBE?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3480 /* ?truename@?$numpunct@G@std@@QEBA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@2@XZ */
3481 static basic_string_wchar* numpunct_wchar_truename(const numpunct_wchar *this, basic_string_wchar *ret)
3482 {
3483     TRACE("(%p)\n", this);
3484     return call_numpunct_wchar_do_truename(this, ret);
3485 }
3486
3487 double __cdecl _Stod(const char *buf, char **buf_end, LONG exp)
3488 {
3489     double ret = strtod(buf, buf_end);
3490
3491     if(exp)
3492         ret *= pow(10, exp);
3493     return ret;
3494 }
3495
3496 double __cdecl _Stodx(const char *buf, char **buf_end, LONG exp, int *err)
3497 {
3498     double ret;
3499
3500     *err = *_errno();
3501     *_errno() = 0;
3502     ret = _Stod(buf, buf_end, exp);
3503     if(*_errno()) {
3504         *err = *_errno();
3505     }else {
3506         *_errno() = *err;
3507         *err = 0;
3508     }
3509     return ret;
3510 }
3511
3512 float __cdecl _Stof(const char *buf, char **buf_end, LONG exp)
3513 {
3514     return _Stod(buf, buf_end, exp);
3515 }
3516
3517 float __cdecl _Stofx(const char *buf, char **buf_end, LONG exp, int *err)
3518 {
3519     return _Stodx(buf, buf_end, exp, err);
3520 }
3521
3522 __int64 __cdecl _Stoll(const char *buf, char **buf_end, int base)
3523 {
3524     return _strtoi64(buf, buf_end, base);
3525 }
3526
3527 __int64 __cdecl _Stollx(const char *buf, char **buf_end, int base, int *err)
3528 {
3529     __int64 ret;
3530
3531     *err = *_errno();
3532     *_errno() = 0;
3533     ret = _strtoi64(buf, buf_end, base);
3534     if(*_errno()) {
3535         *err = *_errno();
3536     }else {
3537         *_errno() = *err;
3538         *err = 0;
3539     }
3540     return ret;
3541 }
3542
3543 LONG __cdecl _Stolx(const char *buf, char **buf_end, int base, int *err)
3544 {
3545     __int64 i = _Stollx(buf, buf_end, base, err);
3546     if(!*err && i!=(__int64)((LONG)i))
3547         *err = ERANGE;
3548     return i;
3549 }
3550
3551 unsigned __int64 __cdecl _Stoull(const char *buf, char **buf_end, int base)
3552 {
3553     return _strtoui64(buf, buf_end, base);
3554 }
3555
3556 unsigned __int64 __cdecl _Stoullx(const char *buf, char **buf_end, int base, int *err)
3557 {
3558     unsigned __int64 ret;
3559
3560     *err = *_errno();
3561     *_errno() = 0;
3562     ret = _strtoui64(buf, buf_end, base);
3563     if(*_errno()) {
3564         *err = *_errno();
3565     }else {
3566         *_errno() = *err;
3567         *err = 0;
3568     }
3569     return ret;
3570 }
3571
3572 ULONG __cdecl _Stoul(const char *buf, char **buf_end, int base)
3573 {
3574     int err;
3575     unsigned __int64 i = _Stoullx(buf[0]=='-' ? buf+1 : buf, buf_end, base, &err);
3576     if(!err && i!=(unsigned __int64)((ULONG)i))
3577         *_errno() = ERANGE;
3578     return buf[0]=='-' ? -i : i;
3579 }
3580
3581 ULONG __cdecl _Stoulx(const char *buf, char **buf_end, int base, int *err)
3582 {
3583     unsigned __int64 i = _Stoullx(buf[0]=='-' ? buf+1 : buf, buf_end, base, err);
3584     if(!*err && i!=(unsigned __int64)((ULONG)i))
3585         *err = ERANGE;
3586     return buf[0]=='-' ? -i : i;
3587 }
3588
3589 /* ?id@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
3590 locale_id num_get_wchar_id = {0};
3591 /* ?id@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
3592 locale_id num_get_short_id = {0};
3593
3594 /* ??_7?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
3595 extern const vtable_ptr MSVCP_num_get_wchar_vtable;
3596 /* ??_7?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
3597 extern const vtable_ptr MSVCP_num_get_short_vtable;
3598
3599 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
3600 /* ?_Init@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
3601 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
3602 /* ?_Init@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
3603 DEFINE_THISCALL_WRAPPER(num_get_wchar__Init, 8)
3604 void __thiscall num_get_wchar__Init(num_get *this, const _Locinfo *locinfo)
3605 {
3606     TRACE("(%p %p)\n", this, locinfo);
3607     _Locinfo__Getcvt(locinfo, &this->cvt);
3608 }
3609
3610 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
3611 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3612 DEFINE_THISCALL_WRAPPER(num_get_wchar_ctor_locinfo, 12)
3613 num_get* __thiscall num_get_wchar_ctor_locinfo(num_get *this,
3614         const _Locinfo *locinfo, MSVCP_size_t refs)
3615 {
3616     TRACE("(%p %p %lu)\n", this, locinfo, refs);
3617
3618     locale_facet_ctor_refs(&this->facet, refs);
3619     this->facet.vtable = &MSVCP_num_get_wchar_vtable;
3620
3621     num_get_wchar__Init(this, locinfo);
3622     return this;
3623 }
3624
3625 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
3626 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
3627 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_locinfo, 12)
3628 num_get* __thiscall num_get_short_ctor_locinfo(num_get *this,
3629         const _Locinfo *locinfo, MSVCP_size_t refs)
3630 {
3631     num_get_wchar_ctor_locinfo(this, locinfo, refs);
3632     this->facet.vtable = &MSVCP_num_get_short_vtable;
3633     return this;
3634 }
3635
3636 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
3637 /* ??0?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
3638 DEFINE_THISCALL_WRAPPER(num_get_wchar_ctor_refs, 8)
3639 num_get* __thiscall num_get_wchar_ctor_refs(num_get *this, MSVCP_size_t refs)
3640 {
3641     _Locinfo locinfo;
3642
3643     TRACE("(%p %lu)\n", this, refs);
3644
3645     _Locinfo_ctor(&locinfo);
3646     num_get_wchar_ctor_locinfo(this, &locinfo, refs);
3647     _Locinfo_dtor(&locinfo);
3648     return this;
3649 }
3650
3651 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
3652 /* ??0?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
3653 DEFINE_THISCALL_WRAPPER(num_get_short_ctor_refs, 8)
3654 num_get* __thiscall num_get_short_ctor_refs(num_get *this, MSVCP_size_t refs)
3655 {
3656     num_get_wchar_ctor_refs(this, refs);
3657     this->facet.vtable = &MSVCP_num_get_short_vtable;
3658     return this;
3659 }
3660
3661 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
3662 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
3663 DEFINE_THISCALL_WRAPPER(num_get_wchar_ctor, 4)
3664 num_get* __thiscall num_get_wchar_ctor(num_get *this)
3665 {
3666     return num_get_wchar_ctor_refs(this, 0);
3667 }
3668
3669 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
3670 /* ??_F?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
3671 DEFINE_THISCALL_WRAPPER(num_get_short_ctor, 4)
3672 num_get* __thiscall num_get_short_ctor(num_get *this)
3673 {
3674     return num_get_short_ctor_refs(this, 0);
3675 }
3676
3677 /* ??1?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
3678 /* ??1?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
3679 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
3680 /* ??1?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
3681 DEFINE_THISCALL_WRAPPER(num_get_wchar_dtor, 4)
3682 void __thiscall num_get_wchar_dtor(num_get *this)
3683 {
3684     TRACE("(%p)\n", this);
3685     locale_facet_dtor(&this->facet);
3686 }
3687
3688 DEFINE_THISCALL_WRAPPER(num_get_wchar_vector_dtor, 8)
3689 num_get* __thiscall num_get_wchar_vector_dtor(num_get *this, unsigned int flags)
3690 {
3691     TRACE("(%p %x)\n", this, flags);
3692     if(flags & 2) {
3693         /* we have an array, with the number of elements stored before the first object */
3694         INT_PTR i, *ptr = (INT_PTR *)this-1;
3695
3696         for(i=*ptr-1; i>=0; i--)
3697             num_get_wchar_dtor(this+i);
3698         MSVCRT_operator_delete(ptr);
3699     } else {
3700         num_get_wchar_dtor(this);
3701         if(flags & 1)
3702             MSVCRT_operator_delete(this);
3703     }
3704
3705     return this;
3706 }
3707
3708 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3709 /* ?_Getcat@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3710 MSVCP_size_t __cdecl num_get_wchar__Getcat(const locale_facet **facet, const locale *loc)
3711 {
3712     TRACE("(%p %p)\n", facet, loc);
3713
3714     if(facet && !*facet) {
3715         _Locinfo locinfo;
3716
3717         *facet = MSVCRT_operator_new(sizeof(num_get));
3718         if(!*facet) {
3719             ERR("Out of memory\n");
3720             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
3721             return 0;
3722         }
3723
3724         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
3725         num_get_wchar_ctor_locinfo((num_get*)*facet, &locinfo, 0);
3726         _Locinfo_dtor(&locinfo);
3727     }
3728
3729     return LC_NUMERIC;
3730 }
3731
3732 num_get* num_get_wchar_use_facet(const locale *loc)
3733 {
3734         static num_get *obj = NULL;
3735
3736         _Lockit lock;
3737         const locale_facet *fac;
3738
3739         _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3740         fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_wchar_id));
3741         if(fac) {
3742             _Lockit_dtor(&lock);
3743             return (num_get*)fac;
3744         }
3745
3746         if(obj) {
3747             _Lockit_dtor(&lock);
3748             return obj;
3749         }
3750
3751         num_get_wchar__Getcat(&fac, loc);
3752         obj = (num_get*)fac;
3753         locale_facet__Incref(&obj->facet);
3754         locale_facet_register(&obj->facet);
3755         _Lockit_dtor(&lock);
3756
3757         return obj;
3758 }
3759
3760 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
3761 /* ?_Getcat@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
3762 MSVCP_size_t __cdecl num_get_short__Getcat(const locale_facet **facet, const locale *loc)
3763 {
3764     if(facet && !*facet) {
3765         num_get_wchar__Getcat(facet, loc);
3766         (*(locale_facet**)facet)->vtable = &MSVCP_num_get_short_vtable;
3767     }
3768
3769     return LC_NUMERIC;
3770 }
3771
3772 num_get* num_get_short_use_facet(const locale *loc)
3773 {
3774     static num_get *obj = NULL;
3775
3776     _Lockit lock;
3777     const locale_facet *fac;
3778
3779     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
3780     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_short_id));
3781     if(fac) {
3782         _Lockit_dtor(&lock);
3783         return (num_get*)fac;
3784     }
3785
3786     if(obj) {
3787         _Lockit_dtor(&lock);
3788         return obj;
3789     }
3790
3791     num_get_short__Getcat(&fac, loc);
3792     obj = (num_get*)fac;
3793     locale_facet__Incref(&obj->facet);
3794     locale_facet_register(&obj->facet);
3795     _Lockit_dtor(&lock);
3796
3797     return obj;
3798 }
3799
3800 static inline wchar_t mb_to_wc(char ch, const _Cvtvec *cvt)
3801 {
3802     int state = 0;
3803     wchar_t ret;
3804
3805     return _Mbrtowc(&ret, &ch, 1, &state, cvt) == 1 ? ret : 0;
3806 }
3807
3808 static int num_get__Getffld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
3809         istreambuf_iterator_wchar *last, const locale *loc, numpunct_wchar *numpunct)
3810 {
3811     basic_string_char grouping_bstr;
3812     basic_string_char groups_found;
3813     int i, groups_no = 0, cur_group = 0, exp = 0;
3814     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31;
3815     wchar_t sep, digits[11], *digits_pos;
3816     const char *grouping, *groups;
3817     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
3818
3819     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
3820
3821     for(i=0; i<10; i++)
3822         digits[i] = mb_to_wc('0'+i, &this->cvt);
3823     digits[10] = 0;
3824
3825     numpunct_wchar_grouping(numpunct, &grouping_bstr);
3826     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
3827     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : 0;
3828
3829     if(sep)
3830         MSVCP_basic_string_char_ctor(&groups_found);
3831
3832     istreambuf_iterator_wchar_val(first);
3833     /* get sign */
3834     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
3835         *dest++ = '-';
3836         istreambuf_iterator_wchar_inc(first);
3837     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
3838         *dest++ = '+';
3839         istreambuf_iterator_wchar_inc(first);
3840     }
3841
3842     /* read possibly grouped numbers before decimal */
3843     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
3844         if(!(digits_pos = wcschr(digits, first->val))) {
3845             if(sep && first->val==sep) {
3846                 if(!groups_no) break; /* empty group - stop parsing */
3847                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
3848                 groups_no = 0;
3849                 ++cur_group;
3850             }else {
3851                 break;
3852             }
3853         }else {
3854             got_digit = TRUE; /* found a digit, zero or non-zero */
3855             /* write digit to dest if not a leading zero (to not waste dest buffer) */
3856             if(!got_nonzero && first->val == digits[0])
3857             {
3858                 ++groups_no;
3859                 continue;
3860             }
3861             got_nonzero = TRUE;
3862             if(dest < num_end)
3863                 *dest++ = '0'+digits_pos-digits;
3864             else
3865                 exp++; /* too many digits, just multiply by 10 */
3866             if(sep && groups_no<CHAR_MAX)
3867                 ++groups_no;
3868         }
3869     }
3870
3871     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
3872     if(got_digit && !got_nonzero)
3873         *dest++ = '0';
3874
3875     /* get decimal, if any */
3876     if(first->strbuf && first->val==numpunct_wchar_decimal_point(numpunct)) {
3877         if(dest < num_end)
3878             *dest++ = *localeconv()->decimal_point;
3879         istreambuf_iterator_wchar_inc(first);
3880     }
3881
3882     /* read non-grouped after decimal */
3883     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
3884         if(!(digits_pos = wcschr(digits, first->val)))
3885             break;
3886         else if(dest<num_end) {
3887             got_digit = TRUE;
3888             *dest++ = '0'+digits_pos-digits;
3889         }
3890     }
3891
3892     /* read exponent, if any */
3893     if(first->strbuf && (first->val==mb_to_wc('e', &this->cvt) || first->val==mb_to_wc('E', &this->cvt))) {
3894         *dest++ = 'e';
3895         istreambuf_iterator_wchar_inc(first);
3896
3897         if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
3898             *dest++ = '-';
3899             istreambuf_iterator_wchar_inc(first);
3900         }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
3901             *dest++ = '+';
3902             istreambuf_iterator_wchar_inc(first);
3903         }
3904
3905         got_digit = got_nonzero = FALSE;
3906         error = TRUE;
3907         /* skip any leading zeroes */
3908         for(; first->strbuf && first->val==digits[0]; istreambuf_iterator_wchar_inc(first))
3909             error = FALSE;
3910
3911         for(; first->strbuf && (digits_pos = wcschr(digits, first->val)); istreambuf_iterator_wchar_inc(first)) {
3912             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
3913             error = FALSE;
3914             if(dest<exp_end)
3915                 *dest++ = '0'+digits_pos-digits;
3916         }
3917
3918         /* if just found zeroes for exponent, use that */
3919         if(got_digit && !got_nonzero)
3920         {
3921             error = FALSE;
3922             if(dest<exp_end)
3923                 *dest++ = '0';
3924         }
3925     }
3926
3927     if(sep && groups_no)
3928         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
3929
3930     if(!cur_group) /* no groups, skip loop */
3931         cur_group--;
3932     else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group])
3933         error = TRUE; /* trailing empty */
3934
3935     for(; cur_group>=0 && !error; cur_group--) {
3936         if(*grouping == CHAR_MAX) {
3937             if(cur_group)
3938                 error = TRUE;
3939             break;
3940         }else if((cur_group && *grouping!=groups[cur_group])
3941                 || (!cur_group && *grouping<groups[cur_group])) {
3942             error = TRUE;
3943             break;
3944         }else if(grouping[1]) {
3945             grouping++;
3946         }
3947     }
3948     MSVCP_basic_string_char_dtor(&grouping_bstr);
3949     if(sep)
3950         MSVCP_basic_string_char_dtor(&groups_found);
3951
3952     if(error) {
3953         *dest_beg = '\0';
3954         return 0;
3955     }
3956     *dest++ = '\0';
3957     return exp;
3958 }
3959
3960 /* ?_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 */
3961 /* ?_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 */
3962 /* ?_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 */
3963 /* ?_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 */
3964 int __cdecl num_get_wchar__Getffldx(num_get *this, char *dest, istreambuf_iterator_wchar *first,
3965     istreambuf_iterator_wchar *last, ios_base *ios, int *phexexp)
3966 {
3967     FIXME("(%p %p %p %p %p) stub\n", dest, first, last, ios, phexexp);
3968     return -1;
3969 }
3970
3971 static int num_get__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
3972     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc, numpunct_wchar *numpunct)
3973 {
3974     wchar_t digits[23], *digits_pos, sep;
3975     basic_string_char grouping_bstr;
3976     basic_string_char groups_found;
3977     int i, basefield, base, groups_no = 0, cur_group = 0;
3978     char *dest_beg = dest, *dest_end = dest+24;
3979     const char *grouping, *groups;
3980     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
3981
3982     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
3983
3984     for(i=0; i<10; i++)
3985         digits[i] = mb_to_wc('0'+i, &this->cvt);
3986     for(i=0; i<6; i++) {
3987         digits[10+i] = mb_to_wc('a'+i, &this->cvt);
3988         digits[16+i] = mb_to_wc('A'+i, &this->cvt);
3989     }
3990
3991     numpunct_wchar_grouping(numpunct, &grouping_bstr);
3992     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
3993     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
3994
3995     basefield = fmtflags & FMTFLAG_basefield;
3996     if(basefield == FMTFLAG_oct)
3997         base = 8;
3998     else if(basefield == FMTFLAG_hex)
3999         base = 22; /* equal to the size of digits buffer */
4000     else if(!basefield)
4001         base = 0;
4002     else
4003         base = 10;
4004
4005     istreambuf_iterator_wchar_val(first);
4006     if(first->strbuf && first->val==mb_to_wc('-', &this->cvt)) {
4007         *dest++ = '-';
4008         istreambuf_iterator_wchar_inc(first);
4009     }else if(first->strbuf && first->val==mb_to_wc('+', &this->cvt)) {
4010         *dest++ = '+';
4011         istreambuf_iterator_wchar_inc(first);
4012     }
4013
4014     if(first->strbuf && first->val==digits[0]) {
4015         found_zero = TRUE;
4016         istreambuf_iterator_wchar_inc(first);
4017         if(first->strbuf && (first->val==mb_to_wc('x', &this->cvt) || first->val==mb_to_wc('X', &this->cvt))) {
4018             if(!base || base == 22) {
4019                 found_zero = FALSE;
4020                 istreambuf_iterator_wchar_inc(first);
4021                 base = 22;
4022             }else {
4023                 base = 10;
4024             }
4025         }else {
4026             error = FALSE;
4027             if(!base) base = 8;
4028         }
4029     }else {
4030         if(!base) base = 10;
4031     }
4032     digits[base] = 0;
4033
4034     if(sep) {
4035         MSVCP_basic_string_char_ctor(&groups_found);
4036         if(found_zero) ++groups_no;
4037     }
4038
4039     for(; first->strbuf; istreambuf_iterator_wchar_inc(first)) {
4040         if(!(digits_pos = wcschr(digits, first->val))) {
4041             if(sep && first->val==sep) {
4042                 if(!groups_no) break; /* empty group - stop parsing */
4043                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4044                 groups_no = 0;
4045                 ++cur_group;
4046             }else {
4047                 break;
4048             }
4049         }else {
4050             error = FALSE;
4051             if(dest_empty && first->val == digits[0]) {
4052                 found_zero = TRUE;
4053                 ++groups_no;
4054                 continue;
4055             }
4056             dest_empty = FALSE;
4057             /* skip digits that can't be copied to dest buffer, other
4058              * functions are responsible for detecting overflows */
4059             if(dest < dest_end)
4060                 *dest++ = (digits_pos-digits<10 ? '0'+digits_pos-digits :
4061                         (digits_pos-digits<16 ? 'a'+digits_pos-digits-10 :
4062                          'A'+digits_pos-digits-16));
4063             if(sep && groups_no<CHAR_MAX)
4064                 ++groups_no;
4065         }
4066     }
4067
4068     if(sep && groups_no)
4069         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4070
4071     if(!cur_group) { /* no groups, skip loop */
4072         cur_group--;
4073     }else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group]) {
4074         error = TRUE; /* trailing empty */
4075         found_zero = FALSE;
4076     }
4077
4078     for(; cur_group>=0 && !error; cur_group--) {
4079         if(*grouping == CHAR_MAX) {
4080             if(cur_group)
4081                 error = TRUE;
4082             break;
4083         }else if((cur_group && *grouping!=groups[cur_group])
4084                 || (!cur_group && *grouping<groups[cur_group])) {
4085             error = TRUE;
4086             break;
4087         }else if(grouping[1]) {
4088             grouping++;
4089         }
4090     }
4091
4092     MSVCP_basic_string_char_dtor(&grouping_bstr);
4093     if(sep)
4094         MSVCP_basic_string_char_dtor(&groups_found);
4095
4096     if(error) {
4097         if (found_zero)
4098             *dest++ = '0';
4099         else
4100             dest = dest_beg;
4101     }else if(dest_empty)
4102         *dest++ = '0';
4103     *dest = '\0';
4104
4105     return (base==22 ? 16 : base);
4106 }
4107
4108 /* ?_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 */
4109 /* ?_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 */
4110 int __cdecl num_get_wchar__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4111     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc)
4112 {
4113     return num_get__Getifld(this, dest, first, last,
4114             fmtflags, loc, numpunct_wchar_use_facet(loc));
4115 }
4116
4117 /* ?_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 */
4118 /* ?_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 */
4119 int __cdecl num_get_short__Getifld(const num_get *this, char *dest, istreambuf_iterator_wchar *first,
4120     istreambuf_iterator_wchar *last, int fmtflags, const locale *loc)
4121 {
4122     return num_get__Getifld(this, dest, first, last,
4123             fmtflags, loc, numpunct_short_use_facet(loc));
4124 }
4125
4126 /* ?_Hexdig@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABEH_W000@Z */
4127 /* ?_Hexdig@?$num_get@_WV?$istreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAH_W000@Z */
4128 /* ?_Hexdig@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABEHGGGG@Z */
4129 /* ?_Hexdig@?$num_get@GV?$istreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAHGGGG@Z */
4130 DEFINE_THISCALL_WRAPPER(MSVCP_num_get_wchar__Hexdig, 20)
4131 int __thiscall MSVCP_num_get_wchar__Hexdig(num_get *this, wchar_t dig, wchar_t e0, wchar_t al, wchar_t au)
4132 {
4133     FIXME("(%p %c %c %c %c) stub\n", this, dig, e0, al, au);
4134     return -1;
4135 }
4136
4137 static istreambuf_iterator_wchar* num_get_do_get_void(const num_get *this,
4138         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4139         istreambuf_iterator_wchar last, ios_base *base, int *state,
4140         void **pval, numpunct_wchar *numpunct)
4141 {
4142     unsigned __int64 v;
4143     char tmp[25], *end;
4144     int err;
4145
4146     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4147
4148     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4149                 &last, FMTFLAG_hex, base->loc, numpunct), &err);
4150     if(v!=(unsigned __int64)((INT_PTR)v))
4151         *state |= IOSTATE_failbit;
4152     else if(end!=tmp && !err)
4153         *pval = (void*)((INT_PTR)v);
4154     else
4155         *state |= IOSTATE_failbit;
4156
4157     if(!first.strbuf)
4158         *state |= IOSTATE_eofbit;
4159
4160     *ret = first;
4161     return ret;
4162 }
4163
4164 /* ?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 */
4165 /* ?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 */
4166 #define call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_wchar*, \
4167         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, void**), \
4168         (this, ret, first, last, base, state, pval))
4169 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_void,36)
4170 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4171     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4172 {
4173     return num_get_do_get_void(this, ret, first, last, base,
4174             state, pval, numpunct_wchar_use_facet(base->loc));
4175 }
4176
4177 /* ?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 */
4178 /* ?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 */
4179 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_void,36)
4180 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4181     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4182 {
4183     return num_get_do_get_void(this, ret, first, last, base,
4184             state, pval, numpunct_short_use_facet(base->loc));
4185 }
4186
4187 /* ?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 */
4188 /* ?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 */
4189 /* ?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 */
4190 /* ?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 */
4191 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_void,36)
4192 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_void(const num_get *this, istreambuf_iterator_wchar *ret,
4193     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, void **pval)
4194 {
4195     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4196     return call_num_get_wchar_do_get_void(this, ret, first, last, base, state, pval);
4197 }
4198
4199 static istreambuf_iterator_wchar* num_get_do_get_double(const num_get *this,
4200         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4201         istreambuf_iterator_wchar last, ios_base *base, int *state,
4202         double *pval, numpunct_wchar *numpunct)
4203 {
4204     double v;
4205     char tmp[32], *end;
4206     int err;
4207
4208     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4209
4210     v = _Stodx(tmp, &end, num_get__Getffld(this, tmp, &first, &last, base->loc, numpunct), &err);
4211     if(end!=tmp && !err)
4212         *pval = v;
4213     else
4214         *state |= IOSTATE_failbit;
4215
4216     if(!first.strbuf)
4217         *state |= IOSTATE_eofbit;
4218
4219     *ret = first;
4220     return ret;
4221 }
4222
4223 /* ?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 */
4224 /* ?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 */
4225 /* ?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 */
4226 /* ?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 */
4227 #define call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_wchar*, \
4228         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4229         (this, ret, first, last, base, state, pval))
4230 #define call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_wchar*, \
4231         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, double*), \
4232         (this, ret, first, last, base, state, pval))
4233 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_double,36)
4234 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4235     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4236 {
4237     return num_get_do_get_double(this, ret, first, last, base,
4238             state, pval, numpunct_wchar_use_facet(base->loc));
4239 }
4240
4241 /* ?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 */
4242 /* ?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 */
4243 /* ?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 */
4244 /* ?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 */
4245 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_double,36)
4246 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4247     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4248 {
4249     return num_get_do_get_double(this, ret, first, last, base,
4250             state, pval, numpunct_short_use_facet(base->loc));
4251 }
4252
4253 /* ?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 */
4254 /* ?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 */
4255 /* ?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 */
4256 /* ?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 */
4257 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ldouble,36)
4258 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ldouble(const num_get *this, istreambuf_iterator_wchar *ret,
4259         istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4260 {
4261     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4262     return call_num_get_wchar_do_get_ldouble(this, ret, first, last, base, state, pval);
4263 }
4264
4265 /* ?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 */
4266 /* ?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 */
4267 /* ?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 */
4268 /* ?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 */
4269 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_double,36)
4270 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_double(const num_get *this, istreambuf_iterator_wchar *ret,
4271     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, double *pval)
4272 {
4273     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4274     return call_num_get_wchar_do_get_double(this, ret, first, last, base, state, pval);
4275 }
4276
4277 static istreambuf_iterator_wchar* num_get_do_get_float(const num_get *this,
4278         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4279         istreambuf_iterator_wchar last, ios_base *base, int *state,
4280         float *pval, numpunct_wchar *numpunct)
4281 {
4282     float v;
4283     char tmp[32], *end;
4284     int err;
4285
4286     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4287
4288     v = _Stofx(tmp, &end, num_get__Getffld(this, tmp, &first,
4289                 &last, base->loc, numpunct), &err);
4290     if(end!=tmp && !err)
4291         *pval = v;
4292     else
4293         *state |= IOSTATE_failbit;
4294
4295     if(!first.strbuf)
4296         *state |= IOSTATE_eofbit;
4297
4298     *ret = first;
4299     return ret;
4300 }
4301
4302 /* ?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 */
4303 /* ?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 */
4304 #define call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_wchar*, \
4305         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, float*), \
4306         (this, ret, first, last, base, state, pval))
4307 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_float,36)
4308 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4309     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4310 {
4311     return num_get_do_get_float(this, ret, first, last, base,
4312             state, pval, numpunct_wchar_use_facet(base->loc));
4313 }
4314
4315 /* ?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 */
4316 /* ?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 */
4317 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_float,36)
4318 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4319     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4320 {
4321     return num_get_do_get_float(this, ret, first, last, base,
4322             state, pval, numpunct_short_use_facet(base->loc));
4323 }
4324
4325 /* ?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 */
4326 /* ?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 */
4327 /* ?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 */
4328 /* ?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 */
4329 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_float,36)
4330 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_float(const num_get *this, istreambuf_iterator_wchar *ret,
4331     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, float *pval)
4332 {
4333     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4334     return call_num_get_wchar_do_get_float(this, ret, first, last, base, state, pval);
4335 }
4336
4337 static istreambuf_iterator_wchar* num_get_do_get_uint64(const num_get *this,
4338         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4339         istreambuf_iterator_wchar last, ios_base *base, int *state,
4340         ULONGLONG *pval, numpunct_wchar *numpunct)
4341 {
4342     unsigned __int64 v;
4343     char tmp[25], *end;
4344     int err;
4345
4346     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4347
4348     v = _Stoullx(tmp, &end, num_get__Getifld(this, tmp, &first,
4349                 &last, base->fmtfl, base->loc, numpunct), &err);
4350     if(end!=tmp && !err)
4351         *pval = v;
4352     else
4353         *state |= IOSTATE_failbit;
4354
4355     if(!first.strbuf)
4356         *state |= IOSTATE_eofbit;
4357
4358     *ret = first;
4359     return ret;
4360 }
4361
4362 /* ?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 */
4363 /* ?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 */
4364 #define call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_wchar*, \
4365         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONGLONG*), \
4366         (this, ret, first, last, base, state, pval))
4367 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint64,36)
4368 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4369     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4370 {
4371     return num_get_do_get_uint64(this, ret, first, last, base,
4372             state, pval, numpunct_wchar_use_facet(base->loc));
4373 }
4374
4375 /* ?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 */
4376 /* ?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 */
4377 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint64,36)
4378 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4379     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4380 {
4381     return num_get_do_get_uint64(this, ret, first, last, base,
4382             state, pval, numpunct_short_use_facet(base->loc));
4383 }
4384
4385 /* ?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 */
4386 /* ?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 */
4387 /* ?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 */
4388 /* ?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 */
4389 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint64,36)
4390 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint64(const num_get *this, istreambuf_iterator_wchar *ret,
4391     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONGLONG *pval)
4392 {
4393     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4394     return call_num_get_wchar_do_get_uint64(this, ret, first, last, base, state, pval);
4395 }
4396
4397 static istreambuf_iterator_wchar* num_get_do_get_int64(const num_get *this,
4398         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4399         istreambuf_iterator_wchar last, ios_base *base, int *state,
4400         LONGLONG *pval, numpunct_wchar *numpunct)
4401 {
4402     __int64 v;
4403     char tmp[25], *end;
4404     int err;
4405
4406     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4407
4408     v = _Stollx(tmp, &end, num_get__Getifld(this, tmp, &first,
4409                 &last, base->fmtfl, base->loc, numpunct), &err);
4410     if(end!=tmp && !err)
4411         *pval = v;
4412     else
4413         *state |= IOSTATE_failbit;
4414
4415     if(!first.strbuf)
4416         *state |= IOSTATE_eofbit;
4417
4418     *ret = first;
4419     return ret;
4420 }
4421
4422 /* ?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 */
4423 /* ?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 */
4424 #define call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_wchar*, \
4425         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONGLONG*), \
4426         (this, ret, first, last, base, state, pval))
4427 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_int64,36)
4428 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4429     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4430 {
4431     return num_get_do_get_int64(this, ret, first, last, base,
4432             state, pval, numpunct_wchar_use_facet(base->loc));
4433 }
4434
4435 /* ?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 */
4436 /* ?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 */
4437 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_int64,36)
4438 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4439     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4440 {
4441     return num_get_do_get_int64(this, ret, first, last, base,
4442             state, pval, numpunct_short_use_facet(base->loc));
4443 }
4444
4445 /* ?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 */
4446 /* ?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 */
4447 /* ?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 */
4448 /* ?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 */
4449 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_int64,36)
4450 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_int64(const num_get *this, istreambuf_iterator_wchar *ret,
4451     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONGLONG *pval)
4452 {
4453     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4454     return call_num_get_wchar_do_get_int64(this, ret, first, last, base, state, pval);
4455 }
4456
4457 static istreambuf_iterator_wchar* num_get_do_get_ulong(const num_get *this,
4458         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4459         istreambuf_iterator_wchar last, ios_base *base, int *state,
4460         ULONG *pval, numpunct_wchar *numpunct)
4461 {
4462     ULONG v;
4463     char tmp[25], *end;
4464     int err;
4465
4466     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4467
4468     v = _Stoulx(tmp, &end, num_get__Getifld(this, tmp, &first,
4469                 &last, base->fmtfl, base->loc, numpunct), &err);
4470     if(end!=tmp && !err)
4471         *pval = v;
4472     else
4473         *state |= IOSTATE_failbit;
4474
4475     if(!first.strbuf)
4476         *state |= IOSTATE_eofbit;
4477
4478     *ret = first;
4479     return ret;
4480 }
4481
4482 /* ?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 */
4483 /* ?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 */
4484 #define call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_wchar*, \
4485         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, ULONG*), \
4486         (this, ret, first, last, base, state, pval))
4487 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ulong,36)
4488 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4489     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4490 {
4491     return num_get_do_get_ulong(this, ret, first, last, base,
4492             state, pval, numpunct_wchar_use_facet(base->loc));
4493 }
4494
4495 /* ?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 */
4496 /* ?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 */
4497 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ulong,36)
4498 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4499     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4500 {
4501     return num_get_do_get_ulong(this, ret, first, last, base,
4502             state, pval, numpunct_short_use_facet(base->loc));
4503 }
4504
4505 /* ?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 */
4506 /* ?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 */
4507 /* ?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 */
4508 /* ?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 */
4509 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ulong,36)
4510 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ulong(const num_get *this, istreambuf_iterator_wchar *ret,
4511     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, ULONG *pval)
4512 {
4513     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4514     return call_num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
4515 }
4516
4517 static istreambuf_iterator_wchar* num_get_do_get_long(const num_get *this,
4518         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4519         istreambuf_iterator_wchar last, ios_base *base, int *state,
4520         LONG *pval, numpunct_wchar *numpunct)
4521 {
4522     LONG v;
4523     char tmp[25], *end;
4524     int err;
4525
4526     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4527
4528     v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
4529                 &last, base->fmtfl, base->loc, numpunct), &err);
4530     if(end!=tmp && !err)
4531         *pval = v;
4532     else
4533         *state |= IOSTATE_failbit;
4534
4535     if(!first.strbuf)
4536         *state |= IOSTATE_eofbit;
4537
4538     *ret = first;
4539     return ret;
4540 }
4541
4542 /* ?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 */
4543 /* ?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 */
4544 #define call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_wchar*, \
4545         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, LONG*), \
4546         (this, ret, first, last, base, state, pval))
4547 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_long,36)
4548 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4549     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4550 {
4551     return num_get_do_get_long(this, ret, first, last, base,
4552             state, pval, numpunct_wchar_use_facet(base->loc));
4553 }
4554
4555 /* ?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 */
4556 /* ?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 */
4557 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_long,36)
4558 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4559     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4560 {
4561     return num_get_do_get_long(this, ret, first, last, base,
4562         state, pval, numpunct_short_use_facet(base->loc));
4563 }
4564
4565 /* ?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 */
4566 /* ?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 */
4567 /* ?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 */
4568 /* ?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 */
4569 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_long,36)
4570 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_long(const num_get *this, istreambuf_iterator_wchar *ret,
4571     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, LONG *pval)
4572 {
4573     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4574     return call_num_get_wchar_do_get_long(this, ret, first, last, base, state, pval);
4575 }
4576
4577 /* ?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 */
4578 /* ?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 */
4579 #define call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_wchar*, \
4580         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned int*), \
4581         (this, ret, first, last, base, state, pval))
4582 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_uint,36)
4583 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4584     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4585 {
4586     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4587     return num_get_wchar_do_get_ulong(this, ret, first, last, base, state, pval);
4588 }
4589
4590 /* ?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 */
4591 /* ?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 */
4592 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_uint,36)
4593 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4594     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4595 {
4596     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4597     return num_get_short_do_get_ulong(this, ret, first, last, base, state, pval);
4598 }
4599
4600 /* ?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 */
4601 /* ?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 */
4602 /* ?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 */
4603 /* ?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 */
4604 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_uint,36)
4605 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_uint(const num_get *this, istreambuf_iterator_wchar *ret,
4606     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned int *pval)
4607 {
4608     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4609     return call_num_get_wchar_do_get_uint(this, ret, first, last, base, state, pval);
4610 }
4611
4612 /* ?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 */
4613 /* ?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 */
4614 #define call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_wchar*, \
4615         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, unsigned short*), \
4616         (this, ret, first, last, base, state, pval))
4617 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_ushort,36)
4618 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4619     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4620 {
4621     ULONG v;
4622     char tmp[25], *beg, *end;
4623     int err, b;
4624
4625     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4626
4627     b = num_get_wchar__Getifld(this, tmp,
4628             &first, &last, base->fmtfl, base->loc);
4629     beg = tmp + (tmp[0]=='-' ? 1 : 0);
4630     v = _Stoulx(beg, &end, b, &err);
4631
4632     if(v != (ULONG)((unsigned short)v))
4633         *state |= IOSTATE_failbit;
4634     else if(end!=beg && !err)
4635         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
4636     else
4637         *state |= IOSTATE_failbit;
4638
4639     if(!first.strbuf)
4640         *state |= IOSTATE_eofbit;
4641
4642     *ret = first;
4643     return ret;
4644 }
4645
4646 /* ?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 */
4647 /* ?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 */
4648 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_ushort,36)
4649 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4650     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4651 {
4652     FIXME("(%p %p %p %p %p) stub\n", this, ret, base, state, pval);
4653     return ret;
4654 }
4655
4656 /* ?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 */
4657 /* ?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 */
4658 /* ?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@ */
4659 /* ?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 */
4660 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_ushort,36)
4661 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_ushort(const num_get *this, istreambuf_iterator_wchar *ret,
4662     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, unsigned short *pval)
4663 {
4664     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4665     return call_num_get_wchar_do_get_ushort(this, ret, first, last, base, state, pval);
4666 }
4667
4668 static istreambuf_iterator_wchar* num_get_do_get_bool(const num_get *this,
4669         istreambuf_iterator_wchar *ret, istreambuf_iterator_wchar first,
4670         istreambuf_iterator_wchar last, ios_base *base, int *state,
4671         MSVCP_bool *pval, numpunct_wchar *numpunct)
4672 {
4673     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4674
4675     if(base->fmtfl & FMTFLAG_boolalpha) {
4676         basic_string_wchar false_bstr, true_bstr;
4677         const wchar_t *pfalse, *ptrue;
4678
4679         numpunct_wchar_falsename(numpunct, &false_bstr);
4680         numpunct_wchar_truename(numpunct, &true_bstr);
4681         pfalse = MSVCP_basic_string_wchar_c_str(&false_bstr);
4682         ptrue = MSVCP_basic_string_wchar_c_str(&true_bstr);
4683
4684         for(istreambuf_iterator_wchar_val(&first); first.strbuf;
4685                 istreambuf_iterator_wchar_inc(&first)) {
4686             if(pfalse && *pfalse && first.val!=*pfalse)
4687                 pfalse = NULL;
4688             if(ptrue && *ptrue && first.val!=*ptrue)
4689                 ptrue = NULL;
4690
4691             if(pfalse && *pfalse && ptrue && !*ptrue)
4692                 ptrue = NULL;
4693             if(ptrue && *ptrue && pfalse && !*pfalse)
4694                 pfalse = NULL;
4695
4696             if(pfalse)
4697                 pfalse++;
4698             if(ptrue)
4699                 ptrue++;
4700
4701             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
4702                 break;
4703         }
4704
4705         if(ptrue)
4706             *pval = TRUE;
4707         else if(pfalse)
4708             *pval = FALSE;
4709         else
4710             *state |= IOSTATE_failbit;
4711
4712         MSVCP_basic_string_wchar_dtor(&false_bstr);
4713         MSVCP_basic_string_wchar_dtor(&true_bstr);
4714     }else {
4715         char tmp[25], *end;
4716         int err;
4717         LONG v = _Stolx(tmp, &end, num_get__Getifld(this, tmp, &first,
4718                     &last, base->fmtfl, base->loc, numpunct), &err);
4719
4720         if(end!=tmp && err==0 && (v==0 || v==1))
4721             *pval = v;
4722         else
4723             *state |= IOSTATE_failbit;
4724     }
4725
4726     if(!first.strbuf)
4727         *state |= IOSTATE_eofbit;
4728     memcpy(ret, &first, sizeof(first));
4729     return ret;
4730 }
4731
4732 /* ?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 */
4733 /* ?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 */
4734 #define call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_wchar*, \
4735         (const num_get*, istreambuf_iterator_wchar*, istreambuf_iterator_wchar, istreambuf_iterator_wchar, ios_base*, int*, MSVCP_bool*), \
4736         (this, ret, first, last, base, state, pval))
4737 DEFINE_THISCALL_WRAPPER(num_get_wchar_do_get_bool,36)
4738 istreambuf_iterator_wchar *__thiscall num_get_wchar_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4739     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4740 {
4741     return num_get_do_get_bool(this, ret, first, last, base,
4742             state, pval, numpunct_wchar_use_facet(base->loc));
4743 }
4744
4745 /* ?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 */
4746 /* ?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 */
4747 DEFINE_THISCALL_WRAPPER(num_get_short_do_get_bool,36)
4748 istreambuf_iterator_wchar *__thiscall num_get_short_do_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4749     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4750 {
4751     return num_get_do_get_bool(this, ret, first, last, base,
4752             state, pval, numpunct_short_use_facet(base->loc));
4753 }
4754
4755 /* ?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 */
4756 /* ?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 */
4757 /* ?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 */
4758 /* ?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 */
4759 DEFINE_THISCALL_WRAPPER(num_get_wchar_get_bool,36)
4760 istreambuf_iterator_wchar *__thiscall num_get_wchar_get_bool(const num_get *this, istreambuf_iterator_wchar *ret,
4761     istreambuf_iterator_wchar first, istreambuf_iterator_wchar last, ios_base *base, int *state, MSVCP_bool *pval)
4762 {
4763     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
4764     return call_num_get_wchar_do_get_bool(this, ret, first, last, base, state, pval);
4765 }
4766
4767 /* ?id@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
4768 locale_id num_get_char_id = {0};
4769
4770 /* ??_7?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
4771 extern const vtable_ptr MSVCP_num_get_char_vtable;
4772
4773 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
4774 /* ?_Init@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
4775 DEFINE_THISCALL_WRAPPER(num_get_char__Init, 8)
4776 void __thiscall num_get_char__Init(num_get *this, const _Locinfo *locinfo)
4777 {
4778     TRACE("(%p %p)\n", this, locinfo);
4779     _Locinfo__Getcvt(locinfo, &this->cvt);
4780 }
4781
4782 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
4783 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
4784 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_locinfo, 12)
4785 num_get* __thiscall num_get_char_ctor_locinfo(num_get *this,
4786         const _Locinfo *locinfo, MSVCP_size_t refs)
4787 {
4788     TRACE("(%p %p %lu)\n", this, locinfo, refs);
4789
4790     locale_facet_ctor_refs(&this->facet, refs);
4791     this->facet.vtable = &MSVCP_num_get_char_vtable;
4792
4793     num_get_char__Init(this, locinfo);
4794     return this;
4795 }
4796
4797 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
4798 /* ??0?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
4799 DEFINE_THISCALL_WRAPPER(num_get_char_ctor_refs, 8)
4800 num_get* __thiscall num_get_char_ctor_refs(num_get *this, MSVCP_size_t refs)
4801 {
4802     _Locinfo locinfo;
4803
4804     TRACE("(%p %lu)\n", this, refs);
4805
4806     _Locinfo_ctor(&locinfo);
4807     num_get_char_ctor_locinfo(this, &locinfo, refs);
4808     _Locinfo_dtor(&locinfo);
4809     return this;
4810 }
4811
4812 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
4813 /* ??_F?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
4814 DEFINE_THISCALL_WRAPPER(num_get_char_ctor, 4)
4815 num_get* __thiscall num_get_char_ctor(num_get *this)
4816 {
4817     return num_get_char_ctor_refs(this, 0);
4818 }
4819
4820 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
4821 /* ??1?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
4822 DEFINE_THISCALL_WRAPPER(num_get_char_dtor, 4)
4823 void __thiscall num_get_char_dtor(num_get *this)
4824 {
4825     TRACE("(%p)\n", this);
4826     locale_facet_dtor(&this->facet);
4827 }
4828
4829 DEFINE_THISCALL_WRAPPER(num_get_char_vector_dtor, 8)
4830 num_get* __thiscall num_get_char_vector_dtor(num_get *this, unsigned int flags)
4831 {
4832     TRACE("(%p %x)\n", this, flags);
4833     if(flags & 2) {
4834         /* we have an array, with the number of elements stored before the first object */
4835         INT_PTR i, *ptr = (INT_PTR *)this-1;
4836
4837         for(i=*ptr-1; i>=0; i--)
4838             num_get_char_dtor(this+i);
4839         MSVCRT_operator_delete(ptr);
4840     } else {
4841         num_get_char_dtor(this);
4842         if(flags & 1)
4843             MSVCRT_operator_delete(this);
4844     }
4845
4846     return this;
4847 }
4848
4849 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
4850 /* ?_Getcat@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
4851 MSVCP_size_t __cdecl num_get_char__Getcat(const locale_facet **facet, const locale *loc)
4852 {
4853     TRACE("(%p %p)\n", facet, loc);
4854
4855     if(facet && !*facet) {
4856         _Locinfo locinfo;
4857
4858         *facet = MSVCRT_operator_new(sizeof(num_get));
4859         if(!*facet) {
4860             ERR("Out of memory\n");
4861             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
4862             return 0;
4863         }
4864
4865         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
4866         num_get_char_ctor_locinfo((num_get*)*facet, &locinfo, 0);
4867         _Locinfo_dtor(&locinfo);
4868     }
4869
4870     return LC_NUMERIC;
4871 }
4872
4873 num_get* num_get_char_use_facet(const locale *loc)
4874 {
4875     static num_get *obj = NULL;
4876
4877     _Lockit lock;
4878     const locale_facet *fac;
4879
4880     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
4881     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_get_char_id));
4882     if(fac) {
4883         _Lockit_dtor(&lock);
4884         return (num_get*)fac;
4885     }
4886
4887     if(obj) {
4888         _Lockit_dtor(&lock);
4889         return obj;
4890     }
4891
4892     num_get_char__Getcat(&fac, loc);
4893     obj = (num_get*)fac;
4894     locale_facet__Incref(&obj->facet);
4895     locale_facet_register(&obj->facet);
4896     _Lockit_dtor(&lock);
4897
4898     return obj;
4899 }
4900
4901 /* ?_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 */
4902 /* ?_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 */
4903 /* Copies number to dest buffer, validates grouping and skips separators.
4904  * Updates first so it points past the number, all digits are skipped.
4905  * Returns how exponent needs to changed.
4906  * Size of dest buffer is not specified, assuming it's not smaller than 32:
4907  * strlen(+0.e+) + 22(digits) + 4(expontent) + 1(nullbyte)
4908  */
4909 static int num_get_char__Getffld(const num_get *this, char *dest, istreambuf_iterator_char *first,
4910         istreambuf_iterator_char *last, const locale *loc)
4911 {
4912     numpunct_char *numpunct = numpunct_char_use_facet(loc);
4913     basic_string_char grouping_bstr;
4914     basic_string_char groups_found;
4915     int groups_no = 0, cur_group = 0, exp = 0;
4916     char *dest_beg = dest, *num_end = dest+25, *exp_end = dest+31, sep;
4917     const char *grouping, *groups;
4918     BOOL error = FALSE, got_digit = FALSE, got_nonzero = FALSE;
4919
4920     TRACE("(%p %p %p %p)\n", dest, first, last, loc);
4921
4922     numpunct_char_grouping(numpunct, &grouping_bstr);
4923     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
4924     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
4925
4926     if(sep)
4927         MSVCP_basic_string_char_ctor(&groups_found);
4928
4929     istreambuf_iterator_char_val(first);
4930     /* get sign */
4931     if(first->strbuf && (first->val=='-' || first->val=='+')) {
4932         *dest++ = first->val;
4933         istreambuf_iterator_char_inc(first);
4934     }
4935
4936     /* read possibly grouped numbers before decimal */
4937     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
4938         if(first->val<'0' || first->val>'9') {
4939             if(sep && first->val==sep) {
4940                 if(!groups_no) break; /* empty group - stop parsing */
4941                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
4942                 groups_no = 0;
4943                 ++cur_group;
4944             }else {
4945                 break;
4946             }
4947         }else {
4948             got_digit = TRUE; /* found a digit, zero or non-zero */
4949             /* write digit to dest if not a leading zero (to not waste dest buffer) */
4950             if(!got_nonzero && first->val == '0')
4951             {
4952                 ++groups_no;
4953                 continue;
4954             }
4955             got_nonzero = TRUE;
4956             if(dest < num_end)
4957                 *dest++ = first->val;
4958             else
4959                 exp++; /* too many digits, just multiply by 10 */
4960             if(sep && groups_no<CHAR_MAX)
4961                 ++groups_no;
4962         }
4963     }
4964
4965     /* if all leading zeroes, we didn't write anything so put a zero we check for a decimal */
4966     if(got_digit && !got_nonzero)
4967         *dest++ = '0';
4968
4969     /* get decimal, if any */
4970     if(first->strbuf && first->val==numpunct_char_decimal_point(numpunct)) {
4971         if(dest < num_end)
4972             *dest++ = *localeconv()->decimal_point;
4973         istreambuf_iterator_char_inc(first);
4974     }
4975
4976     /* read non-grouped after decimal */
4977     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
4978         if(first->val<'0' || first->val>'9')
4979             break;
4980         else if(dest<num_end) {
4981             got_digit = TRUE;
4982             *dest++ = first->val;
4983         }
4984     }
4985
4986     /* read exponent, if any */
4987     if(first->strbuf && (first->val=='e' || first->val=='E')) {
4988         *dest++ = first->val;
4989         istreambuf_iterator_char_inc(first);
4990
4991         if(first->strbuf && (first->val=='-' || first->val=='+')) {
4992             *dest++ = first->val;
4993             istreambuf_iterator_char_inc(first);
4994         }
4995
4996         got_digit = got_nonzero = FALSE;
4997         error = TRUE;
4998         /* skip any leading zeroes */
4999         for(; first->strbuf && first->val=='0'; istreambuf_iterator_char_inc(first))
5000             got_digit = TRUE;
5001
5002         for(; first->strbuf && first->val>='0' && first->val<='9'; istreambuf_iterator_char_inc(first)) {
5003             got_digit = got_nonzero = TRUE; /* leading zeroes would have been skipped, so first digit is non-zero */
5004             error = FALSE;
5005             if(dest<exp_end)
5006                 *dest++ = first->val;
5007         }
5008
5009         /* if just found zeroes for exponent, use that */
5010         if(got_digit && !got_nonzero)
5011         {
5012             error = FALSE;
5013             if(dest<exp_end)
5014                 *dest++ = '0';
5015         }
5016     }
5017
5018     if(sep && groups_no)
5019         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5020
5021     if(!cur_group) /* no groups, skip loop */
5022         cur_group--;
5023     else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group])
5024         error = TRUE; /* trailing empty */
5025
5026     for(; cur_group>=0 && !error; cur_group--) {
5027         if(*grouping == CHAR_MAX) {
5028             if(cur_group)
5029                 error = TRUE;
5030             break;
5031         }else if((cur_group && *grouping!=groups[cur_group])
5032                 || (!cur_group && *grouping<groups[cur_group])) {
5033             error = TRUE;
5034             break;
5035         }else if(grouping[1]) {
5036             grouping++;
5037         }
5038     }
5039     MSVCP_basic_string_char_dtor(&grouping_bstr);
5040     if(sep)
5041         MSVCP_basic_string_char_dtor(&groups_found);
5042
5043     if(error) {
5044         *dest_beg = '\0';
5045         return 0;
5046     }
5047     *dest++ = '\0';
5048     return exp;
5049 }
5050
5051 /* ?_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 */
5052 /* ?_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 */
5053 int __cdecl num_get_char__Getffldx(const num_get *this, char *dest, istreambuf_iterator_char *first,
5054     istreambuf_iterator_char *last, ios_base *ios, int *phexexp)
5055 {
5056     FIXME("(%p %p %p %p %p) stub\n", dest, first, last, ios, phexexp);
5057     return -1;
5058 }
5059
5060 /* ?_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 */
5061 /* ?_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 */
5062 /* Copies number to dest buffer, validates grouping and skips separators.
5063  * Updates first so it points past the number, all digits are skipped.
5064  * Returns number base (8, 10 or 16).
5065  * Size of dest buffer is not specified, assuming it's not smaller than 25:
5066  * 22(8^22>2^64)+1(detect overflows)+1(sign)+1(nullbyte) = 25
5067  */
5068 int __cdecl num_get_char__Getifld(const num_get *this, char *dest, istreambuf_iterator_char *first,
5069         istreambuf_iterator_char *last, int fmtflags, const locale *loc)
5070 {
5071     static const char digits[] = "0123456789abcdefABCDEF";
5072
5073     numpunct_char *numpunct = numpunct_char_use_facet(loc);
5074     basic_string_char grouping_bstr;
5075     basic_string_char groups_found;
5076     int basefield, base, groups_no = 0, cur_group = 0;
5077     char *dest_beg = dest, *dest_end = dest+24, sep;
5078     const char *grouping, *groups;
5079     BOOL error = TRUE, dest_empty = TRUE, found_zero = FALSE;
5080
5081     TRACE("(%p %p %p %04x %p)\n", dest, first, last, fmtflags, loc);
5082
5083     numpunct_char_grouping(numpunct, &grouping_bstr);
5084     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
5085     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5086
5087     basefield = fmtflags & FMTFLAG_basefield;
5088     if(basefield == FMTFLAG_oct)
5089         base = 8;
5090     else if(basefield == FMTFLAG_hex)
5091         base = 22; /* equal to the size of digits buffer */
5092     else if(!basefield)
5093         base = 0;
5094     else
5095         base = 10;
5096
5097     istreambuf_iterator_char_val(first);
5098     if(first->strbuf && (first->val=='-' || first->val=='+')) {
5099         *dest++ = first->val;
5100         istreambuf_iterator_char_inc(first);
5101     }
5102
5103     if(first->strbuf && first->val=='0') {
5104         found_zero = TRUE;
5105         istreambuf_iterator_char_inc(first);
5106         if(first->strbuf && (first->val=='x' || first->val=='X')) {
5107             if(!base || base == 22) {
5108                 found_zero = FALSE;
5109                 istreambuf_iterator_char_inc(first);
5110                 base = 22;
5111             }else {
5112                 base = 10;
5113             }
5114         }else {
5115             error = FALSE;
5116             if(!base) base = 8;
5117         }
5118     }else {
5119         if (!base) base = 10;
5120     }
5121
5122     if(sep)
5123     {
5124         MSVCP_basic_string_char_ctor(&groups_found);
5125         if(found_zero) ++groups_no;
5126     }
5127
5128     for(; first->strbuf; istreambuf_iterator_char_inc(first)) {
5129         if(!memchr(digits, first->val, base)) {
5130             if(sep && first->val==sep) {
5131                 if(!groups_no) break; /* empty group - stop parsing */
5132                 MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5133                 groups_no = 0;
5134                 ++cur_group;
5135             }else {
5136                 break;
5137             }
5138         }else {
5139             error = FALSE;
5140             if(dest_empty && first->val == '0')
5141             {
5142                 found_zero = TRUE;
5143                 ++groups_no;
5144                 continue;
5145             }
5146             dest_empty = FALSE;
5147             /* skip digits that can't be copied to dest buffer, other
5148              * functions are responsible for detecting overflows */
5149             if(dest < dest_end)
5150                 *dest++ = first->val;
5151             if(sep && groups_no<CHAR_MAX)
5152                 ++groups_no;
5153         }
5154     }
5155
5156     if(sep && groups_no)
5157         MSVCP_basic_string_char_append_ch(&groups_found, groups_no);
5158
5159     if(!cur_group) { /* no groups, skip loop */
5160         cur_group--;
5161     }else if(!(groups = MSVCP_basic_string_char_c_str(&groups_found))[cur_group]) {
5162         error = TRUE; /* trailing empty */
5163         found_zero = FALSE;
5164     }
5165
5166     for(; cur_group>=0 && !error; cur_group--) {
5167         if(*grouping == CHAR_MAX) {
5168             if(cur_group)
5169                 error = TRUE;
5170             break;
5171         }else if((cur_group && *grouping!=groups[cur_group])
5172                 || (!cur_group && *grouping<groups[cur_group])) {
5173             error = TRUE;
5174             break;
5175         }else if(grouping[1]) {
5176             grouping++;
5177         }
5178     }
5179
5180     MSVCP_basic_string_char_dtor(&grouping_bstr);
5181     if(sep)
5182         MSVCP_basic_string_char_dtor(&groups_found);
5183
5184     if(error) {
5185         if (found_zero)
5186             *dest++ = '0';
5187         else
5188             dest = dest_beg;
5189     }else if(dest_empty)
5190         *dest++ = '0';
5191     *dest = '\0';
5192
5193     return (base==22 ? 16 : base);
5194 }
5195
5196 /* ?_Hexdig@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABEHD000@Z */
5197 /* ?_Hexdig@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAHD000@Z */
5198 DEFINE_THISCALL_WRAPPER(MSVCP_num_get_char__Hexdig, 20)
5199 int __thiscall MSVCP_num_get_char__Hexdig(num_get *this, char dig, char e0, char al, char au)
5200 {
5201     FIXME("(%p %c %c %c %c) stub\n", this, dig, e0, al, au);
5202     return -1;
5203 }
5204
5205 /* ?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 */
5206 /* ?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 */
5207 #define call_num_get_char_do_get_void(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 4, istreambuf_iterator_char*, \
5208         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, void**), \
5209         (this, ret, first, last, base, state, pval))
5210 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_void,36)
5211 istreambuf_iterator_char *__thiscall num_get_char_do_get_void(const num_get *this, istreambuf_iterator_char *ret,
5212     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5213 {
5214     unsigned __int64 v;
5215     char tmp[25], *end;
5216     int err;
5217
5218     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5219
5220     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5221                 &first, &last, FMTFLAG_hex, base->loc), &err);
5222     if(v!=(unsigned __int64)((INT_PTR)v))
5223         *state |= IOSTATE_failbit;
5224     else if(end!=tmp && !err)
5225         *pval = (void*)((INT_PTR)v);
5226     else
5227         *state |= IOSTATE_failbit;
5228
5229     if(!first.strbuf)
5230         *state |= IOSTATE_eofbit;
5231
5232     *ret = first;
5233     return ret;
5234 }
5235
5236 /* ?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 */
5237 /* ?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 */
5238 DEFINE_THISCALL_WRAPPER(num_get_char_get_void,36)
5239 istreambuf_iterator_char *__thiscall num_get_char_get_void(const num_get *this, istreambuf_iterator_char *ret,
5240     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, void **pval)
5241 {
5242     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5243     return call_num_get_char_do_get_void(this, ret, first, last, base, state, pval);
5244 }
5245
5246 /* ?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 */
5247 /* ?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 */
5248 /* ?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 */
5249 /* ?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 */
5250 #define call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 8, istreambuf_iterator_char*, \
5251         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5252         (this, ret, first, last, base, state, pval))
5253 #define call_num_get_char_do_get_double(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 12, istreambuf_iterator_char*, \
5254         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, double*), \
5255         (this, ret, first, last, base, state, pval))
5256 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_double,36)
5257 istreambuf_iterator_char *__thiscall num_get_char_do_get_double(const num_get *this, istreambuf_iterator_char *ret,
5258     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5259 {
5260     double v;
5261     char tmp[32], *end;
5262     int err;
5263
5264     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5265
5266     v = _Stodx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, base->loc), &err);
5267     if(end!=tmp && !err)
5268         *pval = v;
5269     else
5270         *state |= IOSTATE_failbit;
5271
5272     if(!first.strbuf)
5273         *state |= IOSTATE_eofbit;
5274
5275     *ret = first;
5276     return ret;
5277 }
5278
5279 /* ?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 */
5280 /* ?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 */
5281 DEFINE_THISCALL_WRAPPER(num_get_char_get_ldouble,36)
5282 istreambuf_iterator_char *__thiscall num_get_char_get_ldouble(const num_get *this, istreambuf_iterator_char *ret,
5283         istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5284 {
5285     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5286     return call_num_get_char_do_get_ldouble(this, ret, first, last, base, state, pval);
5287 }
5288
5289 /* ?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 */
5290 /* ?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 */
5291 DEFINE_THISCALL_WRAPPER(num_get_char_get_double,36)
5292 istreambuf_iterator_char *__thiscall num_get_char_get_double(const num_get *this, istreambuf_iterator_char *ret,
5293     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, double *pval)
5294 {
5295     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5296     return call_num_get_char_do_get_double(this, ret, first, last, base, state, pval);
5297 }
5298
5299 /* ?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 */
5300 /* ?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 */
5301 #define call_num_get_char_do_get_float(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 16, istreambuf_iterator_char*, \
5302         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, float*), \
5303         (this, ret, first, last, base, state, pval))
5304 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_float,36)
5305 istreambuf_iterator_char *__thiscall num_get_char_do_get_float(const num_get *this, istreambuf_iterator_char *ret,
5306     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
5307 {
5308     float v;
5309     char tmp[32], *end;
5310     int err;
5311
5312     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5313
5314     v = _Stofx(tmp, &end, num_get_char__Getffld(this, tmp, &first, &last, base->loc), &err);
5315     if(end!=tmp && !err)
5316         *pval = v;
5317     else
5318         *state |= IOSTATE_failbit;
5319
5320     if(!first.strbuf)
5321         *state |= IOSTATE_eofbit;
5322
5323     *ret = first;
5324     return ret;
5325 }
5326
5327 /* ?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 */
5328 /* ?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 */
5329 DEFINE_THISCALL_WRAPPER(num_get_char_get_float,36)
5330 istreambuf_iterator_char *__thiscall num_get_char_get_float(const num_get *this, istreambuf_iterator_char *ret,
5331     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, float *pval)
5332 {
5333     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5334     return call_num_get_char_do_get_float(this, ret, first, last, base, state, pval);
5335 }
5336
5337 /* ?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 */
5338 /* ?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 */
5339 #define call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 20, istreambuf_iterator_char*, \
5340         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONGLONG*), \
5341         (this, ret, first, last, base, state, pval))
5342 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint64,36)
5343 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
5344     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
5345 {
5346     unsigned __int64 v;
5347     char tmp[25], *end;
5348     int err;
5349
5350     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5351
5352     v = _Stoullx(tmp, &end, num_get_char__Getifld(this, tmp,
5353                 &first, &last, base->fmtfl, base->loc), &err);
5354     if(end!=tmp && !err)
5355         *pval = v;
5356     else
5357         *state |= IOSTATE_failbit;
5358
5359     if(!first.strbuf)
5360         *state |= IOSTATE_eofbit;
5361
5362     *ret = first;
5363     return ret;
5364 }
5365
5366 /* ?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 */
5367 /* ?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 */
5368 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint64,36)
5369 istreambuf_iterator_char *__thiscall num_get_char_get_uint64(const num_get *this, istreambuf_iterator_char *ret,
5370     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONGLONG *pval)
5371 {
5372     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5373     return call_num_get_char_do_get_uint64(this, ret, first, last, base, state, pval);
5374 }
5375
5376 /* ?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 */
5377 /* ?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 */
5378 #define call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 24, istreambuf_iterator_char*, \
5379         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONGLONG*), \
5380         (this, ret, first, last, base, state, pval))
5381 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_int64,36)
5382 istreambuf_iterator_char *__thiscall num_get_char_do_get_int64(const num_get *this, istreambuf_iterator_char *ret,
5383     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
5384 {
5385     __int64 v;
5386     char tmp[25], *end;
5387     int err;
5388
5389     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5390
5391     v = _Stollx(tmp, &end, num_get_char__Getifld(this, tmp,
5392                 &first, &last, base->fmtfl, base->loc), &err);
5393     if(end!=tmp && !err)
5394         *pval = v;
5395     else
5396         *state |= IOSTATE_failbit;
5397
5398     if(!first.strbuf)
5399         *state |= IOSTATE_eofbit;
5400
5401     *ret = first;
5402     return ret;
5403 }
5404
5405 /* ?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 */
5406 /* ?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 */
5407 DEFINE_THISCALL_WRAPPER(num_get_char_get_int64,36)
5408 istreambuf_iterator_char *__thiscall num_get_char_get_int64(const num_get *this, istreambuf_iterator_char *ret,
5409     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONGLONG *pval)
5410 {
5411     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5412     return call_num_get_char_do_get_int64(this, ret, first, last, base, state, pval);
5413 }
5414
5415 /* ?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 */
5416 /* ?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 */
5417 #define call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 28, istreambuf_iterator_char*, \
5418         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, ULONG*), \
5419         (this, ret, first, last, base, state, pval))
5420 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ulong,36)
5421 istreambuf_iterator_char *__thiscall num_get_char_do_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
5422     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
5423 {
5424     ULONG v;
5425     char tmp[25], *end;
5426     int err;
5427
5428     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5429
5430     v = _Stoulx(tmp, &end, num_get_char__Getifld(this, tmp,
5431                 &first, &last, base->fmtfl, base->loc), &err);
5432     if(end!=tmp && !err)
5433         *pval = v;
5434     else
5435         *state |= IOSTATE_failbit;
5436
5437     if(!first.strbuf)
5438         *state |= IOSTATE_eofbit;
5439
5440     *ret = first;
5441     return ret;
5442 }
5443
5444 /* ?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 */
5445 /* ?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 */
5446 DEFINE_THISCALL_WRAPPER(num_get_char_get_ulong,36)
5447 istreambuf_iterator_char *__thiscall num_get_char_get_ulong(const num_get *this, istreambuf_iterator_char *ret,
5448     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, ULONG *pval)
5449 {
5450     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5451     return call_num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
5452 }
5453
5454 /* ?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 */
5455 /* ?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 */
5456 #define call_num_get_char_do_get_long(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 32, istreambuf_iterator_char*, \
5457         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, LONG*), \
5458         (this, ret, first, last, base, state, pval))
5459 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_long,36)
5460 istreambuf_iterator_char *__thiscall num_get_char_do_get_long(const num_get *this, istreambuf_iterator_char *ret,
5461     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
5462 {
5463     LONG v;
5464     char tmp[25], *end;
5465     int err;
5466
5467     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5468
5469     v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
5470                 &first, &last, base->fmtfl, base->loc), &err);
5471     if(end!=tmp && !err)
5472         *pval = v;
5473     else
5474         *state |= IOSTATE_failbit;
5475
5476     if(!first.strbuf)
5477         *state |= IOSTATE_eofbit;
5478
5479     *ret = first;
5480     return ret;
5481 }
5482
5483 /* ?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 */
5484 /* ?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 */
5485 DEFINE_THISCALL_WRAPPER(num_get_char_get_long,36)
5486 istreambuf_iterator_char *__thiscall num_get_char_get_long(const num_get *this, istreambuf_iterator_char *ret,
5487     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, LONG *pval)
5488 {
5489     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5490     return call_num_get_char_do_get_long(this, ret, first, last, base, state, pval);
5491 }
5492
5493 /* ?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 */
5494 /* ?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 */
5495 #define call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 36, istreambuf_iterator_char*, \
5496         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned int*), \
5497         (this, ret, first, last, base, state, pval))
5498 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_uint,36)
5499 istreambuf_iterator_char *__thiscall num_get_char_do_get_uint(const num_get *this, istreambuf_iterator_char *ret,
5500     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
5501 {
5502     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5503     return num_get_char_do_get_ulong(this, ret, first, last, base, state, pval);
5504 }
5505
5506 /* ?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 */
5507 /* ?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 */
5508 DEFINE_THISCALL_WRAPPER(num_get_char_get_uint,36)
5509 istreambuf_iterator_char *__thiscall num_get_char_get_uint(const num_get *this, istreambuf_iterator_char *ret,
5510     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned int *pval)
5511 {
5512     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5513     return call_num_get_char_do_get_uint(this, ret, first, last, base, state, pval);
5514 }
5515
5516 /* ?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 */
5517 /* ?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 */
5518 #define call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 40, istreambuf_iterator_char*, \
5519         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, unsigned short*), \
5520         (this, ret, first, last, base, state, pval))
5521 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_ushort,36)
5522 istreambuf_iterator_char *__thiscall num_get_char_do_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
5523     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
5524 {
5525     ULONG v;
5526     char tmp[25], *beg, *end;
5527     int err, b;
5528
5529     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5530
5531     b = num_get_char__Getifld(this, tmp,
5532             &first, &last, base->fmtfl, base->loc);
5533     beg = tmp + (tmp[0]=='-' ? 1 : 0);
5534     v = _Stoulx(beg, &end, b, &err);
5535
5536     if(v != (ULONG)((unsigned short)v))
5537         *state |= IOSTATE_failbit;
5538     else if(end!=beg && !err)
5539         *pval = (tmp[0]=='-' ? -((unsigned short)v) : v);
5540     else
5541         *state |= IOSTATE_failbit;
5542
5543     if(!first.strbuf)
5544         *state |= IOSTATE_eofbit;
5545
5546     *ret = first;
5547     return ret;
5548 }
5549
5550 /* ?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 */
5551 /* ?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 */
5552 DEFINE_THISCALL_WRAPPER(num_get_char_get_ushort,36)
5553 istreambuf_iterator_char *__thiscall num_get_char_get_ushort(const num_get *this, istreambuf_iterator_char *ret,
5554     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, unsigned short *pval)
5555 {
5556     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5557     return call_num_get_char_do_get_ushort(this, ret, first, last, base, state, pval);
5558 }
5559
5560 /* ?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 */
5561 /* ?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 */
5562 #define call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval) CALL_VTBL_FUNC(this, 44, istreambuf_iterator_char*, \
5563         (const num_get*, istreambuf_iterator_char*, istreambuf_iterator_char, istreambuf_iterator_char, ios_base*, int*, MSVCP_bool*), \
5564         (this, ret, first, last, base, state, pval))
5565 DEFINE_THISCALL_WRAPPER(num_get_char_do_get_bool,36)
5566 istreambuf_iterator_char *__thiscall num_get_char_do_get_bool(const num_get *this, istreambuf_iterator_char *ret,
5567     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
5568 {
5569     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5570
5571     if(base->fmtfl & FMTFLAG_boolalpha) {
5572         numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
5573         basic_string_char false_bstr, true_bstr;
5574         const char *pfalse, *ptrue;
5575
5576         numpunct_char_falsename(numpunct, &false_bstr);
5577         numpunct_char_truename(numpunct, &true_bstr);
5578         pfalse = MSVCP_basic_string_char_c_str(&false_bstr);
5579         ptrue = MSVCP_basic_string_char_c_str(&true_bstr);
5580
5581         for(istreambuf_iterator_char_val(&first); first.strbuf;
5582                 istreambuf_iterator_char_inc(&first)) {
5583             if(pfalse && *pfalse && first.val!=*pfalse)
5584                 pfalse = NULL;
5585             if(ptrue && *ptrue && first.val!=*ptrue)
5586                 ptrue = NULL;
5587
5588             if(pfalse && *pfalse && ptrue && !*ptrue)
5589                 ptrue = NULL;
5590             if(ptrue && *ptrue && pfalse && !*pfalse)
5591                 pfalse = NULL;
5592
5593             if(pfalse)
5594                 pfalse++;
5595             if(ptrue)
5596                 ptrue++;
5597
5598             if((!pfalse || !*pfalse) && (!ptrue || !*ptrue))
5599                 break;
5600         }
5601
5602         if(ptrue)
5603             *pval = TRUE;
5604         else if(pfalse)
5605             *pval = FALSE;
5606         else
5607             *state |= IOSTATE_failbit;
5608
5609         MSVCP_basic_string_char_dtor(&false_bstr);
5610         MSVCP_basic_string_char_dtor(&true_bstr);
5611     }else {
5612         char tmp[25], *end;
5613         int err;
5614         LONG v = _Stolx(tmp, &end, num_get_char__Getifld(this, tmp,
5615                     &first, &last, base->fmtfl, base->loc), &err);
5616
5617         if(end!=tmp && err==0 && (v==0 || v==1))
5618             *pval = v;
5619         else
5620             *state |= IOSTATE_failbit;
5621     }
5622
5623     if(!first.strbuf)
5624         *state |= IOSTATE_eofbit;
5625     memcpy(ret, &first, sizeof(first));
5626     return ret;
5627 }
5628
5629 /* ?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 */
5630 /* ?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 */
5631 DEFINE_THISCALL_WRAPPER(num_get_char_get_bool,36)
5632 istreambuf_iterator_char *__thiscall num_get_char_get_bool(const num_get *this, istreambuf_iterator_char *ret,
5633     istreambuf_iterator_char first, istreambuf_iterator_char last, ios_base *base, int *state, MSVCP_bool *pval)
5634 {
5635     TRACE("(%p %p %p %p %p)\n", this, ret, base, state, pval);
5636     return call_num_get_char_do_get_bool(this, ret, first, last, base, state, pval);
5637 }
5638
5639 /* ?id@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@2V0locale@2@A */
5640 locale_id num_put_char_id = {0};
5641
5642 /* num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@6B@ */
5643 extern const vtable_ptr MSVCP_num_put_char_vtable;
5644
5645 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
5646 /* ?_Init@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
5647 DEFINE_THISCALL_WRAPPER(num_put_char__Init, 8)
5648 void __thiscall num_put_char__Init(num_put *this, const _Locinfo *locinfo)
5649 {
5650     TRACE("(%p %p)\n", this, locinfo);
5651     _Locinfo__Getcvt(locinfo, &this->cvt);
5652 }
5653
5654 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
5655 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
5656 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_locinfo, 12)
5657 num_put* __thiscall num_put_char_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
5658 {
5659     TRACE("(%p %p %ld)\n", this, locinfo, refs);
5660
5661     locale_facet_ctor_refs(&this->facet, refs);
5662     this->facet.vtable = &MSVCP_num_put_char_vtable;
5663
5664     num_put_char__Init(this, locinfo);
5665     return this;
5666 }
5667
5668 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAE@I@Z */
5669 /* ??0?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAA@_K@Z */
5670 DEFINE_THISCALL_WRAPPER(num_put_char_ctor_refs, 8)
5671 num_put* __thiscall num_put_char_ctor_refs(num_put *this, MSVCP_size_t refs)
5672 {
5673      _Locinfo locinfo;
5674
5675      TRACE("(%p %lu)\n", this, refs);
5676
5677      _Locinfo_ctor(&locinfo);
5678      num_put_char_ctor_locinfo(this, &locinfo, refs);
5679      _Locinfo_dtor(&locinfo);
5680      return this;
5681 }
5682
5683 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QAEXXZ */
5684 /* ??_F?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@QEAAXXZ */
5685 DEFINE_THISCALL_WRAPPER(num_put_char_ctor, 4)
5686 num_put* __thiscall num_put_char_ctor(num_put *this)
5687 {
5688     return num_put_char_ctor_refs(this, 0);
5689 }
5690
5691 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MAE@XZ */
5692 /* ??1?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MEAA@XZ */
5693 DEFINE_THISCALL_WRAPPER(num_put_char_dtor, 4)
5694 void __thiscall num_put_char_dtor(num_put *this)
5695 {
5696     TRACE("(%p)\n", this);
5697     locale_facet_dtor(&this->facet);
5698 }
5699
5700 DEFINE_THISCALL_WRAPPER(num_put_char_vector_dtor, 8)
5701 num_put* __thiscall num_put_char_vector_dtor(num_put *this, unsigned int flags)
5702 {
5703     TRACE("(%p %x)\n", this, flags);
5704     if(flags & 2) {
5705         /* we have an array, with the number of elements stored before the first object */
5706         INT_PTR i, *ptr = (INT_PTR *)this-1;
5707
5708         for(i=*ptr-1; i>=0; i--)
5709             num_put_char_dtor(this+i);
5710         MSVCRT_operator_delete(ptr);
5711     } else {
5712         num_put_char_dtor(this);
5713         if(flags & 1)
5714             MSVCRT_operator_delete(this);
5715     }
5716
5717     return this;
5718 }
5719
5720 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
5721 /* ?_Getcat@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
5722 MSVCP_size_t __cdecl num_put_char__Getcat(const locale_facet **facet, const locale *loc)
5723 {
5724     TRACE("(%p %p)\n", facet, loc);
5725
5726     if(facet && !*facet) {
5727         _Locinfo locinfo;
5728
5729         *facet = MSVCRT_operator_new(sizeof(num_put));
5730         if(!*facet) {
5731             ERR("Out of memory\n");
5732             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
5733             return 0;
5734         }
5735
5736         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
5737         num_put_char_ctor_locinfo((num_put*)*facet, &locinfo, 0);
5738         _Locinfo_dtor(&locinfo);
5739     }
5740
5741     return LC_NUMERIC;
5742 }
5743
5744 num_put* num_put_char_use_facet(const locale *loc)
5745 {
5746     static num_put *obj = NULL;
5747
5748     _Lockit lock;
5749     const locale_facet *fac;
5750
5751     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
5752     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_char_id));
5753     if(fac) {
5754         _Lockit_dtor(&lock);
5755         return (num_put*)fac;
5756     }
5757
5758     if(obj) {
5759         _Lockit_dtor(&lock);
5760         return obj;
5761     }
5762
5763     num_put_char__Getcat(&fac, loc);
5764     obj = (num_put*)fac;
5765     locale_facet__Incref(&obj->facet);
5766     locale_facet_register(&obj->facet);
5767     _Lockit_dtor(&lock);
5768
5769     return obj;
5770 }
5771
5772 /* ?_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 */
5773 /* ?_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 */
5774 ostreambuf_iterator_char* __cdecl num_put_char__Put(const num_put *this, ostreambuf_iterator_char *ret,
5775         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count)
5776 {
5777     TRACE("(%p %p %p %ld)\n", this, ret, ptr, count);
5778
5779     for(; count>0; count--)
5780         ostreambuf_iterator_char_put(&dest, *ptr++);
5781
5782     *ret = dest;
5783     return ret;
5784 }
5785
5786 /* ?_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 */
5787 /* ?_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 */
5788 ostreambuf_iterator_char* __cdecl num_put_char__Putc(const num_put *this, ostreambuf_iterator_char *ret,
5789         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count)
5790 {
5791     TRACE("(%p %p %p %ld)\n", this, ret, ptr, count);
5792
5793     for(; count>0; count--)
5794         ostreambuf_iterator_char_put(&dest, *ptr++);
5795
5796     *ret = dest;
5797     return ret;
5798 }
5799
5800 /* ?_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 */
5801 /* ?_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 */
5802 ostreambuf_iterator_char* __cdecl num_put_char__Putgrouped(const num_put *this, ostreambuf_iterator_char *ret,
5803         ostreambuf_iterator_char dest, const char *ptr, MSVCP_size_t count, char delim)
5804 {
5805     FIXME("(%p %p %p %ld %d) stub\n", this, ret, ptr, count, delim);
5806     return NULL;
5807 }
5808
5809 /* ?_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 */
5810 /* ?_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 */
5811 ostreambuf_iterator_char* __cdecl num_put_char__Rep(const num_put *this, ostreambuf_iterator_char *ret,
5812         ostreambuf_iterator_char dest, char c, MSVCP_size_t count)
5813 {
5814     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
5815
5816     for(; count>0; count--)
5817         ostreambuf_iterator_char_put(&dest, c);
5818
5819     *ret = dest;
5820     return ret;
5821 }
5822
5823 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADDH@Z */
5824 /* ?_Ffmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADDH@Z */
5825 char* __cdecl num_put_char__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
5826 {
5827     int type = fmtfl & FMTFLAG_floatfield;
5828     char *p = fmt;
5829
5830     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
5831
5832     *p++ = '%';
5833     if(fmtfl & FMTFLAG_showpos)
5834         *p++ = '+';
5835     if(fmtfl & FMTFLAG_showbase)
5836         *p++ = '#';
5837     *p++ = '.';
5838     *p++ = '*';
5839     if(spec)
5840         *p++ = spec;
5841
5842     if(type == FMTFLAG_fixed)
5843         *p++ = 'f';
5844     else if(type == FMTFLAG_scientific)
5845         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
5846     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
5847         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
5848     else
5849         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
5850
5851     *p++ = '\0';
5852     return fmt;
5853 }
5854
5855 /* ?_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 */
5856 /* ?_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 */
5857 ostreambuf_iterator_char* __cdecl num_put_char__Fput(const num_put *this, ostreambuf_iterator_char *ret,
5858         ostreambuf_iterator_char dest, ios_base *base, char fill, const char *buf, MSVCP_size_t bef_point,
5859         MSVCP_size_t aft_point, MSVCP_size_t trailing, MSVCP_size_t count)
5860 {
5861     FIXME("(%p %p %p %d %p %ld %ld %ld %ld) stub\n", this, ret, base,
5862             fill, buf, bef_point, aft_point, trailing, count);
5863     return NULL;
5864 }
5865
5866 /* TODO: This function should be removed when num_put_char__Fput is implemented */
5867 static ostreambuf_iterator_char* num_put_char_fput(const num_put *this, ostreambuf_iterator_char *ret,
5868         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
5869 {
5870     numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
5871     basic_string_char grouping_bstr;
5872     const char *grouping;
5873     char *p, sep = *localeconv()->decimal_point;
5874     int cur_group = 0, group_size = 0;
5875     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
5876     MSVCP_size_t pad;
5877
5878     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
5879
5880     /* Change decimal point */
5881     for(p=buf; p<buf+count; p++) {
5882         if(*p == sep) {
5883             *p = numpunct_char_decimal_point(numpunct);
5884             break;
5885         }
5886     }
5887     p--;
5888
5889     /* Add separators to number */
5890     numpunct_char_grouping(numpunct, &grouping_bstr);
5891     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
5892     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5893
5894     for(; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
5895         group_size++;
5896         if(group_size == grouping[cur_group]) {
5897             group_size = 0;
5898             if(grouping[cur_group+1])
5899                 cur_group++;
5900
5901             memmove(p+1, p, buf+count-p);
5902             *p = sep;
5903             count++;
5904         }
5905     }
5906     MSVCP_basic_string_char_dtor(&grouping_bstr);
5907
5908     /* Display number with padding */
5909     if(count >= base->wide)
5910         pad = 0;
5911     else
5912         pad = base->wide-count;
5913     base->wide = 0;
5914
5915     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
5916         num_put_char__Putc(this, &dest, dest, buf, 1);
5917         buf++;
5918     }
5919     if(adjustfield != FMTFLAG_left) {
5920         num_put_char__Rep(this, ret, dest, fill, pad);
5921         pad = 0;
5922     }
5923     num_put_char__Putc(this, &dest, dest, buf, count);
5924     return num_put_char__Rep(this, ret, dest, fill, pad);
5925 }
5926
5927 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@ABAPADPADPBDH@Z */
5928 /* ?_Ifmt@?$num_put@DV?$ostreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
5929 char* __cdecl num_put_char__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
5930 {
5931     int base = fmtfl & FMTFLAG_basefield;
5932     char *p = fmt;
5933
5934     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
5935
5936     *p++ = '%';
5937     if(fmtfl & FMTFLAG_showpos)
5938         *p++ = '+';
5939     if(fmtfl & FMTFLAG_showbase)
5940         *p++ = '#';
5941
5942     *p++ = *spec++;
5943     if(*spec == 'l')
5944         *p++ = *spec++;
5945
5946     if(base == FMTFLAG_oct)
5947         *p++ = 'o';
5948     else if(base == FMTFLAG_hex)
5949         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
5950     else
5951         *p++ = *spec;
5952
5953     *p++ = '\0';
5954     return fmt;
5955 }
5956
5957 /* ?_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 */
5958 /* ?_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 */
5959 ostreambuf_iterator_char* __cdecl num_put_char__Iput(const num_put *this, ostreambuf_iterator_char *ret,
5960         ostreambuf_iterator_char dest, ios_base *base, char fill, char *buf, MSVCP_size_t count)
5961 {
5962     numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
5963     basic_string_char grouping_bstr;
5964     const char *grouping;
5965     char *p, sep;
5966     int cur_group = 0, group_size = 0;
5967     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
5968     MSVCP_size_t pad;
5969
5970     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
5971
5972     /* Add separators to number */
5973     numpunct_char_grouping(numpunct, &grouping_bstr);
5974     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
5975     sep = grouping[0] ? numpunct_char_thousands_sep(numpunct) : '\0';
5976
5977     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
5978         group_size++;
5979         if(group_size == grouping[cur_group]) {
5980             group_size = 0;
5981             if(grouping[cur_group+1])
5982                 cur_group++;
5983
5984             memmove(p+1, p, buf+count-p);
5985             *p = sep;
5986             count++;
5987         }
5988     }
5989     MSVCP_basic_string_char_dtor(&grouping_bstr);
5990
5991     /* Display number with padding */
5992     if(count >= base->wide)
5993         pad = 0;
5994     else
5995         pad = base->wide-count;
5996     base->wide = 0;
5997
5998     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
5999         num_put_char__Putc(this, &dest, dest, buf, 1);
6000         buf++;
6001     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
6002         num_put_char__Putc(this, &dest, dest, buf, 2);
6003         buf += 2;
6004     }
6005     if(adjustfield != FMTFLAG_left) {
6006         num_put_char__Rep(this, ret, dest, fill, pad);
6007         pad = 0;
6008     }
6009     num_put_char__Putc(this, &dest, dest, buf, count);
6010     return num_put_char__Rep(this, ret, dest, fill, pad);
6011 }
6012
6013 /* ?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 */
6014 /* ?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 */
6015 #define call_num_put_char_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_char*, \
6016         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, LONG), \
6017         (this, ret, dest, base, fill, v))
6018 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_long, 28)
6019 ostreambuf_iterator_char* __thiscall num_put_char_do_put_long(const num_put *this, ostreambuf_iterator_char *ret,
6020         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
6021 {
6022     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6023     char fmt[7]; /* strlen("%+#lld")+1 */
6024
6025     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6026
6027     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6028             sprintf(tmp, num_put_char__Ifmt(this, fmt, "ld", base->fmtfl), v));
6029 }
6030
6031 /* ?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 */
6032 /* ?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 */
6033 DEFINE_THISCALL_WRAPPER(num_put_char_put_long, 28)
6034 ostreambuf_iterator_char* __thiscall num_put_char_put_long(const num_put *this, ostreambuf_iterator_char *ret,
6035         ostreambuf_iterator_char dest, ios_base *base, char fill, LONG v)
6036 {
6037     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6038     return call_num_put_char_do_put_long(this, ret, dest, base, fill, v);
6039 }
6040
6041 /* ?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 */
6042 /* ?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 */
6043 #define call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_char*, \
6044         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, ULONG), \
6045         (this, ret, dest, base, fill, v))
6046 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ulong, 28)
6047 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
6048         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
6049 {
6050     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6051     char fmt[7]; /* strlen("%+#lld")+1 */
6052
6053     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6054
6055     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6056             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lu", base->fmtfl), v));
6057 }
6058
6059 /* ?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 */
6060 /* ?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 */
6061 DEFINE_THISCALL_WRAPPER(num_put_char_put_ulong, 28)
6062 ostreambuf_iterator_char* __thiscall num_put_char_put_ulong(const num_put *this, ostreambuf_iterator_char *ret,
6063         ostreambuf_iterator_char dest, ios_base *base, char fill, ULONG v)
6064 {
6065     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6066     return call_num_put_char_do_put_ulong(this, ret, dest, base, fill, v);
6067 }
6068
6069 static inline streamsize get_precision(const ios_base *base)
6070 {
6071     return base->prec <= 0 && !(base->fmtfl & FMTFLAG_fixed) ? 6 : base->prec;
6072 }
6073
6074 /* ?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 */
6075 /* ?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 */
6076 /* ?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 */
6077 /* ?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 */
6078 #define call_num_put_char_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_char*, \
6079         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
6080         (this, ret, dest, base, fill, v))
6081 #define call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_char*, \
6082         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, double), \
6083         (this, ret, dest, base, fill, v))
6084 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_double, 32)
6085 ostreambuf_iterator_char* __thiscall num_put_char_do_put_double(const num_put *this, ostreambuf_iterator_char *ret,
6086         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
6087 {
6088     char *tmp;
6089     char fmt[8]; /* strlen("%+#.*lg")+1 */
6090     int size;
6091     streamsize prec;
6092
6093     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6094
6095     num_put_char__Ffmt(this, fmt, '\0', base->fmtfl);
6096     prec = get_precision(base);
6097     size = _scprintf(fmt, prec, v);
6098
6099     /* TODO: don't use dynamic allocation */
6100     tmp = MSVCRT_operator_new(size*2);
6101     if(!tmp) {
6102         ERR("Out of memory\n");
6103         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6104     }
6105     num_put_char_fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v));
6106     MSVCRT_operator_delete(tmp);
6107     return ret;
6108 }
6109
6110 /* ?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 */
6111 /* ?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 */
6112 DEFINE_THISCALL_WRAPPER(num_put_char_put_double, 32)
6113 ostreambuf_iterator_char* __thiscall num_put_char_put_double(const num_put *this, ostreambuf_iterator_char *ret,
6114         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
6115 {
6116     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6117     return call_num_put_char_do_put_double(this, ret, dest, base, fill, v);
6118 }
6119
6120 /* ?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 */
6121 /* ?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 */
6122 DEFINE_THISCALL_WRAPPER(num_put_char_put_ldouble, 32)
6123 ostreambuf_iterator_char* __thiscall num_put_char_put_ldouble(const num_put *this, ostreambuf_iterator_char *ret,
6124         ostreambuf_iterator_char dest, ios_base *base, char fill, double v)
6125 {
6126     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6127     return call_num_put_char_do_put_ldouble(this, ret, dest, base, fill, v);
6128 }
6129
6130 /* ?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 */
6131 /* ?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 */
6132 #define call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_char*, \
6133         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, const void*), \
6134         (this, ret, dest, base, fill, v))
6135 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_ptr, 28)
6136 ostreambuf_iterator_char* __thiscall num_put_char_do_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
6137         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
6138 {
6139     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6140
6141     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6142
6143     return num_put_char__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6144 }
6145
6146 /* ?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 */
6147 /* ?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 */
6148 DEFINE_THISCALL_WRAPPER(num_put_char_put_ptr, 28)
6149 ostreambuf_iterator_char* __thiscall num_put_char_put_ptr(const num_put *this, ostreambuf_iterator_char *ret,
6150         ostreambuf_iterator_char dest, ios_base *base, char fill, const void *v)
6151 {
6152     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6153     return call_num_put_char_do_put_ptr(this, ret, dest, base, fill, v);
6154 }
6155
6156 /* ?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 */
6157 /* ?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 */
6158 #define call_num_put_char_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_char*, \
6159         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, __int64), \
6160         (this, ret, dest, base, fill, v))
6161 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_int64, 32)
6162 ostreambuf_iterator_char* __thiscall num_put_char_do_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6163         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6164 {
6165     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6166     char fmt[7]; /* strlen("%+#lld")+1 */
6167
6168     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6169
6170     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6171             sprintf(tmp, num_put_char__Ifmt(this, fmt, "lld", base->fmtfl), v));
6172 }
6173
6174 /* ?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 */
6175 /* ?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 */
6176 DEFINE_THISCALL_WRAPPER(num_put_char_put_int64, 32)
6177 ostreambuf_iterator_char* __thiscall num_put_char_put_int64(const num_put *this, ostreambuf_iterator_char *ret,
6178         ostreambuf_iterator_char dest, ios_base *base, char fill, __int64 v)
6179 {
6180     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6181     return call_num_put_char_do_put_int64(this, ret, dest, base, fill, v);
6182 }
6183
6184 /* ?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 */
6185 /* ?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 */
6186 #define call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_char*, \
6187         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, unsigned __int64), \
6188         (this, ret, dest, base, fill, v))
6189 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_uint64, 32)
6190 ostreambuf_iterator_char* __thiscall num_put_char_do_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6191         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6192 {
6193     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6194     char fmt[7]; /* strlen("%+#lld")+1 */
6195
6196     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6197
6198     return num_put_char__Iput(this, ret, dest, base, fill, tmp,
6199             sprintf(tmp, num_put_char__Ifmt(this, fmt, "llu", base->fmtfl), v));
6200 }
6201
6202 /* ?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 */
6203 /* ?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 */
6204 DEFINE_THISCALL_WRAPPER(num_put_char_put_uint64, 32)
6205 ostreambuf_iterator_char* __thiscall num_put_char_put_uint64(const num_put *this, ostreambuf_iterator_char *ret,
6206         ostreambuf_iterator_char dest, ios_base *base, char fill, unsigned __int64 v)
6207 {
6208     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
6209     return call_num_put_char_do_put_uint64(this, ret, dest, base, fill, v);
6210 }
6211
6212 /* ?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 */
6213 /* ?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 */
6214 #define call_num_put_char_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_char*, \
6215         (const num_put*, ostreambuf_iterator_char*, ostreambuf_iterator_char, ios_base*, char, MSVCP_bool), \
6216         (this, ret, dest, base, fill, v))
6217 DEFINE_THISCALL_WRAPPER(num_put_char_do_put_bool, 28)
6218 ostreambuf_iterator_char* __thiscall num_put_char_do_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6219         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6220 {
6221     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6222
6223     if(base->fmtfl & FMTFLAG_boolalpha) {
6224         numpunct_char *numpunct = numpunct_char_use_facet(base->loc);
6225         basic_string_char str;
6226         MSVCP_size_t pad, len;
6227
6228         if(v)
6229             numpunct_char_truename(numpunct, &str);
6230         else
6231             numpunct_char_falsename(numpunct, &str);
6232
6233         len = MSVCP_basic_string_char_length(&str);
6234         pad = (len>base->wide ? 0 : base->wide-len);
6235         base->wide = 0;
6236
6237         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
6238             num_put_char__Rep(this, &dest, dest, fill, pad);
6239             pad = 0;
6240         }
6241         num_put_char__Putc(this, &dest, dest, MSVCP_basic_string_char_c_str(&str), len);
6242         MSVCP_basic_string_char_dtor(&str);
6243         return num_put_char__Rep(this, ret, dest, fill, pad);
6244     }
6245
6246     return num_put_char_put_long(this, ret, dest, base, fill, v);
6247 }
6248
6249 /* ?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 */
6250 /* ?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 */
6251 DEFINE_THISCALL_WRAPPER(num_put_char_put_bool, 28)
6252 ostreambuf_iterator_char* __thiscall num_put_char_put_bool(const num_put *this, ostreambuf_iterator_char *ret,
6253         ostreambuf_iterator_char dest, ios_base *base, char fill, MSVCP_bool v)
6254 {
6255     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6256     return call_num_put_char_do_put_bool(this, ret, dest, base, fill, v);
6257 }
6258
6259 /* ?id@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@2V0locale@2@A */
6260 locale_id num_put_wchar_id = {0};
6261 /* ?id@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@2V0locale@2@A */
6262 locale_id num_put_short_id = {0};
6263
6264 /* num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@6B@ */
6265 extern const vtable_ptr MSVCP_num_put_wchar_vtable;
6266 /* num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@6B@ */
6267 extern const vtable_ptr MSVCP_num_put_short_vtable;
6268
6269 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IAEXABV_Locinfo@2@@Z */
6270 /* ?_Init@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@IEAAXAEBV_Locinfo@2@@Z */
6271 DEFINE_THISCALL_WRAPPER(num_put_wchar__Init, 8)
6272 void __thiscall num_put_wchar__Init(num_put *this, const _Locinfo *locinfo)
6273 {
6274     TRACE("(%p %p)\n", this, locinfo);
6275     _Locinfo__Getcvt(locinfo, &this->cvt);
6276 }
6277
6278 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6279 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6280 DEFINE_THISCALL_WRAPPER(num_put_wchar_ctor_locinfo, 12)
6281 num_put* __thiscall num_put_wchar_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6282 {
6283     TRACE("(%p %p %ld)\n", this, locinfo, refs);
6284
6285     locale_facet_ctor_refs(&this->facet, refs);
6286     this->facet.vtable = &MSVCP_num_put_wchar_vtable;
6287
6288     num_put_wchar__Init(this, locinfo);
6289     return this;
6290 }
6291
6292 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@ABV_Locinfo@1@I@Z */
6293 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@AEBV_Locinfo@1@_K@Z */
6294 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_locinfo, 12)
6295 num_put* __thiscall num_put_short_ctor_locinfo(num_put *this, const _Locinfo *locinfo, MSVCP_size_t refs)
6296 {
6297     num_put_wchar_ctor_locinfo(this, locinfo, refs);
6298     this->facet.vtable = &MSVCP_num_put_short_vtable;
6299     return this;
6300 }
6301
6302 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAE@I@Z */
6303 /* ??0?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAA@_K@Z */
6304 DEFINE_THISCALL_WRAPPER(num_put_wchar_ctor_refs, 8)
6305 num_put* __thiscall num_put_wchar_ctor_refs(num_put *this, MSVCP_size_t refs)
6306 {
6307     _Locinfo locinfo;
6308
6309     TRACE("(%p %lu)\n", this, refs);
6310
6311     _Locinfo_ctor(&locinfo);
6312     num_put_wchar_ctor_locinfo(this, &locinfo, refs);
6313     _Locinfo_dtor(&locinfo);
6314     return this;
6315 }
6316
6317 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAE@I@Z */
6318 /* ??0?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAA@_K@Z */
6319 DEFINE_THISCALL_WRAPPER(num_put_short_ctor_refs, 8)
6320 num_put* __thiscall num_put_short_ctor_refs(num_put *this, MSVCP_size_t refs)
6321 {
6322     num_put_wchar_ctor_refs(this, refs);
6323     this->facet.vtable = &MSVCP_num_put_short_vtable;
6324     return this;
6325 }
6326
6327 /* ??_F?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QAEXXZ */
6328 /* ??_F?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@QEAAXXZ */
6329 DEFINE_THISCALL_WRAPPER(num_put_wchar_ctor, 4)
6330 num_put* __thiscall num_put_wchar_ctor(num_put *this)
6331 {
6332     return num_put_wchar_ctor_refs(this, 0);
6333 }
6334
6335 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QAEXXZ */
6336 /* ??_F?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@QEAAXXZ */
6337 DEFINE_THISCALL_WRAPPER(num_put_short_ctor, 4)
6338 num_put* __thiscall num_put_short_ctor(num_put *this)
6339 {
6340     return num_put_short_ctor_refs(this, 0);
6341 }
6342
6343 /* ??1?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MAE@XZ */
6344 /* ??1?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@MEAA@XZ */
6345 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MAE@XZ */
6346 /* ??1?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@MEAA@XZ */
6347 DEFINE_THISCALL_WRAPPER(num_put_wchar_dtor, 4)
6348 void __thiscall num_put_wchar_dtor(num_put *this)
6349 {
6350     TRACE("(%p)\n", this);
6351     locale_facet_dtor(&this->facet);
6352 }
6353
6354 DEFINE_THISCALL_WRAPPER(num_put_wchar_vector_dtor, 8)
6355 num_put* __thiscall num_put_wchar_vector_dtor(num_put *this, unsigned int flags)
6356 {
6357     TRACE("(%p %x)\n", this, flags);
6358     if(flags & 2) {
6359         /* we have an array, with the number of elements stored before the first object */
6360         INT_PTR i, *ptr = (INT_PTR *)this-1;
6361
6362         for(i=*ptr-1; i>=0; i--)
6363             num_put_wchar_dtor(this+i);
6364         MSVCRT_operator_delete(ptr);
6365     } else {
6366         num_put_wchar_dtor(this);
6367         if(flags & 1)
6368             MSVCRT_operator_delete(this);
6369     }
6370
6371     return this;
6372 }
6373
6374 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6375 /* ?_Getcat@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6376 MSVCP_size_t __cdecl num_put_wchar__Getcat(const locale_facet **facet, const locale *loc)
6377 {
6378     TRACE("(%p %p)\n", facet, loc);
6379
6380     if(facet && !*facet) {
6381         _Locinfo locinfo;
6382
6383         *facet = MSVCRT_operator_new(sizeof(num_put));
6384         if(!*facet) {
6385             ERR("Out of memory\n");
6386             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6387             return 0;
6388         }
6389
6390         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
6391         num_put_wchar_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6392         _Locinfo_dtor(&locinfo);
6393     }
6394
6395     return LC_NUMERIC;
6396 }
6397
6398 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SAIPAPBVfacet@locale@2@PBV42@@Z */
6399 /* ?_Getcat@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@SA_KPEAPEBVfacet@locale@2@PEBV42@@Z */
6400 MSVCP_size_t __cdecl num_put_short__Getcat(const locale_facet **facet, const locale *loc)
6401 {
6402     TRACE("(%p %p)\n", facet, loc);
6403
6404     if(facet && !*facet) {
6405         _Locinfo locinfo;
6406
6407         *facet = MSVCRT_operator_new(sizeof(num_put));
6408         if(!*facet) {
6409             ERR("Out of memory\n");
6410             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6411             return 0;
6412         }
6413
6414         _Locinfo_ctor_cstr(&locinfo, _Yarn_char_c_str(&loc->ptr->name));
6415         num_put_short_ctor_locinfo((num_put*)*facet, &locinfo, 0);
6416         _Locinfo_dtor(&locinfo);
6417     }
6418
6419     return LC_NUMERIC;
6420 }
6421
6422 num_put* num_put_wchar_use_facet(const locale *loc)
6423 {
6424     static num_put *obj = NULL;
6425
6426     _Lockit lock;
6427     const locale_facet *fac;
6428
6429     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6430     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_wchar_id));
6431     if(fac) {
6432         _Lockit_dtor(&lock);
6433         return (num_put*)fac;
6434     }
6435
6436     if(obj) {
6437         _Lockit_dtor(&lock);
6438         return obj;
6439     }
6440
6441     num_put_wchar__Getcat(&fac, loc);
6442     obj = (num_put*)fac;
6443     locale_facet__Incref(&obj->facet);
6444     locale_facet_register(&obj->facet);
6445     _Lockit_dtor(&lock);
6446
6447     return obj;
6448 }
6449
6450 num_put* num_put_short_use_facet(const locale *loc)
6451 {
6452     static num_put *obj = NULL;
6453
6454     _Lockit lock;
6455     const locale_facet *fac;
6456
6457     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
6458     fac = locale__Getfacet(loc, locale_id_operator_size_t(&num_put_short_id));
6459     if(fac) {
6460         _Lockit_dtor(&lock);
6461         return (num_put*)fac;
6462     }
6463
6464     if(obj) {
6465         _Lockit_dtor(&lock);
6466         return obj;
6467     }
6468
6469     num_put_short__Getcat(&fac, loc);
6470     obj = (num_put*)fac;
6471     locale_facet__Incref(&obj->facet);
6472     locale_facet_register(&obj->facet);
6473     _Lockit_dtor(&lock);
6474
6475     return obj;
6476 }
6477
6478 /* ?_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 */
6479 /* ?_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 */
6480 /* ?_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 */
6481 /* ?_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 */
6482 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Put(const num_put *this, ostreambuf_iterator_wchar *ret,
6483         ostreambuf_iterator_wchar dest, const wchar_t *ptr, MSVCP_size_t count)
6484 {
6485     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_wn(ptr, count), count);
6486
6487     for(; count>0; count--)
6488         ostreambuf_iterator_wchar_put(&dest, *ptr++);
6489
6490     *ret = dest;
6491     return ret;
6492 }
6493
6494 /* ?_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 */
6495 /* ?_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 */
6496 /* ?_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 */
6497 /* ?_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 */
6498 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Putc(const num_put *this, ostreambuf_iterator_wchar *ret,
6499         ostreambuf_iterator_wchar dest, const char *ptr, MSVCP_size_t count)
6500 {
6501     int state = 0;
6502     wchar_t ch;
6503
6504     TRACE("(%p %p %s %ld)\n", this, ret, debugstr_an(ptr, count), count);
6505
6506     for(; count>0; count--) {
6507         if(_Mbrtowc(&ch, ptr++, 1, &state, &this->cvt) == 1)
6508             ostreambuf_iterator_wchar_put(&dest, ch);
6509     }
6510
6511     *ret = dest;
6512     return ret;
6513 }
6514
6515 /* ?_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 */
6516 /* ?_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 */
6517 /* ?_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 */
6518 /* ?_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 */
6519 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Putgrouped(const num_put *this, ostreambuf_iterator_wchar *ret,
6520         ostreambuf_iterator_wchar dest, const char *ptr, MSVCP_size_t count, wchar_t delim)
6521 {
6522     FIXME("(%p %p %p %ld %d) stub\n", this, ret, ptr, count, delim);
6523     return NULL;
6524 }
6525
6526 /* ?_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 */
6527 /* ?_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 */
6528 /* ?_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 */
6529 /* ?_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 */
6530 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Rep(const num_put *this, ostreambuf_iterator_wchar *ret,
6531         ostreambuf_iterator_wchar dest, wchar_t c, MSVCP_size_t count)
6532 {
6533     TRACE("(%p %p %d %ld)\n", this, ret, c, count);
6534
6535     for(; count>0; count--)
6536         ostreambuf_iterator_wchar_put(&dest, c);
6537
6538     *ret = dest;
6539     return ret;
6540 }
6541
6542 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADDH@Z */
6543 /* ?_Ffmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6544 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADDH@Z */
6545 /* ?_Ffmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADDH@Z */
6546 char* __cdecl num_put_wchar__Ffmt(const num_put *this, char *fmt, char spec, int fmtfl)
6547 {
6548     int type = fmtfl & FMTFLAG_floatfield;
6549     char *p = fmt;
6550
6551     TRACE("(%p %p %d %d)\n", this, fmt, spec, fmtfl);
6552
6553     *p++ = '%';
6554     if(fmtfl & FMTFLAG_showpos)
6555         *p++ = '+';
6556     if(fmtfl & FMTFLAG_showbase)
6557         *p++ = '#';
6558     *p++ = '.';
6559     *p++ = '*';
6560     if(spec)
6561         *p++ = spec;
6562
6563     if(type == FMTFLAG_fixed)
6564         *p++ = 'f';
6565     else if(type == FMTFLAG_scientific)
6566         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'E' : 'e';
6567     else if(type == (FMTFLAG_fixed|FMTFLAG_scientific))
6568         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'A' : 'a';
6569     else
6570         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'G' : 'g';
6571
6572     *p++ = '\0';
6573     return fmt;
6574 }
6575
6576 /* ?_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 */
6577 /* ?_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 */
6578 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Fput(const num_put *this, ostreambuf_iterator_wchar *ret,
6579         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const char *buf, MSVCP_size_t bef_point,
6580         MSVCP_size_t aft_point, MSVCP_size_t trailing, MSVCP_size_t count)
6581 {
6582     FIXME("(%p %p %p %d %p %ld %ld %ld %ld) stub\n", this, ret, base,
6583             fill, buf, bef_point, aft_point, trailing, count);
6584     return NULL;
6585 }
6586
6587 /* ?_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 */
6588 /* ?_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 */
6589 ostreambuf_iterator_wchar* __cdecl num_put_short__Fput(const num_put *this, ostreambuf_iterator_wchar *ret,
6590         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const char *buf, MSVCP_size_t bef_point,
6591         MSVCP_size_t aft_point, MSVCP_size_t trailing, MSVCP_size_t count)
6592 {
6593     FIXME("(%p %p %p %d %p %ld %ld %ld %ld) stub\n", this, ret, base,
6594             fill, buf, bef_point, aft_point, trailing, count);
6595     return NULL;
6596 }
6597
6598 /* TODO: This function should be removed when num_put_wchar__Fput is implemented */
6599 static ostreambuf_iterator_wchar* num_put__fput(const num_put *this, ostreambuf_iterator_wchar *ret,
6600         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
6601         MSVCP_size_t count, numpunct_wchar *numpunct)
6602 {
6603     basic_string_char grouping_bstr;
6604     const char *grouping;
6605     char *p, dec_point = *localeconv()->decimal_point;
6606     wchar_t sep;
6607     int cur_group = 0, group_size = 0;
6608     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6609     MSVCP_size_t i, pad;
6610
6611     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6612
6613     for(p=buf; p<buf+count; p++) {
6614         if(*p == dec_point)
6615             break;
6616     }
6617     p--;
6618
6619     /* Add separators to number */
6620     numpunct_wchar_grouping(numpunct, &grouping_bstr);
6621     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
6622     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
6623
6624     for(; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
6625         group_size++;
6626         if(group_size == grouping[cur_group]) {
6627             group_size = 0;
6628             if(grouping[cur_group+1])
6629                 cur_group++;
6630
6631             memmove(p+1, p, buf+count-p);
6632             *p = '\0'; /* mark thousands separator positions */
6633             count++;
6634         }
6635     }
6636     MSVCP_basic_string_char_dtor(&grouping_bstr);
6637
6638     /* Display number with padding */
6639     if(count >= base->wide)
6640         pad = 0;
6641     else
6642         pad = base->wide-count;
6643     base->wide = 0;
6644
6645     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6646         num_put_wchar__Putc(this, &dest, dest, buf, 1);
6647         buf++;
6648     }
6649     if(adjustfield != FMTFLAG_left) {
6650         num_put_wchar__Rep(this, ret, dest, fill, pad);
6651         pad = 0;
6652     }
6653
6654     for(i=0; i<count; i++) {
6655         if(buf[i] == dec_point)
6656             num_put_wchar__Rep(this, &dest, dest, numpunct_wchar_decimal_point(numpunct), 1);
6657         else if(!buf[i])
6658             num_put_wchar__Rep(this, &dest, dest, sep, 1);
6659         else
6660             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
6661     }
6662
6663     return num_put_wchar__Rep(this, ret, dest, fill, pad);
6664 }
6665
6666 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@ABAPADPADPBDH@Z */
6667 /* ?_Ifmt@?$num_put@_WV?$ostreambuf_iterator@_WU?$char_traits@_W@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6668 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@ABAPADPADPBDH@Z */
6669 /* ?_Ifmt@?$num_put@GV?$ostreambuf_iterator@GU?$char_traits@G@std@@@std@@@std@@AEBAPEADPEADPEBDH@Z */
6670 char* __cdecl num_put_wchar__Ifmt(const num_put *this, char *fmt, const char *spec, int fmtfl)
6671 {
6672     int base = fmtfl & FMTFLAG_basefield;
6673     char *p = fmt;
6674
6675     TRACE("(%p %p %p %d)\n", this, fmt, spec, fmtfl);
6676
6677     *p++ = '%';
6678     if(fmtfl & FMTFLAG_showpos)
6679         *p++ = '+';
6680     if(fmtfl & FMTFLAG_showbase)
6681         *p++ = '#';
6682
6683     *p++ = *spec++;
6684     if(*spec == 'l')
6685         *p++ = *spec++;
6686
6687     if(base == FMTFLAG_oct)
6688         *p++ = 'o';
6689     else if(base == FMTFLAG_hex)
6690         *p++ = (fmtfl & FMTFLAG_uppercase) ? 'X' : 'x';
6691     else
6692         *p++ = *spec;
6693
6694     *p++ = '\0';
6695     return fmt;
6696 }
6697
6698 static ostreambuf_iterator_wchar* num_put__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6699         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf,
6700         MSVCP_size_t count, numpunct_wchar *numpunct)
6701 {
6702     basic_string_char grouping_bstr;
6703     const char *grouping;
6704     char *p;
6705     wchar_t sep;
6706     int cur_group = 0, group_size = 0;
6707     int adjustfield = base->fmtfl & FMTFLAG_adjustfield;
6708     MSVCP_size_t i, pad;
6709
6710     TRACE("(%p %p %p %d %s %ld)\n", this, ret, base, fill, buf, count);
6711
6712     /* Add separators to number */
6713     numpunct_wchar_grouping(numpunct, &grouping_bstr);
6714     grouping = MSVCP_basic_string_char_c_str(&grouping_bstr);
6715     sep = grouping[0] ? numpunct_wchar_thousands_sep(numpunct) : '\0';
6716
6717     for(p=buf+count-1; p>buf && sep && grouping[cur_group]!=CHAR_MAX; p--) {
6718         group_size++;
6719         if(group_size == grouping[cur_group]) {
6720             group_size = 0;
6721             if(grouping[cur_group+1])
6722                 cur_group++;
6723
6724             memmove(p+1, p, buf+count-p);
6725             *p = '\0'; /* mark thousands separator positions */
6726             count++;
6727         }
6728     }
6729     MSVCP_basic_string_char_dtor(&grouping_bstr);
6730
6731     /* Display number with padding */
6732     if(count >= base->wide)
6733         pad = 0;
6734     else
6735         pad = base->wide-count;
6736     base->wide = 0;
6737
6738     if((adjustfield & FMTFLAG_internal) && (buf[0]=='-' || buf[0]=='+')) {
6739         num_put_wchar__Putc(this, &dest, dest, buf, 1);
6740         buf++;
6741     }else if((adjustfield & FMTFLAG_internal) && (buf[1]=='x' || buf[1]=='X')) {
6742         num_put_wchar__Putc(this, &dest, dest, buf, 2);
6743         buf += 2;
6744     }
6745     if(adjustfield != FMTFLAG_left) {
6746         num_put_wchar__Rep(this, ret, dest, fill, pad);
6747         pad = 0;
6748     }
6749
6750     for(i=0; i<count; i++) {
6751         if(!buf[i])
6752             num_put_wchar__Rep(this, &dest, dest, sep, 1);
6753         else
6754             num_put_wchar__Putc(this, &dest, dest, buf+i, 1);
6755     }
6756
6757     return num_put_wchar__Rep(this, ret, dest, fill, pad);
6758 }
6759
6760 /* ?_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 */
6761 /* ?_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 */
6762 ostreambuf_iterator_wchar* __cdecl num_put_wchar__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6763         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
6764 {
6765     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_wchar_use_facet(base->loc));
6766 }
6767
6768 /* ?_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 */
6769 /* ?_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 */
6770 ostreambuf_iterator_wchar* __cdecl num_put_short__Iput(const num_put *this, ostreambuf_iterator_wchar *ret,
6771         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, char *buf, MSVCP_size_t count)
6772 {
6773     return num_put__Iput(this, ret, dest, base, fill, buf, count, numpunct_short_use_facet(base->loc));
6774 }
6775
6776 /* ?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 */
6777 /* ?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 */
6778 #define call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 28, ostreambuf_iterator_wchar*, \
6779         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, LONG), \
6780         (this, ret, dest, base, fill, v))
6781 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_long, 28)
6782 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6783         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6784 {
6785     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6786     char fmt[7]; /* strlen("%+#lld")+1 */
6787
6788     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6789
6790     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6791             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
6792 }
6793
6794 /* ?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 */
6795 /* ?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 */
6796 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_long, 28)
6797 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6798         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6799 {
6800     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6801     char fmt[7]; /* strlen("%+#lld")+1 */
6802
6803     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6804
6805     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6806             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "ld", base->fmtfl), v));
6807 }
6808
6809 /* ?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 */
6810 /* ?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 */
6811 /* ?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 */
6812 /* ?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 */
6813 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_long, 28)
6814 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_long(const num_put *this, ostreambuf_iterator_wchar *ret,
6815         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, LONG v)
6816 {
6817     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6818     return call_num_put_wchar_do_put_long(this, ret, dest, base, fill, v);
6819 }
6820
6821 /* ?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 */
6822 /* ?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 */
6823 #define call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 24, ostreambuf_iterator_wchar*, \
6824         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, ULONG), \
6825         (this, ret, dest, base, fill, v))
6826 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ulong, 28)
6827 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6828         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6829 {
6830     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6831     char fmt[7]; /* strlen("%+#lld")+1 */
6832
6833     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6834
6835     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
6836             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
6837 }
6838
6839 /* ?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 */
6840 /* ?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 */
6841 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ulong, 28)
6842 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6843         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6844 {
6845     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
6846     char fmt[7]; /* strlen("%+#lld")+1 */
6847
6848     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6849
6850     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
6851             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lu", base->fmtfl), v));
6852 }
6853
6854 /* ?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 */
6855 /* ?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 */
6856 /* ?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 */
6857 /* ?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 */
6858 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ulong, 28)
6859 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ulong(const num_put *this, ostreambuf_iterator_wchar *ret,
6860         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, ULONG v)
6861 {
6862     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
6863     return call_num_put_wchar_do_put_ulong(this, ret, dest, base, fill, v);
6864 }
6865
6866 /* ?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 */
6867 /* ?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 */
6868 /* ?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 */
6869 /* ?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 */
6870 #define call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 12, ostreambuf_iterator_wchar*, \
6871         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
6872         (this, ret, dest, base, fill, v))
6873 #define call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 8, ostreambuf_iterator_wchar*, \
6874         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, double), \
6875         (this, ret, dest, base, fill, v))
6876 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_double, 32)
6877 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6878         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6879 {
6880     char *tmp;
6881     char fmt[8]; /* strlen("%+#.*lg")+1 */
6882     int size;
6883
6884     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6885
6886     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
6887     size = _scprintf(fmt, base->prec, v);
6888
6889     /* TODO: don't use dynamic allocation */
6890     tmp = MSVCRT_operator_new(size*2);
6891     if(!tmp) {
6892         ERR("Out of memory\n");
6893         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6894     }
6895     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, base->prec, v),
6896             numpunct_wchar_use_facet(base->loc));
6897     MSVCRT_operator_delete(tmp);
6898     return ret;
6899 }
6900
6901 /* ?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 */
6902 /* ?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 */
6903 /* ?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 */
6904 /* ?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 */
6905 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_double, 32)
6906 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6907         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6908 {
6909     char *tmp;
6910     char fmt[8]; /* strlen("%+#.*lg")+1 */
6911     int size;
6912     streamsize prec;
6913
6914     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6915
6916     num_put_wchar__Ffmt(this, fmt, '\0', base->fmtfl);
6917     prec = get_precision(base);
6918     size = _scprintf(fmt, prec, v);
6919
6920     /* TODO: don't use dynamic allocation */
6921     tmp = MSVCRT_operator_new(size*2);
6922     if(!tmp) {
6923         ERR("Out of memory\n");
6924         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
6925     }
6926     num_put__fput(this, ret, dest, base, fill, tmp, sprintf(tmp, fmt, prec, v),
6927             numpunct_short_use_facet(base->loc));
6928     MSVCRT_operator_delete(tmp);
6929     return ret;
6930 }
6931
6932 /* ?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 */
6933 /* ?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 */
6934 /* ?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 */
6935 /* ?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 */
6936 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_double, 32)
6937 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_double(const num_put *this, ostreambuf_iterator_wchar *ret,
6938         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6939 {
6940     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6941     return call_num_put_wchar_do_put_double(this, ret, dest, base, fill, v);
6942 }
6943
6944 /* ?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 */
6945 /* ?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 */
6946 /* ?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 */
6947 /* ?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 */
6948 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ldouble, 32)
6949 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ldouble(const num_put *this, ostreambuf_iterator_wchar *ret,
6950         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, double v)
6951 {
6952     TRACE("(%p %p %p %d %lf)\n", this, ret, base, fill, v);
6953     return call_num_put_wchar_do_put_ldouble(this, ret, dest, base, fill, v);
6954 }
6955
6956 /* ?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 */
6957 /* ?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 */
6958 #define call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 4, ostreambuf_iterator_wchar*, \
6959         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, const void*), \
6960         (this, ret, dest, base, fill, v))
6961 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_ptr, 28)
6962 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6963         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6964 {
6965     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6966
6967     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6968
6969     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6970 }
6971
6972 /* ?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 */
6973 /* ?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 */
6974 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_ptr, 28)
6975 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6976         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6977 {
6978     char tmp[17]; /* 8(16^8==2^64)*2(separators beetwen every digit) + 1 */
6979
6980     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6981
6982     return num_put_short__Iput(this, ret, dest, base, fill, tmp, sprintf(tmp, "%p", v));
6983 }
6984
6985 /* ?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 */
6986 /* ?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 */
6987 /* ?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 */
6988 /* ?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 */
6989 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_ptr, 28)
6990 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_ptr(const num_put *this, ostreambuf_iterator_wchar *ret,
6991         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, const void *v)
6992 {
6993     TRACE("(%p %p %p %d %p)\n", this, ret, base, fill, v);
6994     return call_num_put_wchar_do_put_ptr(this, ret, dest, base, fill, v);
6995 }
6996
6997 /* ?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 */
6998 /* ?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 */
6999 #define call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 20, ostreambuf_iterator_wchar*, \
7000         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, __int64), \
7001         (this, ret, dest, base, fill, v))
7002 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_int64, 32)
7003 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
7004         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
7005 {
7006     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7007     char fmt[7]; /* strlen("%+#lld")+1 */
7008
7009     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7010
7011     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
7012             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
7013 }
7014
7015 /* ?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 */
7016 /* ?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 */
7017 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_int64, 32)
7018 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
7019         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
7020 {
7021     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7022     char fmt[7]; /* strlen("%+#lld")+1 */
7023
7024     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7025
7026     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
7027             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "lld", base->fmtfl), v));
7028 }
7029
7030 /* ?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 */
7031 /* ?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 */
7032 /* ?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 */
7033 /* ?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 */
7034 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_int64, 32)
7035 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_int64(const num_put *this, ostreambuf_iterator_wchar *ret,
7036         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, __int64 v)
7037 {
7038     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7039     return call_num_put_wchar_do_put_int64(this, ret, dest, base, fill, v);
7040 }
7041
7042 /* ?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 */
7043 /* ?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 */
7044 #define call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 16, ostreambuf_iterator_wchar*, \
7045         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, unsigned __int64), \
7046         (this, ret, dest, base, fill, v))
7047 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_uint64, 32)
7048 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
7049         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
7050 {
7051     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7052     char fmt[7]; /* strlen("%+#lld")+1 */
7053
7054     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7055
7056     return num_put_wchar__Iput(this, ret, dest, base, fill, tmp,
7057             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
7058 }
7059
7060 /* ?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 */
7061 /* ?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 */
7062 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_uint64, 32)
7063 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
7064         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
7065 {
7066     char tmp[48]; /* 22(8^22>2^64)*2(separators beetwen every digit) + 3(strlen("+0x"))+1 */
7067     char fmt[7]; /* strlen("%+#lld")+1 */
7068
7069     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7070
7071     return num_put_short__Iput(this, ret, dest, base, fill, tmp,
7072             sprintf(tmp, num_put_wchar__Ifmt(this, fmt, "llu", base->fmtfl), v));
7073 }
7074
7075 /* ?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 */
7076 /* ?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 */
7077 /* ?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 */
7078 /* ?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 */
7079 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_uint64, 32)
7080 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_uint64(const num_put *this, ostreambuf_iterator_wchar *ret,
7081         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, unsigned __int64 v)
7082 {
7083     TRACE("(%p %p %p %d)\n", this, ret, base, fill);
7084     return call_num_put_wchar_do_put_uint64(this, ret, dest, base, fill, v);
7085 }
7086
7087 /* ?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 */
7088 /* ?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 */
7089 #define call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v) CALL_VTBL_FUNC(this, 32, ostreambuf_iterator_wchar*, \
7090         (const num_put*, ostreambuf_iterator_wchar*, ostreambuf_iterator_wchar, ios_base*, wchar_t, MSVCP_bool), \
7091         (this, ret, dest, base, fill, v))
7092 DEFINE_THISCALL_WRAPPER(num_put_wchar_do_put_bool, 28)
7093 ostreambuf_iterator_wchar* __thiscall num_put_wchar_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
7094         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
7095 {
7096     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7097
7098     if(base->fmtfl & FMTFLAG_boolalpha) {
7099         numpunct_wchar *numpunct = numpunct_wchar_use_facet(base->loc);
7100         basic_string_wchar str;
7101         MSVCP_size_t pad, len;
7102
7103         if(v)
7104             numpunct_wchar_truename(numpunct, &str);
7105         else
7106             numpunct_wchar_falsename(numpunct, &str);
7107
7108         len = MSVCP_basic_string_wchar_length(&str);
7109         pad = (len>base->wide ? 0 : base->wide-len);
7110         base->wide = 0;
7111
7112         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
7113             num_put_wchar__Rep(this, &dest, dest, fill, pad);
7114             pad = 0;
7115         }
7116         num_put_wchar__Put(this, &dest, dest, MSVCP_basic_string_wchar_c_str(&str), len);
7117         MSVCP_basic_string_wchar_dtor(&str);
7118         return num_put_wchar__Rep(this, ret, dest, fill, pad);
7119     }
7120
7121     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
7122 }
7123
7124 /* ?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 */
7125 /* ?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 */
7126 DEFINE_THISCALL_WRAPPER(num_put_short_do_put_bool, 28)
7127 ostreambuf_iterator_wchar* __thiscall num_put_short_do_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
7128         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
7129 {
7130     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7131
7132     if(base->fmtfl & FMTFLAG_boolalpha) {
7133         numpunct_wchar *numpunct = numpunct_short_use_facet(base->loc);
7134         basic_string_wchar str;
7135         MSVCP_size_t pad, len;
7136
7137         if(v)
7138             numpunct_wchar_truename(numpunct, &str);
7139         else
7140             numpunct_wchar_falsename(numpunct, &str);
7141
7142         len = MSVCP_basic_string_wchar_length(&str);
7143         pad = (len>base->wide ? 0 : base->wide-len);
7144         base->wide = 0;
7145
7146         if((base->fmtfl & FMTFLAG_adjustfield) != FMTFLAG_left) {
7147             num_put_wchar__Rep(this, &dest, dest, fill, pad);
7148             pad = 0;
7149         }
7150         num_put_wchar__Put(this, &dest, dest, MSVCP_basic_string_wchar_c_str(&str), len);
7151         MSVCP_basic_string_wchar_dtor(&str);
7152         return num_put_wchar__Rep(this, ret, dest, fill, pad);
7153     }
7154
7155     return num_put_wchar_put_long(this, ret, dest, base, fill, v);
7156 }
7157
7158 /* ?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 */
7159 /* ?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 */
7160 /* ?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 */
7161 /* ?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 */
7162 DEFINE_THISCALL_WRAPPER(num_put_wchar_put_bool, 28)
7163 ostreambuf_iterator_wchar* __thiscall num_put_wchar_put_bool(const num_put *this, ostreambuf_iterator_wchar *ret,
7164         ostreambuf_iterator_wchar dest, ios_base *base, wchar_t fill, MSVCP_bool v)
7165 {
7166     TRACE("(%p %p %p %d %d)\n", this, ret, base, fill, v);
7167     return call_num_put_wchar_do_put_bool(this, ret, dest, base, fill, v);
7168 }
7169
7170 /* ??0_Locimp@locale@std@@AAE@_N@Z */
7171 /* ??0_Locimp@locale@std@@AEAA@_N@Z */
7172 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor_transparent, 8)
7173 locale__Locimp* __thiscall locale__Locimp_ctor_transparent(locale__Locimp *this, MSVCP_bool transparent)
7174 {
7175     TRACE("(%p %d)\n", this, transparent);
7176
7177     memset(this, 0, sizeof(locale__Locimp));
7178     locale_facet_ctor_refs(&this->facet, 1);
7179     this->transparent = transparent;
7180     _Yarn_char_ctor_cstr(&this->name, "*");
7181     return this;
7182 }
7183
7184 /* ??_F_Locimp@locale@std@@QAEXXZ */
7185 /* ??_F_Locimp@locale@std@@QEAAXXZ */
7186 DEFINE_THISCALL_WRAPPER(locale__Locimp_ctor, 4)
7187 locale__Locimp* __thiscall locale__Locimp_ctor(locale__Locimp *this)
7188 {
7189     return locale__Locimp_ctor_transparent(this, FALSE);
7190 }
7191
7192 /* ??0_Locimp@locale@std@@AAE@ABV012@@Z */
7193 /* ??0_Locimp@locale@std@@AEAA@AEBV012@@Z */
7194 DEFINE_THISCALL_WRAPPER(locale__Locimp_copy_ctor, 8)
7195 locale__Locimp* __thiscall locale__Locimp_copy_ctor(locale__Locimp *this, const locale__Locimp *copy)
7196 {
7197     _Lockit lock;
7198     MSVCP_size_t i;
7199
7200     TRACE("(%p %p)\n", this, copy);
7201
7202     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7203     memcpy(this, copy, sizeof(locale__Locimp));
7204     locale_facet_ctor_refs(&this->facet, 1);
7205     if(copy->facetvec) {
7206         this->facetvec = MSVCRT_operator_new(copy->facet_cnt*sizeof(locale_facet*));
7207         if(!this->facetvec) {
7208             _Lockit_dtor(&lock);
7209             ERR("Out of memory\n");
7210             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7211             return NULL;
7212         }
7213         for(i=0; i<this->facet_cnt; i++)
7214         {
7215             this->facetvec[i] = copy->facetvec[i];
7216             if(this->facetvec[i])
7217                 locale_facet__Incref(this->facetvec[i]);
7218         }
7219     }
7220     _Yarn_char_copy_ctor(&this->name, &copy->name);
7221     _Lockit_dtor(&lock);
7222     return this;
7223 }
7224
7225 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPAV123@ABV123@@Z */
7226 /* ?_Locimp_ctor@_Locimp@locale@std@@CAXPEAV123@AEBV123@@Z */
7227 locale__Locimp* __cdecl locale__Locimp__Locimp_ctor(locale__Locimp *this, const locale__Locimp *copy)
7228 {
7229     return locale__Locimp_copy_ctor(this, copy);
7230 }
7231
7232 /* ??1_Locimp@locale@std@@MAE@XZ */
7233 /* ??1_Locimp@locale@std@@MEAA@XZ */
7234 DEFINE_THISCALL_WRAPPER(locale__Locimp_dtor, 4)
7235 void __thiscall locale__Locimp_dtor(locale__Locimp *this)
7236 {
7237     MSVCP_size_t i;
7238
7239     TRACE("(%p)\n", this);
7240
7241     locale_facet_dtor(&this->facet);
7242     for(i=0; i<this->facet_cnt; i++)
7243         if(this->facetvec[i] && locale_facet__Decref(this->facetvec[i]))
7244             call_locale_facet_vector_dtor(this->facetvec[i], 1);
7245
7246     MSVCRT_operator_delete(this->facetvec);
7247     _Yarn_char_dtor(&this->name);
7248 }
7249
7250 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPAV123@@Z */
7251 /* ?_Locimp_dtor@_Locimp@locale@std@@CAXPEAV123@@Z */
7252 void __cdecl locale__Locimp__Locimp_dtor(locale__Locimp *this)
7253 {
7254     locale__Locimp_dtor(this);
7255 }
7256
7257 DEFINE_THISCALL_WRAPPER(locale__Locimp_vector_dtor, 8)
7258 locale__Locimp* __thiscall locale__Locimp_vector_dtor(locale__Locimp *this, unsigned int flags)
7259 {
7260     TRACE("(%p %x)\n", this, flags);
7261     if(flags & 2) {
7262         /* we have an array, with the number of elements stored before the first object */
7263         INT_PTR i, *ptr = (INT_PTR *)this-1;
7264
7265         for(i=*ptr-1; i>=0; i--)
7266             locale__Locimp_dtor(this+i);
7267         MSVCRT_operator_delete(ptr);
7268     } else {
7269         locale__Locimp_dtor(this);
7270         if(flags & 1)
7271             MSVCRT_operator_delete(this);
7272     }
7273
7274     return this;
7275 }
7276
7277 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPAV123@PAVfacet@23@I@Z */
7278 /* ?_Locimp_Addfac@_Locimp@locale@std@@CAXPEAV123@PEAVfacet@23@_K@Z */
7279 void __cdecl locale__Locimp__Locimp_Addfac(locale__Locimp *locimp, locale_facet *facet, MSVCP_size_t id)
7280 {
7281     _Lockit lock;
7282
7283     TRACE("(%p %p %lu)\n", locimp, facet, id);
7284
7285     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7286     if(id >= locimp->facet_cnt) {
7287         MSVCP_size_t new_size = id+1;
7288         locale_facet **new_facetvec;
7289
7290         if(new_size < locale_id__Id_cnt+1)
7291             new_size = locale_id__Id_cnt+1;
7292
7293         new_facetvec = MSVCRT_operator_new(sizeof(locale_facet*)*new_size);
7294         if(!new_facetvec) {
7295             _Lockit_dtor(&lock);
7296             ERR("Out of memory\n");
7297             throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7298             return;
7299         }
7300
7301         memset(new_facetvec, 0, sizeof(locale_facet*)*new_size);
7302         memcpy(new_facetvec, locimp->facetvec, sizeof(locale_facet*)*locimp->facet_cnt);
7303         MSVCRT_operator_delete(locimp->facetvec);
7304         locimp->facetvec = new_facetvec;
7305         locimp->facet_cnt = new_size;
7306     }
7307
7308     if(locimp->facetvec[id] && locale_facet__Decref(locimp->facetvec[id]))
7309         call_locale_facet_vector_dtor(locimp->facetvec[id], 1);
7310
7311     locimp->facetvec[id] = facet;
7312     if(facet)
7313         locale_facet__Incref(facet);
7314     _Lockit_dtor(&lock);
7315 }
7316
7317 /* ?_Addfac@_Locimp@locale@std@@AAEXPAVfacet@23@I@Z */
7318 /* ?_Addfac@_Locimp@locale@std@@AEAAXPEAVfacet@23@_K@Z */
7319 DEFINE_THISCALL_WRAPPER(locale__Locimp__Addfac, 12)
7320 void __thiscall locale__Locimp__Addfac(locale__Locimp *this, locale_facet *facet, MSVCP_size_t id)
7321 {
7322     locale__Locimp__Locimp_Addfac(this, facet, id);
7323 }
7324
7325 /* ?_Makeushloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7326 /* ?_Makeushloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7327 /* List of missing facets:
7328  * num_put, collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7329  */
7330 void __cdecl locale__Locimp__Makeushloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7331 {
7332     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7333
7334     if(cat & (1<<(ctype_short__Getcat(NULL, NULL)-1))) {
7335         ctype_wchar *ctype;
7336
7337         if(loc) {
7338             ctype = ctype_short_use_facet(loc);
7339         }else {
7340             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
7341             if(!ctype) {
7342                 ERR("Out of memory\n");
7343                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7344             }
7345             ctype_short_ctor_locinfo(ctype, locinfo, 0);
7346         }
7347         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_short_id));
7348     }
7349
7350     if(cat & (1<<(num_get_short__Getcat(NULL, NULL)-1))) {
7351         num_get *numget;
7352
7353         if(loc) {
7354             numget = num_get_short_use_facet(loc);
7355         }else {
7356             numget = MSVCRT_operator_new(sizeof(num_get));
7357             if(!numget) {
7358                 ERR("Out of memory\n");
7359                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7360             }
7361             num_get_short_ctor_locinfo(numget, locinfo, 0);
7362         }
7363         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_short_id));
7364     }
7365
7366     if(cat & (1<<(num_put_short__Getcat(NULL, NULL)-1))) {
7367         num_put *numput;
7368
7369         if(loc) {
7370             numput = num_put_short_use_facet(loc);
7371         }else {
7372             numput = MSVCRT_operator_new(sizeof(num_put));
7373             if(!numput) {
7374                 ERR("Out of memory\n");
7375                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7376             }
7377             num_put_short_ctor_locinfo(numput, locinfo, 0);
7378         }
7379         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_short_id));
7380     }
7381
7382     if(cat & (1<<(numpunct_short__Getcat(NULL, NULL)-1))) {
7383         numpunct_wchar *numpunct;
7384
7385         if(loc) {
7386             numpunct = numpunct_short_use_facet(loc);
7387         }else {
7388             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
7389             if(!numpunct) {
7390                 ERR("Out of memory\n");
7391                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7392             }
7393             numpunct_short_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7394         }
7395         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_short_id));
7396     }
7397
7398     if(cat & (1<<(codecvt_short__Getcat(NULL, NULL)-1))) {
7399         codecvt_wchar *codecvt;
7400
7401         if(loc) {
7402             codecvt = codecvt_short_use_facet(loc);
7403         }else {
7404             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
7405             if(!codecvt) {
7406                 ERR("Out of memory\n");
7407                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7408             }
7409             codecvt_short_ctor_locinfo(codecvt, locinfo, 0);
7410         }
7411         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_short_id));
7412     }
7413 }
7414
7415 /* ?_Makewloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7416 /* ?_Makewloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7417 /* List of missing facets:
7418  * collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7419  */
7420 void __cdecl locale__Locimp__Makewloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7421 {
7422     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7423
7424     if(cat & (1<<(ctype_wchar__Getcat(NULL, NULL)-1))) {
7425         ctype_wchar *ctype;
7426
7427         if(loc) {
7428             ctype = ctype_wchar_use_facet(loc);
7429         }else {
7430             ctype = MSVCRT_operator_new(sizeof(ctype_wchar));
7431             if(!ctype) {
7432                 ERR("Out of memory\n");
7433                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7434             }
7435             ctype_wchar_ctor_locinfo(ctype, locinfo, 0);
7436         }
7437         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_wchar_id));
7438     }
7439
7440     if(cat & (1<<(num_get_wchar__Getcat(NULL, NULL)-1))) {
7441         num_get *numget;
7442
7443         if(loc) {
7444             numget = num_get_wchar_use_facet(loc);
7445         }else {
7446             numget = MSVCRT_operator_new(sizeof(num_get));
7447             if(!numget) {
7448                 ERR("Out of memory\n");
7449                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7450             }
7451             num_get_wchar_ctor_locinfo(numget, locinfo, 0);
7452         }
7453         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_wchar_id));
7454     }
7455
7456     if(cat & (1<<(num_put_wchar__Getcat(NULL, NULL)-1))) {
7457         num_put *numput;
7458
7459         if(loc) {
7460             numput = num_put_wchar_use_facet(loc);
7461         }else {
7462             numput = MSVCRT_operator_new(sizeof(num_put));
7463             if(!numput) {
7464                 ERR("Out of memory\n");
7465                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7466             }
7467             num_put_wchar_ctor_locinfo(numput, locinfo, 0);
7468         }
7469         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_wchar_id));
7470     }
7471
7472     if(cat & (1<<(numpunct_wchar__Getcat(NULL, NULL)-1))) {
7473         numpunct_wchar *numpunct;
7474
7475         if(loc) {
7476             numpunct = numpunct_wchar_use_facet(loc);
7477         }else {
7478             numpunct = MSVCRT_operator_new(sizeof(numpunct_wchar));
7479             if(!numpunct) {
7480                 ERR("Out of memory\n");
7481                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7482             }
7483             numpunct_wchar_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7484         }
7485         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_wchar_id));
7486     }
7487
7488     if(cat & (1<<(codecvt_wchar__Getcat(NULL, NULL)-1))) {
7489         codecvt_wchar *codecvt;
7490
7491         if(loc) {
7492             codecvt = codecvt_wchar_use_facet(loc);
7493         }else {
7494             codecvt = MSVCRT_operator_new(sizeof(codecvt_wchar));
7495             if(!codecvt) {
7496                 ERR("Out of memory\n");
7497                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7498             }
7499             codecvt_wchar_ctor_locinfo(codecvt, locinfo, 0);
7500         }
7501         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_wchar_id));
7502     }
7503 }
7504
7505 /* ?_Makexloc@_Locimp@locale@std@@CAXABV_Locinfo@3@HPAV123@PBV23@@Z */
7506 /* ?_Makexloc@_Locimp@locale@std@@CAXAEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7507 /* List of missing facets:
7508  * collate, messages, money_get, money_put, moneypunct, moneypunct, time_get, time_put
7509  */
7510 void __cdecl locale__Locimp__Makexloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7511 {
7512     FIXME("(%p %d %p %p) semi-stub\n", locinfo, cat, locimp, loc);
7513
7514     if(cat & (1<<(ctype_char__Getcat(NULL, NULL)-1))) {
7515         ctype_char *ctype;
7516
7517         if(loc) {
7518             ctype = ctype_char_use_facet(loc);
7519         }else {
7520             ctype = MSVCRT_operator_new(sizeof(ctype_char));
7521             if(!ctype) {
7522                 ERR("Out of memory\n");
7523                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7524             }
7525             ctype_char_ctor_locinfo(ctype, locinfo, 0);
7526         }
7527         locale__Locimp__Addfac(locimp, &ctype->base.facet, locale_id_operator_size_t(&ctype_char_id));
7528     }
7529
7530     if(cat & (1<<(num_get_char__Getcat(NULL, NULL)-1))) {
7531         num_get *numget;
7532
7533         if(loc) {
7534             numget = num_get_char_use_facet(loc);
7535         }else {
7536             numget = MSVCRT_operator_new(sizeof(num_get));
7537             if(!numget) {
7538                 ERR("Out of memory\n");
7539                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7540             }
7541             num_get_char_ctor_locinfo(numget, locinfo, 0);
7542         }
7543         locale__Locimp__Addfac(locimp, &numget->facet, locale_id_operator_size_t(&num_get_char_id));
7544     }
7545
7546     if(cat & (1<<(num_put_char__Getcat(NULL, NULL)-1))) {
7547         num_put *numput;
7548
7549         if(loc) {
7550             numput = num_put_char_use_facet(loc);
7551         }else {
7552             numput = MSVCRT_operator_new(sizeof(num_put));
7553             if(!numput) {
7554                 ERR("Out of memory\n");
7555                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7556             }
7557             num_put_char_ctor_locinfo(numput, locinfo, 0);
7558         }
7559         locale__Locimp__Addfac(locimp, &numput->facet, locale_id_operator_size_t(&num_put_char_id));
7560     }
7561
7562     if(cat & (1<<(numpunct_char__Getcat(NULL, NULL)-1))) {
7563         numpunct_char *numpunct;
7564
7565         if(loc) {
7566             numpunct = numpunct_char_use_facet(loc);
7567         }else {
7568             numpunct = MSVCRT_operator_new(sizeof(numpunct_char));
7569             if(!numpunct) {
7570                 ERR("Out of memory\n");
7571                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7572             }
7573             numpunct_char_ctor_locinfo(numpunct, locinfo, 0, FALSE);
7574         }
7575         locale__Locimp__Addfac(locimp, &numpunct->facet, locale_id_operator_size_t(&numpunct_char_id));
7576     }
7577
7578     if(cat & (1<<(codecvt_char__Getcat(NULL, NULL)-1))) {
7579         codecvt_char *codecvt;
7580
7581         if(loc) {
7582             codecvt = codecvt_char_use_facet(loc);
7583         }else {
7584             codecvt = MSVCRT_operator_new(sizeof(codecvt_char));
7585             if(!codecvt) {
7586                 ERR("Out of memory\n");
7587                 throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7588             }
7589             codecvt_char_ctor_locinfo(codecvt, locinfo, 0);
7590         }
7591         locale__Locimp__Addfac(locimp, &codecvt->base.facet, locale_id_operator_size_t(&codecvt_char_id));
7592     }
7593 }
7594
7595 /* ?_Makeloc@_Locimp@locale@std@@CAPAV123@ABV_Locinfo@3@HPAV123@PBV23@@Z */
7596 /* ?_Makeloc@_Locimp@locale@std@@CAPEAV123@AEBV_Locinfo@3@HPEAV123@PEBV23@@Z */
7597 locale__Locimp* __cdecl locale__Locimp__Makeloc(const _Locinfo *locinfo, category cat, locale__Locimp *locimp, const locale *loc)
7598 {
7599     TRACE("(%p %d %p %p)\n", locinfo, cat, locimp, loc);
7600
7601     locale__Locimp__Makexloc(locinfo, cat, locimp, loc);
7602     locale__Locimp__Makewloc(locinfo, cat, locimp, loc);
7603     locale__Locimp__Makeushloc(locinfo, cat, locimp, loc);
7604
7605     locimp->catmask |= cat;
7606     _Yarn_char_copy_ctor(&locimp->name, &locinfo->newlocname);
7607     return locimp;
7608 }
7609
7610 /* ??_7_Locimp@locale@std@@6B@ */
7611 const vtable_ptr MSVCP_locale__Locimp_vtable[] = {
7612     (vtable_ptr)THISCALL_NAME(locale__Locimp_vector_dtor)
7613 };
7614
7615 /* ??0locale@std@@AAE@PAV_Locimp@01@@Z */
7616 /* ??0locale@std@@AEAA@PEAV_Locimp@01@@Z */
7617 static locale* locale_ctor_locimp(locale *this, locale__Locimp *locimp)
7618 {
7619     TRACE("(%p %p)\n", this, locimp);
7620     /* Don't change locimp reference counter */
7621     this->ptr = locimp;
7622     return this;
7623 }
7624
7625 /* ?_Init@locale@std@@CAPAV_Locimp@12@XZ */
7626 /* ?_Init@locale@std@@CAPEAV_Locimp@12@XZ */
7627 locale__Locimp* __cdecl locale__Init(void)
7628 {
7629     _Lockit lock;
7630
7631     TRACE("\n");
7632
7633     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7634     if(global_locale) {
7635         _Lockit_dtor(&lock);
7636         return global_locale;
7637     }
7638
7639     global_locale = MSVCRT_operator_new(sizeof(locale__Locimp));
7640     if(!global_locale) {
7641         _Lockit_dtor(&lock);
7642         ERR("Out of memory\n");
7643         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7644         return NULL;
7645     }
7646
7647     locale__Locimp_ctor(global_locale);
7648     global_locale->catmask = (1<<(LC_MAX+1))-1;
7649     _Yarn_char_dtor(&global_locale->name);
7650     _Yarn_char_ctor_cstr(&global_locale->name, "C");
7651
7652     locale__Locimp__Clocptr = global_locale;
7653     global_locale->facet.refs++;
7654     locale_ctor_locimp(&classic_locale, locale__Locimp__Clocptr);
7655     _Lockit_dtor(&lock);
7656
7657     return global_locale;
7658 }
7659
7660 /* ??0locale@std@@QAE@ABV01@@Z */
7661 /* ??0locale@std@@QEAA@AEBV01@@Z */
7662 locale* locale_copy_ctor(locale *this, const locale *copy)
7663 {
7664     TRACE("(%p %p)\n", this, copy);
7665     this->ptr = copy->ptr;
7666     locale_facet__Incref(&this->ptr->facet);
7667     return this;
7668 }
7669
7670 /* ??0locale@std@@QAE@XZ */
7671 /* ??0locale@std@@QEAA@XZ */
7672 locale* locale_ctor(locale *this)
7673 {
7674     TRACE("(%p)\n", this);
7675     this->ptr = locale__Init();
7676     locale_facet__Incref(&this->ptr->facet);
7677     return this;
7678 }
7679
7680 /* ??1locale@std@@QAE@XZ */
7681 /* ??1locale@std@@QEAA@XZ */
7682 void locale_dtor(locale *this)
7683 {
7684     TRACE("(%p)\n", this);
7685     if(this->ptr && locale_facet__Decref(&this->ptr->facet)) {
7686         locale__Locimp_dtor(this->ptr);
7687         MSVCRT_operator_delete(this->ptr);
7688     }
7689 }
7690
7691 /* ??4locale@std@@QAEAAV01@ABV01@@Z */
7692 /* ??4locale@std@@QEAAAEAV01@AEBV01@@Z */
7693 locale* locale_operator_assign(locale *this, const locale *loc)
7694 {
7695     FIXME("(%p %p) stub\n", this, loc);
7696     return NULL;
7697 }
7698
7699 /* ?_Getfacet@locale@std@@QBEPBVfacet@12@I@Z */
7700 /* ?_Getfacet@locale@std@@QEBAPEBVfacet@12@_K@Z */
7701 static const locale_facet* locale__Getfacet(const locale *this, MSVCP_size_t id)
7702 {
7703     locale_facet *fac;
7704
7705     TRACE("(%p %lu)\n", this, id);
7706
7707     fac = id < this->ptr->facet_cnt ? this->ptr->facetvec[id] : NULL;
7708     if(fac || !this->ptr->transparent)
7709         return fac;
7710
7711     return id < global_locale->facet_cnt ? global_locale->facetvec[id] : NULL;
7712 }
7713
7714 /* ?_Getgloballocale@locale@std@@CAPAV_Locimp@12@XZ */
7715 /* ?_Getgloballocale@locale@std@@CAPEAV_Locimp@12@XZ */
7716 locale__Locimp* __cdecl locale__Getgloballocale(void)
7717 {
7718     TRACE("\n");
7719     return global_locale;
7720 }
7721
7722 /* ?_Setgloballocale@locale@std@@CAXPAX@Z */
7723 /* ?_Setgloballocale@locale@std@@CAXPEAX@Z */
7724 void __cdecl locale__Setgloballocale(void *locimp)
7725 {
7726     TRACE("(%p)\n", locimp);
7727     global_locale = locimp;
7728 }
7729
7730 /* ?classic@locale@std@@SAABV12@XZ */
7731 /* ?classic@locale@std@@SAAEBV12@XZ */
7732 const locale* __cdecl locale_classic(void)
7733 {
7734     TRACE("\n");
7735     locale__Init();
7736     return &classic_locale;
7737 }
7738
7739 /* ?empty@locale@std@@SA?AV12@XZ */
7740 locale* __cdecl locale_empty(locale *ret)
7741 {
7742     TRACE("\n");
7743
7744     locale__Init();
7745
7746     ret->ptr = MSVCRT_operator_new(sizeof(locale__Locimp));
7747     if(!ret->ptr) {
7748         ERR("Out of memory\n");
7749         throw_exception(EXCEPTION_BAD_ALLOC, NULL);
7750     }
7751     locale__Locimp_ctor_transparent(ret->ptr, TRUE);
7752     return ret;
7753 }
7754
7755 /* ?global@locale@std@@SA?AV12@ABV12@@Z */
7756 /* ?global@locale@std@@SA?AV12@AEBV12@@Z */
7757 locale* __cdecl locale_global(locale *ret, const locale *loc)
7758 {
7759     _Lockit lock;
7760     int i;
7761
7762     TRACE("(%p %p)\n", loc, ret);
7763
7764     _Lockit_ctor_locktype(&lock, _LOCK_LOCALE);
7765     locale_ctor(ret);
7766
7767     if(loc->ptr != global_locale) {
7768         locale_facet__Decref(&global_locale->facet);
7769         global_locale = loc->ptr;
7770         locale_facet__Incref(&global_locale->facet);
7771
7772         for(i=LC_ALL+1; i<=LC_MAX; i++) {
7773             if((global_locale->catmask & (1<<(i-1))) == 0)
7774                 continue;
7775             setlocale(i, _Yarn_char_c_str(&global_locale->name));
7776         }
7777     }
7778     _Lockit_dtor(&lock);
7779     return ret;
7780 }
7781
7782 /* wctrans */
7783 wctrans_t __cdecl wctrans(const char *property)
7784 {
7785     static const char str_tolower[] = "tolower";
7786     static const char str_toupper[] = "toupper";
7787
7788     if(!strcmp(property, str_tolower))
7789         return 2;
7790     if(!strcmp(property, str_toupper))
7791         return 1;
7792     return 0;
7793 }
7794
7795 /* towctrans */
7796 wint_t __cdecl towctrans(wint_t c, wctrans_t category)
7797 {
7798     if(category == 1)
7799         return towupper(c);
7800     return towlower(c);
7801 }
7802
7803 DEFINE_RTTI_DATA0(locale_facet, 0, ".?AVfacet@locale@std@@")
7804 DEFINE_RTTI_DATA1(collate_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@D@std@@")
7805 DEFINE_RTTI_DATA1(collate_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@_W@std@@")
7806 DEFINE_RTTI_DATA1(collate_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$collate@G@std@@")
7807 DEFINE_RTTI_DATA1(ctype_base, 0, &locale_facet_rtti_base_descriptor, ".?AUctype_base@std@@")
7808 DEFINE_RTTI_DATA2(ctype_char, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@D@std@@")
7809 DEFINE_RTTI_DATA2(ctype_wchar, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@_W@std@@")
7810 DEFINE_RTTI_DATA2(ctype_short, 0, &ctype_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$ctype@G@std@@")
7811 DEFINE_RTTI_DATA1(codecvt_base, 0, &locale_facet_rtti_base_descriptor, ".?AVcodecvt_base@std@@")
7812 DEFINE_RTTI_DATA2(codecvt_char, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@DDH@std@@")
7813 DEFINE_RTTI_DATA2(codecvt_wchar, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@_WDH@std@@")
7814 DEFINE_RTTI_DATA2(codecvt_short, 0, &codecvt_base_rtti_base_descriptor, &locale_facet_rtti_base_descriptor, ".?AV?$codecvt@GDH@std@@")
7815 DEFINE_RTTI_DATA1(numpunct_char, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@D@std@@")
7816 DEFINE_RTTI_DATA1(numpunct_wchar, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@_W@std@@")
7817 DEFINE_RTTI_DATA1(numpunct_short, 0, &locale_facet_rtti_base_descriptor, ".?AV?$numpunct@G@std@@")
7818 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@@")
7819 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@@")
7820 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@@")
7821 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@@")
7822 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@@")
7823 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@@")
7824
7825 #ifndef __GNUC__
7826 void __asm_dummy_vtables(void) {
7827 #endif
7828     __ASM_VTABLE(locale_facet,
7829             VTABLE_ADD_FUNC(locale_facet_vector_dtor));
7830     __ASM_VTABLE(collate_char,
7831             VTABLE_ADD_FUNC(collate_char_vector_dtor)
7832             VTABLE_ADD_FUNC(collate_char_do_compare)
7833             VTABLE_ADD_FUNC(collate_char_do_transform)
7834             VTABLE_ADD_FUNC(collate_char_do_hash));
7835     __ASM_VTABLE(collate_wchar,
7836             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
7837             VTABLE_ADD_FUNC(collate_wchar_do_compare)
7838             VTABLE_ADD_FUNC(collate_wchar_do_transform)
7839             VTABLE_ADD_FUNC(collate_wchar_do_hash));
7840     __ASM_VTABLE(collate_short,
7841             VTABLE_ADD_FUNC(collate_wchar_vector_dtor)
7842             VTABLE_ADD_FUNC(collate_wchar_do_compare)
7843             VTABLE_ADD_FUNC(collate_wchar_do_transform)
7844             VTABLE_ADD_FUNC(collate_wchar_do_hash));
7845     __ASM_VTABLE(ctype_base,
7846             VTABLE_ADD_FUNC(ctype_base_vector_dtor));
7847     __ASM_VTABLE(ctype_char,
7848             VTABLE_ADD_FUNC(ctype_char_vector_dtor)
7849             VTABLE_ADD_FUNC(ctype_char_do_tolower)
7850             VTABLE_ADD_FUNC(ctype_char_do_tolower_ch)
7851             VTABLE_ADD_FUNC(ctype_char_do_toupper)
7852             VTABLE_ADD_FUNC(ctype_char_do_toupper_ch)
7853             VTABLE_ADD_FUNC(ctype_char_do_widen)
7854             VTABLE_ADD_FUNC(ctype_char_do_widen_ch)
7855             VTABLE_ADD_FUNC(ctype_char_do_narrow)
7856             VTABLE_ADD_FUNC(ctype_char_do_narrow_ch));
7857     __ASM_VTABLE(ctype_wchar,
7858             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
7859             VTABLE_ADD_FUNC(ctype_wchar_do_is)
7860             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
7861             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
7862             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
7863             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
7864             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
7865             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
7866             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
7867             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
7868             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
7869             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
7870             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch));
7871     __ASM_VTABLE(ctype_short,
7872             VTABLE_ADD_FUNC(ctype_wchar_vector_dtor)
7873             VTABLE_ADD_FUNC(ctype_wchar_do_is)
7874             VTABLE_ADD_FUNC(ctype_wchar_do_is_ch)
7875             VTABLE_ADD_FUNC(ctype_wchar_do_scan_is)
7876             VTABLE_ADD_FUNC(ctype_wchar_do_scan_not)
7877             VTABLE_ADD_FUNC(ctype_wchar_do_tolower)
7878             VTABLE_ADD_FUNC(ctype_wchar_do_tolower_ch)
7879             VTABLE_ADD_FUNC(ctype_wchar_do_toupper)
7880             VTABLE_ADD_FUNC(ctype_wchar_do_toupper_ch)
7881             VTABLE_ADD_FUNC(ctype_wchar_do_widen)
7882             VTABLE_ADD_FUNC(ctype_wchar_do_widen_ch)
7883             VTABLE_ADD_FUNC(ctype_wchar_do_narrow)
7884             VTABLE_ADD_FUNC(ctype_wchar_do_narrow_ch));
7885     __ASM_VTABLE(codecvt_base,
7886             VTABLE_ADD_FUNC(codecvt_base_vector_dtor)
7887             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
7888             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
7889             VTABLE_ADD_FUNC(codecvt_base_do_encoding));
7890     __ASM_VTABLE(codecvt_char,
7891             VTABLE_ADD_FUNC(codecvt_char_vector_dtor)
7892             VTABLE_ADD_FUNC(codecvt_base_do_always_noconv)
7893             VTABLE_ADD_FUNC(codecvt_base_do_max_length)
7894             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7895             VTABLE_ADD_FUNC(codecvt_char_do_in)
7896             VTABLE_ADD_FUNC(codecvt_char_do_out)
7897             VTABLE_ADD_FUNC(codecvt_char_do_unshift)
7898             VTABLE_ADD_FUNC(codecvt_char_do_length));
7899     __ASM_VTABLE(codecvt_wchar,
7900             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
7901             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
7902             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
7903             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7904             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
7905             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
7906             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
7907             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
7908     __ASM_VTABLE(codecvt_short,
7909             VTABLE_ADD_FUNC(codecvt_wchar_vector_dtor)
7910             VTABLE_ADD_FUNC(codecvt_wchar_do_always_noconv)
7911             VTABLE_ADD_FUNC(codecvt_wchar_do_max_length)
7912             VTABLE_ADD_FUNC(codecvt_base_do_encoding)
7913             VTABLE_ADD_FUNC(codecvt_wchar_do_in)
7914             VTABLE_ADD_FUNC(codecvt_wchar_do_out)
7915             VTABLE_ADD_FUNC(codecvt_wchar_do_unshift)
7916             VTABLE_ADD_FUNC(codecvt_wchar_do_length));
7917     __ASM_VTABLE(numpunct_char,
7918             VTABLE_ADD_FUNC(numpunct_char_vector_dtor)
7919             VTABLE_ADD_FUNC(numpunct_char_do_decimal_point)
7920             VTABLE_ADD_FUNC(numpunct_char_do_thousands_sep)
7921             VTABLE_ADD_FUNC(numpunct_char_do_grouping)
7922             VTABLE_ADD_FUNC(numpunct_char_do_falsename)
7923             VTABLE_ADD_FUNC(numpunct_char_do_truename));
7924     __ASM_VTABLE(numpunct_wchar,
7925             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
7926             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
7927             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
7928             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
7929             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
7930             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
7931     __ASM_VTABLE(numpunct_short,
7932             VTABLE_ADD_FUNC(numpunct_wchar_vector_dtor)
7933             VTABLE_ADD_FUNC(numpunct_wchar_do_decimal_point)
7934             VTABLE_ADD_FUNC(numpunct_wchar_do_thousands_sep)
7935             VTABLE_ADD_FUNC(numpunct_wchar_do_grouping)
7936             VTABLE_ADD_FUNC(numpunct_wchar_do_falsename)
7937             VTABLE_ADD_FUNC(numpunct_wchar_do_truename));
7938     __ASM_VTABLE(num_get_char,
7939             VTABLE_ADD_FUNC(num_get_char_vector_dtor)
7940             VTABLE_ADD_FUNC(num_get_char_do_get_void)
7941             VTABLE_ADD_FUNC(num_get_char_do_get_double)
7942             VTABLE_ADD_FUNC(num_get_char_do_get_double)
7943             VTABLE_ADD_FUNC(num_get_char_do_get_float)
7944             VTABLE_ADD_FUNC(num_get_char_do_get_uint64)
7945             VTABLE_ADD_FUNC(num_get_char_do_get_int64)
7946             VTABLE_ADD_FUNC(num_get_char_do_get_ulong)
7947             VTABLE_ADD_FUNC(num_get_char_do_get_long)
7948             VTABLE_ADD_FUNC(num_get_char_do_get_uint)
7949             VTABLE_ADD_FUNC(num_get_char_do_get_ushort)
7950             VTABLE_ADD_FUNC(num_get_char_do_get_bool));
7951     __ASM_VTABLE(num_get_short,
7952             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
7953             VTABLE_ADD_FUNC(num_get_short_do_get_void)
7954             VTABLE_ADD_FUNC(num_get_short_do_get_double)
7955             VTABLE_ADD_FUNC(num_get_short_do_get_double)
7956             VTABLE_ADD_FUNC(num_get_short_do_get_float)
7957             VTABLE_ADD_FUNC(num_get_short_do_get_uint64)
7958             VTABLE_ADD_FUNC(num_get_short_do_get_int64)
7959             VTABLE_ADD_FUNC(num_get_short_do_get_ulong)
7960             VTABLE_ADD_FUNC(num_get_short_do_get_long)
7961             VTABLE_ADD_FUNC(num_get_short_do_get_uint)
7962             VTABLE_ADD_FUNC(num_get_short_do_get_ushort)
7963             VTABLE_ADD_FUNC(num_get_short_do_get_bool));
7964     __ASM_VTABLE(num_get_wchar,
7965             VTABLE_ADD_FUNC(num_get_wchar_vector_dtor)
7966             VTABLE_ADD_FUNC(num_get_wchar_do_get_void)
7967             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
7968             VTABLE_ADD_FUNC(num_get_wchar_do_get_double)
7969             VTABLE_ADD_FUNC(num_get_wchar_do_get_float)
7970             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint64)
7971             VTABLE_ADD_FUNC(num_get_wchar_do_get_int64)
7972             VTABLE_ADD_FUNC(num_get_wchar_do_get_ulong)
7973             VTABLE_ADD_FUNC(num_get_wchar_do_get_long)
7974             VTABLE_ADD_FUNC(num_get_wchar_do_get_uint)
7975             VTABLE_ADD_FUNC(num_get_wchar_do_get_ushort)
7976             VTABLE_ADD_FUNC(num_get_wchar_do_get_bool));
7977     __ASM_VTABLE(num_put_char,
7978             VTABLE_ADD_FUNC(num_put_char_vector_dtor)
7979             VTABLE_ADD_FUNC(num_put_char_do_put_ptr)
7980             VTABLE_ADD_FUNC(num_put_char_do_put_double)
7981             VTABLE_ADD_FUNC(num_put_char_do_put_double)
7982             VTABLE_ADD_FUNC(num_put_char_do_put_uint64)
7983             VTABLE_ADD_FUNC(num_put_char_do_put_int64)
7984             VTABLE_ADD_FUNC(num_put_char_do_put_ulong)
7985             VTABLE_ADD_FUNC(num_put_char_do_put_long)
7986             VTABLE_ADD_FUNC(num_put_char_do_put_bool));
7987     __ASM_VTABLE(num_put_wchar,
7988             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
7989             VTABLE_ADD_FUNC(num_put_wchar_do_put_ptr)
7990             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
7991             VTABLE_ADD_FUNC(num_put_wchar_do_put_double)
7992             VTABLE_ADD_FUNC(num_put_wchar_do_put_uint64)
7993             VTABLE_ADD_FUNC(num_put_wchar_do_put_int64)
7994             VTABLE_ADD_FUNC(num_put_wchar_do_put_ulong)
7995             VTABLE_ADD_FUNC(num_put_wchar_do_put_long)
7996             VTABLE_ADD_FUNC(num_put_wchar_do_put_bool));
7997     __ASM_VTABLE(num_put_short,
7998             VTABLE_ADD_FUNC(num_put_wchar_vector_dtor)
7999             VTABLE_ADD_FUNC(num_put_short_do_put_ptr)
8000             VTABLE_ADD_FUNC(num_put_short_do_put_double)
8001             VTABLE_ADD_FUNC(num_put_short_do_put_double)
8002             VTABLE_ADD_FUNC(num_put_short_do_put_uint64)
8003             VTABLE_ADD_FUNC(num_put_short_do_put_int64)
8004             VTABLE_ADD_FUNC(num_put_short_do_put_ulong)
8005             VTABLE_ADD_FUNC(num_put_short_do_put_long)
8006             VTABLE_ADD_FUNC(num_put_short_do_put_bool));
8007 #ifndef __GNUC__
8008 }
8009 #endif
8010
8011 void init_locale(void *base)
8012 {
8013 #ifdef __x86_64__
8014     init_locale_facet_rtti(base);
8015     init_collate_char_rtti(base);
8016     init_collate_wchar_rtti(base);
8017     init_collate_short_rtti(base);
8018     init_ctype_base_rtti(base);
8019     init_ctype_char_rtti(base);
8020     init_ctype_wchar_rtti(base);
8021     init_ctype_short_rtti(base);
8022     init_codecvt_base_rtti(base);
8023     init_codecvt_char_rtti(base);
8024     init_codecvt_wchar_rtti(base);
8025     init_codecvt_short_rtti(base);
8026     init_numpunct_char_rtti(base);
8027     init_numpunct_wchar_rtti(base);
8028     init_numpunct_short_rtti(base);
8029     init_num_get_char_rtti(base);
8030     init_num_get_wchar_rtti(base);
8031     init_num_get_short_rtti(base);
8032     init_num_put_char_rtti(base);
8033     init_num_put_wchar_rtti(base);
8034     init_num_put_short_rtti(base);
8035 #endif
8036 }
8037
8038 void free_locale(void)
8039 {
8040     facets_elem *iter, *safe;
8041
8042     if(global_locale) {
8043         locale__Locimp_dtor(global_locale);
8044         locale_dtor(&classic_locale);
8045     }
8046
8047     LIST_FOR_EACH_ENTRY_SAFE(iter, safe, &lazy_facets, facets_elem, entry) {
8048         list_remove(&iter->entry);
8049         if(locale_facet__Decref(iter->fac))
8050             call_locale_facet_vector_dtor(iter->fac, 1);
8051         MSVCRT_operator_delete(iter);
8052     }
8053 }