mesh-rb 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/ext/mesh/extconf.rb +22 -4
  4. data/ext/mesh/mesh.tar.gz +0 -0
  5. data/lib/mesh/version.rb +1 -1
  6. data/mesh.gemspec +3 -2
  7. metadata +4 -120
  8. data/ext/mesh/mesh/.bazelrc +0 -20
  9. data/ext/mesh/mesh/.bazelversion +0 -1
  10. data/ext/mesh/mesh/.clang-format +0 -15
  11. data/ext/mesh/mesh/.dockerignore +0 -5
  12. data/ext/mesh/mesh/.editorconfig +0 -16
  13. data/ext/mesh/mesh/.gitattributes +0 -4
  14. data/ext/mesh/mesh/.github/workflows/main.yml +0 -144
  15. data/ext/mesh/mesh/.gitignore +0 -51
  16. data/ext/mesh/mesh/AUTHORS +0 -5
  17. data/ext/mesh/mesh/CMakeLists.txt +0 -270
  18. data/ext/mesh/mesh/CODE_OF_CONDUCT.md +0 -77
  19. data/ext/mesh/mesh/Dockerfile +0 -30
  20. data/ext/mesh/mesh/LICENSE +0 -201
  21. data/ext/mesh/mesh/Makefile +0 -81
  22. data/ext/mesh/mesh/README.md +0 -97
  23. data/ext/mesh/mesh/WORKSPACE +0 -50
  24. data/ext/mesh/mesh/bazel +0 -350
  25. data/ext/mesh/mesh/mesh-pldi19-powers.pdf +0 -0
  26. data/ext/mesh/mesh/src/BUILD +0 -222
  27. data/ext/mesh/mesh/src/CMakeLists.txt +0 -85
  28. data/ext/mesh/mesh/src/bitmap.h +0 -590
  29. data/ext/mesh/mesh/src/cheap_heap.h +0 -170
  30. data/ext/mesh/mesh/src/common.h +0 -377
  31. data/ext/mesh/mesh/src/copts.bzl +0 -31
  32. data/ext/mesh/mesh/src/d_assert.cc +0 -75
  33. data/ext/mesh/mesh/src/fixed_array.h +0 -124
  34. data/ext/mesh/mesh/src/global_heap.cc +0 -547
  35. data/ext/mesh/mesh/src/global_heap.h +0 -569
  36. data/ext/mesh/mesh/src/gnu_wrapper.cc +0 -75
  37. data/ext/mesh/mesh/src/internal.h +0 -356
  38. data/ext/mesh/mesh/src/libmesh.cc +0 -239
  39. data/ext/mesh/mesh/src/mac_wrapper.cc +0 -528
  40. data/ext/mesh/mesh/src/measure_rss.cc +0 -44
  41. data/ext/mesh/mesh/src/measure_rss.h +0 -20
  42. data/ext/mesh/mesh/src/meshable_arena.cc +0 -776
  43. data/ext/mesh/mesh/src/meshable_arena.h +0 -309
  44. data/ext/mesh/mesh/src/meshing.h +0 -60
  45. data/ext/mesh/mesh/src/mini_heap.h +0 -532
  46. data/ext/mesh/mesh/src/mmap_heap.h +0 -104
  47. data/ext/mesh/mesh/src/one_way_mmap_heap.h +0 -77
  48. data/ext/mesh/mesh/src/partitioned_heap.h +0 -111
  49. data/ext/mesh/mesh/src/plasma/mesh.h +0 -33
  50. data/ext/mesh/mesh/src/real.cc +0 -52
  51. data/ext/mesh/mesh/src/real.h +0 -36
  52. data/ext/mesh/mesh/src/rng/mwc.h +0 -296
  53. data/ext/mesh/mesh/src/rng/mwc64.h +0 -58
  54. data/ext/mesh/mesh/src/rpl_printf.c +0 -1991
  55. data/ext/mesh/mesh/src/runtime.cc +0 -393
  56. data/ext/mesh/mesh/src/runtime.h +0 -114
  57. data/ext/mesh/mesh/src/shuffle_vector.h +0 -287
  58. data/ext/mesh/mesh/src/size_classes.def +0 -251
  59. data/ext/mesh/mesh/src/static/if.h +0 -36
  60. data/ext/mesh/mesh/src/static/log.h +0 -43
  61. data/ext/mesh/mesh/src/testing/benchmark/local_refill.cc +0 -103
  62. data/ext/mesh/mesh/src/testing/big-alloc.c +0 -28
  63. data/ext/mesh/mesh/src/testing/fragmenter.cc +0 -128
  64. data/ext/mesh/mesh/src/testing/global-large-stress.cc +0 -25
  65. data/ext/mesh/mesh/src/testing/local-alloc.c +0 -16
  66. data/ext/mesh/mesh/src/testing/meshing_benchmark.cc +0 -189
  67. data/ext/mesh/mesh/src/testing/thread.cc +0 -35
  68. data/ext/mesh/mesh/src/testing/unit/alignment.cc +0 -56
  69. data/ext/mesh/mesh/src/testing/unit/bitmap_test.cc +0 -274
  70. data/ext/mesh/mesh/src/testing/unit/concurrent_mesh_test.cc +0 -185
  71. data/ext/mesh/mesh/src/testing/unit/mesh_test.cc +0 -143
  72. data/ext/mesh/mesh/src/testing/unit/rng_test.cc +0 -22
  73. data/ext/mesh/mesh/src/testing/unit/size_class_test.cc +0 -66
  74. data/ext/mesh/mesh/src/testing/unit/triple_mesh_test.cc +0 -285
  75. data/ext/mesh/mesh/src/testing/userfaultfd-kernel-copy.cc +0 -164
  76. data/ext/mesh/mesh/src/thread_local_heap.cc +0 -163
  77. data/ext/mesh/mesh/src/thread_local_heap.h +0 -268
  78. data/ext/mesh/mesh/src/wrapper.cc +0 -433
  79. data/ext/mesh/mesh/support/export_mesh.cmake +0 -28
  80. data/ext/mesh/mesh/support/gen-size-classes +0 -57
  81. data/ext/mesh/mesh/support/install_all_configs +0 -33
  82. data/ext/mesh/mesh/support/remove_export_mesh.cmake +0 -48
  83. data/ext/mesh/mesh/support/update-bazelisk +0 -8
  84. data/ext/mesh/mesh/theory/32m80.png +0 -0
  85. data/ext/mesh/mesh/theory/64m80ind.png +0 -0
  86. data/ext/mesh/mesh/theory/bound_comparison.py +0 -67
  87. data/ext/mesh/mesh/theory/bounds/impdeg+1 +0 -135
  88. data/ext/mesh/mesh/theory/choose.py +0 -43
  89. data/ext/mesh/mesh/theory/common.py +0 -42
  90. data/ext/mesh/mesh/theory/compute_exp_Y.py +0 -134
  91. data/ext/mesh/mesh/theory/createRandomString.py +0 -69
  92. data/ext/mesh/mesh/theory/deg_bound_check.py +0 -100
  93. data/ext/mesh/mesh/theory/degcheck.py +0 -47
  94. data/ext/mesh/mesh/theory/dumps/32,1,80,dumb.txt +0 -81
  95. data/ext/mesh/mesh/theory/dumps/32,2,80,dumb.txt +0 -81
  96. data/ext/mesh/mesh/theory/dumps/32,3,80,dumb.txt +0 -81
  97. data/ext/mesh/mesh/theory/dumps/32,4,80,dumb.txt +0 -81
  98. data/ext/mesh/mesh/theory/dumps/32,5,80,dumb.txt +0 -81
  99. data/ext/mesh/mesh/theory/dumps/32,6,80,dumb.txt +0 -81
  100. data/ext/mesh/mesh/theory/dumps/32,7,80,dumb.txt +0 -81
  101. data/ext/mesh/mesh/theory/dumps/32,8,80,dumb.txt +0 -81
  102. data/ext/mesh/mesh/theory/dumps/32,9,80,dumb.txt +0 -81
  103. data/ext/mesh/mesh/theory/experiment.py +0 -303
  104. data/ext/mesh/mesh/theory/experiment_raw_results/.gitignore +0 -0
  105. data/ext/mesh/mesh/theory/greedy_experiment.py +0 -66
  106. data/ext/mesh/mesh/theory/greedy_experiment_copy.py +0 -46
  107. data/ext/mesh/mesh/theory/greedy_experiment_q.py +0 -75
  108. data/ext/mesh/mesh/theory/makeGraph.py +0 -64
  109. data/ext/mesh/mesh/theory/manyreps.png +0 -0
  110. data/ext/mesh/mesh/theory/manystrings.png +0 -0
  111. data/ext/mesh/mesh/theory/match_vs_color_experiment.py +0 -94
  112. data/ext/mesh/mesh/theory/maxmatch_vs_E[Y].py +0 -162
  113. data/ext/mesh/mesh/theory/maxmatch_vs_greedymatch.py +0 -96
  114. data/ext/mesh/mesh/theory/maxvdeg+1imp++32,80.png +0 -0
  115. data/ext/mesh/mesh/theory/mesh_util.py +0 -322
  116. data/ext/mesh/mesh/theory/meshers.py +0 -452
  117. data/ext/mesh/mesh/theory/meshingBenchmark.py +0 -96
  118. data/ext/mesh/mesh/theory/occupancyComparison.py +0 -133
  119. data/ext/mesh/mesh/theory/randmatch_vs_greedymatch.py +0 -97
  120. data/ext/mesh/mesh/theory/randmatch_vs_greedymatch_q.py +0 -103
  121. data/ext/mesh/mesh/theory/randmatch_vs_greedymatch_time.py +0 -117
  122. data/ext/mesh/mesh/theory/read_mesh_dump.py +0 -82
  123. data/ext/mesh/mesh/theory/test.py +0 -70
  124. data/ext/mesh/mesh/tools/bazel +0 -1
