msvcrt: Import lroundf implementation from musl.
[wine.git] / dlls / msvcrt / scanf.c
blob988cbd0920d1cc344527c4af611ec8f7c13782c8
1 /*
2 * general implementation of scanf used by scanf, sscanf, fscanf,
3 * _cscanf, wscanf, swscanf and fwscanf
5 * Copyright 1996,1998 Marcus Meissner
6 * Copyright 1996 Jukka Iivonen
7 * Copyright 1997,2000 Uwe Bonnes
8 * Copyright 2000 Jon Griffiths
9 * Copyright 2002 Daniel Gudbjartsson
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include <conio.h>
27 #include <stdarg.h>
28 #include <limits.h>
29 #include <math.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winternl.h"
34 #include "msvcrt.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
39 /* helper function for *scanf. Returns the value of character c in the
40 * given base, or -1 if the given character is not a digit of the base.
42 static int char2digit(char c, int base) {
43 if ((c>='0') && (c<='9') && (c<='0'+base-1)) return (c-'0');
44 if (base<=10) return -1;
45 if ((c>='A') && (c<='Z') && (c<='A'+base-11)) return (c-'A'+10);
46 if ((c>='a') && (c<='z') && (c<='a'+base-11)) return (c-'a'+10);
47 return -1;
50 /* helper function for *wscanf. Returns the value of character c in the
51 * given base, or -1 if the given character is not a digit of the base.
53 static int wchar2digit(wchar_t c, int base) {
54 if ((c>='0') && (c<='9') && (c<='0'+base-1)) return (c-'0');
55 if (base<=10) return -1;
56 if ((c>='A') && (c<='Z') && (c<='A'+base-11)) return (c-'A'+10);
57 if ((c>='a') && (c<='z') && (c<='a'+base-11)) return (c-'a'+10);
58 return -1;
61 /* vfscanf_l */
62 #undef WIDE_SCANF
63 #undef CONSOLE
64 #undef STRING
65 #undef SECURE
66 #include "scanf.h"
68 /* vfscanf_s_l */
69 #define SECURE 1
70 #include "scanf.h"
72 /* vfwscanf_l */
73 #define WIDE_SCANF 1
74 #undef CONSOLE
75 #undef STRING
76 #undef SECURE
77 #include "scanf.h"
79 /* vfwscanf_s_l */
80 #define SECURE 1
81 #include "scanf.h"
83 /* vsscanf_l */
84 #undef WIDE_SCANF
85 #undef CONSOLE
86 #define STRING 1
87 #undef SECURE
88 #include "scanf.h"
90 /* vsscanf_s_l */
91 #define SECURE 1
92 #include "scanf.h"
94 /* vsnscanf_l */
95 #undef SECURE
96 #define STRING_LEN 1
97 #include "scanf.h"
99 /* vsnscanf_s_l */
100 #define SECURE
101 #include "scanf.h"
102 #undef STRING_LEN
104 /* vswscanf_l */
105 #define WIDE_SCANF 1
106 #undef CONSOLE
107 #define STRING 1
108 #undef SECURE
109 #include "scanf.h"
111 /* vsnwscanf_l */
112 #define STRING_LEN 1
113 #include "scanf.h"
115 /* vsnwscanf_s_l */
116 #define SECURE 1
117 #include "scanf.h"
118 #undef STRING_LEN
120 /* vswscanf_s_l */
121 #define SECURE 1
122 #include "scanf.h"
124 /* vcscanf_l */
125 #undef WIDE_SCANF
126 #define CONSOLE 1
127 #undef STRING
128 #undef SECURE
129 #include "scanf.h"
131 /* vcscanf_s_l */
132 #define SECURE 1
133 #include "scanf.h"
135 /* vcwscanf_l */
136 #define WIDE_SCANF 1
137 #define CONSOLE 1
138 #undef STRING
139 #undef SECURE
140 #include "scanf.h"
142 /* vcwscanf_s_l */
143 #define SECURE 1
144 #include "scanf.h"
147 /*********************************************************************
148 * fscanf (MSVCRT.@)
150 int WINAPIV fscanf(FILE *file, const char *format, ...)
152 __ms_va_list valist;
153 int res;
155 __ms_va_start(valist, format);
156 res = vfscanf_l(file, format, NULL, valist);
157 __ms_va_end(valist);
158 return res;
161 /*********************************************************************
162 * _fscanf_l (MSVCRT.@)
164 int WINAPIV _fscanf_l(FILE *file, const char *format,
165 _locale_t locale, ...)
167 __ms_va_list valist;
168 int res;
170 __ms_va_start(valist, locale);
171 res = vfscanf_l(file, format, locale, valist);
172 __ms_va_end(valist);
173 return res;
176 /*********************************************************************
177 * fscanf_s (MSVCRT.@)
179 int WINAPIV fscanf_s(FILE *file, const char *format, ...)
181 __ms_va_list valist;
182 int res;
184 __ms_va_start(valist, format);
185 res = vfscanf_s_l(file, format, NULL, valist);
186 __ms_va_end(valist);
187 return res;
190 /*********************************************************************
191 * _fscanf_s_l (MSVCRT.@)
193 int WINAPIV _fscanf_s_l(FILE *file, const char *format,
194 _locale_t locale, ...)
196 __ms_va_list valist;
197 int res;
199 __ms_va_start(valist, locale);
200 res = vfscanf_s_l(file, format, locale, valist);
201 __ms_va_end(valist);
202 return res;
205 /*********************************************************************
206 * scanf (MSVCRT.@)
208 int WINAPIV scanf(const char *format, ...)
210 __ms_va_list valist;
211 int res;
213 __ms_va_start(valist, format);
214 res = vfscanf_l(MSVCRT_stdin, format, NULL, valist);
215 __ms_va_end(valist);
216 return res;
219 /*********************************************************************
220 * _scanf_l (MSVCRT.@)
222 int WINAPIV _scanf_l(const char *format, _locale_t locale, ...)
224 __ms_va_list valist;
225 int res;
227 __ms_va_start(valist, locale);
228 res = vfscanf_l(MSVCRT_stdin, format, locale, valist);
229 __ms_va_end(valist);
230 return res;
233 /*********************************************************************
234 * scanf_s (MSVCRT.@)
236 int WINAPIV scanf_s(const char *format, ...)
238 __ms_va_list valist;
239 int res;
241 __ms_va_start(valist, format);
242 res = vfscanf_s_l(MSVCRT_stdin, format, NULL, valist);
243 __ms_va_end(valist);
244 return res;
247 /*********************************************************************
248 * _scanf_s_l (MSVCRT.@)
250 int WINAPIV _scanf_s_l(const char *format, _locale_t locale, ...)
252 __ms_va_list valist;
253 int res;
255 __ms_va_start(valist, locale);
256 res = vfscanf_s_l(MSVCRT_stdin, format, locale, valist);
257 __ms_va_end(valist);
258 return res;
261 /*********************************************************************
262 * fwscanf (MSVCRT.@)
264 int WINAPIV fwscanf(FILE *file, const wchar_t *format, ...)
266 __ms_va_list valist;
267 int res;
269 __ms_va_start(valist, format);
270 res = vfwscanf_l(file, format, NULL, valist);
271 __ms_va_end(valist);
272 return res;
275 /*********************************************************************
276 * _fwscanf_l (MSVCRT.@)
278 int WINAPIV _fwscanf_l(FILE *file, const wchar_t *format,
279 _locale_t locale, ...)
281 __ms_va_list valist;
282 int res;
284 __ms_va_start(valist, locale);
285 res = vfwscanf_l(file, format, locale, valist);
286 __ms_va_end(valist);
287 return res;
290 /*********************************************************************
291 * fwscanf_s (MSVCRT.@)
293 int WINAPIV fwscanf_s(FILE *file, const wchar_t *format, ...)
295 __ms_va_list valist;
296 int res;
298 __ms_va_start(valist, format);
299 res = vfwscanf_s_l(file, format, NULL, valist);
300 __ms_va_end(valist);
301 return res;
304 /*********************************************************************
305 * _fwscanf_s_l (MSVCRT.@)
307 int WINAPIV _fwscanf_s_l(FILE *file, const wchar_t *format,
308 _locale_t locale, ...)
310 __ms_va_list valist;
311 int res;
313 __ms_va_start(valist, locale);
314 res = vfwscanf_s_l(file, format, locale, valist);
315 __ms_va_end(valist);
316 return res;
319 /*********************************************************************
320 * wscanf (MSVCRT.@)
322 int WINAPIV wscanf(const wchar_t *format, ...)
324 __ms_va_list valist;
325 int res;
327 __ms_va_start(valist, format);
328 res = vfwscanf_l(MSVCRT_stdin, format, NULL, valist);
329 __ms_va_end(valist);
330 return res;
333 /*********************************************************************
334 * _wscanf_l (MSVCRT.@)
336 int WINAPIV _wscanf_l(const wchar_t *format,
337 _locale_t locale, ...)
339 __ms_va_list valist;
340 int res;
342 __ms_va_start(valist, locale);
343 res = vfwscanf_l(MSVCRT_stdin, format, locale, valist);
344 __ms_va_end(valist);
345 return res;
348 /*********************************************************************
349 * wscanf_s (MSVCRT.@)
351 int WINAPIV wscanf_s(const wchar_t *format, ...)
353 __ms_va_list valist;
354 int res;
356 __ms_va_start(valist, format);
357 res = vfwscanf_s_l(MSVCRT_stdin, format, NULL, valist);
358 __ms_va_end(valist);
359 return res;
362 /*********************************************************************
363 * _wscanf_s_l (MSVCRT.@)
365 int WINAPIV _wscanf_s_l(const wchar_t *format,
366 _locale_t locale, ...)
368 __ms_va_list valist;
369 int res;
371 __ms_va_start(valist, locale);
372 res = vfwscanf_s_l(MSVCRT_stdin, format, locale, valist);
373 __ms_va_end(valist);
374 return res;
377 /*********************************************************************
378 * sscanf (MSVCRT.@)
380 int WINAPIV sscanf(const char *str, const char *format, ...)
382 __ms_va_list valist;
383 int res;
385 __ms_va_start(valist, format);
386 res = vsscanf_l(str, format, NULL, valist);
387 __ms_va_end(valist);
388 return res;
391 /*********************************************************************
392 * _sscanf_l (MSVCRT.@)
394 int WINAPIV _sscanf_l(const char *str, const char *format,
395 _locale_t locale, ...)
397 __ms_va_list valist;
398 int res;
400 __ms_va_start(valist, locale);
401 res = vsscanf_l(str, format, locale, valist);
402 __ms_va_end(valist);
403 return res;
406 /*********************************************************************
407 * sscanf_s (MSVCRT.@)
409 int WINAPIV sscanf_s(const char *str, const char *format, ...)
411 __ms_va_list valist;
412 int res;
414 __ms_va_start(valist, format);
415 res = vsscanf_s_l(str, format, NULL, valist);
416 __ms_va_end(valist);
417 return res;
420 /*********************************************************************
421 * _sscanf_s_l (MSVCRT.@)
423 int WINAPIV _sscanf_s_l(const char *str, const char *format,
424 _locale_t locale, ...)
426 __ms_va_list valist;
427 int res;
429 __ms_va_start(valist, locale);
430 res = vsscanf_s_l(str, format, locale, valist);
431 __ms_va_end(valist);
432 return res;
435 /*********************************************************************
436 * swscanf (MSVCRT.@)
438 int WINAPIV swscanf(const wchar_t *str, const wchar_t *format, ...)
440 __ms_va_list valist;
441 int res;
443 __ms_va_start(valist, format);
444 res = vswscanf_l(str, format, NULL, valist);
445 __ms_va_end(valist);
446 return res;
449 /*********************************************************************
450 * _swscanf_l (MSVCRT.@)
452 int WINAPIV _swscanf_l(const wchar_t *str, const wchar_t *format,
453 _locale_t locale, ...)
455 __ms_va_list valist;
456 int res;
458 __ms_va_start(valist, locale);
459 res = vswscanf_l(str, format, locale, valist);
460 __ms_va_end(valist);
461 return res;
464 /*********************************************************************
465 * swscanf_s (MSVCRT.@)
467 int WINAPIV swscanf_s(const wchar_t *str, const wchar_t *format, ...)
469 __ms_va_list valist;
470 int res;
472 __ms_va_start(valist, format);
473 res = vswscanf_s_l(str, format, NULL, valist);
474 __ms_va_end(valist);
475 return res;
478 /*********************************************************************
479 * _swscanf_s_l (MSVCRT.@)
481 int WINAPIV _swscanf_s_l(const wchar_t *str, const wchar_t *format,
482 _locale_t locale, ...)
484 __ms_va_list valist;
485 int res;
487 __ms_va_start(valist, locale);
488 res = vswscanf_s_l(str, format, locale, valist);
489 __ms_va_end(valist);
490 return res;
493 /*********************************************************************
494 * _cscanf (MSVCRT.@)
496 int WINAPIV _cscanf(const char *format, ...)
498 __ms_va_list valist;
499 int res;
501 __ms_va_start(valist, format);
502 res = vcscanf_l(format, NULL, valist);
503 __ms_va_end(valist);
504 return res;
507 /*********************************************************************
508 * _cscanf_l (MSVCRT.@)
510 int WINAPIV _cscanf_l(const char *format, _locale_t locale, ...)
512 __ms_va_list valist;
513 int res;
515 __ms_va_start(valist, locale);
516 res = vcscanf_l(format, locale, valist);
517 __ms_va_end(valist);
518 return res;
521 /*********************************************************************
522 * _cscanf_s (MSVCRT.@)
524 int WINAPIV _cscanf_s(const char *format, ...)
526 __ms_va_list valist;
527 int res;
529 __ms_va_start(valist, format);
530 res = vcscanf_s_l(format, NULL, valist);
531 __ms_va_end(valist);
532 return res;
535 /*********************************************************************
536 * _cscanf_s_l (MSVCRT.@)
538 int WINAPIV _cscanf_s_l(const char *format, _locale_t locale, ...)
540 __ms_va_list valist;
541 int res;
543 __ms_va_start(valist, locale);
544 res = vcscanf_s_l(format, locale, valist);
545 __ms_va_end(valist);
546 return res;
549 /*********************************************************************
550 * _cwscanf (MSVCRT.@)
552 int WINAPIV _cwscanf(const wchar_t *format, ...)
554 __ms_va_list valist;
555 int res;
557 __ms_va_start(valist, format);
558 res = vcwscanf_l(format, NULL, valist);
559 __ms_va_end(valist);
560 return res;
563 /*********************************************************************
564 * _cwscanf_l (MSVCRT.@)
566 int WINAPIV _cwscanf_l(const wchar_t *format, _locale_t locale, ...)
568 __ms_va_list valist;
569 int res;
571 __ms_va_start(valist, locale);
572 res = vcwscanf_l(format, locale, valist);
573 __ms_va_end(valist);
574 return res;
577 /*********************************************************************
578 * _cwscanf_s (MSVCRT.@)
580 int WINAPIV _cwscanf_s(const wchar_t *format, ...)
582 __ms_va_list valist;
583 int res;
585 __ms_va_start(valist, format);
586 res = vcwscanf_s_l(format, NULL, valist);
587 __ms_va_end(valist);
588 return res;
591 /*********************************************************************
592 * _cwscanf_s_l (MSVCRT.@)
594 int WINAPIV _cwscanf_s_l(const wchar_t *format, _locale_t locale, ...)
596 __ms_va_list valist;
597 int res;
599 __ms_va_start(valist, locale);
600 res = vcwscanf_s_l(format, locale, valist);
601 __ms_va_end(valist);
602 return res;
605 /*********************************************************************
606 * _snscanf (MSVCRT.@)
608 int WINAPIV _snscanf(const char *input, size_t length, const char *format, ...)
610 __ms_va_list valist;
611 int res;
613 __ms_va_start(valist, format);
614 res = vsnscanf_l(input, length, format, NULL, valist);
615 __ms_va_end(valist);
616 return res;
619 /*********************************************************************
620 * _snscanf_l (MSVCRT.@)
622 int WINAPIV _snscanf_l(const char *input, size_t length,
623 const char *format, _locale_t locale, ...)
625 __ms_va_list valist;
626 int res;
628 __ms_va_start(valist, locale);
629 res = vsnscanf_l(input, length, format, locale, valist);
630 __ms_va_end(valist);
631 return res;
634 /*********************************************************************
635 * _snscanf_s (MSVCRT.@)
637 int WINAPIV _snscanf_s(const char *input, size_t length, const char *format, ...)
639 __ms_va_list valist;
640 int res;
642 __ms_va_start(valist, format);
643 res = vsnscanf_s_l(input, length, format, NULL, valist);
644 __ms_va_end(valist);
645 return res;
648 /*********************************************************************
649 * _snscanf_s_l (MSVCRT.@)
651 int WINAPIV _snscanf_s_l(const char *input, size_t length,
652 const char *format, _locale_t locale, ...)
654 __ms_va_list valist;
655 int res;
657 __ms_va_start(valist, locale);
658 res = vsnscanf_s_l(input, length, format, locale, valist);
659 __ms_va_end(valist);
660 return res;
664 /*********************************************************************
665 * __stdio_common_vsscanf (UCRTBASE.@)
667 int CDECL __stdio_common_vsscanf(unsigned __int64 options,
668 const char *input, size_t length,
669 const char *format,
670 _locale_t locale,
671 __ms_va_list valist)
673 /* LEGACY_WIDE_SPECIFIERS only has got an effect on the wide
674 * scanf. LEGACY_MSVCRT_COMPATIBILITY affects parsing of nan/inf,
675 * but parsing of those isn't implemented at all yet. */
676 if (options & ~UCRTBASE_SCANF_MASK)
677 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
678 if (options & _CRT_INTERNAL_SCANF_SECURECRT)
679 return vsnscanf_s_l(input, length, format, locale, valist);
680 else
681 return vsnscanf_l(input, length, format, locale, valist);
684 /*********************************************************************
685 * __stdio_common_vswscanf (UCRTBASE.@)
687 int CDECL __stdio_common_vswscanf(unsigned __int64 options,
688 const wchar_t *input, size_t length,
689 const wchar_t *format,
690 _locale_t locale,
691 __ms_va_list valist)
693 /* LEGACY_WIDE_SPECIFIERS only has got an effect on the wide
694 * scanf. LEGACY_MSVCRT_COMPATIBILITY affects parsing of nan/inf,
695 * but parsing of those isn't implemented at all yet. */
696 if (options & ~UCRTBASE_SCANF_MASK)
697 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
698 if (options & _CRT_INTERNAL_SCANF_SECURECRT)
699 return vsnwscanf_s_l(input, length, format, locale, valist);
700 else
701 return vsnwscanf_l(input, length, format, locale, valist);
704 /*********************************************************************
705 * __stdio_common_vfscanf (UCRTBASE.@)
707 int CDECL __stdio_common_vfscanf(unsigned __int64 options,
708 FILE *file,
709 const char *format,
710 _locale_t locale,
711 __ms_va_list valist)
713 if (options & ~_CRT_INTERNAL_SCANF_SECURECRT)
714 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
715 if (options & _CRT_INTERNAL_SCANF_SECURECRT)
716 return vfscanf_s_l(file, format, locale, valist);
717 else
718 return vfscanf_l(file, format, locale, valist);
721 /*********************************************************************
722 * __stdio_common_vfwscanf (UCRTBASE.@)
724 int CDECL __stdio_common_vfwscanf(unsigned __int64 options,
725 FILE *file,
726 const wchar_t *format,
727 _locale_t locale,
728 __ms_va_list valist)
730 if (options & ~_CRT_INTERNAL_SCANF_SECURECRT)
731 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
732 if (options & _CRT_INTERNAL_SCANF_SECURECRT)
733 return vfwscanf_s_l(file, format, locale, valist);
734 else
735 return vfwscanf_l(file, format, locale, valist);
738 /*********************************************************************
739 * _snwscanf (MSVCRT.@)
741 int WINAPIV _snwscanf(wchar_t *input, size_t length,
742 const wchar_t *format, ...)
744 __ms_va_list valist;
745 int res;
747 __ms_va_start(valist, format);
748 res = vsnwscanf_l(input, length, format, NULL, valist);
749 __ms_va_end(valist);
750 return res;
753 /*********************************************************************
754 * _snwscanf_l (MSVCRT.@)
756 int WINAPIV _snwscanf_l(wchar_t *input, size_t length,
757 const wchar_t *format, _locale_t locale, ...)
759 __ms_va_list valist;
760 int res;
762 __ms_va_start(valist, locale);
763 res = vsnwscanf_l(input, length, format, locale, valist);
764 __ms_va_end(valist);
765 return res;
768 /*********************************************************************
769 * _snwscanf_s (MSVCRT.@)
771 int WINAPIV _snwscanf_s(wchar_t *input, size_t length,
772 const wchar_t *format, ...)
774 __ms_va_list valist;
775 int res;
777 __ms_va_start(valist, format);
778 res = vsnwscanf_s_l(input, length, format, NULL, valist);
779 __ms_va_end(valist);
780 return res;
783 /*********************************************************************
784 * _snscanf_s_l (MSVCRT.@)
786 int WINAPIV _snwscanf_s_l(wchar_t *input, size_t length,
787 const wchar_t *format, _locale_t locale, ...)
789 __ms_va_list valist;
790 int res;
792 __ms_va_start(valist, locale);
793 res = vsnwscanf_s_l(input, length, format, locale, valist);
794 __ms_va_end(valist);
795 return res;
798 #if _MSVCR_VER==120
800 /*********************************************************************
801 * vsscanf (MSVCRT120.@)
803 int CDECL MSVCRT_vsscanf(const char *buffer, const char *format, __ms_va_list valist)
805 if (!MSVCRT_CHECK_PMT(buffer != NULL && format != NULL)) return -1;
807 return vsscanf_l(buffer, format, NULL, valist);
810 /*********************************************************************
811 * vswscanf (MSVCRT120.@)
813 int CDECL vswscanf(const wchar_t *buffer, const wchar_t *format, __ms_va_list valist)
815 if (!MSVCRT_CHECK_PMT(buffer != NULL && format != NULL)) return -1;
817 return vswscanf_l(buffer, format, NULL, valist);
820 #endif /* _MSVCR_VER>=120 */