summaryrefslogtreecommitdiff
path: root/legacy/evil
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-02-17 20:48:11 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-02-17 20:48:11 +0000
commitb9728980ab27a46054fa41531b7c56662c7205b3 (patch)
tree3d7337089f745b8dae42c17d4f0d1a4340b0d158 /legacy/evil
parent30d73cffd7f44766ccae82524959a8c25306d80e (diff)
* AUTHORS:
* src/lib/Evil.h: * src/lib/Makefile.am: * src/lib/evil_inet.c: * src/lib/evil_mman.c: * src/lib/evil_stdio.c: * src/lib/evil_stdio.h: * src/lib/evil_stdlib.c: * src/lib/evil_util.c: * src/lib/sys/mman.h: * src/lib/evil_printa.c (added): * src/lib/evil_pformatw.c (added): * src/lib/evil_pformat.h (added): * src/lib/evil_printw.c (added): * src/lib/evil_print.h (added): * src/lib/evil_macro.h (added): * src/lib/evil_pformata.c (added): Add POSIX printf family. Code taken from the MinGW-w64 project and modified to be integrated into Evil. * src/bin/Makefile.am: * src/bin/evil_suite.c: * src/bin/evil_test_util.h (added): * src/bin/evil_test_print.c (added): * src/bin/evil_test_print.h (added): * src/bin/evil_test_util.c (added): Add util and printf unit tests * src/lib/evil_errno.c: * src/lib/errno.h (deleted): * src/lib/mingw32ce (added): * src/lib/mingw32ce/errno.h (added): Move errno.h for Windows CE in its own directory to suppress conflicts with standard errno.h when compiling for Windows XP. * src/lib/dlfcn/dlfcn.c: * src/lib/evil_link_ce.c: * src/lib/evil_main.c: * src/lib/evil_unistd.c: Define WIN32_LEAN_AND_MEAN only if it's not defined. * src/lib/evil_fcntl.c: Remove debug. * src/bin/evil_test_dlfcn.c: * src/bin/evil_test_environment.c: * src/bin/evil_test_gettimeofday.c: * src/bin/evil_test_link.c: * src/bin/evil_test_mkstemp.c: * src/bin/evil_test_pipe.c: * src/bin/evil_test_realpath.c: Remove warnings. * src/lib/evil_link_xp.cpp: Formatting. SVN revision: 68084
Diffstat (limited to 'legacy/evil')
-rw-r--r--legacy/evil/AUTHORS1
-rw-r--r--legacy/evil/ChangeLog59
-rw-r--r--legacy/evil/src/bin/Makefile.am2
-rw-r--r--legacy/evil/src/bin/evil_suite.c2
-rw-r--r--legacy/evil/src/bin/evil_test_dlfcn.c2
-rw-r--r--legacy/evil/src/bin/evil_test_environment.c2
-rw-r--r--legacy/evil/src/bin/evil_test_gettimeofday.c2
-rw-r--r--legacy/evil/src/bin/evil_test_link.c2
-rw-r--r--legacy/evil/src/bin/evil_test_mkstemp.c2
-rw-r--r--legacy/evil/src/bin/evil_test_pipe.c11
-rw-r--r--legacy/evil/src/bin/evil_test_print.c46
-rw-r--r--legacy/evil/src/bin/evil_test_print.h8
-rw-r--r--legacy/evil/src/bin/evil_test_realpath.c5
-rw-r--r--legacy/evil/src/bin/evil_test_util.c110
-rw-r--r--legacy/evil/src/bin/evil_test_util.h8
-rw-r--r--legacy/evil/src/lib/Evil.h46
-rw-r--r--legacy/evil/src/lib/Makefile.am11
-rw-r--r--legacy/evil/src/lib/dlfcn/dlfcn.c5
-rw-r--r--legacy/evil/src/lib/evil_errno.c2
-rw-r--r--legacy/evil/src/lib/evil_fcntl.c3
-rw-r--r--legacy/evil/src/lib/evil_inet.c11
-rw-r--r--legacy/evil/src/lib/evil_link_ce.c4
-rw-r--r--legacy/evil/src/lib/evil_link_xp.cpp4
-rw-r--r--legacy/evil/src/lib/evil_macro.h192
-rw-r--r--legacy/evil/src/lib/evil_main.c6
-rw-r--r--legacy/evil/src/lib/evil_mman.c10
-rw-r--r--legacy/evil/src/lib/evil_pformat.h61
-rw-r--r--legacy/evil/src/lib/evil_pformata.c2538
-rw-r--r--legacy/evil/src/lib/evil_pformatw.c9
-rw-r--r--legacy/evil/src/lib/evil_print.h103
-rw-r--r--legacy/evil/src/lib/evil_printa.c1785
-rw-r--r--legacy/evil/src/lib/evil_printw.c4
-rw-r--r--legacy/evil/src/lib/evil_stdio.c46
-rw-r--r--legacy/evil/src/lib/evil_stdio.h45
-rw-r--r--legacy/evil/src/lib/evil_stdlib.c16
-rw-r--r--legacy/evil/src/lib/evil_unistd.c4
-rw-r--r--legacy/evil/src/lib/evil_util.c13
-rw-r--r--legacy/evil/src/lib/mingw32ce/errno.h (renamed from legacy/evil/src/lib/errno.h)0
-rw-r--r--legacy/evil/src/lib/sys/mman.h2
39 files changed, 5028 insertions, 154 deletions
diff --git a/legacy/evil/AUTHORS b/legacy/evil/AUTHORS
index e73fed1fdf..cee8fc9f11 100644
--- a/legacy/evil/AUTHORS
+++ b/legacy/evil/AUTHORS
@@ -5,3 +5,4 @@ Main Authors:
5 Vincent Richomme <vrichomme at smartmobili dot com> 5 Vincent Richomme <vrichomme at smartmobili dot com>
6 Paul Vixie (ISC) (inet_pton and inet_ntop functions) 6 Paul Vixie (ISC) (inet_pton and inet_ntop functions)
7 Daniel Stenberg (inet_pton and inet_ntop functions) 7 Daniel Stenberg (inet_pton and inet_ntop functions)
8 The MinGW and MinGW-w64 teams (POSIX printf family functions)
diff --git a/legacy/evil/ChangeLog b/legacy/evil/ChangeLog
index 85d9569145..4650b20e86 100644
--- a/legacy/evil/ChangeLog
+++ b/legacy/evil/ChangeLog
@@ -1,3 +1,62 @@
12012-02-17 Vincent Torri <doursse at users dot sf dot net>
2
3 * AUTHORS:
4 * src/lib/Evil.h:
5 * src/lib/Makefile.am:
6 * src/lib/evil_inet.c:
7 * src/lib/evil_mman.c:
8 * src/lib/evil_stdio.c:
9 * src/lib/evil_stdio.h:
10 * src/lib/evil_stdlib.c:
11 * src/lib/evil_util.c:
12 * src/lib/sys/mman.h:
13 * src/lib/evil_printa.c (added):
14 * src/lib/evil_pformatw.c (added):
15 * src/lib/evil_pformat.h (added):
16 * src/lib/evil_printw.c (added):
17 * src/lib/evil_print.h (added):
18 * src/lib/evil_macro.h (added):
19 * src/lib/evil_pformata.c (added):
20 Add POSIX printf family. Code taken from the MinGW-w64
21 project and modified to be integrated into Evil.
22
23 * src/bin/Makefile.am:
24 * src/bin/evil_suite.c:
25 * src/bin/evil_test_util.h (added):
26 * src/bin/evil_test_print.c (added):
27 * src/bin/evil_test_print.h (added):
28 * src/bin/evil_test_util.c (added):
29 Add util and printf unit tests
30
31 * src/lib/evil_errno.c:
32 * src/lib/errno.h (deleted):
33 * src/lib/mingw32ce (added):
34 * src/lib/mingw32ce/errno.h (added):
35 Move errno.h for Windows CE in its own directory to
36 suppress conflicts with standard errno.h when compiling
37 for Windows XP.
38
39 * src/lib/dlfcn/dlfcn.c:
40 * src/lib/evil_link_ce.c:
41 * src/lib/evil_main.c:
42 * src/lib/evil_unistd.c:
43 Define WIN32_LEAN_AND_MEAN only if it's not defined.
44
45 * src/lib/evil_fcntl.c:
46 Remove debug.
47
48 * src/bin/evil_test_dlfcn.c:
49 * src/bin/evil_test_environment.c:
50 * src/bin/evil_test_gettimeofday.c:
51 * src/bin/evil_test_link.c:
52 * src/bin/evil_test_mkstemp.c:
53 * src/bin/evil_test_pipe.c:
54 * src/bin/evil_test_realpath.c:
55 Remove warnings.
56
57 * src/lib/evil_link_xp.cpp:
58 Formatting.
59
12012-01-20 Vincent Torri <doursse at users dot sf dot net> 602012-01-20 Vincent Torri <doursse at users dot sf dot net>
2 61
3 * Makefile.am: 62 * Makefile.am:
diff --git a/legacy/evil/src/bin/Makefile.am b/legacy/evil/src/bin/Makefile.am
index f466365c94..697bd3f97a 100644
--- a/legacy/evil/src/bin/Makefile.am
+++ b/legacy/evil/src/bin/Makefile.am
@@ -21,6 +21,7 @@ evil_test_link.c \
21evil_test_memcpy.c \ 21evil_test_memcpy.c \
22evil_test_mkstemp.c \ 22evil_test_mkstemp.c \
23evil_test_pipe.c \ 23evil_test_pipe.c \
24evil_test_print.c \
24evil_test_realpath.c \ 25evil_test_realpath.c \
25evil_test_util.c \ 26evil_test_util.c \
26evil_suite.h \ 27evil_suite.h \
@@ -31,6 +32,7 @@ evil_test_link.h \
31evil_test_memcpy.h \ 32evil_test_memcpy.h \
32evil_test_mkstemp.h \ 33evil_test_mkstemp.h \
33evil_test_pipe.h \ 34evil_test_pipe.h \
35evil_test_print.h \
34evil_test_realpath.h \ 36evil_test_realpath.h \
35evil_test_util.h 37evil_test_util.h
36 38
diff --git a/legacy/evil/src/bin/evil_suite.c b/legacy/evil/src/bin/evil_suite.c
index 429959c79a..ba928f0682 100644
--- a/legacy/evil/src/bin/evil_suite.c
+++ b/legacy/evil/src/bin/evil_suite.c
@@ -18,6 +18,7 @@
18#include "evil_test_memcpy.h" 18#include "evil_test_memcpy.h"
19#include "evil_test_mkstemp.h" 19#include "evil_test_mkstemp.h"
20#include "evil_test_pipe.h" 20#include "evil_test_pipe.h"
21#include "evil_test_print.h"
21#include "evil_test_realpath.h" 22#include "evil_test_realpath.h"
22#include "evil_test_util.h" 23#include "evil_test_util.h"
23 24
@@ -185,6 +186,7 @@ main(void)
185 { "link ", test_link }, 186 { "link ", test_link },
186 { "mkstemp ", test_mkstemp }, 187 { "mkstemp ", test_mkstemp },
187 { "pipe ", test_pipe }, 188 { "pipe ", test_pipe },
189 { "print ", test_print },
188 { "realpath ", test_realpath }, 190 { "realpath ", test_realpath },
189 { "util ", test_util }, 191 { "util ", test_util },
190/* { "memcpy ", test_memcpy }, */ 192/* { "memcpy ", test_memcpy }, */
diff --git a/legacy/evil/src/bin/evil_test_dlfcn.c b/legacy/evil/src/bin/evil_test_dlfcn.c
index b84a9eb238..fb32dd1540 100644
--- a/legacy/evil/src/bin/evil_test_dlfcn.c
+++ b/legacy/evil/src/bin/evil_test_dlfcn.c
@@ -62,7 +62,7 @@ test_dlfcn_test_dlsym(void)
62} 62}
63 63
64static int 64static int
65test_dlfcn_tests_run(suite *s) 65test_dlfcn_tests_run(suite *s __UNUSED__)
66{ 66{
67 int res; 67 int res;
68 68
diff --git a/legacy/evil/src/bin/evil_test_environment.c b/legacy/evil/src/bin/evil_test_environment.c
index 0d31b7912a..3048a40124 100644
--- a/legacy/evil/src/bin/evil_test_environment.c
+++ b/legacy/evil/src/bin/evil_test_environment.c
@@ -156,7 +156,7 @@ test_env_test_unsetenv(void)
156} 156}
157 157
158static int 158static int
159test_env_tests_run(suite *s) 159test_env_tests_run(suite *s __UNUSED__)
160{ 160{
161 int res; 161 int res;
162 162
diff --git a/legacy/evil/src/bin/evil_test_gettimeofday.c b/legacy/evil/src/bin/evil_test_gettimeofday.c
index 6be9970ad4..44fa79e809 100644
--- a/legacy/evil/src/bin/evil_test_gettimeofday.c
+++ b/legacy/evil/src/bin/evil_test_gettimeofday.c
@@ -33,7 +33,7 @@ test_time_test_gettimeofday(void)
33} 33}
34 34
35static int 35static int
36test_time_tests_run(suite *s) 36test_time_tests_run(suite *s __UNUSED__)
37{ 37{
38 int res; 38 int res;
39 39
diff --git a/legacy/evil/src/bin/evil_test_link.c b/legacy/evil/src/bin/evil_test_link.c
index 868e9f23d2..cf4cd931ae 100644
--- a/legacy/evil/src/bin/evil_test_link.c
+++ b/legacy/evil/src/bin/evil_test_link.c
@@ -140,7 +140,7 @@ test_link_test_readlink(void)
140} 140}
141 141
142static int 142static int
143test_link_tests_run(suite *s) 143test_link_tests_run(suite *s __UNUSED__)
144{ 144{
145 int res; 145 int res;
146 146
diff --git a/legacy/evil/src/bin/evil_test_mkstemp.c b/legacy/evil/src/bin/evil_test_mkstemp.c
index a716b726aa..dc8c4e64f5 100644
--- a/legacy/evil/src/bin/evil_test_mkstemp.c
+++ b/legacy/evil/src/bin/evil_test_mkstemp.c
@@ -36,7 +36,7 @@ test_mkstemp_test(void)
36} 36}
37 37
38static int 38static int
39test_mkstemp_run(suite *s) 39test_mkstemp_run(suite *s __UNUSED__)
40{ 40{
41 int res; 41 int res;
42 42
diff --git a/legacy/evil/src/bin/evil_test_pipe.c b/legacy/evil/src/bin/evil_test_pipe.c
index 426c27e818..2fc530d545 100644
--- a/legacy/evil/src/bin/evil_test_pipe.c
+++ b/legacy/evil/src/bin/evil_test_pipe.c
@@ -75,11 +75,9 @@ test_pipe_test(void)
75 75
76 if (ret < 0) 76 if (ret < 0)
77 goto free_d; 77 goto free_d;
78 78 else if (ret == 0)
79 if (ret == 0)
80 goto close_h; 79 goto close_h;
81 80 else /* ret > 0 */
82 if (ret > 0)
83 { 81 {
84 void *buf[1]; 82 void *buf[1];
85 data *d2 = NULL; 83 data *d2 = NULL;
@@ -102,7 +100,7 @@ test_pipe_test(void)
102 CloseHandle(h); 100 CloseHandle(h);
103 free(d); 101 free(d);
104 102
105 return 1; 103 return ret;
106 104
107 close_h: 105 close_h:
108 CloseHandle(h); 106 CloseHandle(h);
@@ -112,7 +110,7 @@ test_pipe_test(void)
112} 110}
113 111
114static int 112static int
115test_pipe_run(suite *s) 113test_pipe_run(suite *s __UNUSED__)
116{ 114{
117 int res; 115 int res;
118 116
@@ -124,6 +122,5 @@ test_pipe_run(suite *s)
124int 122int
125test_pipe(suite *s) 123test_pipe(suite *s)
126{ 124{
127
128 return test_pipe_run(s); 125 return test_pipe_run(s);
129} 126}
diff --git a/legacy/evil/src/bin/evil_test_print.c b/legacy/evil/src/bin/evil_test_print.c
new file mode 100644
index 0000000000..b930a538f4
--- /dev/null
+++ b/legacy/evil/src/bin/evil_test_print.c
@@ -0,0 +1,46 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif /* HAVE_CONFIG_H */
4
5#include <stdlib.h>
6#include <stdio.h>
7
8#include <Evil.h>
9
10#include "evil_suite.h"
11#include "evil_test_print.h"
12
13static int
14test_print_test(void)
15{
16 char buf[16];
17 int i1 = 1;
18 size_t i2 = 123456;
19 int res;
20
21 res = printf("%02hhd\n", i1);
22 if (res != 3)
23 return 0;
24
25 res = snprintf(buf, sizeof(buf), "%zu", i2);
26 if (res != 6)
27 return 0;
28
29 return 1;
30}
31
32static int
33test_print_run(suite *s __UNUSED__)
34{
35 int res;
36
37 res = test_print_test();
38
39 return res;
40}
41
42int
43test_print(suite *s)
44{
45 return test_print_run(s);
46}
diff --git a/legacy/evil/src/bin/evil_test_print.h b/legacy/evil/src/bin/evil_test_print.h
new file mode 100644
index 0000000000..2bbf43904f
--- /dev/null
+++ b/legacy/evil/src/bin/evil_test_print.h
@@ -0,0 +1,8 @@
1#ifndef __EVIL_TEST_PRINT_H__
2#define __EVIL_TEST_PRINT_H__
3
4
5int test_print(suite *s);
6
7
8#endif /* __EVIL_TEST_PRINT_H__ */
diff --git a/legacy/evil/src/bin/evil_test_realpath.c b/legacy/evil/src/bin/evil_test_realpath.c
index 01c390f10e..f9a48cb977 100644
--- a/legacy/evil/src/bin/evil_test_realpath.c
+++ b/legacy/evil/src/bin/evil_test_realpath.c
@@ -10,7 +10,8 @@
10#include "evil_test_realpath.h" 10#include "evil_test_realpath.h"
11 11
12 12
13int test_realpath_test(void) 13static int
14test_realpath_test(void)
14{ 15{
15 char buf[PATH_MAX]; 16 char buf[PATH_MAX];
16 char *filename; 17 char *filename;
@@ -27,7 +28,7 @@ int test_realpath_test(void)
27} 28}
28 29
29static int 30static int
30test_realpath_run(suite *s) 31test_realpath_run(suite *s __UNUSED__)
31{ 32{
32 int res; 33 int res;
33 34
diff --git a/legacy/evil/src/bin/evil_test_util.c b/legacy/evil/src/bin/evil_test_util.c
new file mode 100644
index 0000000000..6226ceb040
--- /dev/null
+++ b/legacy/evil/src/bin/evil_test_util.c
@@ -0,0 +1,110 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif /* HAVE_CONFIG_H */
4
5#include <string.h>
6
7#include <Evil.h>
8
9#include "evil_suite.h"
10#include "evil_test_util.h"
11
12
13static int test_path_absolute_test_1(void)
14{
15 char *path;
16 int result;
17
18 path = NULL;
19 result = evil_path_is_absolute(path);
20 if (result != 0)
21 return 0;
22
23 return 1;
24}
25
26static int test_path_absolute_test_2(void)
27{
28 char *path;
29 int result;
30
31 path = "1";
32 result = evil_path_is_absolute(path);
33 if (result != 0)
34 return 0;
35
36 return 1;
37}
38
39static int test_path_absolute_test_3(void)
40{
41 char *path;
42 int result;
43
44 path = "1:\\";
45 result = evil_path_is_absolute(path);
46 if (result != 0)
47 return 0;
48
49 return 1;
50}
51
52static int test_path_absolute_test_4(void)
53{
54 char *path;
55 int result;
56
57 path = "1/\\";
58 result = evil_path_is_absolute(path);
59 if (result != 0)
60 return 0;
61
62 return 1;
63}
64
65static int test_path_absolute_test_5(void)
66{
67 char *path;
68 int result;
69
70 path = "F:/foo";
71 result = evil_path_is_absolute(path);
72 if (result == 0)
73 return 0;
74
75 return 1;
76}
77
78static int test_path_absolute_test_6(void)
79{
80 char *path;
81 int result;
82
83 path = "C:\\foo";
84 result = evil_path_is_absolute(path);
85 if (result == 0)
86 return 0;
87
88 return 1;
89}
90
91static int
92test_path_absolute_run(suite *s __UNUSED__)
93{
94 int res;
95
96 res = test_path_absolute_test_1();
97 res &= test_path_absolute_test_2();
98 res &= test_path_absolute_test_3();
99 res &= test_path_absolute_test_4();
100 res &= test_path_absolute_test_5();
101 res &= test_path_absolute_test_6();
102
103 return res;
104}
105
106int
107test_util(suite *s)
108{
109 return test_path_absolute_run(s);
110}
diff --git a/legacy/evil/src/bin/evil_test_util.h b/legacy/evil/src/bin/evil_test_util.h
new file mode 100644
index 0000000000..bee5c7a164
--- /dev/null
+++ b/legacy/evil/src/bin/evil_test_util.h
@@ -0,0 +1,8 @@
1#ifndef __EVIL_TEST_UTIL_H__
2#define __EVIL_TEST_UTIL_H__
3
4
5int test_util(suite *s);
6
7
8#endif /* __EVIL_TEST_UTIL_H__ */
diff --git a/legacy/evil/src/lib/Evil.h b/legacy/evil/src/lib/Evil.h
index ff0a62c086..6d3ccb779b 100644
--- a/legacy/evil/src/lib/Evil.h
+++ b/legacy/evil/src/lib/Evil.h
@@ -1,23 +1,6 @@
1#ifndef __EVIL_H__ 1#ifndef __EVIL_H__
2#define __EVIL_H__ 2#define __EVIL_H__
3 3
4#ifdef EAPI
5# undef EAPI
6#endif /* EAPI */
7
8#ifdef _WIN32
9# ifdef EFL_EVIL_BUILD
10# ifdef DLL_EXPORT
11# define EAPI __declspec(dllexport)
12# else
13# define EAPI
14# endif /* ! DLL_EXPORT */
15# else
16# define EAPI __declspec(dllimport)
17# endif /* ! EFL_EVIL_BUILD */
18#endif /* _WIN32 */
19
20
21/** 4/**
22 * @mainpage Evil 5 * @mainpage Evil
23 * @image html e_big.png 6 * @image html e_big.png
@@ -87,7 +70,6 @@ extern "C" {
87 70
88#include <stdlib.h> 71#include <stdlib.h>
89#include <stdio.h> 72#include <stdio.h>
90#include <sys/time.h>
91#include <time.h> 73#include <time.h>
92#include <limits.h> 74#include <limits.h>
93#include <sys/stat.h> 75#include <sys/stat.h>
@@ -95,13 +77,6 @@ extern "C" {
95#include <math.h> 77#include <math.h>
96 78
97 79
98#ifdef PATH_MAX
99# undef PATH_MAX
100#endif /* PATH_MAX */
101
102#define PATH_MAX MAX_PATH
103
104
105#ifdef _MSC_VER 80#ifdef _MSC_VER
106 81
107# include <io.h> 82# include <io.h>
@@ -141,11 +116,13 @@ typedef unsigned long uid_t;
141typedef unsigned long gid_t; 116typedef unsigned long gid_t;
142 117
143 118
119#include "evil_macro.h"
144#include "evil_fcntl.h" 120#include "evil_fcntl.h"
145#include "evil_inet.h" 121#include "evil_inet.h"
146#include "evil_langinfo.h" 122#include "evil_langinfo.h"
147#include "evil_libgen.h" 123#include "evil_libgen.h"
148#include "evil_main.h" 124#include "evil_main.h"
125#include "evil_print.h"
149#include "evil_stdlib.h" 126#include "evil_stdlib.h"
150#include "evil_stdio.h" 127#include "evil_stdio.h"
151#include "evil_string.h" 128#include "evil_string.h"
@@ -153,6 +130,25 @@ typedef unsigned long gid_t;
153#include "evil_unistd.h" 130#include "evil_unistd.h"
154#include "evil_util.h" 131#include "evil_util.h"
155 132
133#define fprintf _evil_fprintfa
134#define printf _evil_printfa
135#define snprintf _evil_snprintfa
136#define sprintf _evil_sprintfa
137#define vfprintf _evil_vfprintfa
138#define vprintf _evil_vprintfa
139#define vsnprintf _evil_vsnprintfa
140#define vsprintf _evil_vsprintfa
141
142#define fscanf _evil_fscanf
143#define scanf _evil_scanf
144#define sscanf _evil_sscanf
145#define vfscanf _evil_vfscanf
146#define vscanf _evil_vscanf
147#define vsscanf _evil_vsscanf
148
149#define asprintf _evil_asprintf
150#define vasprintf _evil_vasprintf
151
156 152
157#if (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) 153#if (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__))
158# if defined(_MSC_VER) || defined(__MINGW32__) 154# if defined(_MSC_VER) || defined(__MINGW32__)
diff --git a/legacy/evil/src/lib/Makefile.am b/legacy/evil/src/lib/Makefile.am
index ce980b8706..54f2beddba 100644
--- a/legacy/evil/src/lib/Makefile.am
+++ b/legacy/evil/src/lib/Makefile.am
@@ -12,7 +12,9 @@ evil_fcntl.h \
12evil_inet.h \ 12evil_inet.h \
13evil_langinfo.h \ 13evil_langinfo.h \
14evil_libgen.h \ 14evil_libgen.h \
15evil_macro.h \
15evil_main.h \ 16evil_main.h \
17evil_print.h \
16evil_stdlib.h \ 18evil_stdlib.h \
17evil_stdio.h \ 19evil_stdio.h \
18evil_string.h \ 20evil_string.h \
@@ -25,7 +27,7 @@ nobase_dist_stdheaders_DATA = pwd.h sys/mman.h fnmatch.h dirent.h
25 27
26if EVIL_HAVE_WINCE 28if EVIL_HAVE_WINCE
27 29
28nobase_dist_stdheaders_DATA += errno.h 30nobase_dist_stdheaders_DATA += mingw32ce/errno.h
29 31
30endif 32endif
31 33
@@ -39,6 +41,10 @@ evil_langinfo.c \
39evil_libgen.c \ 41evil_libgen.c \
40evil_main.c \ 42evil_main.c \
41evil_mman.c \ 43evil_mman.c \
44evil_pformata.c \
45evil_pformatw.c \
46evil_printa.c \
47evil_printw.c \
42evil_pwd.c \ 48evil_pwd.c \
43evil_stdlib.c \ 49evil_stdlib.c \
44evil_stdio.c \ 50evil_stdio.c \
@@ -47,6 +53,7 @@ evil_time.c \
47evil_unistd.c \ 53evil_unistd.c \
48evil_util.c \ 54evil_util.c \
49evil_uuid.c \ 55evil_uuid.c \
56evil_pformat.h \
50evil_private.h \ 57evil_private.h \
51evil_fnmatch_private.h 58evil_fnmatch_private.h
52 59
@@ -64,7 +71,7 @@ libevil_la_CPPFLAGS = @win32_cppflags@
64libevil_la_CFLAGS = @win32_cflags@ 71libevil_la_CFLAGS = @win32_cflags@
65libevil_la_CXXFLAGS = @win32_cxxflags@ 72libevil_la_CXXFLAGS = @win32_cxxflags@
66libevil_la_LIBADD = @win32_libs@ $(EFL_MPATROL_LIBS) 73libevil_la_LIBADD = @win32_libs@ $(EFL_MPATROL_LIBS)
67libevil_la_LDFLAGS = -no-undefined -Wl,--enable-auto-import -version-info @version_info@ 74libevil_la_LDFLAGS = -no-undefined -Wl,--enable-auto-import -version-info @version_info@
68 75
69if EVIL_HAVE_WINCE 76if EVIL_HAVE_WINCE
70 77
diff --git a/legacy/evil/src/lib/dlfcn/dlfcn.c b/legacy/evil/src/lib/dlfcn/dlfcn.c
index 9daa94675b..126b68c3ed 100644
--- a/legacy/evil/src/lib/dlfcn/dlfcn.c
+++ b/legacy/evil/src/lib/dlfcn/dlfcn.c
@@ -8,7 +8,12 @@
8# include <limits.h> 8# include <limits.h>
9#endif /* __MINGW32CE__ || _MSC_VER */ 9#endif /* __MINGW32CE__ || _MSC_VER */
10 10
11#ifndef WIN32_LEAN_AND_MEAN
12# define WIN32_LEAN_AND_MEAN
13#endif
11#include <windows.h> 14#include <windows.h>
15#undef WIN32_LEAN_AND_MEAN
16
12#ifdef _WIN32_WCE 17#ifdef _WIN32_WCE
13# include <tlhelp32.h> /* CreateToolhelp32Snapshot */ 18# include <tlhelp32.h> /* CreateToolhelp32Snapshot */
14#else 19#else
diff --git a/legacy/evil/src/lib/evil_errno.c b/legacy/evil/src/lib/evil_errno.c
index ed0c5cdebe..37cac611f0 100644
--- a/legacy/evil/src/lib/evil_errno.c
+++ b/legacy/evil/src/lib/evil_errno.c
@@ -3,7 +3,7 @@
3#endif 3#endif
4 4
5#include "Evil.h" 5#include "Evil.h"
6#include "errno.h" 6#include "mingw32ce/errno.h"
7 7
8 8
9int errno = 0; 9int errno = 0;
diff --git a/legacy/evil/src/lib/evil_fcntl.c b/legacy/evil/src/lib/evil_fcntl.c
index f180417418..7c62c2a310 100644
--- a/legacy/evil/src/lib/evil_fcntl.c
+++ b/legacy/evil/src/lib/evil_fcntl.c
@@ -104,17 +104,14 @@ int fcntl(int fd, int cmd, ...)
104 if (pos != -1L) 104 if (pos != -1L)
105 res = 0; 105 res = 0;
106 106
107 printf ("Evil 1 %d %d %d\n", fl->l_type, F_RDLCK, F_WRLCK);
108 if ((fl->l_type == F_RDLCK) || (fl->l_type == F_WRLCK)) 107 if ((fl->l_type == F_RDLCK) || (fl->l_type == F_WRLCK))
109 { 108 {
110 printf ("Evil 2\n");
111 if (cmd == F_SETLK) 109 if (cmd == F_SETLK)
112 res = _locking(fd, _LK_NBLCK, fl->l_len); /* if cannot be locked, we return immediatly */ 110 res = _locking(fd, _LK_NBLCK, fl->l_len); /* if cannot be locked, we return immediatly */
113 else /* F_SETLKW */ 111 else /* F_SETLKW */
114 res = _locking(fd, _LK_LOCK, fl->l_len); /* otherwise, we try several times */ 112 res = _locking(fd, _LK_LOCK, fl->l_len); /* otherwise, we try several times */
115 } 113 }
116 114
117 printf ("Evil 3\n");
118 if (fl->l_type == F_UNLCK) 115 if (fl->l_type == F_UNLCK)
119 res = _locking(fd, _LK_UNLCK, fl->l_len); 116 res = _locking(fd, _LK_UNLCK, fl->l_len);
120 } 117 }
diff --git a/legacy/evil/src/lib/evil_inet.c b/legacy/evil/src/lib/evil_inet.c
index d4eacee617..1b679ea808 100644
--- a/legacy/evil/src/lib/evil_inet.c
+++ b/legacy/evil/src/lib/evil_inet.c
@@ -26,17 +26,24 @@
26# include "config.h" 26# include "config.h"
27#endif /* HAVE_CONFIG_H */ 27#endif /* HAVE_CONFIG_H */
28 28
29#include <errno.h> 29#include <stdio.h>
30#include <ctype.h> 30#include <ctype.h>
31 31
32#ifdef HAVE_ERRNO_H
33# include <errno.h>
34#endif /* HAVE_ERRNO_H */
35
32#ifndef WIN32_LEAN_AND_MEAN 36#ifndef WIN32_LEAN_AND_MEAN
33# define WIN32_LEAN_AND_MEAN 37# define WIN32_LEAN_AND_MEAN
34#endif 38#endif
35#include <winsock2.h> 39#include <winsock2.h>
36#undef WIN32_LEAN_AND_MEAN 40#undef WIN32_LEAN_AND_MEAN
37 41
38#include "Evil.h" 42#include "evil_macro.h"
43#include "evil_inet.h"
39#include "evil_private.h" 44#include "evil_private.h"
45#define APICHAR char
46#include "evil_print.h"
40 47
41 48
42# define SPRINTF(x) ((size_t)sprintf x) 49# define SPRINTF(x) ((size_t)sprintf x)
diff --git a/legacy/evil/src/lib/evil_link_ce.c b/legacy/evil/src/lib/evil_link_ce.c
index 06385d63d8..17532cc4d6 100644
--- a/legacy/evil/src/lib/evil_link_ce.c
+++ b/legacy/evil/src/lib/evil_link_ce.c
@@ -2,7 +2,9 @@
2# include "config.h" 2# include "config.h"
3#endif /* HAVE_CONFIG_H */ 3#endif /* HAVE_CONFIG_H */
4 4
5#define WIN32_LEAN_AND_MEAN 5#ifndef WIN32_LEAN_AND_MEAN
6# define WIN32_LEAN_AND_MEAN
7#endif
6#include <windows.h> 8#include <windows.h>
7#undef WIN32_LEAN_AND_MEAN 9#undef WIN32_LEAN_AND_MEAN
8 10
diff --git a/legacy/evil/src/lib/evil_link_xp.cpp b/legacy/evil/src/lib/evil_link_xp.cpp
index 7b6cdc3809..aacc1ef8fc 100644
--- a/legacy/evil/src/lib/evil_link_xp.cpp
+++ b/legacy/evil/src/lib/evil_link_xp.cpp
@@ -7,8 +7,8 @@
7#include <errno.h> 7#include <errno.h>
8#endif /* HAVE_ERRNO_H */ 8#endif /* HAVE_ERRNO_H */
9 9
10# include <shlobj.h> 10#include <shlobj.h>
11# include <objidl.h> 11#include <objidl.h>
12#include <cstdio> 12#include <cstdio>
13 13
14#include "Evil.h" 14#include "Evil.h"
diff --git a/legacy/evil/src/lib/evil_macro.h b/legacy/evil/src/lib/evil_macro.h
new file mode 100644
index 0000000000..b8d043db01
--- /dev/null
+++ b/legacy/evil/src/lib/evil_macro.h
@@ -0,0 +1,192 @@
1#ifndef __EVIL_MACRO_H__
2#define __EVIL_MACRO_H__
3
4
5#ifndef __cdecl
6# ifdef __GNUC__
7# define __cdecl __attribute__((__cdecl__))
8# else
9# define __cdecl
10# endif
11#endif /* __cdecl */
12
13
14#ifdef EAPI
15# undef EAPI
16#endif /* EAPI */
17
18#ifdef _WIN32
19# ifdef EFL_EVIL_BUILD
20# ifdef DLL_EXPORT
21# define EAPI __declspec(dllexport)
22# else
23# define EAPI
24# endif /* ! DLL_EXPORT */
25# else
26# define EAPI __declspec(dllimport)
27# endif /* ! EFL_EVIL_BUILD */
28#endif /* _WIN32 */
29
30
31#ifndef __EVIL_GNUC_PREREQ
32# if defined __GNUC__ && defined __GNUC_MINOR__
33# define __EVIL_GNUC_PREREQ( major, minor )\
34 (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
35# else
36# define __EVIL_GNUC_PREREQ( major, minor )
37# endif
38#endif /* __EVIL_GNUC_PREREQ */
39
40
41#ifndef __EVIL_NOTHROW
42# if __EVIL_GNUC_PREREQ( 3, 3 )
43# define __EVIL_NOTHROW __attribute__((__nothrow__))
44# else
45# define __EVIL_NOTHROW
46# endif
47#endif /* __EVIL_NOTHROW */
48
49
50#ifndef __EVIL_PRINTF
51# if __EVIL_GNUC_PREREQ( 2, 4 )
52# define __EVIL_PRINTF(fmt, arg) __attribute__((__format__ (__gnu_printf__, fmt, arg)))
53# else
54# define __EVIL_PRINTF(fmt, arg)
55# endif
56#endif /* __EVIL_PRINTF */
57
58
59#ifndef PATH_MAX
60# define PATH_MAX MAX_PATH
61#endif /* PATH_MAX */
62#ifdef fprintf
63# undef fprintf
64#endif
65
66#ifdef printf
67# undef printf
68#endif
69
70#ifdef sprintf
71# undef sprintf
72#endif
73
74#ifdef snprintf
75# undef snprintf
76#endif
77
78#ifdef vfprintf
79# undef vfprintf
80#endif
81
82#ifdef vprintf
83# undef vprintf
84#endif
85
86#ifdef vsprintf
87# undef vsprintf
88#endif
89
90#ifdef vsnprintf
91# undef vsnprintf
92#endif
93
94#ifdef fscanf
95# undef fscanf
96#endif
97
98#ifdef scanf
99# undef scanf
100#endif
101
102#ifdef sscanf
103# undef sscanf
104#endif
105
106#ifdef vfscanf
107# undef vfscanf
108#endif
109
110#ifdef vscanf
111# undef vscanf
112#endif
113
114#ifdef vsscanf
115# undef vsscanf
116#endif
117
118#ifdef asprintf
119# undef asprintf
120#endif
121
122#ifdef vasprintf
123# undef vasprintf
124#endif
125
126
127#if defined(_INTTYPES_H_) && defined(PRId64)
128
129#undef PRId64
130#undef PRIdLEAST64
131#undef PRIdFAST64
132#undef PRIdMAX
133#undef PRIi64
134#undef PRIiLEAST64
135#undef PRIiFAST64
136#undef PRIiMAX
137#undef PRIo64
138#undef PRIoLEAST64
139#undef PRIoFAST64
140#undef PRIoMAX
141#undef PRIu64
142#undef PRIuLEAST64
143#undef PRIuFAST64
144#undef PRIuMAX
145#undef PRIx64
146#undef PRIxLEAST64
147#undef PRIxFAST64
148#undef PRIxMAX
149#undef PRIX64
150#undef PRIXLEAST64
151#undef PRIXFAST64
152#undef PRIXMAX
153
154#undef SCNd64
155#undef SCNdLEAST64
156#undef SCNdFAST64
157#undef SCNdMAX
158#undef SCNi64
159#undef SCNiLEAST64
160#undef SCNiFAST64
161#undef SCNiMAX
162#undef SCNo64
163#undef SCNoLEAST64
164#undef SCNoFAST64
165#undef SCNoMAX
166#undef SCNx64
167#undef SCNxLEAST64
168#undef SCNxFAST64
169#undef SCNxMAX
170#undef SCNu64
171#undef SCNuLEAST64
172#undef SCNuFAST64
173#undef SCNuMAX
174
175#ifdef _WIN64
176#undef PRIdPTR
177#undef PRIiPTR
178#undef PRIoPTR
179#undef PRIuPTR
180#undef PRIxPTR
181#undef PRIXPTR
182
183#undef SCNdPTR
184#undef SCNiPTR
185#undef SCNoPTR
186#undef SCNxPTR
187#undef SCNuPTR
188#endif /* _WIN64 */
189
190#endif /* defined(_INTTYPES_H_) && defined(PRId64) */
191
192#endif /* __EVIL_MACRO_H__ */
diff --git a/legacy/evil/src/lib/evil_main.c b/legacy/evil/src/lib/evil_main.c
index acefa890e7..ee1eb1d113 100644
--- a/legacy/evil/src/lib/evil_main.c
+++ b/legacy/evil/src/lib/evil_main.c
@@ -2,9 +2,11 @@
2# include <config.h> 2# include <config.h>
3#endif 3#endif
4 4
5#ifndef WIN32_LEAN_AND_MEAN
5# define WIN32_LEAN_AND_MEAN 6# define WIN32_LEAN_AND_MEAN
6# include <winsock2.h> 7#endif
7# undef WIN32_LEAN_AND_MEAN 8#include <winsock2.h>
9#undef WIN32_LEAN_AND_MEAN
8 10
9#include "Evil.h" 11#include "Evil.h"
10#include "evil_private.h" 12#include "evil_private.h"
diff --git a/legacy/evil/src/lib/evil_mman.c b/legacy/evil/src/lib/evil_mman.c
index abc2f7c0e1..8898357cfc 100644
--- a/legacy/evil/src/lib/evil_mman.c
+++ b/legacy/evil/src/lib/evil_mman.c
@@ -2,6 +2,7 @@
2# include "config.h" 2# include "config.h"
3#endif /* HAVE_CONFIG_H */ 3#endif /* HAVE_CONFIG_H */
4 4
5#include <stdlib.h>
5#include <stdio.h> 6#include <stdio.h>
6#include <sys/types.h> 7#include <sys/types.h>
7 8
@@ -9,13 +10,20 @@
9# include <unistd.h> 10# include <unistd.h>
10#endif 11#endif
11 12
12#define WIN32_LEAN_AND_MEAN 13#ifndef WIN32_LEAN_AND_MEAN
14# define WIN32_LEAN_AND_MEAN
15#endif
13#include <windows.h> 16#include <windows.h>
14#undef WIN32_LEAN_AND_MEAN 17#undef WIN32_LEAN_AND_MEAN
15 18
16# include <io.h> 19# include <io.h>
17 20
21#include "evil_macro.h"
18#include "sys/mman.h" 22#include "sys/mman.h"
23#include "evil_util.h"
24#include "evil_private.h"
25#define APICHAR char
26#include "evil_print.h"
19 27
20#ifdef __MINGW32CE__ 28#ifdef __MINGW32CE__
21# define _get_osfhandle(FILEDES) ((long)FILEDES) 29# define _get_osfhandle(FILEDES) ((long)FILEDES)
diff --git a/legacy/evil/src/lib/evil_pformat.h b/legacy/evil/src/lib/evil_pformat.h
new file mode 100644
index 0000000000..ad9b61e024
--- /dev/null
+++ b/legacy/evil/src/lib/evil_pformat.h
@@ -0,0 +1,61 @@
1#ifndef __EVIL_PRIVATE_H__
2#define __EVIL_PRIVATE_H__
3
4
5#include "evil_macro.h"
6
7
8#ifdef __BUILD_WIDEAPI
9#define APICHAR wchar_t
10#else
11#define APICHAR char
12#endif
13
14/* The following are the declarations specific to the `pformat' API...
15 */
16#define PFORMAT_TO_FILE 0x1000
17#define PFORMAT_NOLIMIT 0x2000
18
19
20#ifdef __cplusplus
21extern "C" {
22#endif
23
24
25#ifdef __BUILD_WIDEAPI
26# define __fputc(X,STR) fputwc((wchar_t) (X), (STR))
27# define _evil_pformat _evil_pformatw
28
29# define _evil_fprintf _evil_fprintfw
30# define _evil_printf _evil_printfw
31# define _evil_snprintf _evil_snprintfw
32# define _evil_sprintf _evil_sprintfw
33
34# define _evil_vfprintf _evil_vfprintfw
35# define _evil_vprintf _evil_vprintfw
36# define _evil_vsnprintf _evil_vsnprintfw
37# define _evil_vsprintf _evil_vsprintfw
38#else
39# define __fputc(X,STR) fputc((X), (STR))
40# define _evil_pformat _evil_pformata
41
42# define _evil_fprintf _evil_fprintfa
43# define _evil_printf _evil_printfa
44# define _evil_snprintf _evil_snprintfa
45# define _evil_sprintf _evil_sprintfa
46
47# define _evil_vfprintf _evil_vfprintfa
48# define _evil_vprintf _evil_vprintfa
49# define _evil_vsnprintf _evil_vsnprintfa
50# define _evil_vsprintf _evil_vsprintfa
51#endif
52
53int __cdecl _evil_pformat(int, void *, int, const APICHAR *, va_list) __EVIL_NOTHROW;
54
55
56#ifdef __cplusplus
57}
58#endif
59
60
61#endif /* __EVIL_PRIVATE_H__ */
diff --git a/legacy/evil/src/lib/evil_pformata.c b/legacy/evil/src/lib/evil_pformata.c
new file mode 100644
index 0000000000..b53765a756
--- /dev/null
+++ b/legacy/evil/src/lib/evil_pformata.c
@@ -0,0 +1,2538 @@
1/* pformat.c
2 *
3 * $Id: pformat.c,v 1.9 2011/01/07 22:57:00 keithmarshall Exp $
4 *
5 * Provides a core implementation of the formatting capabilities
6 * common to the entire `printf()' family of functions; it conforms
7 * generally to C99 and SUSv3/POSIX specifications, with extensions
8 * to support Microsoft's non-standard format specifications.
9 *
10 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
11 *
12 * This is free software. You may redistribute and/or modify it as you
13 * see fit, without restriction of copyright.
14 *
15 * This software is provided "as is", in the hope that it may be useful,
16 * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
17 * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
18 * time will the author accept any form of liability for any damages,
19 * however caused, resulting from the use of this software.
20 *
21 * The elements of this implementation which deal with the formatting
22 * of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g'
23 * and `%G' format specifiers, but excluding the hexadecimal floating
24 * point `%a' and `%A' specifiers), make use of the `__gdtoa' function
25 * written by David M. Gay, and are modelled on his sample code, which
26 * has been deployed under its accompanying terms of use:--
27 *
28 ******************************************************************
29 * Copyright (C) 1997, 1999, 2001 Lucent Technologies
30 * All Rights Reserved
31 *
32 * Permission to use, copy, modify, and distribute this software and
33 * its documentation for any purpose and without fee is hereby
34 * granted, provided that the above copyright notice appear in all
35 * copies and that both that the copyright notice and this
36 * permission notice and warranty disclaimer appear in supporting
37 * documentation, and that the name of Lucent or any of its entities
38 * not be used in advertising or publicity pertaining to
39 * distribution of the software without specific, written prior
40 * permission.
41 *
42 * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
43 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
44 * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
45 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
46 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
47 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
48 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
49 * THIS SOFTWARE.
50 ******************************************************************
51 *
52 */
53#include <stdio.h>
54#include <stdarg.h>
55#include <stddef.h>
56#include <stdint.h>
57#include <stdlib.h>
58#include <string.h>
59#include <limits.h>
60#include <locale.h>
61#include <wchar.h>
62#include <math.h>
63
64/* FIXME: The following belongs in values.h, but current MinGW
65 * has nothing useful there! OTOH, values.h is not a standard
66 * header, and it's use may be considered obsolete; perhaps it
67 * is better to just keep these definitions here.
68 */
69#ifndef _VALUES_H
70/*
71 * values.h
72 *
73 */
74#define _VALUES_H
75
76#include <limits.h>
77
78#define _TYPEBITS(type) (sizeof(type) * CHAR_BIT)
79
80#define LLONGBITS _TYPEBITS(long long)
81
82#endif /* !defined _VALUES_H -- end of file */
83
84#include "evil_pformat.h"
85
86/* Bit-map constants, defining the internal format control
87 * states, which propagate through the flags.
88 */
89#define PFORMAT_GROUPED 0x1000
90#define PFORMAT_HASHED 0x0800
91#define PFORMAT_LJUSTIFY 0x0400
92#define PFORMAT_ZEROFILL 0x0200
93
94#define PFORMAT_JUSTIFY (PFORMAT_LJUSTIFY | PFORMAT_ZEROFILL)
95#define PFORMAT_IGNORE -1
96
97#define PFORMAT_SIGNED 0x01C0
98#define PFORMAT_POSITIVE 0x0100
99#define PFORMAT_NEGATIVE 0x0080
100#define PFORMAT_ADDSPACE 0x0040
101
102#define PFORMAT_XCASE 0x0020
103
104#define PFORMAT_LDOUBLE 0x0004
105
106/* `%o' format digit extraction mask, and shift count...
107 * (These are constant, and do not propagate through the flags).
108 */
109#define PFORMAT_OMASK 0x0007
110#define PFORMAT_OSHIFT 0x0003
111
112/* `%x' and `%X' format digit extraction mask, and shift count...
113 * (These are constant, and do not propagate through the flags).
114 */
115#define PFORMAT_XMASK 0x000F
116#define PFORMAT_XSHIFT 0x0004
117
118/* The radix point character, used in floating point formats, is
119 * localised on the basis of the active LC_NUMERIC locale category.
120 * It is stored locally, as a `wchar_t' entity, which is converted
121 * to a (possibly multibyte) character on output. Initialisation
122 * of the stored `wchar_t' entity, together with a record of its
123 * effective multibyte character length, is required each time
124 * `__pformat()' is entered, (static storage would not be thread
125 * safe), but this initialisation is deferred until it is actually
126 * needed; on entry, the effective character length is first set to
127 * the following value, (and the `wchar_t' entity is zeroed), to
128 * indicate that a call of `localeconv()' is needed, to complete
129 * the initialisation.
130 */
131#define PFORMAT_RPINIT -3
132
133/* The floating point format handlers return the following value
134 * for the radix point position index, when the argument value is
135 * infinite, or not a number.
136 */
137#define PFORMAT_INFNAN -32768
138
139#ifdef _WIN32
140/*
141 * The Microsoft standard for printing `%e' format exponents is
142 * with a minimum of three digits, unless explicitly set otherwise,
143 * by a prior invocation of the `_set_output_format()' function.
144 *
145 * The following macro allows us to replicate this behaviour.
146 */
147# define PFORMAT_MINEXP __pformat_exponent_digits()
148 /*
149 * However, this feature is unsupported for versions of the
150 * MSVC runtime library prior to msvcr80.dll, and by default,
151 * MinGW uses an earlier version, (equivalent to msvcr60.dll),
152 * for which `_TWO_DIGIT_EXPONENT' will be undefined.
153 */
154# ifndef _TWO_DIGIT_EXPONENT
155 /*
156 * This hack works around the lack of the `_set_output_format()'
157 * feature, when supporting versions of the MSVC runtime library
158 * prior to msvcr80.dll; it simply enforces Microsoft's original
159 * convention, for all cases where the feature is unsupported.
160 */
161# define _get_output_format() 0
162# define _TWO_DIGIT_EXPONENT 1
163# endif
164/*
165 * Irrespective of the MSVCRT version supported, *we* will add
166 * an additional capability, through the following inline function,
167 * which will allow the user to choose his own preferred default
168 * for `PRINTF_EXPONENT_DIGITS', through the simple expedient
169 * of defining it as an environment variable.
170 */
171static
172int __pformat_exponent_digits( void )
173{
174 char *exponent_digits = getenv( "PRINTF_EXPONENT_DIGITS" );
175 return ((exponent_digits != NULL) && ((unsigned)(*exponent_digits - '0') < 3))
176 || (_get_output_format() & _TWO_DIGIT_EXPONENT)
177 ? 2
178 : 3
179 ;
180}
181#else
182/*
183 * When we don't care to mimic Microsoft's standard behaviour,
184 * we adopt the C99/POSIX standard of two digit exponents.
185 */
186# define PFORMAT_MINEXP 2
187#endif
188
189typedef union
190{
191 /* A data type agnostic representation,
192 * for printf arguments of any integral data type...
193 */
194 signed long __pformat_long_t;
195 signed long long __pformat_llong_t;
196 unsigned long __pformat_ulong_t;
197 unsigned long long __pformat_ullong_t;
198 unsigned short __pformat_ushort_t;
199 unsigned char __pformat_uchar_t;
200 signed short __pformat_short_t;
201 signed char __pformat_char_t;
202 void * __pformat_ptr_t;
203} __pformat_intarg_t;
204
205typedef enum
206{
207 /* Format interpreter state indices...
208 * (used to identify the active phase of format string parsing).
209 */
210 PFORMAT_INIT = 0,
211 PFORMAT_SET_WIDTH,
212 PFORMAT_GET_PRECISION,
213 PFORMAT_SET_PRECISION,
214 PFORMAT_END
215} __pformat_state_t;
216
217typedef enum
218{
219 /* Argument length classification indices...
220 * (used for arguments representing integer data types).
221 */
222 PFORMAT_LENGTH_INT = 0,
223 PFORMAT_LENGTH_SHORT,
224 PFORMAT_LENGTH_LONG,
225 PFORMAT_LENGTH_LLONG,
226 PFORMAT_LENGTH_CHAR
227} __pformat_length_t;
228/*
229 * And a macro to map any arbitrary data type to an appropriate
230 * matching index, selected from those above; the compiler should
231 * collapse this to a simple assignment.
232 */
233#define __pformat_arg_length( type ) \
234 sizeof( type ) == sizeof( long long ) ? PFORMAT_LENGTH_LLONG : \
235 sizeof( type ) == sizeof( long ) ? PFORMAT_LENGTH_LONG : \
236 sizeof( type ) == sizeof( short ) ? PFORMAT_LENGTH_SHORT : \
237 sizeof( type ) == sizeof( char ) ? PFORMAT_LENGTH_CHAR : \
238 /* should never need this default */ PFORMAT_LENGTH_INT
239
240typedef struct
241{
242 /* Formatting and output control data...
243 * An instance of this control block is created, (on the stack),
244 * for each call to `__pformat()', and is passed by reference to
245 * each of the output handlers, as required.
246 */
247 void * dest;
248 int flags;
249 int width;
250 int precision;
251 int rplen;
252 wchar_t rpchr;
253 int thousands_chr_len;
254 wchar_t thousands_chr;
255 int count;
256 int quota;
257 int expmin;
258} __pformat_t;
259
260static
261void __pformat_putc( int c, __pformat_t *stream )
262{
263 /* Place a single character into the `__pformat()' output queue,
264 * provided any specified output quota has not been exceeded.
265 */
266 if( (stream->flags & PFORMAT_NOLIMIT) || (stream->quota > stream->count) )
267 {
268 /* Either there was no quota specified,
269 * or the active quota has not yet been reached.
270 */
271 if( stream->flags & PFORMAT_TO_FILE )
272 /*
273 * This is single character output to a FILE stream...
274 */
275 __fputc(c, (FILE *)(stream->dest));
276
277 else
278 /* Whereas, this is to an internal memory buffer...
279 */
280 ((APICHAR *)(stream->dest))[stream->count] = c;
281 }
282 ++stream->count;
283}
284
285static
286void __pformat_putchars( const char *s, int count, __pformat_t *stream )
287{
288 /* Handler for `%c' and (indirectly) `%s' conversion specifications.
289 *
290 * Transfer characters from the string buffer at `s', character by
291 * character, up to the number of characters specified by `count', or
292 * if `precision' has been explicitly set to a value less than `count',
293 * stopping after the number of characters specified for `precision',
294 * to the `__pformat()' output stream.
295 *
296 * Characters to be emitted are passed through `__pformat_putc()', to
297 * ensure that any specified output quota is honoured.
298 */
299 if( (stream->precision >= 0) && (count > stream->precision) )
300 /*
301 * Ensure that the maximum number of characters transferred doesn't
302 * exceed any explicitly set `precision' specification.
303 */
304 count = stream->precision;
305
306 /* Establish the width of any field padding required...
307 */
308 if( stream->width > count )
309 /*
310 * as the number of spaces equivalent to the number of characters
311 * by which those to be emitted is fewer than the field width...
312 */
313 stream->width -= count;
314
315 else
316 /* ignoring any width specification which is insufficient.
317 */
318 stream->width = PFORMAT_IGNORE;
319
320 if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
321 /*
322 * When not doing flush left justification, (i.e. the `-' flag
323 * is not set), any residual unreserved field width must appear
324 * as blank padding, to the left of the output string.
325 */
326 while( stream->width-- )
327 __pformat_putc( '\x20', stream );
328
329 /* Emit the data...
330 */
331#ifdef __BUILD_WIDEAPI
332 {
333 /* mbrtowc */
334 size_t l;
335 wchar_t w[12], *p;
336 while( count > 0 )
337 {
338 mbstate_t ps;
339 memset(&ps, 0, sizeof(ps) );
340 --count;
341 p = &w[0];
342 l = mbrtowc (p, s, strlen (s), &ps);
343 if (!l)
344 break;
345 if ((ssize_t)l < 0)
346 {
347 l = 1;
348 w[0] = (wchar_t) *s;
349 }
350 s += l;
351 __pformat_putc((int)w[0], stream);
352 }
353 }
354#else
355 while( count-- )
356 /*
357 * copying the requisite number of characters from the input.
358 */
359 __pformat_putc( *s++, stream );
360#endif
361
362 /* If we still haven't consumed the entire specified field width,
363 * we must be doing flush left justification; any residual width
364 * must be filled with blanks, to the right of the output value.
365 */
366 while( stream->width-- > 0 )
367 __pformat_putc( '\x20', stream );
368}
369
370static
371void __pformat_puts( const char *s, __pformat_t *stream )
372{
373 /* Handler for `%s' conversion specifications.
374 *
375 * Transfer a NUL terminated character string, character by character,
376 * stopping when the end of the string is encountered, or if `precision'
377 * has been explicitly set, when the specified number of characters has
378 * been emitted, if that is less than the length of the input string,
379 * to the `__pformat()' output stream.
380 *
381 * This is implemented as a trivial call to `__pformat_putchars()',
382 * passing the length of the input string as the character count,
383 * (after first verifying that the input pointer is not NULL).
384 */
385 if( s == NULL ) s = "(null)";
386 __pformat_putchars( s, strlen( s ), stream );
387}
388
389static
390void __pformat_wputchars( const wchar_t *s, int count, __pformat_t *stream )
391{
392 /* Handler for `%C'(`%lc') and `%S'(`%ls') conversion specifications;
393 * (this is a wide character variant of `__pformat_putchars()').
394 *
395 * Each multibyte character sequence to be emitted is passed, byte
396 * by byte, through `__pformat_putc()', to ensure that any specified
397 * output quota is honoured.
398 */
399 char buf[16];
400 mbstate_t state;
401 int len = wcrtomb(buf, L'\0', &state);
402
403 if( (stream->precision >= 0) && (count > stream->precision) )
404 /*
405 * Ensure that the maximum number of characters transferred doesn't
406 * exceed any explicitly set `precision' specification.
407 */
408 count = stream->precision;
409
410 /* Establish the width of any field padding required...
411 */
412 if( stream->width > count )
413 /*
414 * as the number of spaces equivalent to the number of characters
415 * by which those to be emitted is fewer than the field width...
416 */
417 stream->width -= count;
418
419 else
420 /* ignoring any width specification which is insufficient.
421 */
422 stream->width = PFORMAT_IGNORE;
423
424 if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
425 /*
426 * When not doing flush left justification, (i.e. the `-' flag
427 * is not set), any residual unreserved field width must appear
428 * as blank padding, to the left of the output string.
429 */
430 while( stream->width-- )
431 __pformat_putc( '\x20', stream );
432
433 /* Emit the data, converting each character from the wide
434 * to the multibyte domain as we go...
435 */
436#ifdef __BUILD_WIDEAPI
437 len = count;
438 while(len-- > 0 && *s != 0)
439 {
440 __pformat_putc(*s++, stream);
441 }
442 count = len;
443#else
444 while( (count-- > 0) && ((len = wcrtomb( buf, *s++, &state )) > 0) )
445 {
446 char *p = buf;
447 while( len-- > 0 )
448 __pformat_putc( *p++, stream );
449 }
450#endif
451 /* If we still haven't consumed the entire specified field width,
452 * we must be doing flush left justification; any residual width
453 * must be filled with blanks, to the right of the output value.
454 */
455 while( stream->width-- > 0 )
456 __pformat_putc( '\x20', stream );
457}
458
459static
460void __pformat_wcputs( const wchar_t *s, __pformat_t *stream )
461{
462 /* Handler for `%S' (`%ls') conversion specifications.
463 *
464 * Transfer a NUL terminated wide character string, character by
465 * character, converting to its equivalent multibyte representation
466 * on output, and stopping when the end of the string is encountered,
467 * or if `precision' has been explicitly set, when the specified number
468 * of characters has been emitted, if that is less than the length of
469 * the input string, to the `__pformat()' output stream.
470 *
471 * This is implemented as a trivial call to `__pformat_wputchars()',
472 * passing the length of the input string as the character count,
473 * (after first verifying that the input pointer is not NULL).
474 */
475 if( s == NULL ) s = L"(null)";
476 __pformat_wputchars( s, wcslen( s ), stream );
477}
478
479static
480int __pformat_int_bufsiz( int bias, int size, __pformat_t *stream )
481{
482 /* Helper to establish the size of the internal buffer, which
483 * is required to queue the ASCII decomposition of an integral
484 * data value, prior to transfer to the output stream.
485 */
486 size = ((size - 1 + LLONGBITS) / size) + bias;
487 size += (stream->precision > 0) ? stream->precision : 0;
488 if ((stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0)
489 size += (size / 3);
490 return (size > stream->width) ? size : stream->width;
491}
492
493static
494void __pformat_int( __pformat_intarg_t value, __pformat_t *stream )
495{
496 /* Handler for `%d', `%i' and `%u' conversion specifications.
497 *
498 * Transfer the ASCII representation of an integer value parameter,
499 * formatted as a decimal number, to the `__pformat()' output queue;
500 * output will be truncated, if any specified quota is exceeded.
501 */
502 char buf[__pformat_int_bufsiz(1, PFORMAT_OSHIFT, stream)];
503 char *p = buf; int precision;
504
505 if( stream->flags & PFORMAT_NEGATIVE )
506 {
507 /* The input value might be negative, (i.e. it is a signed value)...
508 */
509 if( value.__pformat_llong_t < 0LL )
510 /*
511 * It IS negative, but we want to encode it as unsigned,
512 * displayed with a leading minus sign, so convert it...
513 */
514 value.__pformat_llong_t = -value.__pformat_llong_t;
515
516 else
517 /* It is unequivocally a POSITIVE value, so turn off the
518 * request to prefix it with a minus sign...
519 */
520 stream->flags &= ~PFORMAT_NEGATIVE;
521 }
522
523 /* Encode the input value for display...
524 */
525 while( value.__pformat_ullong_t )
526 {
527 /* decomposing it into its constituent decimal digits,
528 * in order from least significant to most significant, using
529 * the local buffer as a LIFO queue in which to store them.
530 */
531 if (p != buf && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
532 && ((p - buf) % 4) == 3)
533 {
534 *p++ = ',';
535 }
536 *p++ = '0' + (unsigned char)(value.__pformat_ullong_t % 10LL);
537 value.__pformat_ullong_t /= 10LL;
538 }
539
540 if( (stream->precision > 0)
541 && ((precision = stream->precision - (p - buf)) > 0) )
542 /*
543 * We have not yet queued sufficient digits to fill the field width
544 * specified for minimum `precision'; pad with zeros to achieve this.
545 */
546 while( precision-- > 0 )
547 *p++ = '0';
548
549 if( (p == buf) && (stream->precision != 0) )
550 /*
551 * Input value was zero; make sure we print at least one digit,
552 * unless the precision is also explicitly zero.
553 */
554 *p++ = '0';
555
556 if( (stream->width > 0) && ((stream->width -= p - buf) > 0) )
557 {
558 /* We have now queued sufficient characters to display the input value,
559 * at the desired precision, but this will not fill the output field...
560 */
561 if( stream->flags & PFORMAT_SIGNED )
562 /*
563 * We will fill one additional space with a sign...
564 */
565 stream->width--;
566
567 if( (stream->precision < 0)
568 && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
569 /*
570 * and the `0' flag is in effect, so we pad the remaining spaces,
571 * to the left of the displayed value, with zeros.
572 */
573 while( stream->width-- > 0 )
574 *p++ = '0';
575
576 else if( (stream->flags & PFORMAT_LJUSTIFY) == 0 )
577 /*
578 * the `0' flag is not in effect, and neither is the `-' flag,
579 * so we pad to the left of the displayed value with spaces, so that
580 * the value appears right justified within the output field.
581 */
582 while( stream->width-- > 0 )
583 __pformat_putc( '\x20', stream );
584 }
585
586 if( stream->flags & PFORMAT_NEGATIVE )
587 /*
588 * A negative value needs a sign...
589 */
590 *p++ = '-';
591
592 else if( stream->flags & PFORMAT_POSITIVE )
593 /*
594 * A positive value may have an optionally displayed sign...
595 */
596 *p++ = '+';
597
598 else if( stream->flags & PFORMAT_ADDSPACE )
599 /*
600 * Space was reserved for displaying a sign, but none was emitted...
601 */
602 *p++ = '\x20';
603
604 while( p > buf )
605 /*
606 * Emit the accumulated constituent digits,
607 * in order from most significant to least significant...
608 */
609 __pformat_putc( *--p, stream );
610
611 while( stream->width-- > 0 )
612 /*
613 * The specified output field has not yet been completely filled;
614 * the `-' flag must be in effect, resulting in a displayed value which
615 * appears left justified within the output field; we must pad the field
616 * to the right of the displayed value, by emitting additional spaces,
617 * until we reach the rightmost field boundary.
618 */
619 __pformat_putc( '\x20', stream );
620}
621
622static
623void __pformat_xint( int fmt, __pformat_intarg_t value, __pformat_t *stream )
624{
625 /* Handler for `%o', `%p', `%x' and `%X' conversions.
626 *
627 * These can be implemented using a simple `mask and shift' strategy;
628 * set up the mask and shift values appropriate to the conversion format,
629 * and allocate a suitably sized local buffer, in which to queue encoded
630 * digits of the formatted value, in preparation for output.
631 */
632 int width;
633 int mask = (fmt == 'o') ? PFORMAT_OMASK : PFORMAT_XMASK;
634 int shift = (fmt == 'o') ? PFORMAT_OSHIFT : PFORMAT_XSHIFT;
635 char buf[__pformat_int_bufsiz(2, shift, stream)];
636 char *p = buf;
637
638 while( value.__pformat_ullong_t )
639 {
640 /* Encode the specified non-zero input value as a sequence of digits,
641 * in the appropriate `base' encoding and in reverse digit order, each
642 * encoded in its printable ASCII form, with no leading zeros, using
643 * the local buffer as a LIFO queue in which to store them.
644 */
645 char *q;
646 if( (*(q = p++) = '0' + (value.__pformat_ullong_t & mask)) > '9' )
647 *q = (*q + 'A' - '9' - 1) | (fmt & PFORMAT_XCASE);
648 value.__pformat_ullong_t >>= shift;
649 }
650
651 if( p == buf )
652 /*
653 * Nothing was queued; input value must be zero, which should never be
654 * emitted in the `alternative' PFORMAT_HASHED style.
655 */
656 stream->flags &= ~PFORMAT_HASHED;
657
658 if( ((width = stream->precision) > 0) && ((width -= p - buf) > 0) )
659 /*
660 * We have not yet queued sufficient digits to fill the field width
661 * specified for minimum `precision'; pad with zeros to achieve this.
662 */
663 while( width-- > 0 )
664 *p++ = '0';
665
666 else if( (fmt == 'o') && (stream->flags & PFORMAT_HASHED) )
667 /*
668 * The field width specified for minimum `precision' has already
669 * been filled, but the `alternative' PFORMAT_HASHED style for octal
670 * output requires at least one initial zero; that will not have
671 * been queued, so add it now.
672 */
673 *p++ = '0';
674
675 if( (p == buf) && (stream->precision != 0) )
676 /*
677 * Still nothing queued for output, but the `precision' has not been
678 * explicitly specified as zero, (which is necessary if no output for
679 * an input value of zero is desired); queue exactly one zero digit.
680 */
681 *p++ = '0';
682
683 if( stream->width > (width = p - buf) )
684 /*
685 * Specified field width exceeds the minimum required...
686 * Adjust so that we retain only the additional padding width.
687 */
688 stream->width -= width;
689
690 else
691 /* Ignore any width specification which is insufficient.
692 */
693 stream->width = PFORMAT_IGNORE;
694
695 if( ((width = stream->width) > 0)
696 && (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
697 /*
698 * For `%#x' or `%#X' formats, (which have the `#' flag set),
699 * further reduce the padding width to accommodate the radix
700 * indicating prefix.
701 */
702 width -= 2;
703
704 if( (width > 0) && (stream->precision < 0)
705 && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
706 /*
707 * When the `0' flag is set, and not overridden by the `-' flag,
708 * or by a specified precision, add sufficient leading zeros to
709 * consume the remaining field width.
710 */
711 while( width-- > 0 )
712 *p++ = '0';
713
714 if( (fmt != 'o') && (stream->flags & PFORMAT_HASHED) )
715 {
716 /* For formats other than octal, the PFORMAT_HASHED output style
717 * requires the addition of a two character radix indicator, as a
718 * prefix to the actual encoded numeric value.
719 */
720 *p++ = fmt;
721 *p++ = '0';
722 }
723
724 if( (width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) )
725 /*
726 * When not doing flush left justification, (i.e. the `-' flag
727 * is not set), any residual unreserved field width must appear
728 * as blank padding, to the left of the output value.
729 */
730 while( width-- > 0 )
731 __pformat_putc( '\x20', stream );
732
733 while( p > buf )
734 /*
735 * Move the queued output from the local buffer to the ultimate
736 * destination, in LIFO order.
737 */
738 __pformat_putc( *--p, stream );
739
740 /* If we still haven't consumed the entire specified field width,
741 * we must be doing flush left justification; any residual width
742 * must be filled with blanks, to the right of the output value.
743 */
744 while( width-- > 0 )
745 __pformat_putc( '\x20', stream );
746}
747
748typedef union
749{
750 /* A multifaceted representation of an IEEE extended precision,
751 * (80-bit), floating point number, facilitating access to its
752 * component parts.
753 */
754 double __pformat_fpreg_double_t;
755 long double __pformat_fpreg_ldouble_t;
756 struct
757 { unsigned long long __pformat_fpreg_mantissa;
758 signed short __pformat_fpreg_exponent;
759 };
760 unsigned short __pformat_fpreg_bitmap[5];
761 unsigned long __pformat_fpreg_bits;
762} __pformat_fpreg_t;
763
764/* gdtoa.h relevant declarations */
765
766enum { /* return values from strtodg */
767 STRTOG_Zero = 0,
768 STRTOG_Normal = 1,
769 STRTOG_Denormal = 2,
770 STRTOG_Infinite = 3,
771 STRTOG_NaN = 4,
772 STRTOG_NaNbits = 5,
773 STRTOG_NoNumber = 6,
774 STRTOG_Retmask = 7,
775
776 /* The following may be or-ed into one of the above values. */
777
778 STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */
779 STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */
780 STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */
781 STRTOG_Inexact = 0x30,
782 STRTOG_Underflow= 0x40,
783 STRTOG_Overflow = 0x80
784};
785
786typedef struct
787FPI {
788 int nbits;
789 int emin;
790 int emax;
791 int rounding;
792 int sudden_underflow;
793 int int_max;
794} FPI;
795
796enum { /* FPI.rounding values: same as FLT_ROUNDS */
797 FPI_Round_zero = 0,
798 FPI_Round_near = 1,
799 FPI_Round_up = 2,
800 FPI_Round_down = 3
801};
802
803extern char* __gdtoa (FPI *fpi, int be, unsigned long *bits, int *kindp,
804 int mode, int ndigits, int *decpt, char **rve);
805extern void __freedtoa (char *);
806
807
808/* end of gdtoa.h relevant declarations */
809
810
811static
812char *__pformat_cvt( int mode, __pformat_fpreg_t x, int nd, int *dp, int *sign )
813{
814 /* Helper function, derived from David M. Gay's `g_xfmt()', calling
815 * his `__gdtoa()' function in a manner to provide extended precision
816 * replacements for `ecvt()' and `fcvt()'.
817 */
818 int k; unsigned int e = 0; char *ep;
819 static FPI fpi = { 64, 1-16383-64+1, 32766-16383-64+1, FPI_Round_near, 0, 14 /* Int_max */ };
820
821 /* Classify the argument into an appropriate `__gdtoa()' category...
822 */
823 if( (k = __fpclassifyl( x.__pformat_fpreg_ldouble_t )) & FP_NAN )
824 /*
825 * identifying infinities or not-a-number...
826 */
827 k = (k & FP_NORMAL) ? STRTOG_Infinite : STRTOG_NaN;
828
829 else if( k & FP_NORMAL )
830 {
831 /* normal and near-zero `denormals'...
832 */
833 if( k & FP_ZERO )
834 {
835 /* with appropriate exponent adjustment for a `denormal'...
836 */
837 k = STRTOG_Denormal;
838 e = 1 - 0x3FFF - 63;
839 }
840 else
841 {
842 /* or with `normal' exponent adjustment...
843 */
844 k = STRTOG_Normal;
845 e = (x.__pformat_fpreg_exponent & 0x7FFF) - 0x3FFF - 63;
846 }
847 }
848
849 else
850 /* or, if none of the above, it's a zero, (positive or negative).
851 */
852 k = STRTOG_Zero;
853
854 /* Check for negative values, always treating NaN as unsigned...
855 * (return value is zero for positive/unsigned; non-zero for negative).
856 */
857 *sign = (k == STRTOG_NaN) ? 0 : x.__pformat_fpreg_exponent & 0x8000;
858
859 /* Finally, get the raw digit string, and radix point position index.
860 */
861 return __gdtoa( &fpi, e, &x.__pformat_fpreg_bits, &k, mode, nd, dp, &ep );
862}
863
864static
865char *__pformat_ecvt( long double x, int precision, int *dp, int *sign )
866{
867 /* A convenience wrapper for the above...
868 * it emulates `ecvt()', but takes a `long double' argument.
869 */
870 __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
871 return __pformat_cvt( 2, z, precision, dp, sign );
872}
873
874static
875char *__pformat_fcvt( long double x, int precision, int *dp, int *sign )
876{
877 /* A convenience wrapper for the above...
878 * it emulates `fcvt()', but takes a `long double' argument.
879 */
880 __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
881 return __pformat_cvt( 3, z, precision, dp, sign );
882}
883
884/* The following are required, to clean up the `__gdtoa()' memory pool,
885 * after processing the data returned by the above.
886 */
887#define __pformat_ecvt_release( value ) __freedtoa( value )
888#define __pformat_fcvt_release( value ) __freedtoa( value )
889
890static
891void __pformat_emit_radix_point( __pformat_t *stream )
892{
893 /* Helper to place a localised representation of the radix point
894 * character at the ultimate destination, when formatting fixed or
895 * floating point numbers.
896 */
897 if( stream->rplen == PFORMAT_RPINIT )
898 {
899 /* Radix point initialisation not yet completed;
900 * establish a multibyte to `wchar_t' converter...
901 */
902 int len; wchar_t rpchr; mbstate_t state;
903
904 /* Initialise the conversion state...
905 */
906 memset( &state, 0, sizeof( state ) );
907
908 /* Fetch and convert the localised radix point representation...
909 */
910 if( (len = mbrtowc( &rpchr, localeconv()->decimal_point, 16, &state )) > 0 )
911 /*
912 * and store it, if valid.
913 */
914 stream->rpchr = rpchr;
915
916 /* In any case, store the reported effective multibyte length,
917 * (or the error flag), marking initialisation as `done'.
918 */
919 stream->rplen = len;
920 }
921
922 if( stream->rpchr != (wchar_t)(0) )
923 {
924 /* We have a localised radix point mark;
925 * establish a converter to make it a multibyte character...
926 */
927#ifdef __BUILD_WIDEAPI
928 __pformat_putc (stream->rpchr, stream);
929#else
930 int len; char buf[len = stream->rplen]; mbstate_t state;
931
932 /* Initialise the conversion state...
933 */
934 memset( &state, 0, sizeof( state ) );
935
936 /* Convert the `wchar_t' representation to multibyte...
937 */
938 if( (len = wcrtomb( buf, stream->rpchr, &state )) > 0 )
939 {
940 /* and copy to the output destination, when valid...
941 */
942 char *p = buf;
943 while( len-- > 0 )
944 __pformat_putc( *p++, stream );
945 }
946
947 else
948 /* otherwise fall back to plain ASCII '.'...
949 */
950 __pformat_putc( '.', stream );
951#endif
952 }
953 else
954 /* No localisation: just use ASCII '.'...
955 */
956 __pformat_putc( '.', stream );
957}
958
959static
960void __pformat_emit_numeric_value( int c, __pformat_t *stream )
961{
962 /* Convenience helper to transfer numeric data from an internal
963 * formatting buffer to the ultimate destination...
964 */
965 if( c == '.' )
966 /*
967 * converting this internal representation of the the radix
968 * point to the appropriately localised representation...
969 */
970 __pformat_emit_radix_point( stream );
971 else if (c == ',')
972 {
973 wchar_t wcs;
974 if ((wcs = stream->thousands_chr) != 0)
975 __pformat_wputchars (&wcs, 1, stream);
976 }
977 else
978 /* and passing all other characters through, unmodified.
979 */
980 __pformat_putc( c, stream );
981}
982
983static
984void __pformat_emit_inf_or_nan( int sign, char *value, __pformat_t *stream )
985{
986 /* Helper to emit INF or NAN where a floating point value
987 * resolves to one of these special states.
988 */
989 int i;
990 char buf[4];
991 char *p = buf;
992
993 /* We use the string formatting helper to display INF/NAN,
994 * but we don't want truncation if the precision set for the
995 * original floating point output request was insufficient;
996 * ignore it!
997 */
998 stream->precision = PFORMAT_IGNORE;
999
1000 if( sign )
1001 /*
1002 * Negative infinity: emit the sign...
1003 */
1004 *p++ = '-';
1005
1006 else if( stream->flags & PFORMAT_POSITIVE )
1007 /*
1008 * Not negative infinity, but '+' flag is in effect;
1009 * thus, we emit a positive sign...
1010 */
1011 *p++ = '+';
1012
1013 else if( stream->flags & PFORMAT_ADDSPACE )
1014 /*
1015 * No sign required, but space was reserved for it...
1016 */
1017 *p++ = '\x20';
1018
1019 /* Copy the appropriate status indicator, up to a maximum of
1020 * three characters, transforming to the case corresponding to
1021 * the format specification...
1022 */
1023 for( i = 3; i > 0; --i )
1024 *p++ = (*value++ & ~PFORMAT_XCASE) | (stream->flags & PFORMAT_XCASE);
1025
1026 /* and emit the result.
1027 */
1028 __pformat_putchars( buf, p - buf, stream );
1029}
1030
1031static
1032void __pformat_emit_float( int sign, char *value, int len, __pformat_t *stream )
1033{
1034 /* Helper to emit a fixed point representation of numeric data,
1035 * as encoded by a prior call to `ecvt()' or `fcvt()'; (this does
1036 * NOT include the exponent, for floating point format).
1037 */
1038 if( len > 0 )
1039 {
1040 /* The magnitude of `x' is greater than or equal to 1.0...
1041 * reserve space in the output field, for the required number of
1042 * decimal digits to be placed before the decimal point...
1043 */
1044 if( stream->width > len )
1045 /*
1046 * adjusting as appropriate, when width is sufficient...
1047 */
1048 stream->width -= len;
1049
1050 else
1051 /* or simply ignoring the width specification, if not.
1052 */
1053 stream->width = PFORMAT_IGNORE;
1054 }
1055
1056 else if( stream->width > 0 )
1057 /*
1058 * The magnitude of `x' is less than 1.0...
1059 * reserve space for exactly one zero before the decimal point.
1060 */
1061 stream->width--;
1062
1063 /* Reserve additional space for the digits which will follow the
1064 * decimal point...
1065 */
1066 if( (stream->width >= 0) && (stream->width > stream->precision) )
1067 /*
1068 * adjusting appropriately, when sufficient width remains...
1069 * (note that we must check both of these conditions, because
1070 * precision may be more negative than width, as a result of
1071 * adjustment to provide extra padding when trailing zeros
1072 * are to be discarded from "%g" format conversion with a
1073 * specified field width, but if width itself is negative,
1074 * then there is explicitly to be no padding anyway).
1075 */
1076 stream->width -= stream->precision;
1077
1078 else
1079 /* or again, ignoring the width specification, if not.
1080 */
1081 stream->width = PFORMAT_IGNORE;
1082
1083 /* Reserve space in the output field, for display of the decimal point,
1084 * unless the precision is explicity zero, with the `#' flag not set.
1085 */
1086 if ((stream->width > 0)
1087 && ((stream->precision > 0) || (stream->flags & PFORMAT_HASHED)))
1088 stream->width--;
1089
1090 if (len > 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0)
1091 {
1092 int cths = ((len + 2) / 3) - 1;
1093 while (cths > 0 && stream->width > 0)
1094 {
1095 --cths; stream->width--;
1096 }
1097 }
1098
1099 /* Reserve space in the output field, for display of the sign of the
1100 * formatted value, if required; (i.e. if the value is negative, or if
1101 * either the `space' or `+' formatting flags are set).
1102 */
1103 if( (stream->width > 0) && (sign || (stream->flags & PFORMAT_SIGNED)) )
1104 stream->width--;
1105
1106 /* Emit any padding space, as required to correctly right justify
1107 * the output within the alloted field width.
1108 */
1109 if( (stream->width > 0) && ((stream->flags & PFORMAT_JUSTIFY) == 0) )
1110 while( stream->width-- > 0 )
1111 __pformat_putc( '\x20', stream );
1112
1113 /* Emit the sign indicator, as appropriate...
1114 */
1115 if( sign )
1116 /*
1117 * mandatory, for negative values...
1118 */
1119 __pformat_putc( '-', stream );
1120
1121 else if( stream->flags & PFORMAT_POSITIVE )
1122 /*
1123 * optional, for positive values...
1124 */
1125 __pformat_putc( '+', stream );
1126
1127 else if( stream->flags & PFORMAT_ADDSPACE )
1128 /*
1129 * or just fill reserved space, when the space flag is in effect.
1130 */
1131 __pformat_putc( '\x20', stream );
1132
1133 /* If the `0' flag is in effect, and not overridden by the `-' flag,
1134 * then zero padding, to fill out the field, goes here...
1135 */
1136 if( (stream->width > 0)
1137 && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) )
1138 while( stream->width-- > 0 )
1139 __pformat_putc( '0', stream );
1140
1141 /* Emit the digits of the encoded numeric value...
1142 */
1143 if( len > 0 )
1144 {
1145 /*
1146 * ...beginning with those which precede the radix point,
1147 * and appending any necessary significant trailing zeros.
1148 */
1149 do {
1150 __pformat_putc( *value ? *value++ : '0', stream);
1151 --len;
1152 if (len != 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0
1153 && (len % 3) == 0)
1154 __pformat_wputchars (&stream->thousands_chr, 1, stream);
1155 }
1156 while (len > 0);
1157 }
1158 else
1159 /* The magnitude of the encoded value is less than 1.0, so no
1160 * digits precede the radix point; we emit a mandatory initial
1161 * zero, followed immediately by the radix point.
1162 */
1163 __pformat_putc( '0', stream );
1164
1165 /* Unless the encoded value is integral, AND the radix point
1166 * is not expressly demanded by the `#' flag, we must insert
1167 * the appropriately localised radix point mark here...
1168 */
1169 if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1170 __pformat_emit_radix_point( stream );
1171
1172 /* When the radix point offset, `len', is negative, this implies
1173 * that additional zeros must appear, following the radix point,
1174 * and preceding the first significant digit...
1175 */
1176 if( len < 0 )
1177 {
1178 /* To accommodate these, we adjust the precision, (reducing it
1179 * by adding a negative value), and then we emit as many zeros
1180 * as are required.
1181 */
1182 stream->precision += len;
1183 do __pformat_putc( '0', stream );
1184 while( ++len < 0 );
1185 }
1186
1187 /* Now we emit any remaining significant digits, or trailing zeros,
1188 * until the required precision has been achieved.
1189 */
1190 while( stream->precision-- > 0 )
1191 __pformat_putc( *value ? *value++ : '0', stream );
1192}
1193
1194static
1195void __pformat_emit_efloat( int sign, char *value, int e, __pformat_t *stream )
1196{
1197 /* Helper to emit a floating point representation of numeric data,
1198 * as encoded by a prior call to `ecvt()' or `fcvt()'; (this DOES
1199 * include the following exponent).
1200 */
1201 int exp_width = 1;
1202 __pformat_intarg_t exponent; exponent.__pformat_llong_t = e -= 1;
1203
1204 /* Determine how many digit positions are required for the exponent.
1205 */
1206 while( (e /= 10) != 0 )
1207 exp_width++;
1208
1209 /* Ensure that this is at least as many as the standard requirement.
1210 */
1211 if( exp_width < stream->expmin )
1212 exp_width = stream->expmin;
1213
1214 /* Adjust the residual field width allocation, to allow for the
1215 * number of exponent digits to be emitted, together with a sign
1216 * and exponent separator...
1217 */
1218 if( stream->width > (exp_width += 2) )
1219 stream->width -= exp_width;
1220
1221 else
1222 /* ignoring the field width specification, if insufficient.
1223 */
1224 stream->width = PFORMAT_IGNORE;
1225
1226 /* Emit the significand, as a fixed point value with one digit
1227 * preceding the radix point.
1228 */
1229 __pformat_emit_float( sign, value, 1, stream );
1230
1231 /* Reset precision, to ensure the mandatory minimum number of
1232 * exponent digits will be emitted, and set the flags to ensure
1233 * the sign is displayed.
1234 */
1235 stream->precision = stream->expmin;
1236 stream->flags |= PFORMAT_SIGNED;
1237
1238 /* Emit the exponent separator.
1239 */
1240 __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream );
1241
1242 /* Readjust the field width setting, such that it again allows
1243 * for the digits of the exponent, (which had been discounted when
1244 * computing any left side padding requirement), so that they are
1245 * correctly included in the computation of any right side padding
1246 * requirement, (but here we exclude the exponent separator, which
1247 * has been emitted, and so counted already).
1248 */
1249 stream->width += exp_width - 1;
1250
1251 /* And finally, emit the exponent itself, as a signed integer,
1252 * with any padding required to achieve flush left justification,
1253 * (which will be added automatically, by `__pformat_int()').
1254 */
1255 __pformat_int( exponent, stream );
1256}
1257
1258static
1259void __pformat_float( long double x, __pformat_t *stream )
1260{
1261 /* Handler for `%f' and `%F' format specifiers.
1262 *
1263 * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()'
1264 * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1265 * output in fixed point format.
1266 */
1267 int sign, intlen; char *value;
1268
1269 /* Establish the precision for the displayed value, defaulting to six
1270 * digits following the decimal point, if not explicitly specified.
1271 */
1272 if( stream->precision < 0 )
1273 stream->precision = 6;
1274
1275 /* Encode the input value as ASCII, for display...
1276 */
1277 value = __pformat_fcvt( x, stream->precision, &intlen, &sign );
1278
1279 if( intlen == PFORMAT_INFNAN )
1280 /*
1281 * handle cases of `infinity' or `not-a-number'...
1282 */
1283 __pformat_emit_inf_or_nan( sign, value, stream );
1284
1285 else
1286 { /* or otherwise, emit the formatted result.
1287 */
1288 __pformat_emit_float( sign, value, intlen, stream );
1289
1290 /* and, if there is any residual field width as yet unfilled,
1291 * then we must be doing flush left justification, so pad out to
1292 * the right hand field boundary.
1293 */
1294 while( stream->width-- > 0 )
1295 __pformat_putc( '\x20', stream );
1296 }
1297
1298 /* Clean up `__pformat_fcvt()' memory allocation for `value'...
1299 */
1300 __pformat_fcvt_release( value );
1301}
1302
1303static
1304void __pformat_efloat( long double x, __pformat_t *stream )
1305{
1306 /* Handler for `%e' and `%E' format specifiers.
1307 *
1308 * This wraps calls to `__pformat_cvt()', `__pformat_emit_efloat()'
1309 * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve
1310 * output in floating point format.
1311 */
1312 int sign, intlen; char *value;
1313
1314 /* Establish the precision for the displayed value, defaulting to six
1315 * digits following the decimal point, if not explicitly specified.
1316 */
1317 if( stream->precision < 0 )
1318 stream->precision = 6;
1319
1320 /* Encode the input value as ASCII, for display...
1321 */
1322 value = __pformat_ecvt( x, stream->precision + 1, &intlen, &sign );
1323
1324 if( intlen == PFORMAT_INFNAN )
1325 /*
1326 * handle cases of `infinity' or `not-a-number'...
1327 */
1328 __pformat_emit_inf_or_nan( sign, value, stream );
1329
1330 else
1331 /* or otherwise, emit the formatted result.
1332 */
1333 __pformat_emit_efloat( sign, value, intlen, stream );
1334
1335 /* Clean up `__pformat_ecvt()' memory allocation for `value'...
1336 */
1337 __pformat_ecvt_release( value );
1338}
1339
1340static
1341void __pformat_gfloat( long double x, __pformat_t *stream )
1342{
1343 /* Handler for `%g' and `%G' format specifiers.
1344 *
1345 * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()',
1346 * `__pformat_emit_efloat()' and `__pformat_emit_inf_or_nan()', as
1347 * appropriate, to achieve output in the more suitable of either
1348 * fixed or floating point format.
1349 */
1350 int sign, intlen; char *value;
1351
1352 /* Establish the precision for the displayed value, defaulting to
1353 * six significant digits, if not explicitly specified...
1354 */
1355 if( stream->precision < 0 )
1356 stream->precision = 6;
1357
1358 /* or to a minimum of one digit, otherwise...
1359 */
1360 else if( stream->precision == 0 )
1361 stream->precision = 1;
1362
1363 /* Encode the input value as ASCII, for display.
1364 */
1365 value = __pformat_ecvt( x, stream->precision, &intlen, &sign );
1366
1367 if( intlen == PFORMAT_INFNAN )
1368 /*
1369 * Handle cases of `infinity' or `not-a-number'.
1370 */
1371 __pformat_emit_inf_or_nan( sign, value, stream );
1372
1373 else if( (-4 < intlen) && (intlen <= stream->precision) )
1374 {
1375 /* Value lies in the acceptable range for fixed point output,
1376 * (i.e. the exponent is no less than minus four, and the number
1377 * of significant digits which precede the radix point is fewer
1378 * than the least number which would overflow the field width,
1379 * specified or implied by the established precision).
1380 */
1381 if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1382 /*
1383 * The `#' flag is in effect...
1384 * Adjust precision to retain the specified number of significant
1385 * digits, with the proper number preceding the radix point, and
1386 * the balance following it...
1387 */
1388 stream->precision -= intlen;
1389
1390 else
1391 /* The `#' flag is not in effect...
1392 * Here we adjust the precision to accommodate all digits which
1393 * precede the radix point, but we truncate any balance following
1394 * it, to suppress output of non-significant trailing zeros...
1395 */
1396 if( ((stream->precision = strlen( value ) - intlen) < 0)
1397 /*
1398 * This may require a compensating adjustment to the field
1399 * width, to accommodate significant trailing zeros, which
1400 * precede the radix point...
1401 */
1402 && (stream->width > 0) )
1403 stream->width += stream->precision;
1404
1405 /* Now, we format the result as any other fixed point value.
1406 */
1407 __pformat_emit_float( sign, value, intlen, stream );
1408
1409 /* If there is any residual field width as yet unfilled, then
1410 * we must be doing flush left justification, so pad out to the
1411 * right hand field boundary.
1412 */
1413 while( stream->width-- > 0 )
1414 __pformat_putc( '\x20', stream );
1415 }
1416
1417 else
1418 { /* Value lies outside the acceptable range for fixed point;
1419 * one significant digit will precede the radix point, so we
1420 * decrement the precision to retain only the appropriate number
1421 * of additional digits following it, when we emit the result
1422 * in floating point format.
1423 */
1424 if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED )
1425 /*
1426 * The `#' flag is in effect...
1427 * Adjust precision to emit the specified number of significant
1428 * digits, with one preceding the radix point, and the balance
1429 * following it, retaining any non-significant trailing zeros
1430 * which are required to exactly match the requested precision...
1431 */
1432 stream->precision--;
1433
1434 else
1435 /* The `#' flag is not in effect...
1436 * Adjust precision to emit only significant digits, with one
1437 * preceding the radix point, and any others following it, but
1438 * suppressing non-significant trailing zeros...
1439 */
1440 stream->precision = strlen( value ) - 1;
1441
1442 /* Now, we format the result as any other floating point value.
1443 */
1444 __pformat_emit_efloat( sign, value, intlen, stream );
1445 }
1446
1447 /* Clean up `__pformat_ecvt()' memory allocation for `value'.
1448 */
1449 __pformat_ecvt_release( value );
1450}
1451
1452static
1453void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream )
1454{
1455 /* Helper for emitting floating point data, originating as
1456 * either `double' or `long double' type, as a hexadecimal
1457 * representation of the argument value.
1458 */
1459 char buf[18 + 6], *p = buf;
1460 __pformat_intarg_t exponent; short exp_width = 2;
1461
1462 /* The mantissa field of the argument value representation can
1463 * accommodate at most 16 hexadecimal digits, of which one will
1464 * be placed before the radix point, leaving at most 15 digits
1465 * to satisfy any requested precision; thus...
1466 */
1467 if( (stream->precision >= 0) && (stream->precision < 15) )
1468 {
1469 /* When the user specifies a precision within this range,
1470 * we want to adjust the mantissa, to retain just the number
1471 * of digits required, rounding up when the high bit of the
1472 * leftmost discarded digit is set; (mask of 0x08 accounts
1473 * for exactly one digit discarded, shifting 4 bits per
1474 * digit, with up to 14 additional digits, to consume the
1475 * full availability of 15 precision digits).
1476 *
1477 * However, before we perform the rounding operation, we
1478 * normalise the mantissa, shifting it to the left by as many
1479 * bit positions may be necessary, until its highest order bit
1480 * is set, thus preserving the maximum number of bits in the
1481 * rounded result as possible.
1482 */
1483 while( value.__pformat_fpreg_mantissa < (LLONG_MAX + 1ULL) )
1484 value.__pformat_fpreg_mantissa <<= 1;
1485
1486 /* We then shift the mantissa one bit position back to the
1487 * right, to guard against possible overflow when the rounding
1488 * adjustment is added.
1489 */
1490 value.__pformat_fpreg_mantissa >>= 1;
1491
1492 /* We now add the rounding adjustment, noting that to keep the
1493 * 0x08 mask aligned with the shifted mantissa, we also need to
1494 * shift it right by one bit initially, changing its starting
1495 * value to 0x04...
1496 */
1497 value.__pformat_fpreg_mantissa += 0x04LL << (4 * (14 - stream->precision));
1498 if( (value.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0ULL )
1499 /*
1500 * When the rounding adjustment would not have overflowed,
1501 * then we shift back to the left again, to fill the vacated
1502 * bit we reserved to accommodate the carry.
1503 */
1504 value.__pformat_fpreg_mantissa <<= 1;
1505
1506 else
1507 /* Otherwise the rounding adjustment would have overflowed,
1508 * so the carry has already filled the vacated bit; the effect
1509 * of this is equivalent to an increment of the exponent.
1510 */
1511 value.__pformat_fpreg_exponent++;
1512
1513 /* We now complete the rounding to the required precision, by
1514 * shifting the unwanted digits out, from the right hand end of
1515 * the mantissa.
1516 */
1517 value.__pformat_fpreg_mantissa >>= 4 * (15 - stream->precision);
1518 }
1519
1520 /* Encode the significant digits of the mantissa in hexadecimal
1521 * ASCII notation, ready for transfer to the output stream...
1522 */
1523 while( value.__pformat_fpreg_mantissa )
1524 {
1525 /* taking the rightmost digit in each pass...
1526 */
1527 int c = value.__pformat_fpreg_mantissa & 0xF;
1528 if( c == (int) value.__pformat_fpreg_mantissa)
1529 {
1530 /* inserting the radix point, when we reach the last,
1531 * (i.e. the most significant digit), unless we found no
1532 * less significant digits, with no mandatory radix point
1533 * inclusion, and no additional required precision...
1534 */
1535 if( (p > buf)
1536 || (stream->flags & PFORMAT_HASHED) || (stream->precision > 0) )
1537 {
1538 /*
1539 * Internally, we represent the radix point as an ASCII '.';
1540 * we will replace it with any locale specific alternative,
1541 * at the time of transfer to the ultimate destination.
1542 */
1543 *p++ = '.';
1544 }
1545
1546 /* If the most significant hexadecimal digit of the encoded
1547 * output value is greater than one, then the indicated value
1548 * will appear too large, by an additional binary exponent
1549 * corresponding to the number of higher order bit positions
1550 * which it occupies...
1551 */
1552 while( value.__pformat_fpreg_mantissa > 1 )
1553 {
1554 /* so reduce the exponent value to compensate...
1555 */
1556 value.__pformat_fpreg_exponent--;
1557 value.__pformat_fpreg_mantissa >>= 1;
1558 }
1559 }
1560
1561 else if( stream->precision > 0 )
1562 /*
1563 * we have not yet fulfilled the desired precision,
1564 * and we have not yet found the most significant digit,
1565 * so account for the current digit, within the field
1566 * width required to meet the specified precision.
1567 */
1568 stream->precision--;
1569
1570 if( (c > 0) || (p > buf) || (stream->precision >= 0) )
1571 {
1572 /*
1573 * Ignoring insignificant trailing zeros, (unless required to
1574 * satisfy specified precision), store the current encoded digit
1575 * into the pending output buffer, in LIFO order, and using the
1576 * appropriate case for digits in the `A'..`F' range.
1577 */
1578 *p++ = c > 9 ? (c - 10 + 'A') | (stream->flags & PFORMAT_XCASE) : c + '0';
1579 }
1580 /* Shift out the current digit, (4-bit logical shift right),
1581 * to align the next more significant digit to be extracted,
1582 * and encoded in the next pass.
1583 */
1584 value.__pformat_fpreg_mantissa >>= 4;
1585 }
1586
1587 if( p == buf )
1588 {
1589 /* Nothing has been queued for output...
1590 * We need at least one zero, and possibly a radix point.
1591 */
1592 if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) )
1593 *p++ = '.';
1594
1595 *p++ = '0';
1596 }
1597
1598 if( stream->width > 0 )
1599 {
1600 /* Adjust the user specified field width, to account for the
1601 * number of digits minimally required, to display the encoded
1602 * value, at the requested precision.
1603 *
1604 * FIXME: this uses the minimum number of digits possible for
1605 * representation of the binary exponent, in strict conformance
1606 * with C99 and POSIX specifications. Although there appears to
1607 * be no Microsoft precedent for doing otherwise, we may wish to
1608 * relate this to the `_get_output_format()' result, to maintain
1609 * consistency with `%e', `%f' and `%g' styles.
1610 */
1611 int min_width = p - buf;
1612 int exponent2 = value.__pformat_fpreg_exponent;
1613
1614 /* If we have not yet queued sufficient digits to fulfil the
1615 * requested precision, then we must adjust the minimum width
1616 * specification, to accommodate the additional digits which
1617 * are required to do so.
1618 */
1619 if( stream->precision > 0 )
1620 min_width += stream->precision;
1621
1622 /* Adjust the minimum width requirement, to accomodate the
1623 * sign, radix indicator and at least one exponent digit...
1624 */
1625 min_width += stream->flags & PFORMAT_SIGNED ? 6 : 5;
1626 while( (exponent2 = exponent2 / 10) != 0 )
1627 {
1628 /* and increase as required, if additional exponent digits
1629 * are needed, also saving the exponent field width adjustment,
1630 * for later use when that is emitted.
1631 */
1632 min_width++;
1633 exp_width++;
1634 }
1635
1636 if( stream->width > min_width )
1637 {
1638 /* When specified field width exceeds the minimum required,
1639 * adjust to retain only the excess...
1640 */
1641 stream->width -= min_width;
1642
1643 /* and then emit any required left side padding spaces.
1644 */
1645 if( (stream->flags & PFORMAT_JUSTIFY) == 0 )
1646 while( stream->width-- > 0 )
1647 __pformat_putc( '\x20', stream );
1648 }
1649
1650 else
1651 /* Specified field width is insufficient; just ignore it!
1652 */
1653 stream->width = PFORMAT_IGNORE;
1654 }
1655
1656 /* Emit the sign of the encoded value, as required...
1657 */
1658 if( stream->flags & PFORMAT_NEGATIVE )
1659 /*
1660 * this is mandatory, to indicate a negative value...
1661 */
1662 __pformat_putc( '-', stream );
1663
1664 else if( stream->flags & PFORMAT_POSITIVE )
1665 /*
1666 * but this is optional, for a positive value...
1667 */
1668 __pformat_putc( '+', stream );
1669
1670 else if( stream->flags & PFORMAT_ADDSPACE )
1671 /*
1672 * with this optional alternative.
1673 */
1674 __pformat_putc( '\x20', stream );
1675
1676 /* Prefix a `0x' or `0X' radix indicator to the encoded value,
1677 * with case appropriate to the format specification.
1678 */
1679 __pformat_putc( '0', stream );
1680 __pformat_putc( 'X' | (stream->flags & PFORMAT_XCASE), stream );
1681
1682 /* If the `0' flag is in effect...
1683 * Zero padding, to fill out the field, goes here...
1684 */
1685 if( (stream->width > 0) && (stream->flags & PFORMAT_ZEROFILL) )
1686 while( stream->width-- > 0 )
1687 __pformat_putc( '0', stream );
1688
1689 /* Next, we emit the encoded value, without its exponent...
1690 */
1691 while( p > buf )
1692 __pformat_emit_numeric_value( *--p, stream );
1693
1694 /* followed by any additional zeros needed to satisfy the
1695 * precision specification...
1696 */
1697 while( stream->precision-- > 0 )
1698 __pformat_putc( '0', stream );
1699
1700 /* then the exponent prefix, (C99 and POSIX specify `p'),
1701 * in the case appropriate to the format specification...
1702 */
1703 __pformat_putc( 'P' | (stream->flags & PFORMAT_XCASE), stream );
1704
1705 /* and finally, the decimal representation of the binary exponent,
1706 * as a signed value with mandatory sign displayed, in a field width
1707 * adjusted to accommodate it, LEFT justified, with any additional
1708 * right side padding remaining from the original field width.
1709 */
1710 stream->width += exp_width;
1711 stream->flags |= PFORMAT_SIGNED;
1712 exponent.__pformat_llong_t = value.__pformat_fpreg_exponent;
1713 __pformat_int( exponent, stream );
1714}
1715
1716static
1717void __pformat_xldouble( long double x, __pformat_t *stream )
1718{
1719 /* Handler for `%La' and `%LA' format specifiers, (with argument
1720 * value specified as `long double' type).
1721 */
1722 unsigned sign_bit = 0;
1723 __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x;
1724
1725 /* First check for NaN; it is emitted unsigned...
1726 */
1727 if( isnan( x ) )
1728 __pformat_emit_inf_or_nan( sign_bit, "NaN", stream );
1729
1730 else
1731 { /* Capture the sign bit up-front, so we can show it correctly
1732 * even when the argument value is zero or infinite.
1733 */
1734 if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 )
1735 stream->flags |= PFORMAT_NEGATIVE;
1736
1737 /* Check for infinity, (positive or negative)...
1738 */
1739 if( isinf( x ) )
1740 /*
1741 * displaying the appropriately signed indicator,
1742 * when appropriate.
1743 */
1744 __pformat_emit_inf_or_nan( sign_bit, "Inf", stream );
1745
1746 else
1747 { /* The argument value is a representable number...
1748 * extract the effective value of the biased exponent...
1749 */
1750 z.__pformat_fpreg_exponent &= 0x7FFF;
1751 if( z.__pformat_fpreg_exponent == 0 )
1752 {
1753 /* A biased exponent value of zero means either a
1754 * true zero value, if the mantissa field also has
1755 * a zero value, otherwise...
1756 */
1757 if( z.__pformat_fpreg_mantissa != 0 )
1758 {
1759 /* ...this mantissa represents a subnormal value;
1760 * adjust the exponent, while shifting the mantissa
1761 * to the left, until its leading bit is 1.
1762 */
1763 z.__pformat_fpreg_exponent = 1-0x3FFF;
1764 while( (z.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0 )
1765 {
1766 z.__pformat_fpreg_mantissa <<= 1;
1767 --z.__pformat_fpreg_exponent;
1768 }
1769 }
1770 }
1771 else
1772 /* This argument represents a non-zero normal number;
1773 * eliminate the bias from the exponent...
1774 */
1775 z.__pformat_fpreg_exponent -= 0x3FFF;
1776
1777 /* Finally, hand the adjusted representation off to the
1778 * generalised hexadecimal floating point format handler...
1779 */
1780 __pformat_emit_xfloat( z, stream );
1781 }
1782 }
1783}
1784
1785int __cdecl
1786_evil_pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv)
1787{
1788 int c;
1789 int saved_errno = errno;
1790
1791 __pformat_t stream =
1792 {
1793 /* Create and initialise a format control block
1794 * for this output request.
1795 */
1796 dest, /* output goes to here */
1797 flags &= PFORMAT_TO_FILE | PFORMAT_NOLIMIT, /* only these valid initially */
1798 PFORMAT_IGNORE, /* no field width yet */
1799 PFORMAT_IGNORE, /* nor any precision spec */
1800 PFORMAT_RPINIT, /* radix point uninitialised */
1801 (wchar_t)(0), /* leave it unspecified */
1802 0,
1803 (wchar_t)(0), /* leave it unspecified */
1804 0, /* zero output char count */
1805 max, /* establish output limit */
1806 PFORMAT_MINEXP /* exponent chars preferred */
1807 };
1808
1809 format_scan: while( (c = *fmt++) != 0 )
1810 {
1811 /* Format string parsing loop...
1812 * The entry point is labelled, so that we can return to the start state
1813 * from within the inner `conversion specification' interpretation loop,
1814 * as soon as a conversion specification has been resolved.
1815 */
1816 if( c == '%' )
1817 {
1818 /* Initiate parsing of a `conversion specification'...
1819 */
1820 __pformat_intarg_t argval;
1821 __pformat_state_t state = PFORMAT_INIT;
1822 __pformat_length_t length = PFORMAT_LENGTH_INT;
1823
1824 /* Save the current format scan position, so that we can backtrack
1825 * in the event of encountering an invalid format specification...
1826 */
1827 const APICHAR *backtrack = fmt;
1828
1829 /* Restart capture for dynamic field width and precision specs...
1830 */
1831 int *width_spec = &stream.width;
1832
1833 /* Reset initial state for flags, width and precision specs...
1834 */
1835 stream.flags = flags;
1836 stream.width = stream.precision = PFORMAT_IGNORE;
1837
1838 while( *fmt )
1839 {
1840 switch( c = *fmt++ )
1841 {
1842 /* Data type specifiers...
1843 * All are terminal, so exit the conversion spec parsing loop
1844 * with a `goto format_scan', thus resuming at the outer level
1845 * in the regular format string parser.
1846 */
1847 case '%':
1848 /*
1849 * Not strictly a data type specifier...
1850 * it simply converts as a literal `%' character.
1851 *
1852 * FIXME: should we require this to IMMEDIATELY follow the
1853 * initial `%' of the "conversion spec"? (glibc `printf()'
1854 * on GNU/Linux does NOT appear to require this, but POSIX
1855 * and SUSv3 do seem to demand it).
1856 */
1857 __pformat_putc( c, &stream );
1858 goto format_scan;
1859
1860 case 'C':
1861 /*
1862 * Equivalent to `%lc'; set `length' accordingly,
1863 * and simply fall through.
1864 */
1865 length = PFORMAT_LENGTH_LONG;
1866
1867 case 'c':
1868 /*
1869 * Single, (or single multibyte), character output...
1870 *
1871 * We handle these by copying the argument into our local
1872 * `argval' buffer, and then we pass the address of that to
1873 * either `__pformat_putchars()' or `__pformat_wputchars()',
1874 * as appropriate, effectively formatting it as a string of
1875 * the appropriate type, with a length of one.
1876 *
1877 * A side effect of this method of handling character data
1878 * is that, if the user sets a precision of zero, then no
1879 * character is actually emitted; we don't want that, so we
1880 * forcibly override any user specified precision.
1881 */
1882 stream.precision = PFORMAT_IGNORE;
1883
1884 /* Now we invoke the appropriate format handler...
1885 */
1886 if( (length == PFORMAT_LENGTH_LONG)
1887 || (length == PFORMAT_LENGTH_LLONG) )
1888 {
1889 /* considering any `long' type modifier as a reference to
1890 * `wchar_t' data, (which is promoted to an `int' argument)...
1891 */
1892 wchar_t iargval = (wchar_t)(va_arg( argv, int ));
1893 __pformat_wputchars( &iargval, 1, &stream );
1894 }
1895 else
1896 { /* while anything else is simply taken as `char', (which
1897 * is also promoted to an `int' argument)...
1898 */
1899 argval.__pformat_uchar_t = (unsigned char)(va_arg( argv, int ));
1900 __pformat_putchars( (char *)(&argval), 1, &stream );
1901 }
1902 goto format_scan;
1903
1904 case 'S':
1905 /*
1906 * Equivalent to `%ls'; set `length' accordingly,
1907 * and simply fall through.
1908 */
1909 length = PFORMAT_LENGTH_LONG;
1910
1911 case 's':
1912 if( (length == PFORMAT_LENGTH_LONG)
1913 || (length == PFORMAT_LENGTH_LLONG))
1914 {
1915 /* considering any `long' type modifier as a reference to
1916 * a `wchar_t' string...
1917 */
1918 __pformat_wcputs( va_arg( argv, wchar_t * ), &stream );
1919 }
1920 else
1921 /* This is normal string output;
1922 * we simply invoke the appropriate handler...
1923 */
1924 __pformat_puts( va_arg( argv, char * ), &stream );
1925 goto format_scan;
1926 case 'm': /* strerror (errno) */
1927 __pformat_puts (strerror (saved_errno), &stream);
1928 goto format_scan;
1929
1930 case 'o':
1931 case 'u':
1932 case 'x':
1933 case 'X':
1934 /*
1935 * Unsigned integer values; octal, decimal or hexadecimal format...
1936 */
1937 if( length == PFORMAT_LENGTH_LLONG )
1938 /*
1939 * with an `unsigned long long' argument, which we
1940 * process `as is'...
1941 */
1942 argval.__pformat_ullong_t = va_arg( argv, unsigned long long );
1943
1944 else if( length == PFORMAT_LENGTH_LONG )
1945 /*
1946 * or with an `unsigned long', which we promote to
1947 * `unsigned long long'...
1948 */
1949 argval.__pformat_ullong_t = va_arg( argv, unsigned long );
1950
1951 else
1952 { /* or for any other size, which will have been promoted
1953 * to `unsigned int', we select only the appropriately sized
1954 * least significant segment, and again promote to the same
1955 * size as `unsigned long long'...
1956 */
1957 argval.__pformat_ullong_t = va_arg( argv, unsigned int );
1958 if( length == PFORMAT_LENGTH_SHORT )
1959 /*
1960 * from `unsigned short'...
1961 */
1962 argval.__pformat_ullong_t = argval.__pformat_ushort_t;
1963
1964 else if( length == PFORMAT_LENGTH_CHAR )
1965 /*
1966 * or even from `unsigned char'...
1967 */
1968 argval.__pformat_ullong_t = argval.__pformat_uchar_t;
1969 }
1970
1971 /* so we can pass any size of argument to either of two
1972 * common format handlers...
1973 */
1974 if( c == 'u' )
1975 /*
1976 * depending on whether output is to be encoded in
1977 * decimal format...
1978 */
1979 __pformat_int( argval, &stream );
1980
1981 else
1982 /* or in octal or hexadecimal format...
1983 */
1984 __pformat_xint( c, argval, &stream );
1985
1986 goto format_scan;
1987
1988 case 'd':
1989 case 'i':
1990 /*
1991 * Signed integer values; decimal format...
1992 * This is similar to `u', but must process `argval' as signed,
1993 * and be prepared to handle negative numbers.
1994 */
1995 stream.flags |= PFORMAT_NEGATIVE;
1996
1997 if( length == PFORMAT_LENGTH_LLONG )
1998 /*
1999 * The argument is a `long long' type...
2000 */
2001 argval.__pformat_llong_t = va_arg( argv, long long );
2002
2003 else if( length == PFORMAT_LENGTH_LONG )
2004 /*
2005 * or here, a `long' type...
2006 */
2007 argval.__pformat_llong_t = va_arg( argv, long );
2008
2009 else
2010 { /* otherwise, it's an `int' type...
2011 */
2012 argval.__pformat_llong_t = va_arg( argv, int );
2013 if( length == PFORMAT_LENGTH_SHORT )
2014 /*
2015 * but it was promoted from a `short' type...
2016 */
2017 argval.__pformat_llong_t = argval.__pformat_short_t;
2018 else if( length == PFORMAT_LENGTH_CHAR )
2019 /*
2020 * or even from a `char' type...
2021 */
2022 argval.__pformat_llong_t = argval.__pformat_char_t;
2023 }
2024
2025 /* In any case, all share a common handler...
2026 */
2027 __pformat_int( argval, &stream );
2028 goto format_scan;
2029
2030 case 'p':
2031 /*
2032 * Pointer argument; format as hexadecimal, subject to...
2033 */
2034 if( (state == PFORMAT_INIT) && (stream.flags == flags) )
2035 {
2036 /* Here, the user didn't specify any particular
2037 * formatting attributes. We must choose a default
2038 * which will be compatible with Microsoft's (broken)
2039 * scanf() implementation, (i.e. matching the default
2040 * used by MSVCRT's printf(), which appears to resemble
2041 * "%0.8X" for 32-bit pointers); in particular, we MUST
2042 * NOT adopt a GNU-like format resembling "%#x", because
2043 * Microsoft's scanf() will choke on the "0x" prefix.
2044 */
2045 stream.flags |= PFORMAT_ZEROFILL;
2046 stream.precision = 2 * sizeof( uintptr_t );
2047 }
2048 argval.__pformat_ullong_t = va_arg( argv, uintptr_t );
2049 __pformat_xint( 'x', argval, &stream );
2050 goto format_scan;
2051
2052 case 'e':
2053 /*
2054 * Floating point format, with lower case exponent indicator
2055 * and lower case `inf' or `nan' representation when required;
2056 * select lower case mode, and simply fall through...
2057 */
2058 stream.flags |= PFORMAT_XCASE;
2059
2060 case 'E':
2061 /*
2062 * Floating point format, with upper case exponent indicator
2063 * and upper case `INF' or `NAN' representation when required,
2064 * (or lower case for all of these, on fall through from above);
2065 * select lower case mode, and simply fall through...
2066 */
2067 if( stream.flags & PFORMAT_LDOUBLE )
2068 /*
2069 * for a `long double' argument...
2070 */
2071 __pformat_efloat( va_arg( argv, long double ), &stream );
2072
2073 else
2074 /* or just a `double', which we promote to `long double',
2075 * so the two may share a common format handler.
2076 */
2077 __pformat_efloat( (long double)(va_arg( argv, double )), &stream );
2078
2079 goto format_scan;
2080
2081 case 'f':
2082 /*
2083 * Fixed point format, using lower case for `inf' and
2084 * `nan', when appropriate; select lower case mode, and
2085 * simply fall through...
2086 */
2087 stream.flags |= PFORMAT_XCASE;
2088
2089 case 'F':
2090 /*
2091 * Fixed case format using upper case, or lower case on
2092 * fall through from above, for `INF' and `NAN'...
2093 */
2094 if( stream.flags & PFORMAT_LDOUBLE )
2095 /*
2096 * for a `long double' argument...
2097 */
2098 __pformat_float( va_arg( argv, long double ), &stream );
2099
2100 else
2101 /* or just a `double', which we promote to `long double',
2102 * so the two may share a common format handler.
2103 */
2104 __pformat_float( (long double)(va_arg( argv, double )), &stream );
2105
2106 goto format_scan;
2107
2108 case 'g':
2109 /*
2110 * Generalised floating point format, with lower case
2111 * exponent indicator when required; select lower case
2112 * mode, and simply fall through...
2113 */
2114 stream.flags |= PFORMAT_XCASE;
2115
2116 case 'G':
2117 /*
2118 * Generalised floating point format, with upper case,
2119 * or on fall through from above, with lower case exponent
2120 * indicator when required...
2121 */
2122 if( stream.flags & PFORMAT_LDOUBLE )
2123 /*
2124 * for a `long double' argument...
2125 */
2126 __pformat_gfloat( va_arg( argv, long double ), &stream );
2127
2128 else
2129 /* or just a `double', which we promote to `long double',
2130 * so the two may share a common format handler.
2131 */
2132 __pformat_gfloat( (long double)(va_arg( argv, double )), &stream );
2133
2134 goto format_scan;
2135
2136 case 'a':
2137 /*
2138 * Hexadecimal floating point format, with lower case radix
2139 * and exponent indicators; select the lower case mode, and
2140 * fall through...
2141 */
2142 stream.flags |= PFORMAT_XCASE;
2143
2144 case 'A':
2145 /*
2146 * Hexadecimal floating point format; handles radix and
2147 * exponent indicators in either upper or lower case...
2148 */
2149 if( stream.flags & PFORMAT_LDOUBLE )
2150 /*
2151 * with a `long double' argument...
2152 */
2153 __pformat_xldouble( va_arg( argv, long double ), &stream );
2154
2155 else
2156 /* or just a `double'.
2157 */
2158 __pformat_xldouble( (long double)(va_arg( argv, double )), &stream );
2159
2160 goto format_scan;
2161
2162 case 'n':
2163 /*
2164 * Save current output character count...
2165 */
2166 if( length == PFORMAT_LENGTH_CHAR )
2167 /*
2168 * to a signed `char' destination...
2169 */
2170 *va_arg( argv, char * ) = stream.count;
2171
2172 else if( length == PFORMAT_LENGTH_SHORT )
2173 /*
2174 * or to a signed `short'...
2175 */
2176 *va_arg( argv, short * ) = stream.count;
2177
2178 else if( length == PFORMAT_LENGTH_LONG )
2179 /*
2180 * or to a signed `long'...
2181 */
2182 *va_arg( argv, long * ) = stream.count;
2183
2184 else if( length == PFORMAT_LENGTH_LLONG )
2185 /*
2186 * or to a signed `long long'...
2187 */
2188 *va_arg( argv, long long * ) = stream.count;
2189
2190 else
2191 /*
2192 * or, by default, to a signed `int'.
2193 */
2194 *va_arg( argv, int * ) = stream.count;
2195
2196 goto format_scan;
2197
2198 /* Argument length modifiers...
2199 * These are non-terminal; each sets the format parser
2200 * into the PFORMAT_END state, and ends with a `break'.
2201 */
2202 case 'h':
2203 /*
2204 * Interpret the argument as explicitly of a `short'
2205 * or `char' data type, truncated from the standard
2206 * length defined for integer promotion.
2207 */
2208 if( *fmt == 'h' )
2209 {
2210 /* Modifier is `hh'; data type is `char' sized...
2211 * Skip the second `h', and set length accordingly.
2212 */
2213 ++fmt;
2214 length = PFORMAT_LENGTH_CHAR;
2215 }
2216
2217 else
2218 /* Modifier is `h'; data type is `short' sized...
2219 */
2220 length = PFORMAT_LENGTH_SHORT;
2221
2222 state = PFORMAT_END;
2223 break;
2224
2225 case 'j':
2226 /*
2227 * Interpret the argument as being of the same size as
2228 * a `intmax_t' entity...
2229 */
2230 length = __pformat_arg_length( intmax_t );
2231 state = PFORMAT_END;
2232 break;
2233
2234# ifdef _WIN32
2235
2236 case 'I':
2237 /*
2238 * The MSVCRT implementation of the printf() family of
2239 * functions explicitly uses...
2240 */
2241 if( (fmt[0] == '6') && (fmt[1] == '4') )
2242 {
2243 /* I64' instead of `ll',
2244 * when referring to `long long' integer types...
2245 */
2246 length = PFORMAT_LENGTH_LLONG;
2247 fmt += 2;
2248 }
2249
2250 else if( (fmt[0] == '3') && (fmt[1] == '2') )
2251 {
2252 /* and `I32' instead of `l',
2253 * when referring to `long' integer types...
2254 */
2255 length = PFORMAT_LENGTH_LONG;
2256 fmt += 2;
2257 }
2258
2259 else
2260 /* or unqualified `I' instead of `t' or `z',
2261 * when referring to `ptrdiff_t' or `size_t' entities;
2262 * (we will choose to map it to `ptrdiff_t').
2263 */
2264 length = __pformat_arg_length( ptrdiff_t );
2265
2266 state = PFORMAT_END;
2267 break;
2268
2269# endif
2270
2271 case 'l':
2272 /*
2273 * Interpret the argument as explicitly of a
2274 * `long' or `long long' data type.
2275 */
2276 if( *fmt == 'l' )
2277 {
2278 /* Modifier is `ll'; data type is `long long' sized...
2279 * Skip the second `l', and set length accordingly.
2280 */
2281 ++fmt;
2282 length = PFORMAT_LENGTH_LLONG;
2283 }
2284
2285 else
2286 /* Modifier is `l'; data type is `long' sized...
2287 */
2288 length = PFORMAT_LENGTH_LONG;
2289
2290 state = PFORMAT_END;
2291 break;
2292
2293 case 'L':
2294 /*
2295 * Identify the appropriate argument as a `long double',
2296 * when associated with `%a', `%A', `%e', `%E', `%f', `%F',
2297 * `%g' or `%G' format specifications.
2298 */
2299 stream.flags |= PFORMAT_LDOUBLE;
2300 state = PFORMAT_END;
2301 break;
2302
2303 case 't':
2304 /*
2305 * Interpret the argument as being of the same size as
2306 * a `ptrdiff_t' entity...
2307 */
2308 length = __pformat_arg_length( ptrdiff_t );
2309 state = PFORMAT_END;
2310 break;
2311
2312 case 'z':
2313 /*
2314 * Interpret the argument as being of the same size as
2315 * a `size_t' entity...
2316 */
2317 length = __pformat_arg_length( size_t );
2318 state = PFORMAT_END;
2319 break;
2320
2321 /* Precision indicator...
2322 * May appear once only; it must precede any modifier
2323 * for argument length, or any data type specifier.
2324 */
2325 case '.':
2326 if( state < PFORMAT_GET_PRECISION )
2327 {
2328 /* We haven't seen a precision specification yet,
2329 * so initialise it to zero, (in case no digits follow),
2330 * and accept any following digits as the precision.
2331 */
2332 stream.precision = 0;
2333 width_spec = &stream.precision;
2334 state = PFORMAT_GET_PRECISION;
2335 }
2336
2337 else
2338 /* We've already seen a precision specification,
2339 * so this is just junk; proceed to end game.
2340 */
2341 state = PFORMAT_END;
2342
2343 /* Either way, we must not fall through here.
2344 */
2345 break;
2346
2347 /* Variable field width, or precision specification,
2348 * derived from the argument list...
2349 */
2350 case '*':
2351 /*
2352 * When this appears...
2353 */
2354 if( width_spec
2355 && ((state == PFORMAT_INIT) || (state == PFORMAT_GET_PRECISION)) )
2356 {
2357 /* in proper context; assign to field width
2358 * or precision, as appropriate.
2359 */
2360 if( (*width_spec = va_arg( argv, int )) < 0 )
2361 {
2362 /* Assigned value was negative...
2363 */
2364 if( state == PFORMAT_INIT )
2365 {
2366 /* For field width, this is equivalent to
2367 * a positive value with the `-' flag...
2368 */
2369 stream.flags |= PFORMAT_LJUSTIFY;
2370 stream.width = -stream.width;
2371 }
2372
2373 else
2374 /* while as a precision specification,
2375 * it should simply be ignored.
2376 */
2377 stream.precision = PFORMAT_IGNORE;
2378 }
2379 }
2380
2381 else
2382 /* out of context; give up on width and precision
2383 * specifications for this conversion.
2384 */
2385 state = PFORMAT_END;
2386
2387 /* Mark as processed...
2388 * we must not see `*' again, in this context.
2389 */
2390 width_spec = NULL;
2391 break;
2392
2393 /* Formatting flags...
2394 * Must appear while in the PFORMAT_INIT state,
2395 * and are non-terminal, so again, end with `break'.
2396 */
2397 case '#':
2398 /*
2399 * Select alternate PFORMAT_HASHED output style.
2400 */
2401 if( state == PFORMAT_INIT )
2402 stream.flags |= PFORMAT_HASHED;
2403 break;
2404
2405 case '+':
2406 /*
2407 * Print a leading sign with numeric output,
2408 * for both positive and negative values.
2409 */
2410 if( state == PFORMAT_INIT )
2411 stream.flags |= PFORMAT_POSITIVE;
2412 break;
2413
2414 case '-':
2415 /*
2416 * Select left justification of displayed output
2417 * data, within the output field width, instead of
2418 * the default flush right justification.
2419 */
2420 if( state == PFORMAT_INIT )
2421 stream.flags |= PFORMAT_LJUSTIFY;
2422 break;
2423
2424 case '\'':
2425 /*
2426 * This is an XSI extension to the POSIX standard,
2427 * which we do not support, at present.
2428 */
2429 if (state == PFORMAT_INIT)
2430 {
2431 int len; wchar_t rpchr; mbstate_t cstate;
2432 stream.flags |= PFORMAT_GROUPED; /* $$$$ */
2433 memset (&cstate, 0, sizeof(state));
2434 if ((len = mbrtowc( &rpchr, localeconv()->thousands_sep, 16, &cstate)) > 0)
2435 stream.thousands_chr = rpchr;
2436 stream.thousands_chr_len = len;
2437 }
2438 break;
2439
2440 case '\x20':
2441 /*
2442 * Reserve a single space, within the output field,
2443 * for display of the sign of signed data; this will
2444 * be occupied by the minus sign, if the data value
2445 * is negative, or by a plus sign if the data value
2446 * is positive AND the `+' flag is also present, or
2447 * by a space otherwise. (Technically, this flag
2448 * is redundant, if the `+' flag is present).
2449 */
2450 if( state == PFORMAT_INIT )
2451 stream.flags |= PFORMAT_ADDSPACE;
2452 break;
2453
2454 case '0':
2455 /*
2456 * May represent a flag, to activate the `pad with zeros'
2457 * option, or it may simply be a digit in a width or in a
2458 * precision specification...
2459 */
2460 if( state == PFORMAT_INIT )
2461 {
2462 /* This is the flag usage...
2463 */
2464 stream.flags |= PFORMAT_ZEROFILL;
2465 break;
2466 }
2467
2468 default:
2469 /*
2470 * If we didn't match anything above, then we will check
2471 * for digits, which we may accumulate to generate field
2472 * width or precision specifications...
2473 */
2474 if( (state < PFORMAT_END) && ('9' >= c) && (c >= '0') )
2475 {
2476 if( state == PFORMAT_INIT )
2477 /*
2478 * Initial digits explicitly relate to field width...
2479 */
2480 state = PFORMAT_SET_WIDTH;
2481
2482 else if( state == PFORMAT_GET_PRECISION )
2483 /*
2484 * while those following a precision indicator
2485 * explicitly relate to precision.
2486 */
2487 state = PFORMAT_SET_PRECISION;
2488
2489 if( width_spec )
2490 {
2491 /* We are accepting a width or precision specification...
2492 */
2493 if( *width_spec < 0 )
2494 /*
2495 * and accumulation hasn't started yet; we simply
2496 * initialise the accumulator with the current digit
2497 * value, converting from ASCII to decimal.
2498 */
2499 *width_spec = c - '0';
2500
2501 else
2502 /* Accumulation has already started; we perform a
2503 * `leftwise decimal digit shift' on the accumulator,
2504 * (i.e. multiply it by ten), then add the decimal
2505 * equivalent value of the current digit.
2506 */
2507 *width_spec = *width_spec * 10 + c - '0';
2508 }
2509 }
2510
2511 else
2512 {
2513 /* We found a digit out of context, or some other character
2514 * with no designated meaning; reject this format specification,
2515 * backtrack, and emit it as literal text...
2516 */
2517 fmt = backtrack;
2518 __pformat_putc( '%', &stream );
2519 goto format_scan;
2520 }
2521 }
2522 }
2523 }
2524
2525 else
2526 /* We just parsed a character which is not included within any format
2527 * specification; we simply emit it as a literal.
2528 */
2529 __pformat_putc( c, &stream );
2530 }
2531
2532 /* When we have fully dispatched the format string, the return value is the
2533 * total number of bytes we transferred to the output destination.
2534 */
2535 return stream.count;
2536}
2537
2538/* $RCSfile: pformat.c,v $Revision: 1.9 $: end of file */
diff --git a/legacy/evil/src/lib/evil_pformatw.c b/legacy/evil/src/lib/evil_pformatw.c
new file mode 100644
index 0000000000..592b56881c
--- /dev/null
+++ b/legacy/evil/src/lib/evil_pformatw.c
@@ -0,0 +1,9 @@
1/**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the w64 mingw-runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6#define __BUILD_WIDEAPI 1
7
8#include "evil_pformata.c"
9
diff --git a/legacy/evil/src/lib/evil_print.h b/legacy/evil/src/lib/evil_print.h
new file mode 100644
index 0000000000..1622b03b70
--- /dev/null
+++ b/legacy/evil/src/lib/evil_print.h
@@ -0,0 +1,103 @@
1#ifndef __EVIL_PRINT_H__
2#define __EVIL_PRINT_H__
3
4
5#include "evil_macro.h"
6
7
8EAPI int __cdecl _evil_fprintfa(FILE *, const char *, ...) __EVIL_NOTHROW;
9EAPI int __cdecl _evil_printfa(const char *, ...) __EVIL_PRINTF(1, 2) __EVIL_NOTHROW;
10EAPI int __cdecl _evil_sprintfa(char *, const char *, ...) __EVIL_NOTHROW;
11EAPI int __cdecl _evil_snprintfa(char *, size_t, const char *, ...) __EVIL_PRINTF(3, 4) __EVIL_NOTHROW;
12EAPI int __cdecl _evil_vfprintfa(FILE *, const char *, va_list) __EVIL_NOTHROW;
13EAPI int __cdecl _evil_vprintfa(const char *, va_list) __EVIL_NOTHROW;
14EAPI int __cdecl _evil_vsprintfa(char *, const char *, va_list) __EVIL_NOTHROW;
15EAPI int __cdecl _evil_vsnprintfa(char *, size_t, const char *, va_list) __EVIL_NOTHROW;
16
17EAPI int __cdecl _evil_fscanf (FILE *, const char *, ...) __EVIL_NOTHROW;
18EAPI int __cdecl _evil_scanf (const char *, ...) __EVIL_NOTHROW;
19EAPI int __cdecl _evil_sscanf (const char *, const char *, ...) __EVIL_NOTHROW;
20EAPI int __cdecl _evil_vfscanf(FILE *, const char *, va_list) __EVIL_NOTHROW;
21EAPI int __cdecl _evil_vscanf (const char *, va_list) __EVIL_NOTHROW;
22EAPI int __cdecl _evil_vsscanf(const char *, const char *, va_list) __EVIL_NOTHROW;
23
24EAPI int __cdecl _evil_asprintf(char ** __restrict__, const char * __restrict__, ...) __EVIL_NOTHROW;
25EAPI int __cdecl _evil_vasprintf(char ** __restrict__, const char * __restrict__, va_list) __EVIL_NOTHROW;
26
27EAPI int __cdecl _evil_fprintfw(FILE *, const wchar_t *, ...) __EVIL_NOTHROW;
28EAPI int __cdecl _evil_printfw(const wchar_t *, ...) __EVIL_NOTHROW;
29EAPI int __cdecl _evil_sprintfw(wchar_t *, const wchar_t *, ...) __EVIL_NOTHROW;
30EAPI int __cdecl _evil_snprintfw(wchar_t *, size_t, const wchar_t *, ...) __EVIL_NOTHROW;
31EAPI int __cdecl _evil_vfprintfw(FILE *, const wchar_t *, va_list) __EVIL_NOTHROW;
32EAPI int __cdecl _evil_vprintfw(const wchar_t *, va_list) __EVIL_NOTHROW;
33EAPI int __cdecl _evil_vsprintfw(wchar_t *, const wchar_t *, va_list) __EVIL_NOTHROW;
34EAPI int __cdecl _evil_vsnprintfw(wchar_t *, size_t, const wchar_t *, va_list) __EVIL_NOTHROW;
35
36/* Redefine to GNU specific PRI... and SCN... macros. */
37/* #if defined(_INTTYPES_H_) && defined(PRId64) */
38
39#define PRId64 "lld"
40#define PRIdLEAST64 "lld"
41#define PRIdFAST64 "lld"
42#define PRIdMAX "lld"
43#define PRIi64 "lli"
44#define PRIiLEAST64 "lli"
45#define PRIiFAST64 "lli"
46#define PRIiMAX "lli"
47#define PRIo64 "llo"
48#define PRIoLEAST64 "llo"
49#define PRIoFAST64 "llo"
50#define PRIoMAX "llo"
51#define PRIu64 "llu"
52#define PRIuLEAST64 "llu"
53#define PRIuFAST64 "llu"
54#define PRIuMAX "llu"
55#define PRIx64 "llx"
56#define PRIxLEAST64 "llx"
57#define PRIxFAST64 "llx"
58#define PRIxMAX "llx"
59#define PRIX64 "llX"
60#define PRIXLEAST64 "llX"
61#define PRIXFAST64 "llX"
62#define PRIXMAX "llX"
63
64#define SCNd64 "lld"
65#define SCNdLEAST64 "lld"
66#define SCNdFAST64 "lld"
67#define SCNdMAX "lld"
68#define SCNi64 "lli"
69#define SCNiLEAST64 "lli"
70#define SCNiFAST64 "lli"
71#define SCNiMAX "lli"
72#define SCNo64 "llo"
73#define SCNoLEAST64 "llo"
74#define SCNoFAST64 "llo"
75#define SCNoMAX "llo"
76#define SCNx64 "llx"
77#define SCNxLEAST64 "llx"
78#define SCNxFAST64 "llx"
79#define SCNxMAX "llx"
80#define SCNu64 "llu"
81#define SCNuLEAST64 "llu"
82#define SCNuFAST64 "llu"
83#define SCNuMAX "llu"
84
85#ifdef _WIN64
86#define PRIdPTR "lld"
87#define PRIiPTR "lli"
88#define PRIoPTR "llo"
89#define PRIuPTR "llu"
90#define PRIxPTR "llx"
91#define PRIXPTR "llX"
92
93#define SCNdPTR "lld"
94#define SCNiPTR "lli"
95#define SCNoPTR "llo"