@@ -1,58 +0,0 @@
1
- // -*- C++ -*-
2
-
3
- #ifndef MESH_MWC64_H
4
- #define MESH_MWC64_H
5
-
6
- #include <stdint.h>
7
-
8
- #include "../common.h"
9
-
10
- class MWC64 {
11
- inline void ATTRIBUTE_ALWAYS_INLINE init(uint64_t seed1, uint64_t seed2) {
12
- _x = seed1;
13
- _x <<= 32;
14
- _x += seed2;
15
- _c = 123456123456123456ULL;
16
- _index = 2;
17
- }
18
-
19
- inline uint64_t ATTRIBUTE_ALWAYS_INLINE MWC() {
20
- _t = (_x << 58) + _c;
21
- _c = _x >> 6;
22
- _x += _t;
23
- _c += (_x < _t);
24
- return _x;
25
- }
26
-
27
- uint64_t _x;
28
- uint64_t _c;
29
- uint64_t _t;
30
- uint64_t _value;
31
- int _index;
32
-
33
- public:
34
- MWC64() {
35
- auto a = mesh::internal::seed();
36
- auto b = mesh::internal::seed();
37
- init(a, b);
38
- }
39
-
40
- MWC64(uint64_t seed1, uint64_t seed2) {
41
- init(seed1, seed2);
42
- }
43
-
44
- inline uint64_t ATTRIBUTE_ALWAYS_INLINE next() {
45
- if (_index == 2) {
46
- _value = MWC();
47
- _index = 0;
48
- }
49
- // grab either the top or bottom 32-bits of the 64-bit _value
50
- uint32_t v = ((uint32_t *)&_value)[_index];
51
- _index++;
52
- return v;
53
- }
54
- };
55
-
56
- static_assert(sizeof(MWC64) == 40, "MWC64 not expected size!");
57
-
58
- #endif
@@ -1,1991 +0,0 @@
1
- /*
2
- * Copyright (c) 1995 Patrick Powell.
3
- *
4
- * This code is based on code written by Patrick Powell <papowell@astart.com>.
5
- * It may be used for any purpose as long as this notice remains intact on all
6
- * source code distributions.
7
- */
8
-
9
- /*
10
- * Copyright (c) 2008 Holger Weiss.
11
- *
12
- * This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
13
- * My changes to the code may freely be used, modified and/or redistributed for
14
- * any purpose. It would be nice if additions and fixes to this file (including
15
- * trivial code cleanups) would be sent back in order to let me include them in
16
- * the version available at <http://www.jhweiss.de/software/snprintf.html>.
17
- * However, this is not a requirement for using or redistributing (possibly
18
- * modified) versions of this file, nor is leaving this notice intact mandatory.
19
- */
20
-
21
- /*
22
- * History
23
- *
24
- * 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
25
- *
26
- * Fixed the detection of infinite floating point values on IRIX (and
27
- * possibly other systems) and applied another few minor cleanups.
28
- *
29
- * 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
30
- *
31
- * Added a lot of new features, fixed many bugs, and incorporated various
32
- * improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
33
- * <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
34
- * <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
35
- * projects. The additions include: support the "e", "E", "g", "G", and
36
- * "F" conversion specifiers (and use conversion style "f" or "F" for the
37
- * still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
38
- * "t", and "z" length modifiers; support the "#" flag and the (non-C99)
39
- * "'" flag; use localeconv(3) (if available) to get both the current
40
- * locale's decimal point character and the separator between groups of
41
- * digits; fix the handling of various corner cases of field width and
42
- * precision specifications; fix various floating point conversion bugs;
43
- * handle infinite and NaN floating point values; don't attempt to write to
44
- * the output buffer (which may be NULL) if a size of zero was specified;
45
- * check for integer overflow of the field width, precision, and return
46
- * values and during the floating point conversion; use the OUTCHAR() macro
47
- * instead of a function for better performance; provide asprintf(3) and
48
- * vasprintf(3) functions; add new test cases. The replacement functions
49
- * have been renamed to use an "rpl_" prefix, the function calls in the
50
- * main project (and in this file) must be redefined accordingly for each
51
- * replacement function which is needed (by using Autoconf or other means).
52
- * Various other minor improvements have been applied and the coding style
53
- * was cleaned up for consistency.
54
- *
55
- * 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
56
- *
57
- * C99 compliant snprintf(3) and vsnprintf(3) functions return the number
58
- * of characters that would have been written to a sufficiently sized
59
- * buffer (excluding the '\0'). The original code simply returned the
60
- * length of the resulting output string, so that's been fixed.
61
- *
62
- * 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
63
- *
64
- * The original code assumed that both snprintf(3) and vsnprintf(3) were
65
- * missing. Some systems only have snprintf(3) but not vsnprintf(3), so
66
- * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
67
- *
68
- * 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
69
- *
70
- * The PGP code was using unsigned hexadecimal formats. Unfortunately,
71
- * unsigned formats simply didn't work.
72
- *
73
- * 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
74
- *
75
- * Ok, added some minimal floating point support, which means this probably
76
- * requires libm on most operating systems. Don't yet support the exponent
77
- * (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
78
- * wasn't being exercised in ways which showed it, so that's been fixed.
79
- * Also, formatted the code to Mutt conventions, and removed dead code left
80
- * over from the original. Also, there is now a builtin-test, run with:
81
- * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
82
- *
83
- * 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
84
- *
85
- * This was ugly. It is still ugly. I opted out of floating point
86
- * numbers, but the formatter understands just about everything from the
87
- * normal C string format, at least as far as I can tell from the Solaris
88
- * 2.5 printf(3S) man page.
89
- */
90
-
91
- /*
92
- * ToDo
93
- *
94
- * - Add wide character support.
95
- * - Add support for "%a" and "%A" conversions.
96
- * - Create test routines which predefine the expected results. Our test cases
97
- * usually expose bugs in system implementations rather than in ours :-)
98
- */
99
-
100
- /*
101
- * Usage
102
- *
103
- * 1) The following preprocessor macros should be defined to 1 if the feature or
104
- * file in question is available on the target system (by using Autoconf or
105
- * other means), though basic functionality should be available as long as
106
- * HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
107
- *
108
- * HAVE_VSNPRINTF
109
- * HAVE_SNPRINTF
110
- * HAVE_VASPRINTF
111
- * HAVE_ASPRINTF
112
- * HAVE_STDARG_H
113
- * HAVE_STDDEF_H
114
- * HAVE_STDINT_H
115
- * HAVE_STDLIB_H
116
- * HAVE_FLOAT_H
117
- * HAVE_INTTYPES_H
118
- * HAVE_LOCALE_H
119
- * HAVE_LOCALECONV
120
- * HAVE_LCONV_DECIMAL_POINT
121
- * HAVE_LCONV_THOUSANDS_SEP
122
- * HAVE_LONG_DOUBLE
123
- * HAVE_LONG_LONG_INT
124
- * HAVE_UNSIGNED_LONG_LONG_INT
125
- * HAVE_INTMAX_T
126
- * HAVE_UINTMAX_T
127
- * HAVE_UINTPTR_T
128
- * HAVE_PTRDIFF_T
129
- * HAVE_VA_COPY
130
- * HAVE___VA_COPY
131
- *
132
- * 2) The calls to the functions which should be replaced must be redefined
133
- * throughout the project files (by using Autoconf or other means):
134
- *
135
- * #define vsnprintf rpl_vsnprintf
136
- * #define snprintf rpl_snprintf
137
- * #define vasprintf rpl_vasprintf
138
- * #define asprintf rpl_asprintf
139
- *
140
- * 3) The required replacement functions should be declared in some header file
141
- * included throughout the project files:
142
- *
143
- * #if HAVE_CONFIG_H
144
- * #include <config.h>
145
- * #endif
146
- * #if HAVE_STDARG_H
147
- * #include <stdarg.h>
148
- * #if !HAVE_VSNPRINTF
149
- * int rpl_vsnprintf(char *, size_t, const char *, va_list);
150
- * #endif
151
- * #if !HAVE_SNPRINTF
152
- * int rpl_snprintf(char *, size_t, const char *, ...);
153
- * #endif
154
- * #if !HAVE_VASPRINTF
155
- * int rpl_vasprintf(char **, const char *, va_list);
156
- * #endif
157
- * #if !HAVE_ASPRINTF
158
- * int rpl_asprintf(char **, const char *, ...);
159
- * #endif
160
- * #endif
161
- *
162
- * Autoconf macros for handling step 1 and step 2 are available at
163
- * <http://www.jhweiss.de/software/snprintf.html>.
164
- */
165
-
166
- /* EMERY start */
167
- #undef HAVE_STDARG_H
168
- #define HAVE_STDARG_H 1
169
- /* EMERY end */
170
-
171
- #if HAVE_CONFIG_H
172
- #include <config.h>
173
- #endif /* HAVE_CONFIG_H */
174
-
175
- #if TEST_SNPRINTF
176
- #include <math.h> /* For pow(3), NAN, and INFINITY. */
177
- #include <string.h> /* For strcmp(3). */
178
- #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NeXT__) || defined(__bsd__)
179
- #define OS_BSD 1
180
- #elif defined(sgi) || defined(__sgi)
181
- #ifndef __c99
182
- #define __c99 /* Force C99 mode to get <stdint.h> included on IRIX 6.5.30. */
183
- #endif /* !defined(__c99) */
184
- #define OS_IRIX 1
185
- #define OS_SYSV 1
186
- #elif defined(__svr4__)
187
- #define OS_SYSV 1
188
- #elif defined(__linux__)
189
- #define OS_LINUX 1
190
- #endif /* defined(__NetBSD__) || defined(__FreeBSD__) || [...] */
191
- #if HAVE_CONFIG_H /* Undefine definitions possibly done in config.h. */
192
- #ifdef HAVE_SNPRINTF
193
- #undef HAVE_SNPRINTF
194
- #endif /* defined(HAVE_SNPRINTF) */
195
- #ifdef HAVE_VSNPRINTF
196
- #undef HAVE_VSNPRINTF
197
- #endif /* defined(HAVE_VSNPRINTF) */
198
- #ifdef HAVE_ASPRINTF
199
- #undef HAVE_ASPRINTF
200
- #endif /* defined(HAVE_ASPRINTF) */
201
- #ifdef HAVE_VASPRINTF
202
- #undef HAVE_VASPRINTF
203
- #endif /* defined(HAVE_VASPRINTF) */
204
- #ifdef snprintf
205
- #undef snprintf
206
- #endif /* defined(snprintf) */
207
- #ifdef vsnprintf
208
- #undef vsnprintf
209
- #endif /* defined(vsnprintf) */
210
- #ifdef asprintf
211
- #undef asprintf
212
- #endif /* defined(asprintf) */
213
- #ifdef vasprintf
214
- #undef vasprintf
215
- #endif /* defined(vasprintf) */
216
- #else /* By default, we assume a modern system for testing. */
217
-
218
- #ifndef HAVE_STDARG_H
219
- #define HAVE_STDARG_H 1
220
- #endif /* HAVE_STDARG_H */
221
- #ifndef HAVE_STDDEF_H
222
- #define HAVE_STDDEF_H 1
223
- #endif /* HAVE_STDDEF_H */
224
- #ifndef HAVE_STDINT_H
225
- #define HAVE_STDINT_H 1
226
- #endif /* HAVE_STDINT_H */
227
- #ifndef HAVE_STDLIB_H
228
- #define HAVE_STDLIB_H 1
229
- #endif /* HAVE_STDLIB_H */
230
- #ifndef HAVE_FLOAT_H
231
- #define HAVE_FLOAT_H 1
232
- #endif /* HAVE_FLOAT_H */
233
- #ifndef HAVE_INTTYPES_H
234
- #define HAVE_INTTYPES_H 1
235
- #endif /* HAVE_INTTYPES_H */
236
- #ifndef HAVE_LOCALE_H
237
- #define HAVE_LOCALE_H 1
238
- #endif /* HAVE_LOCALE_H */
239
- #ifndef HAVE_LOCALECONV
240
- #define HAVE_LOCALECONV 1
241
- #endif /* !defined(HAVE_LOCALECONV) */
242
- #ifndef HAVE_LCONV_DECIMAL_POINT
243
- #define HAVE_LCONV_DECIMAL_POINT 1
244
- #endif /* HAVE_LCONV_DECIMAL_POINT */
245
- #ifndef HAVE_LCONV_THOUSANDS_SEP
246
- #define HAVE_LCONV_THOUSANDS_SEP 1
247
- #endif /* HAVE_LCONV_THOUSANDS_SEP */
248
- #ifndef HAVE_LONG_DOUBLE
249
- #define HAVE_LONG_DOUBLE 1
250
- #endif /* !defined(HAVE_LONG_DOUBLE) */
251
- #ifndef HAVE_LONG_LONG_INT
252
- #define HAVE_LONG_LONG_INT 1
253
- #endif /* !defined(HAVE_LONG_LONG_INT) */
254
- #ifndef HAVE_UNSIGNED_LONG_LONG_INT
255
- #define HAVE_UNSIGNED_LONG_LONG_INT 1
256
- #endif /* !defined(HAVE_UNSIGNED_LONG_LONG_INT) */
257
- #ifndef HAVE_INTMAX_T
258
- #define HAVE_INTMAX_T 1
259
- #endif /* !defined(HAVE_INTMAX_T) */
260
- #ifndef HAVE_UINTMAX_T
261
- #define HAVE_UINTMAX_T 1
262
- #endif /* !defined(HAVE_UINTMAX_T) */
263
- #ifndef HAVE_UINTPTR_T
264
- #define HAVE_UINTPTR_T 1
265
- #endif /* !defined(HAVE_UINTPTR_T) */
266
- #ifndef HAVE_PTRDIFF_T
267
- #define HAVE_PTRDIFF_T 1
268
- #endif /* !defined(HAVE_PTRDIFF_T) */
269
- #ifndef HAVE_VA_COPY
270
- #define HAVE_VA_COPY 1
271
- #endif /* !defined(HAVE_VA_COPY) */
272
- #ifndef HAVE___VA_COPY
273
- #define HAVE___VA_COPY 1
274
- #endif /* !defined(HAVE___VA_COPY) */
275
- #endif /* HAVE_CONFIG_H */
276
- #define snprintf rpl_snprintf
277
- #define vsnprintf rpl_vsnprintf
278
- #define asprintf rpl_asprintf
279
- #define vasprintf rpl_vasprintf
280
- #endif /* TEST_SNPRINTF */
281
-
282
- #if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
283
- #include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
284
- #ifdef VA_START
285
- #undef VA_START
286
- #endif /* defined(VA_START) */
287
- #ifdef VA_SHIFT
288
- #undef VA_SHIFT
289
- #endif /* defined(VA_SHIFT) */
290
- #if 1 /* EMERY --- was HAVE_STDARG_H */
291
- #include <stdarg.h>
292
- #define VA_START(ap, last) va_start(ap, last)
293
- #define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
294
- #else /* Assume <varargs.h> is available. */
295
- #include <varargs.h>
296
- #define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
297
- #define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
298
- #endif /* HAVE_STDARG_H */
299
-
300
- #if !HAVE_VASPRINTF
301
- #if HAVE_STDLIB_H
302
- #include <stdlib.h> /* For malloc(3). */
303
- #endif /* HAVE_STDLIB_H */
304
- #ifdef VA_COPY
305
- #undef VA_COPY
306
- #endif /* defined(VA_COPY) */
307
- #ifdef VA_END_COPY
308
- #undef VA_END_COPY
309
- #endif /* defined(VA_END_COPY) */
310
- #if HAVE_VA_COPY
311
- #define VA_COPY(dest, src) va_copy(dest, src)
312
- #define VA_END_COPY(ap) va_end(ap)
313
- #elif HAVE___VA_COPY
314
- #define VA_COPY(dest, src) __va_copy(dest, src)
315
- #define VA_END_COPY(ap) va_end(ap)
316
- #else
317
- #define VA_COPY(dest, src) (void)memcpy(&dest, &src, sizeof(va_list))
318
- #define VA_END_COPY(ap) /* No-op. */
319
- #define NEED_MYMEMCPY 0
320
- // static void *mymemcpy(void *, void *, size_t);
321
- #endif /* HAVE_VA_COPY */
322
- #endif /* !HAVE_VASPRINTF */
323
-
324
- #if !HAVE_VSNPRINTF
325
- #include <errno.h> /* For ERANGE and errno. */
326
- #include <limits.h> /* For *_MAX. */
327
-
328
- #if 1 /* EMERY was ---- HAVE_FLOAT_H */
329
- #include <float.h> /* For *DBL_{MIN,MAX}_10_EXP. */
330
- #endif /* HAVE_FLOAT_H */
331
- #if HAVE_INTTYPES_H
332
- #include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
333
- #endif /* HAVE_INTTYPES_H */
334
- #if HAVE_LOCALE_H
335
- #include <locale.h> /* For localeconv(3). */
336
- #endif /* HAVE_LOCALE_H */
337
- #if HAVE_STDDEF_H
338
- #include <stddef.h> /* For ptrdiff_t. */
339
- #endif /* HAVE_STDDEF_H */
340
- #if HAVE_STDINT_H
341
- #include <stdint.h> /* For intmax_t. */
342
- #endif /* HAVE_STDINT_H */
343
-
344
- /* Support for unsigned long long int. We may also need ULLONG_MAX. */
345
- #ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
346
- #ifdef UINT_MAX
347
- #define ULONG_MAX UINT_MAX
348
- #else
349
- #define ULONG_MAX INT_MAX
350
- #endif /* defined(UINT_MAX) */
351
- #endif /* !defined(ULONG_MAX) */
352
- #ifdef ULLONG
353
- #undef ULLONG
354
- #endif /* defined(ULLONG) */
355
- #if HAVE_UNSIGNED_LONG_LONG_INT
356
- #define ULLONG unsigned long long int
357
- #ifndef ULLONG_MAX
358
- #define ULLONG_MAX ULONG_MAX
359
- #endif /* !defined(ULLONG_MAX) */
360
- #else
361
- #define ULLONG unsigned long int
362
- #ifdef ULLONG_MAX
363
- #undef ULLONG_MAX
364
- #endif /* defined(ULLONG_MAX) */
365
- #define ULLONG_MAX ULONG_MAX
366
- #endif /* HAVE_LONG_LONG_INT */
367
-
368
- /* Support for uintmax_t. We also need UINTMAX_MAX. */
369
- #ifdef UINTMAX_T
370
- #undef UINTMAX_T
371
- #endif /* defined(UINTMAX_T) */
372
- #if HAVE_UINTMAX_T || defined(uintmax_t)
373
- #define UINTMAX_T uintmax_t
374
- #ifndef UINTMAX_MAX
375
- #define UINTMAX_MAX ULLONG_MAX
376
- #endif /* !defined(UINTMAX_MAX) */
377
- #else
378
- #define UINTMAX_T ULLONG
379
- #ifdef UINTMAX_MAX
380
- #undef UINTMAX_MAX
381
- #endif /* defined(UINTMAX_MAX) */
382
- #define UINTMAX_MAX ULLONG_MAX
383
- #endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
384
-
385
- /* Support for long double. */
386
- #ifndef LDOUBLE
387
- #if HAVE_LONG_DOUBLE
388
- #define LDOUBLE long double
389
- #define LDOUBLE_MIN_10_EXP LDBL_MIN_10_EXP
390
- #define LDOUBLE_MAX_10_EXP LDBL_MAX_10_EXP
391
- #else
392
- #define LDOUBLE double
393
- #define LDOUBLE_MIN_10_EXP DBL_MIN_10_EXP
394
- #define LDOUBLE_MAX_10_EXP DBL_MAX_10_EXP
395
- #endif /* HAVE_LONG_DOUBLE */
396
- #endif /* !defined(LDOUBLE) */
397
-
398
- /* Support for long long int. */
399
- #ifndef LLONG
400
- #if HAVE_LONG_LONG_INT
401
- #define LLONG long long int
402
- #else
403
- #define LLONG long int
404
- #endif /* HAVE_LONG_LONG_INT */
405
- #endif /* !defined(LLONG) */
406
-
407
- /* Support for intmax_t. */
408
- #ifndef INTMAX_T
409
- #if HAVE_INTMAX_T || defined(intmax_t)
410
- #define INTMAX_T intmax_t
411
- #else
412
- #define INTMAX_T LLONG
413
- #endif /* HAVE_INTMAX_T || defined(intmax_t) */
414
- #endif /* !defined(INTMAX_T) */
415
-
416
- /* Support for uintptr_t. */
417
- #ifndef UINTPTR_T
418
- #if HAVE_UINTPTR_T || defined(uintptr_t)
419
- #define UINTPTR_T uintptr_t
420
- #else
421
- #define UINTPTR_T unsigned long int
422
- #endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
423
- #endif /* !defined(UINTPTR_T) */
424
-
425
- /* Support for ptrdiff_t. */
426
- #ifndef PTRDIFF_T
427
- #if HAVE_PTRDIFF_T || defined(ptrdiff_t)
428
- #define PTRDIFF_T ptrdiff_t
429
- #else
430
- #define PTRDIFF_T long int
431
- #endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
432
- #endif /* !defined(PTRDIFF_T) */
433
-
434
- /*
435
- * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
436
- * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
437
- * unsigned type if necessary. This should work just fine in practice.
438
- */
439
- #ifndef UPTRDIFF_T
440
- #define UPTRDIFF_T PTRDIFF_T
441
- #endif /* !defined(UPTRDIFF_T) */
442
-
443
- /*
444
- * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
445
- * However, we'll simply use size_t and convert it to a signed type if
446
- * necessary. This should work just fine in practice.
447
- */
448
- #ifndef SSIZE_T
449
- #define SSIZE_T size_t
450
- #endif /* !defined(SSIZE_T) */
451
-
452
- /* Either ERANGE or E2BIG should be available everywhere. */
453
- #ifndef ERANGE
454
- #define ERANGE E2BIG
455
- #endif /* !defined(ERANGE) */
456
- #ifndef EOVERFLOW
457
- #define EOVERFLOW ERANGE
458
- #endif /* !defined(EOVERFLOW) */
459
-
460
- /*
461
- * Buffer size to hold the octal string representation of UINT128_MAX without
462
- * nul-termination ("3777777777777777777777777777777777777777777").
463
- */
464
- #ifdef MAX_CONVERT_LENGTH
465
- #undef MAX_CONVERT_LENGTH
466
- #endif /* defined(MAX_CONVERT_LENGTH) */
467
- #define MAX_CONVERT_LENGTH 43
468
-
469
- /* Format read states. */
470
- #define PRINT_S_DEFAULT 0
471
- #define PRINT_S_FLAGS 1
472
- #define PRINT_S_WIDTH 2
473
- #define PRINT_S_DOT 3
474
- #define PRINT_S_PRECISION 4
475
- #define PRINT_S_MOD 5
476
- #define PRINT_S_CONV 6
477
-
478
- /* Format flags. */
479
- #define PRINT_F_MINUS (1 << 0)
480
- #define PRINT_F_PLUS (1 << 1)
481
- #define PRINT_F_SPACE (1 << 2)
482
- #define PRINT_F_NUM (1 << 3)
483
- #define PRINT_F_ZERO (1 << 4)
484
- #define PRINT_F_QUOTE (1 << 5)
485
- #define PRINT_F_UP (1 << 6)
486
- #define PRINT_F_UNSIGNED (1 << 7)
487
- #define PRINT_F_TYPE_G (1 << 8)
488
- #define PRINT_F_TYPE_E (1 << 9)
489
-
490
- /* Conversion flags. */
491
- #define PRINT_C_CHAR 1
492
- #define PRINT_C_SHORT 2
493
- #define PRINT_C_LONG 3
494
- #define PRINT_C_LLONG 4
495
- #define PRINT_C_LDOUBLE 5
496
- #define PRINT_C_SIZE 6
497
- #define PRINT_C_PTRDIFF 7
498
- #define PRINT_C_INTMAX 8
499
-
500
- #ifndef MAX
501
- #define MAX(x, y) ((x >= y) ? x : y)
502
- #endif /* !defined(MAX) */
503
- #ifndef CHARTOINT
504
- #define CHARTOINT(ch) (ch - '0')
505
- #endif /* !defined(CHARTOINT) */
506
- #ifndef ISDIGIT
507
- #define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
508
- #endif /* !defined(ISDIGIT) */
509
- #ifndef ISNAN
510
- #define ISNAN(x) (x != x)
511
- #endif /* !defined(ISNAN) */
512
- #ifndef ISINF
513
- #define ISINF(x) ((x < -1 || x > 1) && x + x == x)
514
- #endif /* !defined(ISINF) */
515
-
516
- #ifdef OUTCHAR
517
- #undef OUTCHAR
518
- #endif /* defined(OUTCHAR) */
519
- #define OUTCHAR(str, len, size, ch) \
520
- do { \
521
- if (len + 1 < size) \
522
- str[len] = ch; \
523
- (len)++; \
524
- } while (/* CONSTCOND */ 0)
525
-
526
- static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
527
- static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
528
- static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
529
- static void printsep(char *, size_t *, size_t);
530
- static int getnumsep(int);
531
- static int getexponent(LDOUBLE);
532
- static int convert(UINTMAX_T, char *, size_t, int, int);
533
- static UINTMAX_T cast(LDOUBLE);
534
- static UINTMAX_T myround(LDOUBLE);
535
- static LDOUBLE mypow10(int);
536
-
537
- extern int errno;
538
-
539
- int rpl_vsnprintf(char *str, size_t size, const char *format, va_list args) {
540
- LDOUBLE fvalue;
541
- INTMAX_T value;
542
- unsigned char cvalue;
543
- const char *strvalue;
544
- INTMAX_T *intmaxptr;
545
- PTRDIFF_T *ptrdiffptr;
546
- SSIZE_T *sizeptr;
547
- LLONG *llongptr;
548
- long int *longptr;
549
- int *intptr;
550
- short int *shortptr;
551
- signed char *charptr;
552
- size_t len = 0;
553
- int overflow = 0;
554
- int base = 0;
555
- int cflags = 0;
556
- int flags = 0;
557
- int width = 0;
558
- int precision = -1;
559
- int state = PRINT_S_DEFAULT;
560
- char ch = *format++;
561
-
562
- /*
563
- * C99 says: "If `n' is zero, nothing is written, and `s' may be a null
564
- * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
565
- * even if a size larger than zero was specified. At least NetBSD's
566
- * snprintf(3) does the same, as well as other versions of this file.
567
- * (Though some of these versions will write to a non-NULL buffer even
568
- * if a size of zero was specified, which violates the standard.)
569
- */
570
- if (str == NULL && size != 0)
571
- size = 0;
572
-
573
- while (ch != '\0')
574
- switch (state) {
575
- case PRINT_S_DEFAULT:
576
- if (ch == '%')
577
- state = PRINT_S_FLAGS;
578
- else
579
- OUTCHAR(str, len, size, ch);
580
- ch = *format++;
581
- break;
582
- case PRINT_S_FLAGS:
583
- switch (ch) {
584
- case '-':
585
- flags |= PRINT_F_MINUS;
586
- ch = *format++;
587
- break;
588
- case '+':
589
- flags |= PRINT_F_PLUS;
590
- ch = *format++;
591
- break;
592
- case ' ':
593
- flags |= PRINT_F_SPACE;
594
- ch = *format++;
595
- break;
596
- case '#':
597
- flags |= PRINT_F_NUM;
598
- ch = *format++;
599
- break;
600
- case '0':
601
- flags |= PRINT_F_ZERO;
602
- ch = *format++;
603
- break;
604
- case '\'': /* SUSv2 flag (not in C99). */
605
- flags |= PRINT_F_QUOTE;
606
- ch = *format++;
607
- break;
608
- default:
609
- state = PRINT_S_WIDTH;
610
- break;
611
- }
612
- break;
613
- case PRINT_S_WIDTH:
614
- if (ISDIGIT(ch)) {
615
- ch = CHARTOINT(ch);
616
- if (width > (INT_MAX - ch) / 10) {
617
- overflow = 1;
618
- goto out;
619
- }
620
- width = 10 * width + ch;
621
- ch = *format++;
622
- } else if (ch == '*') {
623
- /*
624
- * C99 says: "A negative field width argument is
625
- * taken as a `-' flag followed by a positive
626
- * field width." (7.19.6.1, 5)
627
- */
628
- if ((width = va_arg(args, int)) < 0) {
629
- flags |= PRINT_F_MINUS;
630
- width = -width;
631
- }
632
- ch = *format++;
633
- state = PRINT_S_DOT;
634
- } else
635
- state = PRINT_S_DOT;
636
- break;
637
- case PRINT_S_DOT:
638
- if (ch == '.') {
639
- state = PRINT_S_PRECISION;
640
- ch = *format++;
641
- } else
642
- state = PRINT_S_MOD;
643
- break;
644
- case PRINT_S_PRECISION:
645
- if (precision == -1)
646
- precision = 0;
647
- if (ISDIGIT(ch)) {
648
- ch = CHARTOINT(ch);
649
- if (precision > (INT_MAX - ch) / 10) {
650
- overflow = 1;
651
- goto out;
652
- }
653
- precision = 10 * precision + ch;
654
- ch = *format++;
655
- } else if (ch == '*') {
656
- /*
657
- * C99 says: "A negative precision argument is
658
- * taken as if the precision were omitted."
659
- * (7.19.6.1, 5)
660
- */
661
- if ((precision = va_arg(args, int)) < 0)
662
- precision = -1;
663
- ch = *format++;
664
- state = PRINT_S_MOD;
665
- } else
666
- state = PRINT_S_MOD;
667
- break;
668
- case PRINT_S_MOD:
669
- switch (ch) {
670
- case 'h':
671
- ch = *format++;
672
- if (ch == 'h') { /* It's a char. */
673
- ch = *format++;
674
- cflags = PRINT_C_CHAR;
675
- } else
676
- cflags = PRINT_C_SHORT;
677
- break;
678
- case 'l':
679
- ch = *format++;
680
- if (ch == 'l') { /* It's a long long. */
681
- ch = *format++;
682
- cflags = PRINT_C_LLONG;
683
- } else
684
- cflags = PRINT_C_LONG;
685
- break;
686
- case 'L':
687
- cflags = PRINT_C_LDOUBLE;
688
- ch = *format++;
689
- break;
690
- case 'j':
691
- cflags = PRINT_C_INTMAX;
692
- ch = *format++;
693
- break;
694
- case 't':
695
- cflags = PRINT_C_PTRDIFF;
696
- ch = *format++;
697
- break;
698
- case 'z':
699
- cflags = PRINT_C_SIZE;
700
- ch = *format++;
701
- break;
702
- }
703
- state = PRINT_S_CONV;
704
- break;
705
- case PRINT_S_CONV:
706
- switch (ch) {
707
- case 'd':
708
- /* FALLTHROUGH */
709
- case 'i':
710
- switch (cflags) {
711
- case PRINT_C_CHAR:
712
- value = (signed char)va_arg(args, int);
713
- break;
714
- case PRINT_C_SHORT:
715
- value = (short int)va_arg(args, int);
716
- break;
717
- case PRINT_C_LONG:
718
- value = va_arg(args, long int);
719
- break;
720
- case PRINT_C_LLONG:
721
- value = va_arg(args, LLONG);
722
- break;
723
- case PRINT_C_SIZE:
724
- value = va_arg(args, SSIZE_T);
725
- break;
726
- case PRINT_C_INTMAX:
727
- value = va_arg(args, INTMAX_T);
728
- break;
729
- case PRINT_C_PTRDIFF:
730
- value = va_arg(args, PTRDIFF_T);
731
- break;
732
- default:
733
- value = va_arg(args, int);
734
- break;
735
- }
736
- fmtint(str, &len, size, value, 10, width, precision, flags);
737
- break;
738
- case 'X':
739
- flags |= PRINT_F_UP;
740
- /* FALLTHROUGH */
741
- case 'x':
742
- base = 16;
743
- /* FALLTHROUGH */
744
- case 'o':
745
- if (base == 0)
746
- base = 8;
747
- /* FALLTHROUGH */
748
- case 'u':
749
- if (base == 0)
750
- base = 10;
751
- flags |= PRINT_F_UNSIGNED;
752
- switch (cflags) {
753
- case PRINT_C_CHAR:
754
- value = (unsigned char)va_arg(args, unsigned int);
755
- break;
756
- case PRINT_C_SHORT:
757
- value = (unsigned short int)va_arg(args, unsigned int);
758
- break;
759
- case PRINT_C_LONG:
760
- value = va_arg(args, unsigned long int);
761
- break;
762
- case PRINT_C_LLONG:
763
- value = va_arg(args, ULLONG);
764
- break;
765
- case PRINT_C_SIZE:
766
- value = va_arg(args, size_t);
767
- break;
768
- case PRINT_C_INTMAX:
769
- value = va_arg(args, UINTMAX_T);
770
- break;
771
- case PRINT_C_PTRDIFF:
772
- value = va_arg(args, UPTRDIFF_T);
773
- break;
774
- default:
775
- value = va_arg(args, unsigned int);
776
- break;
777
- }
778
- fmtint(str, &len, size, value, base, width, precision, flags);
779
- break;
780
- case 'A':
781
- /* Not yet supported, we'll use "%F". */
782
- /* FALLTHROUGH */
783
- case 'E':
784
- if (ch == 'E')
785
- flags |= PRINT_F_TYPE_E;
786
- /* FALLTHROUGH */
787
- case 'G':
788
- if (ch == 'G')
789
- flags |= PRINT_F_TYPE_G;
790
- /* FALLTHROUGH */
791
- case 'F':
792
- flags |= PRINT_F_UP;
793
- /* FALLTHROUGH */
794
- case 'a':
795
- /* Not yet supported, we'll use "%f". */
796
- /* FALLTHROUGH */
797
- case 'e':
798
- if (ch == 'e')
799
- flags |= PRINT_F_TYPE_E;
800
- /* FALLTHROUGH */
801
- case 'g':
802
- if (ch == 'g')
803
- flags |= PRINT_F_TYPE_G;
804
- /* FALLTHROUGH */
805
- case 'f':
806
- if (cflags == PRINT_C_LDOUBLE)
807
- fvalue = va_arg(args, LDOUBLE);
808
- else
809
- fvalue = va_arg(args, double);
810
- fmtflt(str, &len, size, fvalue, width, precision, flags, &overflow);
811
- if (overflow)
812
- goto out;
813
- break;
814
- case 'c':
815
- cvalue = va_arg(args, int);
816
- OUTCHAR(str, len, size, cvalue);
817
- break;
818
- case 's':
819
- strvalue = va_arg(args, char *);
820
- fmtstr(str, &len, size, strvalue, width, precision, flags);
821
- break;
822
- case 'p':
823
- /*
824
- * C99 says: "The value of the pointer is
825
- * converted to a sequence of printing
826
- * characters, in an implementation-defined
827
- * manner." (C99: 7.19.6.1, 8)
828
- */
829
- if ((strvalue = va_arg(args, char *)) == NULL)
830
- /*
831
- * We use the glibc format. BSD prints
832
- * "0x0", SysV "0".
833
- */
834
- fmtstr(str, &len, size, "(nil)", width, -1, flags);
835
- else {
836
- /*
837
- * We use the BSD/glibc format. SysV
838
- * omits the "0x" prefix (which we emit
839
- * using the PRINT_F_NUM flag).
840
- */
841
- flags |= PRINT_F_NUM;
842
- flags |= PRINT_F_UNSIGNED;
843
- fmtint(str, &len, size, (UINTPTR_T)strvalue, 16, width, precision, flags);
844
- }
845
- break;
846
- case 'n':
847
- switch (cflags) {
848
- case PRINT_C_CHAR:
849
- charptr = va_arg(args, signed char *);
850
- *charptr = len;
851
- break;
852
- case PRINT_C_SHORT:
853
- shortptr = va_arg(args, short int *);
854
- *shortptr = len;
855
- break;
856
- case PRINT_C_LONG:
857
- longptr = va_arg(args, long int *);
858
- *longptr = len;
859
- break;
860
- case PRINT_C_LLONG:
861
- llongptr = va_arg(args, LLONG *);
862
- *llongptr = len;
863
- break;
864
- case PRINT_C_SIZE:
865
- /*
866
- * C99 says that with the "z" length
867
- * modifier, "a following `n' conversion
868
- * specifier applies to a pointer to a
869
- * signed integer type corresponding to
870
- * size_t argument." (7.19.6.1, 7)
871
- */
872
- sizeptr = va_arg(args, SSIZE_T *);
873
- *sizeptr = len;
874
- break;
875
- case PRINT_C_INTMAX:
876
- intmaxptr = va_arg(args, INTMAX_T *);
877
- *intmaxptr = len;
878
- break;
879
- case PRINT_C_PTRDIFF:
880
- ptrdiffptr = va_arg(args, PTRDIFF_T *);
881
- *ptrdiffptr = len;
882
- break;
883
- default:
884
- intptr = va_arg(args, int *);
885
- *intptr = len;
886
- break;
887
- }
888
- break;
889
- case '%': /* Print a "%" character verbatim. */
890
- OUTCHAR(str, len, size, ch);
891
- break;
892
- default: /* Skip other characters. */
893
- break;
894
- }
895
- ch = *format++;
896
- state = PRINT_S_DEFAULT;
897
- base = cflags = flags = width = 0;
898
- precision = -1;
899
- break;
900
- }
901
- out:
902
- if (len < size)
903
- str[len] = '\0';
904
- else if (size > 0)
905
- str[size - 1] = '\0';
906
-
907
- if (overflow || len > INT_MAX) {
908
- errno = EOVERFLOW;
909
- return -1;
910
- }
911
- return (int)len;
912
- }
913
-
914
- static void fmtstr(char *str, size_t *len, size_t size, const char *value, int width, int precision, int flags) {
915
- int padlen, strln; /* Amount to pad. */
916
- int noprecision = (precision == -1);
917
-
918
- if (value == NULL) /* We're forgiving. */
919
- value = "(null)";
920
-
921
- /* If a precision was specified, don't read the string past it. */
922
- for (strln = 0; value[strln] != '\0' && (noprecision || strln < precision); strln++)
923
- continue;
924
-
925
- if ((padlen = width - strln) < 0)
926
- padlen = 0;
927
- if (flags & PRINT_F_MINUS) /* Left justify. */
928
- padlen = -padlen;
929
-
930
- while (padlen > 0) { /* Leading spaces. */
931
- OUTCHAR(str, *len, size, ' ');
932
- padlen--;
933
- }
934
- while (*value != '\0' && (noprecision || precision-- > 0)) {
935
- OUTCHAR(str, *len, size, *value);
936
- value++;
937
- }
938
- while (padlen < 0) { /* Trailing spaces. */
939
- OUTCHAR(str, *len, size, ' ');
940
- padlen++;
941
- }
942
- }
943
-
944
- static void fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, int precision, int flags) {
945
- UINTMAX_T uvalue;
946
- char iconvert[MAX_CONVERT_LENGTH];
947
- char sign = 0;
948
- char hexprefix = 0;
949
- int spadlen = 0; /* Amount to space pad. */
950
- int zpadlen = 0; /* Amount to zero pad. */
951
- int pos;
952
- int separators = (flags & PRINT_F_QUOTE);
953
- int noprecision = (precision == -1);
954
-
955
- if (flags & PRINT_F_UNSIGNED)
956
- uvalue = value;
957
- else {
958
- uvalue = (value >= 0) ? value : -value;
959
- if (value < 0)
960
- sign = '-';
961
- else if (flags & PRINT_F_PLUS) /* Do a sign. */
962
- sign = '+';
963
- else if (flags & PRINT_F_SPACE)
964
- sign = ' ';
965
- }
966
-
967
- pos = convert(uvalue, iconvert, sizeof(iconvert), base, flags & PRINT_F_UP);
968
-
969
- if (flags & PRINT_F_NUM && uvalue != 0) {
970
- /*
971
- * C99 says: "The result is converted to an `alternative form'.
972
- * For `o' conversion, it increases the precision, if and only
973
- * if necessary, to force the first digit of the result to be a
974
- * zero (if the value and precision are both 0, a single 0 is
975
- * printed). For `x' (or `X') conversion, a nonzero result has
976
- * `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
977
- */
978
- switch (base) {
979
- case 8:
980
- if (precision <= pos)
981
- precision = pos + 1;
982
- break;
983
- case 16:
984
- hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
985
- break;
986
- }
987
- }
988
-
989
- if (separators) /* Get the number of group separators we'll print. */
990
- separators = getnumsep(pos);
991
-
992
- zpadlen = precision - pos - separators;
993
- spadlen = width /* Minimum field width. */
994
- - separators /* Number of separators. */
995
- - MAX(precision, pos) /* Number of integer digits. */
996
- - ((sign != 0) ? 1 : 0) /* Will we print a sign? */
997
- - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
998
-
999
- if (zpadlen < 0)
1000
- zpadlen = 0;
1001
- if (spadlen < 0)
1002
- spadlen = 0;
1003
-
1004
- /*
1005
- * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1006
- * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
1007
- * precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
1008
- */
1009
- if (flags & PRINT_F_MINUS) /* Left justify. */
1010
- spadlen = -spadlen;
1011
- else if (flags & PRINT_F_ZERO && noprecision) {
1012
- zpadlen += spadlen;
1013
- spadlen = 0;
1014
- }
1015
- while (spadlen > 0) { /* Leading spaces. */
1016
- OUTCHAR(str, *len, size, ' ');
1017
- spadlen--;
1018
- }
1019
- if (sign != 0) /* Sign. */
1020
- OUTCHAR(str, *len, size, sign);
1021
- if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
1022
- OUTCHAR(str, *len, size, '0');
1023
- OUTCHAR(str, *len, size, hexprefix);
1024
- }
1025
- while (zpadlen > 0) { /* Leading zeros. */
1026
- OUTCHAR(str, *len, size, '0');
1027
- zpadlen--;
1028
- }
1029
- while (pos > 0) { /* The actual digits. */
1030
- pos--;
1031
- OUTCHAR(str, *len, size, iconvert[pos]);
1032
- if (separators > 0 && pos > 0 && pos % 3 == 0)
1033
- printsep(str, len, size);
1034
- }
1035
- while (spadlen < 0) { /* Trailing spaces. */
1036
- OUTCHAR(str, *len, size, ' ');
1037
- spadlen++;
1038
- }
1039
- }
1040
-
1041
- static void fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, int precision, int flags,
1042
- int *overflow) {
1043
- LDOUBLE ufvalue;
1044
- UINTMAX_T intpart;
1045
- UINTMAX_T fracpart;
1046
- UINTMAX_T mask;
1047
- const char *infnan = NULL;
1048
- char iconvert[MAX_CONVERT_LENGTH];
1049
- char fconvert[MAX_CONVERT_LENGTH];
1050
- char econvert[5]; /* "e-300" (without nul-termination). */
1051
- char esign = 0;
1052
- char sign = 0;
1053
- int leadfraczeros = 0;
1054
- int exponent = 0;
1055
- int emitpoint = 0;
1056
- int omitzeros = 0;
1057
- int omitcount = 0;
1058
- int padlen = 0;
1059
- int epos = 0;
1060
- int fpos = 0;
1061
- int ipos = 0;
1062
- int separators = (flags & PRINT_F_QUOTE);
1063
- int estyle = (flags & PRINT_F_TYPE_E);
1064
- #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1065
- struct lconv *lc = localeconv();
1066
- #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1067
-
1068
- /*
1069
- * AIX' man page says the default is 0, but C99 and at least Solaris'
1070
- * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
1071
- * defaults to 6.
1072
- */
1073
- if (precision == -1)
1074
- precision = 6;
1075
-
1076
- if (fvalue < 0.0)
1077
- sign = '-';
1078
- else if (flags & PRINT_F_PLUS) /* Do a sign. */
1079
- sign = '+';
1080
- else if (flags & PRINT_F_SPACE)
1081
- sign = ' ';
1082
-
1083
- if (ISNAN(fvalue))
1084
- infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
1085
- else if (ISINF(fvalue))
1086
- infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
1087
-
1088
- if (infnan != NULL) {
1089
- if (sign != 0)
1090
- iconvert[ipos++] = sign;
1091
- while (*infnan != '\0')
1092
- iconvert[ipos++] = *infnan++;
1093
- fmtstr(str, len, size, iconvert, width, ipos, flags);
1094
- return;
1095
- }
1096
-
1097
- /* "%e" (or "%E") or "%g" (or "%G") conversion. */
1098
- if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
1099
- if (flags & PRINT_F_TYPE_G) {
1100
- /*
1101
- * If the precision is zero, it is treated as one (cf.
1102
- * C99: 7.19.6.1, 8).
1103
- */
1104
- if (precision == 0)
1105
- precision = 1;
1106
- /*
1107
- * For "%g" (and "%G") conversions, the precision
1108
- * specifies the number of significant digits, which
1109
- * includes the digits in the integer part. The
1110
- * conversion will or will not be using "e-style" (like
1111
- * "%e" or "%E" conversions) depending on the precision
1112
- * and on the exponent. However, the exponent can be
1113
- * affected by rounding the converted value, so we'll
1114
- * leave this decision for later. Until then, we'll
1115
- * assume that we're going to do an "e-style" conversion
1116
- * (in order to get the exponent calculated). For
1117
- * "e-style", the precision must be decremented by one.
1118
- */
1119
- precision--;
1120
- /*
1121
- * For "%g" (and "%G") conversions, trailing zeros are
1122
- * removed from the fractional portion of the result
1123
- * unless the "#" flag was specified.
1124
- */
1125
- if (!(flags & PRINT_F_NUM))
1126
- omitzeros = 1;
1127
- }
1128
- exponent = getexponent(fvalue);
1129
- estyle = 1;
1130
- }
1131
-
1132
- again:
1133
- /*
1134
- * Sorry, we only support 9, 19, or 38 digits (that is, the number of
1135
- * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
1136
- * minus one) past the decimal point due to our conversion method.
1137
- */
1138
- switch (sizeof(UINTMAX_T)) {
1139
- case 16:
1140
- if (precision > 38)
1141
- precision = 38;
1142
- break;
1143
- case 8:
1144
- if (precision > 19)
1145
- precision = 19;
1146
- break;
1147
- default:
1148
- if (precision > 9)
1149
- precision = 9;
1150
- break;
1151
- }
1152
-
1153
- ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
1154
- if (estyle) /* We want exactly one integer digit. */
1155
- ufvalue /= mypow10(exponent);
1156
-
1157
- if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
1158
- *overflow = 1;
1159
- return;
1160
- }
1161
-
1162
- /*
1163
- * Factor of ten with the number of digits needed for the fractional
1164
- * part. For example, if the precision is 3, the mask will be 1000.
1165
- */
1166
- mask = mypow10(precision);
1167
- /*
1168
- * We "cheat" by converting the fractional part to integer by
1169
- * multiplying by a factor of ten.
1170
- */
1171
- if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
1172
- /*
1173
- * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
1174
- * (because precision = 3). Now, myround(1000 * 0.99962) will
1175
- * return 1000. So, the integer part must be incremented by one
1176
- * and the fractional part must be set to zero.
1177
- */
1178
- intpart++;
1179
- fracpart = 0;
1180
- if (estyle && intpart == 10) {
1181
- /*
1182
- * The value was rounded up to ten, but we only want one
1183
- * integer digit if using "e-style". So, the integer
1184
- * part must be set to one and the exponent must be
1185
- * incremented by one.
1186
- */
1187
- intpart = 1;
1188
- exponent++;
1189
- }
1190
- }
1191
-
1192
- /*
1193
- * Now that we know the real exponent, we can check whether or not to
1194
- * use "e-style" for "%g" (and "%G") conversions. If we don't need
1195
- * "e-style", the precision must be adjusted and the integer and
1196
- * fractional parts must be recalculated from the original value.
1197
- *
1198
- * C99 says: "Let P equal the precision if nonzero, 6 if the precision
1199
- * is omitted, or 1 if the precision is zero. Then, if a conversion
1200
- * with style `E' would have an exponent of X:
1201
- *
1202
- * - if P > X >= -4, the conversion is with style `f' (or `F') and
1203
- * precision P - (X + 1).
1204
- *
1205
- * - otherwise, the conversion is with style `e' (or `E') and precision
1206
- * P - 1." (7.19.6.1, 8)
1207
- *
1208
- * Note that we had decremented the precision by one.
1209
- */
1210
- if (flags & PRINT_F_TYPE_G && estyle && precision + 1 > exponent && exponent >= -4) {
1211
- precision -= exponent;
1212
- estyle = 0;
1213
- goto again;
1214
- }
1215
-
1216
- if (estyle) {
1217
- if (exponent < 0) {
1218
- exponent = -exponent;
1219
- esign = '-';
1220
- } else
1221
- esign = '+';
1222
-
1223
- /*
1224
- * Convert the exponent. The sizeof(econvert) is 5. So, the
1225
- * econvert buffer can hold e.g. "e+999" and "e-999". We don't
1226
- * support an exponent which contains more than three digits.
1227
- * Therefore, the following stores are safe.
1228
- */
1229
- epos = convert(exponent, econvert, 3, 10, 0);
1230
- /*
1231
- * C99 says: "The exponent always contains at least two digits,
1232
- * and only as many more digits as necessary to represent the
1233
- * exponent." (7.19.6.1, 8)
1234
- */
1235
- if (epos == 1)
1236
- econvert[epos++] = '0';
1237
- econvert[epos++] = esign;
1238
- econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
1239
- }
1240
-
1241
- /* Convert the integer part and the fractional part. */
1242
- ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
1243
- if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
1244
- fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
1245
-
1246
- leadfraczeros = precision - fpos;
1247
-
1248
- if (omitzeros) {
1249
- if (fpos > 0) /* Omit trailing fractional part zeros. */
1250
- while (omitcount < fpos && fconvert[omitcount] == '0')
1251
- omitcount++;
1252
- else { /* The fractional part is zero, omit it completely. */
1253
- omitcount = precision;
1254
- leadfraczeros = 0;
1255
- }
1256
- precision -= omitcount;
1257
- }
1258
-
1259
- /*
1260
- * Print a decimal point if either the fractional part is non-zero
1261
- * and/or the "#" flag was specified.
1262
- */
1263
- if (precision > 0 || flags & PRINT_F_NUM)
1264
- emitpoint = 1;
1265
- if (separators) /* Get the number of group separators we'll print. */
1266
- separators = getnumsep(ipos);
1267
-
1268
- padlen = width /* Minimum field width. */
1269
- - ipos /* Number of integer digits. */
1270
- - epos /* Number of exponent characters. */
1271
- - precision /* Number of fractional digits. */
1272
- - separators /* Number of group separators. */
1273
- - (emitpoint ? 1 : 0) /* Will we print a decimal point? */
1274
- - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
1275
-
1276
- if (padlen < 0)
1277
- padlen = 0;
1278
-
1279
- /*
1280
- * C99 says: "If the `0' and `-' flags both appear, the `0' flag is
1281
- * ignored." (7.19.6.1, 6)
1282
- */
1283
- if (flags & PRINT_F_MINUS) /* Left justifty. */
1284
- padlen = -padlen;
1285
- else if (flags & PRINT_F_ZERO && padlen > 0) {
1286
- if (sign != 0) { /* Sign. */
1287
- OUTCHAR(str, *len, size, sign);
1288
- sign = 0;
1289
- }
1290
- while (padlen > 0) { /* Leading zeros. */
1291
- OUTCHAR(str, *len, size, '0');
1292
- padlen--;
1293
- }
1294
- }
1295
- while (padlen > 0) { /* Leading spaces. */
1296
- OUTCHAR(str, *len, size, ' ');
1297
- padlen--;
1298
- }
1299
- if (sign != 0) /* Sign. */
1300
- OUTCHAR(str, *len, size, sign);
1301
- while (ipos > 0) { /* Integer part. */
1302
- ipos--;
1303
- OUTCHAR(str, *len, size, iconvert[ipos]);
1304
- if (separators > 0 && ipos > 0 && ipos % 3 == 0)
1305
- printsep(str, len, size);
1306
- }
1307
- if (emitpoint) { /* Decimal point. */
1308
- #if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
1309
- if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
1310
- OUTCHAR(str, *len, size, *lc->decimal_point);
1311
- else /* We'll always print some decimal point character. */
1312
- #endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
1313
- OUTCHAR(str, *len, size, '.');
1314
- }
1315
- while (leadfraczeros > 0) { /* Leading fractional part zeros. */
1316
- OUTCHAR(str, *len, size, '0');
1317
- leadfraczeros--;
1318
- }
1319
- while (fpos > omitcount) { /* The remaining fractional part. */
1320
- fpos--;
1321
- OUTCHAR(str, *len, size, fconvert[fpos]);
1322
- }
1323
- while (epos > 0) { /* Exponent. */
1324
- epos--;
1325
- OUTCHAR(str, *len, size, econvert[epos]);
1326
- }
1327
- while (padlen < 0) { /* Trailing spaces. */
1328
- OUTCHAR(str, *len, size, ' ');
1329
- padlen++;
1330
- }
1331
- }
1332
-
1333
- static void printsep(char *str, size_t *len, size_t size) {
1334
- #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1335
- struct lconv *lc = localeconv();
1336
- int i;
1337
-
1338
- if (lc->thousands_sep != NULL)
1339
- for (i = 0; lc->thousands_sep[i] != '\0'; i++)
1340
- OUTCHAR(str, *len, size, lc->thousands_sep[i]);
1341
- else
1342
- #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1343
- OUTCHAR(str, *len, size, ',');
1344
- }
1345
-
1346
- static int getnumsep(int digits) {
1347
- int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
1348
- #if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
1349
- int strln;
1350
- struct lconv *lc = localeconv();
1351
-
1352
- /* We support an arbitrary separator length (including zero). */
1353
- if (lc->thousands_sep != NULL) {
1354
- for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
1355
- continue;
1356
- separators *= strln;
1357
- }
1358
- #endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
1359
- return separators;
1360
- }
1361
-
1362
- static int getexponent(LDOUBLE value) {
1363
- LDOUBLE tmp = (value >= 0.0) ? value : -value;
1364
- int exponent = 0;
1365
-
1366
- /*
1367
- * We check for LDOUBLE_MAX_10_EXP >= exponent >= LDOUBLE_MIN_10_EXP in
1368
- * order to work around possible endless loops which could happen (at
1369
- * least) in the second loop (at least) if we're called with an infinite
1370
- * value. However, we checked for infinity before calling this function
1371
- * using our ISINF() macro, so this might be somewhat paranoid.
1372
- */
1373
- while (tmp < 1.0 && tmp > 0.0 && --exponent >= LDOUBLE_MIN_10_EXP)
1374
- tmp *= 10;
1375
- while (tmp >= 10.0 && ++exponent <= LDOUBLE_MAX_10_EXP)
1376
- tmp /= 10;
1377
-
1378
- return exponent;
1379
- }
1380
-
1381
- static int convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) {
1382
- const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
1383
- size_t pos = 0;
1384
-
1385
- /* We return an unterminated buffer with the digits in reverse order. */
1386
- do {
1387
- buf[pos++] = digits[value % base];
1388
- value /= base;
1389
- } while (value != 0 && pos < size);
1390
-
1391
- return (int)pos;
1392
- }
1393
-
1394
- static UINTMAX_T cast(LDOUBLE value) {
1395
- UINTMAX_T result;
1396
-
1397
- /*
1398
- * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
1399
- * represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
1400
- * it may be increased to the nearest higher representable value for the
1401
- * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
1402
- * value although converting the latter to UINTMAX_T would overflow.
1403
- */
1404
- if (value >= (LDOUBLE)UINTMAX_MAX)
1405
- return UINTMAX_MAX;
1406
-
1407
- result = value;
1408
- /*
1409
- * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
1410
- * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
1411
- * the standard). Sigh.
1412
- */
1413
- return (result <= value) ? result : result - 1;
1414
- }
1415
-
1416
- static UINTMAX_T myround(LDOUBLE value) {
1417
- UINTMAX_T intpart = cast(value);
1418
-
1419
- return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
1420
- }
1421
-
1422
- static LDOUBLE mypow10(int exponent) {
1423
- LDOUBLE result = 1;
1424
-
1425
- while (exponent > 0) {
1426
- result *= 10;
1427
- exponent--;
1428
- }
1429
- while (exponent < 0) {
1430
- result /= 10;
1431
- exponent++;
1432
- }
1433
- return result;
1434
- }
1435
- #endif /* !HAVE_VSNPRINTF */
1436
-
1437
- #if !HAVE_VASPRINTF
1438
- #if NEED_MYMEMCPY
1439
- void *mymemcpy(void *dst, void *src, size_t len) {
1440
- const char *from = src;
1441
- char *to = dst;
1442
-
1443
- /* No need for optimization, we use this only to replace va_copy(3). */
1444
- while (len-- > 0)
1445
- *to++ = *from++;
1446
- return dst;
1447
- }
1448
- #endif /* NEED_MYMEMCPY */
1449
-
1450
- #if 0
1451
- int
1452
- rpl_vasprintf(char **ret, const char *format, va_list ap)
1453
- {
1454
- size_t size;
1455
- int len;
1456
- va_list aq;
1457
-
1458
- VA_COPY(aq, ap);
1459
- len = rpl_vsnprintf(NULL, 0, format, aq);
1460
- VA_END_COPY(aq);
1461
- if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
1462
- return -1;
1463
- return rpl_vsnprintf(*ret, size, format, ap);
1464
- }
1465
- #endif
1466
-
1467
- #endif /* !HAVE_VASPRINTF */
1468
-
1469
- #if !HAVE_SNPRINTF
1470
- #if HAVE_STDARG_H
1471
- int rpl_snprintf(char *str, size_t size, const char *format, ...)
1472
- #else
1473
- int rpl_snprintf(va_alist) va_dcl
1474
- #endif /* HAVE_STDARG_H */
1475
- {
1476
- #if !HAVE_STDARG_H
1477
- char *str;
1478
- size_t size;
1479
- char *format;
1480
- #endif /* HAVE_STDARG_H */
1481
- va_list ap;
1482
- int len;
1483
-
1484
- VA_START(ap, format);
1485
- VA_SHIFT(ap, str, char *);
1486
- VA_SHIFT(ap, size, size_t);
1487
- VA_SHIFT(ap, format, const char *);
1488
- len = rpl_vsnprintf(str, size, format, ap);
1489
- va_end(ap);
1490
- return len;
1491
- }
1492
- #endif /* !HAVE_SNPRINTF */
1493
-
1494
- #if !HAVE_ASPRINTF
1495
- #if HAVE_STDARG_H
1496
- int rpl_asprintf(char **ret, const char *format, ...)
1497
- #else
1498
- int rpl_asprintf(va_alist) va_dcl
1499
- #endif /* HAVE_STDARG_H */
1500
- {
1501
- #if !HAVE_STDARG_H
1502
- char **ret;
1503
- char *format;
1504
- #endif /* HAVE_STDARG_H */
1505
- va_list ap;
1506
- int len;
1507
-
1508
- VA_START(ap, format);
1509
- VA_SHIFT(ap, ret, char **);
1510
- VA_SHIFT(ap, format, const char *);
1511
- len = vasprintf(ret, format, ap);
1512
- va_end(ap);
1513
- return len;
1514
- }
1515
- #endif /* !HAVE_ASPRINTF */
1516
- #else /* Dummy declaration to avoid empty translation unit warnings. */
1517
- int main(int argc, char **argv);
1518
- #endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
1519
-
1520
- #if TEST_SNPRINTF
1521
- int main(void) {
1522
- const char *float_fmt[] = {
1523
- /* "%E" and "%e" formats. */
1524
- #if HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX
1525
- "%.16e",
1526
- "%22.16e",
1527
- "%022.16e",
1528
- "%-22.16e",
1529
- "%#+'022.16e",
1530
- #endif /* HAVE_LONG_LONG_INT && !OS_BSD && !OS_IRIX */
1531
- "foo|%#+0123.9E|bar",
1532
- "%-123.9e",
1533
- "%123.9e",
1534
- "%+23.9e",
1535
- "%+05.8e",
1536
- "%-05.8e",
1537
- "%05.8e",
1538
- "%+5.8e",
1539
- "%-5.8e",
1540
- "% 5.8e",
1541
- "%5.8e",
1542
- "%+4.9e",
1543
- #if !OS_LINUX /* glibc sometimes gets these wrong. */
1544
- "%+#010.0e",
1545
- "%#10.1e",
1546
- "%10.5e",
1547
- "% 10.5e",
1548
- "%5.0e",
1549
- "%5.e",
1550
- "%#5.0e",
1551
- "%#5.e",
1552
- "%3.2e",
1553
- "%3.1e",
1554
- "%-1.5e",
1555
- "%1.5e",
1556
- "%01.3e",
1557
- "%1.e",
1558
- "%.1e",
1559
- "%#.0e",
1560
- "%+.0e",
1561
- "% .0e",
1562
- "%.0e",
1563
- "%#.e",
1564
- "%+.e",
1565
- "% .e",
1566
- "%.e",
1567
- "%4e",
1568
- "%e",
1569
- "%E",
1570
- #endif /* !OS_LINUX */
1571
- /* "%F" and "%f" formats. */
1572
- #if !OS_BSD && !OS_IRIX
1573
- "% '022f",
1574
- "%+'022f",
1575
- "%-'22f",
1576
- "%'22f",
1577
- #if HAVE_LONG_LONG_INT
1578
- "%.16f",
1579
- "%22.16f",
1580
- "%022.16f",
1581
- "%-22.16f",
1582
- "%#+'022.16f",
1583
- #endif /* HAVE_LONG_LONG_INT */
1584
- #endif /* !OS_BSD && !OS_IRIX */
1585
- "foo|%#+0123.9F|bar",
1586
- "%-123.9f",
1587
- "%123.9f",
1588
- "%+23.9f",
1589
- "%+#010.0f",
1590
- "%#10.1f",
1591
- "%10.5f",
1592
- "% 10.5f",
1593
- "%+05.8f",
1594
- "%-05.8f",
1595
- "%05.8f",
1596
- "%+5.8f",
1597
- "%-5.8f",
1598
- "% 5.8f",
1599
- "%5.8f",
1600
- "%5.0f",
1601
- "%5.f",
1602
- "%#5.0f",
1603
- "%#5.f",
1604
- "%+4.9f",
1605
- "%3.2f",
1606
- "%3.1f",
1607
- "%-1.5f",
1608
- "%1.5f",
1609
- "%01.3f",
1610
- "%1.f",
1611
- "%.1f",
1612
- "%#.0f",
1613
- "%+.0f",
1614
- "% .0f",
1615
- "%.0f",
1616
- "%#.f",
1617
- "%+.f",
1618
- "% .f",
1619
- "%.f",
1620
- "%4f",
1621
- "%f",
1622
- "%F",
1623
- /* "%G" and "%g" formats. */
1624
- #if !OS_BSD && !OS_IRIX && !OS_LINUX
1625
- "% '022g",
1626
- "%+'022g",
1627
- "%-'22g",
1628
- "%'22g",
1629
- #if HAVE_LONG_LONG_INT
1630
- "%.16g",
1631
- "%22.16g",
1632
- "%022.16g",
1633
- "%-22.16g",
1634
- "%#+'022.16g",
1635
- #endif /* HAVE_LONG_LONG_INT */
1636
- #endif /* !OS_BSD && !OS_IRIX && !OS_LINUX */
1637
- "foo|%#+0123.9G|bar",
1638
- "%-123.9g",
1639
- "%123.9g",
1640
- "%+23.9g",
1641
- "%+05.8g",
1642
- "%-05.8g",
1643
- "%05.8g",
1644
- "%+5.8g",
1645
- "%-5.8g",
1646
- "% 5.8g",
1647
- "%5.8g",
1648
- "%+4.9g",
1649
- #if !OS_LINUX /* glibc sometimes gets these wrong. */
1650
- "%+#010.0g",
1651
- "%#10.1g",
1652
- "%10.5g",
1653
- "% 10.5g",
1654
- "%5.0g",
1655
- "%5.g",
1656
- "%#5.0g",
1657
- "%#5.g",
1658
- "%3.2g",
1659
- "%3.1g",
1660
- "%-1.5g",
1661
- "%1.5g",
1662
- "%01.3g",
1663
- "%1.g",
1664
- "%.1g",
1665
- "%#.0g",
1666
- "%+.0g",
1667
- "% .0g",
1668
- "%.0g",
1669
- "%#.g",
1670
- "%+.g",
1671
- "% .g",
1672
- "%.g",
1673
- "%4g",
1674
- "%g",
1675
- "%G",
1676
- #endif /* !OS_LINUX */
1677
- NULL
1678
- };
1679
- double float_val[] = {
1680
- -4.136,
1681
- -134.52,
1682
- -5.04030201,
1683
- -3410.01234,
1684
- -999999.999999,
1685
- -913450.29876,
1686
- -913450.2,
1687
- -91345.2,
1688
- -9134.2,
1689
- -913.2,
1690
- -91.2,
1691
- -9.2,
1692
- -9.9,
1693
- 4.136,
1694
- 134.52,
1695
- 5.04030201,
1696
- 3410.01234,
1697
- 999999.999999,
1698
- 913450.29876,
1699
- 913450.2,
1700
- 91345.2,
1701
- 9134.2,
1702
- 913.2,
1703
- 91.2,
1704
- 9.2,
1705
- 9.9,
1706
- 9.96,
1707
- 9.996,
1708
- 9.9996,
1709
- 9.99996,
1710
- 9.999996,
1711
- 9.9999996,
1712
- 9.99999996,
1713
- 0.99999996,
1714
- 0.99999999,
1715
- 0.09999999,
1716
- 0.00999999,
1717
- 0.00099999,
1718
- 0.00009999,
1719
- 0.00000999,
1720
- 0.00000099,
1721
- 0.00000009,
1722
- 0.00000001,
1723
- 0.0000001,
1724
- 0.000001,
1725
- 0.00001,
1726
- 0.0001,
1727
- 0.001,
1728
- 0.01,
1729
- 0.1,
1730
- 1.0,
1731
- 1.5,
1732
- -1.5,
1733
- -1.0,
1734
- -0.1,
1735
- #if !OS_BSD /* BSD sometimes gets these wrong. */
1736
- #ifdef INFINITY
1737
- INFINITY,
1738
- -INFINITY,
1739
- #endif /* defined(INFINITY) */
1740
- #ifdef NAN
1741
- NAN,
1742
- #endif /* defined(NAN) */
1743
- #endif /* !OS_BSD */
1744
- 0
1745
- };
1746
- const char *long_fmt[] = {
1747
- "foo|%0123ld|bar",
1748
- #if !OS_IRIX
1749
- "% '0123ld",
1750
- "%+'0123ld",
1751
- "%-'123ld",
1752
- "%'123ld",
1753
- #endif /* !OS_IRiX */
1754
- "%123.9ld",
1755
- "% 123.9ld",
1756
- "%+123.9ld",
1757
- "%-123.9ld",
1758
- "%0123ld",
1759
- "% 0123ld",
1760
- "%+0123ld",
1761
- "%-0123ld",
1762
- "%10.5ld",
1763
- "% 10.5ld",
1764
- "%+10.5ld",
1765
- "%-10.5ld",
1766
- "%010ld",
1767
- "% 010ld",
1768
- "%+010ld",
1769
- "%-010ld",
1770
- "%4.2ld",
1771
- "% 4.2ld",
1772
- "%+4.2ld",
1773
- "%-4.2ld",
1774
- "%04ld",
1775
- "% 04ld",
1776
- "%+04ld",
1777
- "%-04ld",
1778
- "%5.5ld",
1779
- "%+22.33ld",
1780
- "%01.3ld",
1781
- "%1.5ld",
1782
- "%-1.5ld",
1783
- "%44ld",
1784
- "%4ld",
1785
- "%4.0ld",
1786
- "%4.ld",
1787
- "%.44ld",
1788
- "%.4ld",
1789
- "%.0ld",
1790
- "%.ld",
1791
- "%ld",
1792
- NULL
1793
- };
1794
- long int long_val[] = {
1795
- #ifdef LONG_MAX
1796
- LONG_MAX,
1797
- #endif /* LONG_MAX */
1798
- #ifdef LONG_MIN
1799
- LONG_MIN,
1800
- #endif /* LONG_MIN */
1801
- -91340, 91340, 341, 134, 0203, -1, 1, 0};
1802
- const char *ulong_fmt[] = {
1803
- /* "%u" formats. */
1804
- "foo|%0123lu|bar",
1805
- #if !OS_IRIX
1806
- "% '0123lu",
1807
- "%+'0123lu",
1808
- "%-'123lu",
1809
- "%'123lu",
1810
- #endif /* !OS_IRiX */
1811
- "%123.9lu",
1812
- "% 123.9lu",
1813
- "%+123.9lu",
1814
- "%-123.9lu",
1815
- "%0123lu",
1816
- "% 0123lu",
1817
- "%+0123lu",
1818
- "%-0123lu",
1819
- "%5.5lu",
1820
- "%+22.33lu",
1821
- "%01.3lu",
1822
- "%1.5lu",
1823
- "%-1.5lu",
1824
- "%44lu",
1825
- "%lu",
1826
- /* "%o" formats. */
1827
- "foo|%#0123lo|bar",
1828
- "%#123.9lo",
1829
- "%# 123.9lo",
1830
- "%#+123.9lo",
1831
- "%#-123.9lo",
1832
- "%#0123lo",
1833
- "%# 0123lo",
1834
- "%#+0123lo",
1835
- "%#-0123lo",
1836
- "%#5.5lo",
1837
- "%#+22.33lo",
1838
- "%#01.3lo",
1839
- "%#1.5lo",
1840
- "%#-1.5lo",
1841
- "%#44lo",
1842
- "%#lo",
1843
- "%123.9lo",
1844
- "% 123.9lo",
1845
- "%+123.9lo",
1846
- "%-123.9lo",
1847
- "%0123lo",
1848
- "% 0123lo",
1849
- "%+0123lo",
1850
- "%-0123lo",
1851
- "%5.5lo",
1852
- "%+22.33lo",
1853
- "%01.3lo",
1854
- "%1.5lo",
1855
- "%-1.5lo",
1856
- "%44lo",
1857
- "%lo",
1858
- /* "%X" and "%x" formats. */
1859
- "foo|%#0123lX|bar",
1860
- "%#123.9lx",
1861
- "%# 123.9lx",
1862
- "%#+123.9lx",
1863
- "%#-123.9lx",
1864
- "%#0123lx",
1865
- "%# 0123lx",
1866
- "%#+0123lx",
1867
- "%#-0123lx",
1868
- "%#5.5lx",
1869
- "%#+22.33lx",
1870
- "%#01.3lx",
1871
- "%#1.5lx",
1872
- "%#-1.5lx",
1873
- "%#44lx",
1874
- "%#lx",
1875
- "%#lX",
1876
- "%123.9lx",
1877
- "% 123.9lx",
1878
- "%+123.9lx",
1879
- "%-123.9lx",
1880
- "%0123lx",
1881
- "% 0123lx",
1882
- "%+0123lx",
1883
- "%-0123lx",
1884
- "%5.5lx",
1885
- "%+22.33lx",
1886
- "%01.3lx",
1887
- "%1.5lx",
1888
- "%-1.5lx",
1889
- "%44lx",
1890
- "%lx",
1891
- "%lX",
1892
- NULL
1893
- };
1894
- unsigned long int ulong_val[] = {
1895
- #ifdef ULONG_MAX
1896
- ULONG_MAX,
1897
- #endif /* ULONG_MAX */
1898
- 91340, 341, 134, 0203, 1, 0};
1899
- const char *llong_fmt[] = {"foo|%0123lld|bar", "%123.9lld", "% 123.9lld", "%+123.9lld", "%-123.9lld", "%0123lld",
1900
- "% 0123lld", "%+0123lld", "%-0123lld", "%5.5lld", "%+22.33lld", "%01.3lld",
1901
- "%1.5lld", "%-1.5lld", "%44lld", "%lld", NULL};
1902
- LLONG llong_val[] = {
1903
- #ifdef LLONG_MAX
1904
- LLONG_MAX,
1905
- #endif /* LLONG_MAX */
1906
- #ifdef LLONG_MIN
1907
- LLONG_MIN,
1908
- #endif /* LLONG_MIN */
1909
- -91340, 91340, 341, 134, 0203, -1, 1, 0};
1910
- const char *string_fmt[] = {
1911
- "foo|%10.10s|bar", "%-10.10s", "%10.10s", "%10.5s", "%5.10s", "%10.1s", "%1.10s", "%10.0s", "%0.10s",
1912
- "%-42.5s", "%2.s", "%.10s", "%.1s", "%.0s", "%.s", "%4s", "%s", NULL};
1913
- const char *string_val[] = {"Hello",
1914
- "Hello, world!",
1915
- "Sound check: One, two, three.",
1916
- "This string is a little longer than the other strings.",
1917
- "1",
1918
- "",
1919
- NULL};
1920
- #if !OS_SYSV /* SysV uses a different format than we do. */
1921
- const char *pointer_fmt[] = {"foo|%p|bar", "%42p", "%p", NULL};
1922
- const char *pointer_val[] = {*pointer_fmt, *string_fmt, *string_val, NULL};
1923
- #endif /* !OS_SYSV */
1924
- char buf1[1024], buf2[1024];
1925
- double value, digits = 9.123456789012345678901234567890123456789;
1926
- int i, j, r1, r2, failed = 0, num = 0;
1927
-
1928
- /*
1929
- * Use -DTEST_NILS in order to also test the conversion of nil values. Might
1930
- * segfault on systems which don't support converting a NULL pointer with "%s"
1931
- * and lets some test cases fail against BSD and glibc due to bugs in their
1932
- * implementations.
1933
- */
1934
- #ifndef TEST_NILS
1935
- #define TEST_NILS 0
1936
- #elif TEST_NILS
1937
- #undef TEST_NILS
1938
- #define TEST_NILS 1
1939
- #endif /* !defined(TEST_NILS) */
1940
- #ifdef TEST
1941
- #undef TEST
1942
- #endif /* defined(TEST) */
1943
- #define TEST(fmt, val) \
1944
- do { \
1945
- for (i = 0; fmt[i] != NULL; i++) \
1946
- for (j = 0; j == 0 || val[j - TEST_NILS] != 0; j++) { \
1947
- r1 = sprintf(buf1, fmt[i], val[j]); \
1948
- r2 = snprintf(buf2, sizeof(buf2), fmt[i], val[j]); \
1949
- if (strcmp(buf1, buf2) != 0 || r1 != r2) { \
1950
- (void)printf( \
1951
- "Results don't match, " \
1952
- "format string: %s\n" \
1953
- "\t sprintf(3): [%s] (%d)\n" \
1954
- "\tsnprintf(3): [%s] (%d)\n", \
1955
- fmt[i], buf1, r1, buf2, r2); \
1956
- failed++; \
1957
- } \
1958
- num++; \
1959
- } \
1960
- } while (/* CONSTCOND */ 0)
1961
-
1962
- #if HAVE_LOCALE_H
1963
- (void)setlocale(LC_ALL, "");
1964
- #endif /* HAVE_LOCALE_H */
1965
-
1966
- (void)puts("Testing our snprintf(3) against your system's sprintf(3).");
1967
- TEST(float_fmt, float_val);
1968
- TEST(long_fmt, long_val);
1969
- TEST(ulong_fmt, ulong_val);
1970
- TEST(llong_fmt, llong_val);
1971
- TEST(string_fmt, string_val);
1972
- #if !OS_SYSV /* SysV uses a different format than we do. */
1973
- TEST(pointer_fmt, pointer_val);
1974
- #endif /* !OS_SYSV */
1975
- (void)printf("Result: %d out of %d tests failed.\n", failed, num);
1976
-
1977
- (void)fputs("Checking how many digits we support: ", stdout);
1978
- for (i = 0; i < 100; i++) {
1979
- value = pow(10, i) * digits;
1980
- (void)sprintf(buf1, "%.1f", value);
1981
- (void)snprintf(buf2, sizeof(buf2), "%.1f", value);
1982
- if (strcmp(buf1, buf2) != 0) {
1983
- (void)printf("apparently %d.\n", i);
1984
- break;
1985
- }
1986
- }
1987
- return (failed == 0) ? 0 : 1;
1988
- }
1989
- #endif /* TEST_SNPRINTF */
1990
-
1991
- /* vim: set joinspaces noexpandtab textwidth=80 cinoptions=(4,u0: */