t_snprintb.c revision 1.13 1 1.13 rillig /* $NetBSD: t_snprintb.c,v 1.13 2024/02/14 20:51:17 rillig Exp $ */
2 1.1 jmmv
3 1.1 jmmv /*
4 1.9 rillig * Copyright (c) 2002, 2004, 2008, 2010, 2024 The NetBSD Foundation, Inc.
5 1.1 jmmv * All rights reserved.
6 1.1 jmmv *
7 1.9 rillig * This code was contributed to The NetBSD Foundation by Christos Zoulas and
8 1.9 rillig * Roland Illig.
9 1.1 jmmv *
10 1.1 jmmv * Redistribution and use in source and binary forms, with or without
11 1.1 jmmv * modification, are permitted provided that the following conditions
12 1.1 jmmv * are met:
13 1.1 jmmv * 1. Redistributions of source code must retain the above copyright
14 1.1 jmmv * notice, this list of conditions and the following disclaimer.
15 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 jmmv * notice, this list of conditions and the following disclaimer in the
17 1.1 jmmv * documentation and/or other materials provided with the distribution.
18 1.1 jmmv *
19 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 jmmv * POSSIBILITY OF SUCH DAMAGE.
30 1.1 jmmv */
31 1.1 jmmv
32 1.1 jmmv #include <sys/cdefs.h>
33 1.1 jmmv __COPYRIGHT("@(#) Copyright (c) 2008, 2010\
34 1.1 jmmv The NetBSD Foundation, inc. All rights reserved.");
35 1.13 rillig __RCSID("$NetBSD: t_snprintb.c,v 1.13 2024/02/14 20:51:17 rillig Exp $");
36 1.1 jmmv
37 1.9 rillig #include <stdio.h>
38 1.1 jmmv #include <string.h>
39 1.1 jmmv #include <util.h>
40 1.9 rillig #include <vis.h>
41 1.1 jmmv
42 1.1 jmmv #include <atf-c.h>
43 1.1 jmmv
44 1.9 rillig static const char *
45 1.10 rillig vis_arr(const char *arr, size_t arrlen)
46 1.9 rillig {
47 1.10 rillig static char buf[6][1024];
48 1.9 rillig static size_t i;
49 1.9 rillig
50 1.10 rillig i = (i + 1) % (sizeof(buf) / sizeof(buf[0]));
51 1.10 rillig int rv = strnvisx(buf[i], sizeof(buf[i]), arr, arrlen,
52 1.10 rillig VIS_WHITE | VIS_OCTAL);
53 1.10 rillig ATF_REQUIRE_MSG(rv >= 0, "strnvisx failed for length %zu", arrlen);
54 1.9 rillig return buf[i];
55 1.9 rillig }
56 1.9 rillig
57 1.1 jmmv static void
58 1.10 rillig h_snprintb_loc(const char *file, size_t line,
59 1.10 rillig size_t bufsize, const char *fmt, size_t fmtlen, uint64_t val,
60 1.10 rillig int exp_rv, const char *res, size_t reslen)
61 1.1 jmmv {
62 1.9 rillig char buf[1024];
63 1.9 rillig
64 1.10 rillig // Calling snprintb with bufsize == 0 invokes undefined
65 1.10 rillig // behavior due to out-of-range 'bp'.
66 1.10 rillig ATF_REQUIRE(bufsize > 0);
67 1.10 rillig ATF_REQUIRE(bufsize <= sizeof(buf));
68 1.10 rillig
69 1.10 rillig memset(buf, 'Z', sizeof(buf));
70 1.10 rillig int rv = snprintb(buf, bufsize, fmt, val);
71 1.10 rillig ATF_REQUIRE(rv >= 0);
72 1.10 rillig size_t rlen = rv;
73 1.1 jmmv
74 1.9 rillig ATF_CHECK_MSG(
75 1.10 rillig rv == exp_rv && memcmp(buf, res, reslen) == 0
76 1.10 rillig && buf[rlen < bufsize ? rlen : bufsize - 1] == '\0',
77 1.9 rillig "failed:\n"
78 1.9 rillig "\ttest case: %s:%zu\n"
79 1.9 rillig "\tformat: %s\n"
80 1.9 rillig "\tvalue: %#jx\n"
81 1.10 rillig "\twant: %d bytes %s\n"
82 1.10 rillig "\thave: %d bytes %s\n",
83 1.9 rillig file, line,
84 1.11 rillig vis_arr(fmt, fmtlen),
85 1.11 rillig (uintmax_t)val,
86 1.10 rillig exp_rv, vis_arr(res, reslen),
87 1.10 rillig rv, vis_arr(buf, reslen));
88 1.1 jmmv }
89 1.1 jmmv
90 1.10 rillig #define h_snprintb_len(bufsize, fmt, val, exp_rv, res) \
91 1.10 rillig h_snprintb_loc(__FILE__, __LINE__, \
92 1.10 rillig bufsize, fmt, sizeof(fmt) - 1, val, \
93 1.10 rillig exp_rv, res, sizeof(res) - 1)
94 1.9 rillig #define h_snprintb(fmt, val, res) \
95 1.10 rillig h_snprintb_len(1024, fmt, val, sizeof(res) - 1, res)
96 1.10 rillig
97 1.10 rillig static void
98 1.10 rillig h_snprintb_error_loc(const char *file, size_t line,
99 1.10 rillig const char *fmt, size_t fmtlen)
100 1.10 rillig {
101 1.10 rillig char buf[1024];
102 1.10 rillig
103 1.10 rillig memset(buf, 'Z', sizeof(buf));
104 1.10 rillig int rv = snprintb(buf, sizeof(buf), fmt, 0);
105 1.10 rillig size_t buflen = rv;
106 1.10 rillig
107 1.10 rillig ATF_REQUIRE(rv >= -1);
108 1.10 rillig ATF_CHECK_MSG(rv == -1,
109 1.10 rillig "expected error but got success:\n"
110 1.10 rillig "\ttest case: %s:%zu\n"
111 1.10 rillig "\tformat: %s\n"
112 1.10 rillig "\tresult: %zu bytes %s\n",
113 1.10 rillig file, line,
114 1.10 rillig vis_arr(fmt, fmtlen),
115 1.10 rillig buflen, vis_arr(buf, buflen));
116 1.10 rillig }
117 1.10 rillig
118 1.10 rillig #define h_snprintb_error(fmt) \
119 1.10 rillig h_snprintb_error_loc(__FILE__, __LINE__, fmt, sizeof(fmt) - 1)
120 1.9 rillig
121 1.1 jmmv ATF_TC(snprintb);
122 1.1 jmmv ATF_TC_HEAD(snprintb, tc)
123 1.1 jmmv {
124 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks snprintb(3)");
125 1.1 jmmv }
126 1.1 jmmv ATF_TC_BODY(snprintb, tc)
127 1.1 jmmv {
128 1.10 rillig
129 1.10 rillig // old-style format, octal
130 1.9 rillig h_snprintb(
131 1.9 rillig "\010"
132 1.9 rillig "\002BITTWO"
133 1.9 rillig "\001BITONE",
134 1.9 rillig 3,
135 1.9 rillig "03<BITTWO,BITONE>");
136 1.9 rillig
137 1.10 rillig // old-style format, decimal
138 1.9 rillig h_snprintb(
139 1.10 rillig "\012"
140 1.10 rillig "\0011"
141 1.10 rillig "\0119"
142 1.10 rillig "\02117"
143 1.10 rillig "\04032",
144 1.10 rillig 0xffffffff,
145 1.10 rillig "4294967295<1,9,17,32>");
146 1.10 rillig
147 1.10 rillig // old-style format, hexadecimal, from msb downto lsb
148 1.10 rillig h_snprintb(
149 1.10 rillig "\020"
150 1.10 rillig "\04032"
151 1.10 rillig "\03024"
152 1.10 rillig "\02016"
153 1.10 rillig "\0108"
154 1.10 rillig "\0077"
155 1.10 rillig "\0066"
156 1.10 rillig "\0055"
157 1.10 rillig "\0044"
158 1.10 rillig "\0033"
159 1.10 rillig "\0022"
160 1.10 rillig "\0011"
161 1.10 rillig // The old-style format supports only 32 bits, interpreting the
162 1.10 rillig // \041 as part of the text belonging to bit 1.
163 1.10 rillig "\04133",
164 1.12 rillig 0x0000ffff00ff0f35,
165 1.10 rillig "0xffff00ff0f35<24,6,5,3,1!33>");
166 1.10 rillig
167 1.10 rillig // old-style format, hexadecimal, from lsb to msb
168 1.10 rillig h_snprintb(
169 1.10 rillig "\020"
170 1.10 rillig "\0011"
171 1.10 rillig "\0022"
172 1.10 rillig "\0033"
173 1.10 rillig "\0044"
174 1.10 rillig "\0055"
175 1.10 rillig "\0066"
176 1.10 rillig "\0077"
177 1.10 rillig "\0108"
178 1.10 rillig "\02016"
179 1.10 rillig "\03024"
180 1.10 rillig "\04032"
181 1.10 rillig // The old-style format supports only 32 bits, interpreting the
182 1.10 rillig // \041 as part of the text belonging to bit 32.
183 1.10 rillig "\04133",
184 1.12 rillig 0xffff0000ff00f0ca,
185 1.10 rillig "0xffff0000ff00f0ca<2,4,7,8,16,32!33>");
186 1.10 rillig
187 1.10 rillig // The bits can be listed in arbitrary order, there can also be
188 1.10 rillig // duplicates. A bit's description can be empty, resulting in several
189 1.10 rillig // commas in a row.
190 1.10 rillig h_snprintb(
191 1.10 rillig "\020"
192 1.10 rillig "\001lsb"
193 1.10 rillig "\040msb"
194 1.10 rillig "\011"
195 1.10 rillig "\012"
196 1.10 rillig "\002above-lsb"
197 1.10 rillig "\037below-msb"
198 1.10 rillig "\001lsb-again"
199 1.10 rillig "\040msb-again",
200 1.10 rillig 0xc0000303,
201 1.10 rillig "0xc0000303<lsb,msb,,,above-lsb,below-msb,lsb-again,msb-again>");
202 1.10 rillig
203 1.10 rillig #if 0
204 1.10 rillig // If the first bit number is 33 or more, snprintb invokes undefined
205 1.10 rillig // behavior due to an out-of-bounds bit shift, though undetected by
206 1.10 rillig // -ftrapv. Later bit numbers are properly checked.
207 1.10 rillig h_snprintb(
208 1.10 rillig "\020"
209 1.10 rillig "\177undefined_behavior"
210 1.10 rillig "\001lsb",
211 1.12 rillig 0xffffffffffffffff,
212 1.10 rillig "0xffffffffffffffff<?>");
213 1.10 rillig #endif
214 1.10 rillig
215 1.10 rillig // old-style format, invalid number base 0
216 1.10 rillig h_snprintb_error(
217 1.10 rillig "");
218 1.10 rillig
219 1.10 rillig // old-style format, invalid number base 2
220 1.10 rillig h_snprintb_error(
221 1.10 rillig "\002");
222 1.10 rillig
223 1.10 rillig // old-style format, invalid number base 255 or -1
224 1.10 rillig h_snprintb_error(
225 1.10 rillig "\377");
226 1.10 rillig
227 1.10 rillig // old-style format, small buffer
228 1.10 rillig #if 0
229 1.10 rillig // FIXME: Calling snprintb with buffer size 0 invokes undefined
230 1.10 rillig // behavior due to out-of-bounds 'bp' pointer.
231 1.10 rillig h_snprintb_len(
232 1.10 rillig 0, "\020", 0,
233 1.10 rillig 1, "ZZZ");
234 1.10 rillig #endif
235 1.10 rillig h_snprintb_len(
236 1.10 rillig 1, "\020", 0,
237 1.10 rillig 1, "\0ZZZ");
238 1.10 rillig h_snprintb_len(
239 1.10 rillig 2, "\020", 0,
240 1.10 rillig 1, "0\0ZZZ");
241 1.10 rillig h_snprintb_len(
242 1.10 rillig 3, "\020", 0,
243 1.10 rillig 1, "0\0ZZZ");
244 1.10 rillig h_snprintb_len(
245 1.10 rillig 3, "\020", 7,
246 1.10 rillig 3, "0x\0ZZZ");
247 1.10 rillig h_snprintb_len(
248 1.10 rillig 4, "\020", 7,
249 1.10 rillig 3, "0x7\0ZZZ");
250 1.10 rillig h_snprintb_len(
251 1.10 rillig 7, "\020\001lsb", 7,
252 1.10 rillig 8, "0x7<ls\0ZZZ");
253 1.10 rillig h_snprintb_len(
254 1.10 rillig 8, "\020\001lsb", 7,
255 1.10 rillig 8, "0x7<lsb\0ZZZ");
256 1.10 rillig h_snprintb_len(
257 1.10 rillig 9, "\020\001lsb", 7,
258 1.10 rillig 8, "0x7<lsb>\0ZZZ");
259 1.10 rillig h_snprintb_len(
260 1.10 rillig 9, "\020\001one\002two", 7,
261 1.10 rillig 12, "0x7<one,\0ZZZ");
262 1.10 rillig h_snprintb_len(
263 1.10 rillig 10, "\020\001one\002two", 7,
264 1.10 rillig 12, "0x7<one,t\0ZZZ");
265 1.10 rillig h_snprintb_len(
266 1.10 rillig 12, "\020\001one\002two", 7,
267 1.10 rillig 12, "0x7<one,two\0ZZZ");
268 1.10 rillig h_snprintb_len(
269 1.10 rillig 13, "\020\001one\002two", 7,
270 1.10 rillig 12, "0x7<one,two>\0ZZZ");
271 1.10 rillig
272 1.10 rillig // new-style format, single bits, octal
273 1.10 rillig h_snprintb(
274 1.10 rillig "\177\010"
275 1.10 rillig "b\000bit0\0"
276 1.10 rillig "b\037bit31\0"
277 1.10 rillig "b\040bit32\0"
278 1.10 rillig "b\077bit63\0",
279 1.12 rillig 0xf000000ff000000f,
280 1.10 rillig "01700000000776000000017<bit0,bit31,bit32,bit63>");
281 1.10 rillig
282 1.10 rillig // new-style format, single bits, decimal
283 1.10 rillig h_snprintb(
284 1.10 rillig "\177\012"
285 1.10 rillig "b\000bit0\0"
286 1.10 rillig "b\037bit31\0"
287 1.10 rillig "b\040bit32\0"
288 1.10 rillig "b\077bit63\0",
289 1.12 rillig 0xf000000ff000000f,
290 1.10 rillig "17293822637553745935<bit0,bit31,bit32,bit63>");
291 1.9 rillig
292 1.10 rillig // new-style format, single bits, hexadecimal
293 1.10 rillig h_snprintb(
294 1.10 rillig "\177\020"
295 1.10 rillig "b\000bit0\0"
296 1.10 rillig "b\037bit31\0"
297 1.10 rillig "b\040bit32\0"
298 1.10 rillig "b\077bit63\0",
299 1.12 rillig 0xf000000ff000000f,
300 1.10 rillig "0xf000000ff000000f<bit0,bit31,bit32,bit63>");
301 1.10 rillig
302 1.10 rillig // new-style format, invalid number base 2
303 1.10 rillig h_snprintb_error(
304 1.10 rillig "\177\002");
305 1.10 rillig
306 1.10 rillig // new-style format, invalid number base 255 or -1
307 1.10 rillig h_snprintb_error(
308 1.10 rillig "\177\377");
309 1.10 rillig
310 1.10 rillig // new-style format, single bits, edge cases
311 1.10 rillig //
312 1.10 rillig // The bits can be listed in arbitrary order, there can also be
313 1.10 rillig // duplicates. A bit's description can be empty, resulting in several
314 1.10 rillig // commas in a row.
315 1.9 rillig h_snprintb(
316 1.9 rillig "\177\020"
317 1.10 rillig "b\01lsb\0"
318 1.10 rillig "b\02\0"
319 1.10 rillig "b\03\0"
320 1.9 rillig "b\05NOTBOOT\0"
321 1.9 rillig "b\06FPP\0"
322 1.9 rillig "b\13SDVMA\0"
323 1.9 rillig "b\15VIDEO\0"
324 1.9 rillig "b\20LORES\0"
325 1.9 rillig "b\21FPA\0"
326 1.9 rillig "b\22DIAG\0"
327 1.9 rillig "b\16CACHE\0"
328 1.9 rillig "b\17IOCACHE\0"
329 1.9 rillig "b\22LOOPBACK\0"
330 1.9 rillig "b\04DBGCACHE\0",
331 1.10 rillig 0xe86f,
332 1.10 rillig "0xe86f<lsb,,,NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
333 1.10 rillig
334 1.10 rillig // new-style format, octal, named bit-field
335 1.10 rillig h_snprintb(
336 1.10 rillig "\177\010"
337 1.10 rillig "f\010\004Field\0"
338 1.10 rillig "=\001one\0"
339 1.10 rillig "=\002two\0",
340 1.10 rillig 0x100,
341 1.10 rillig "0400<Field=01=one>");
342 1.10 rillig
343 1.10 rillig // new-style format, decimal, named bit-field
344 1.10 rillig h_snprintb(
345 1.10 rillig "\177\012"
346 1.10 rillig "f\010\004Field\0"
347 1.10 rillig "=\1one\0"
348 1.10 rillig "=\2two\0",
349 1.10 rillig 0x100,
350 1.10 rillig "256<Field=1=one>");
351 1.10 rillig
352 1.10 rillig // new-style format, hexadecimal, named bit-field
353 1.10 rillig h_snprintb(
354 1.10 rillig "\177\020"
355 1.10 rillig "f\010\004Field\0"
356 1.10 rillig "=\1one\0"
357 1.10 rillig "=\2two\0",
358 1.10 rillig 0x100,
359 1.10 rillig "0x100<Field=0x1=one>");
360 1.10 rillig
361 1.10 rillig // new-style format, octal, unnamed bit-field
362 1.10 rillig h_snprintb(
363 1.10 rillig "\177\010"
364 1.10 rillig "F\010\004Field\0"
365 1.10 rillig ":\001one\0"
366 1.10 rillig ":\002two\0",
367 1.10 rillig 0x100,
368 1.10 rillig "0400<one>");
369 1.10 rillig
370 1.10 rillig // new-style format, decimal, unnamed bit-field
371 1.10 rillig h_snprintb(
372 1.10 rillig "\177\012"
373 1.10 rillig "F\010\004Field\0"
374 1.10 rillig ":\1one\0"
375 1.10 rillig ":\2two\0",
376 1.10 rillig 0x100,
377 1.10 rillig "256<one>");
378 1.9 rillig
379 1.10 rillig // new-style format, hexadecimal, unnamed bit-field
380 1.9 rillig h_snprintb(
381 1.10 rillig "\177\020"
382 1.10 rillig "F\010\004Field\0"
383 1.10 rillig ":\1one\0"
384 1.10 rillig ":\2two\0",
385 1.10 rillig 0x100,
386 1.10 rillig "0x100<one>");
387 1.10 rillig
388 1.10 rillig // new-style format, hexadecimal, named bit-field, edge cases
389 1.10 rillig //
390 1.10 rillig // Field values can be listed in arbitrary order, there can also be
391 1.10 rillig // duplicates. A field value's description can be empty, resulting in
392 1.10 rillig // several '=' in a row. The ':' directive can emulate the '='
393 1.10 rillig // directive, but not vice versa.
394 1.10 rillig h_snprintb(
395 1.10 rillig "\177\20"
396 1.10 rillig "f\0\4Field\0"
397 1.10 rillig "=\1one\0"
398 1.10 rillig "=\1one-again\0"
399 1.10 rillig "=\1\0"
400 1.10 rillig "=\1\0"
401 1.10 rillig ":\1double\0"
402 1.10 rillig ":\1-colon\0"
403 1.10 rillig ":\1=equal\0"
404 1.9 rillig "=\2TWO\0",
405 1.9 rillig 1,
406 1.10 rillig "0x1<Field=0x1=one=one-again==double-colon=equal>");
407 1.10 rillig
408 1.10 rillig // new-style format, hexadecimal, unnamed bit-field, edge cases
409 1.10 rillig //
410 1.10 rillig // Combining the 'F' and '=' directives generates output that doesn't
411 1.10 rillig // look well-formed.
412 1.10 rillig h_snprintb(
413 1.10 rillig "\177\20"
414 1.10 rillig "=\0all-zero\0"
415 1.10 rillig "=\1all-one\0"
416 1.10 rillig ":\1-continued\0"
417 1.10 rillig "F\0\4Field\0"
418 1.10 rillig "=\1one\0"
419 1.10 rillig "=\1one-again\0"
420 1.10 rillig "=\1\0"
421 1.10 rillig "=\1\0"
422 1.10 rillig ":\1double\0"
423 1.10 rillig ":\1-colon\0"
424 1.10 rillig ":\1=equal\0"
425 1.9 rillig "=\2TWO\0",
426 1.9 rillig 1,
427 1.10 rillig "0x1=all-one-continued<=one=one-again==double-colon=equal>");
428 1.10 rillig
429 1.10 rillig // new-style format, bit-fields with fixed fallback value
430 1.10 rillig //
431 1.10 rillig // Only the first fallback value is used, all others are ignored.
432 1.9 rillig h_snprintb(
433 1.10 rillig "\177\020"
434 1.10 rillig "f\0\4Field\0"
435 1.10 rillig "=\1one\0"
436 1.10 rillig "=\2two\0"
437 1.10 rillig "*=other\0"
438 1.10 rillig "*=yet-another\0"
439 1.10 rillig "b\1separator\0"
440 1.10 rillig "F\0\4Field\0"
441 1.10 rillig ":\1one\0"
442 1.10 rillig ":\2two\0"
443 1.10 rillig "*other\0"
444 1.10 rillig "*yet-another\0",
445 1.10 rillig 3,
446 1.10 rillig "0x3<Field=0x3=other,separator,other>");
447 1.5 ryo
448 1.10 rillig // new-style format, bit-fields with numeric fallback value
449 1.9 rillig h_snprintb(
450 1.10 rillig "\177\020"
451 1.10 rillig "f\010\004Field\0"
452 1.10 rillig "*=other(%04ju)\0"
453 1.10 rillig "b\000separator\0"
454 1.10 rillig "F\010\004Field\0"
455 1.10 rillig "*other(%04ju)\0",
456 1.10 rillig 0x301,
457 1.10 rillig "0x301<Field=0x3=other(0003),separator,other(0003)>");
458 1.10 rillig
459 1.10 rillig // new-style format, bit-field with more than 8 bits
460 1.10 rillig //
461 1.10 rillig // The '=' and ':' directives can only match values from 0 to 255, so
462 1.10 rillig // the fallback value always steps in. The complete value of the
463 1.10 rillig // bit-field appears in the output, though.
464 1.9 rillig h_snprintb(
465 1.9 rillig "\177\020"
466 1.10 rillig "f\010\020Field\0"
467 1.10 rillig "=\377ones\0"
468 1.10 rillig "*=other(%jx)\0"
469 1.10 rillig "F\010\020\0"
470 1.10 rillig ":\377ones\0"
471 1.10 rillig "*other(%jx)\0",
472 1.10 rillig 0x77ff55,
473 1.10 rillig "0x77ff55<Field=0x77ff=other(77ff),other(77ff)>");
474 1.6 kre
475 1.10 rillig // new-style format, bit-fields with no match
476 1.9 rillig h_snprintb(
477 1.10 rillig "\177\020"
478 1.10 rillig "f\010\004Field\0"
479 1.10 rillig "=\1one\0"
480 1.10 rillig "=\2two\0",
481 1.10 rillig 0x301,
482 1.10 rillig "0x301<Field=0x3>");
483 1.9 rillig h_snprintb(
484 1.10 rillig "\177\020"
485 1.10 rillig "F\010\004\0"
486 1.10 rillig ":\1one\0"
487 1.10 rillig ":\2two\0",
488 1.10 rillig 0x301,
489 1.10 rillig "0x301<>");
490 1.9 rillig h_snprintb(
491 1.9 rillig "\177\020"
492 1.10 rillig "f\010\004Field\0"
493 1.10 rillig "=\1one\0"
494 1.10 rillig "=\2two\0"
495 1.10 rillig "b\000separator\0"
496 1.10 rillig "F\010\004\0"
497 1.10 rillig ":\1one\0"
498 1.10 rillig ":\2two\0",
499 1.10 rillig 0x301,
500 1.10 rillig "0x301<Field=0x3,separator,>");
501 1.6 kre
502 1.10 rillig // new-style format, two separate bit-fields
503 1.9 rillig h_snprintb(
504 1.9 rillig "\177\20"
505 1.9 rillig "f\0\4Field_1\0"
506 1.9 rillig "=\1ONE\0"
507 1.9 rillig "=\2TWO\0"
508 1.9 rillig "f\4\4Field_2\0"
509 1.9 rillig "=\1ONE\0"
510 1.9 rillig "=\2TWO\0",
511 1.9 rillig 0x12,
512 1.6 kre "0x12<Field_1=0x2=TWO,Field_2=0x1=ONE>");
513 1.6 kre
514 1.10 rillig // new-style format, mixed named and unnamed bit-fields
515 1.9 rillig h_snprintb(
516 1.9 rillig "\177\20"
517 1.9 rillig "f\0\4Field_1\0"
518 1.9 rillig "=\1ONE\0"
519 1.9 rillig "=\2TWO\0"
520 1.9 rillig "F\x8\4\0"
521 1.9 rillig "*Field_3=%jd\0"
522 1.9 rillig "f\4\4Field_2\0"
523 1.9 rillig ":\1:ONE\0"
524 1.9 rillig ":\2:TWO\0",
525 1.9 rillig 0xD12,
526 1.6 kre "0xd12<Field_1=0x2=TWO,Field_3=13,Field_2=0x1:ONE>");
527 1.9 rillig
528 1.10 rillig // new-style format, descriptions with spaces
529 1.10 rillig h_snprintb(
530 1.10 rillig "\177\020"
531 1.10 rillig "b\000has std options\0"
532 1.10 rillig "f\010\004std options\0"
533 1.10 rillig "=\000no options\0"
534 1.10 rillig "=\017all options\0"
535 1.10 rillig "F\020\004ext options\0"
536 1.10 rillig ":\000no ext options\0"
537 1.10 rillig ":\017all ext options\0",
538 1.10 rillig 0x000001,
539 1.10 rillig "0x1<has std options,std options=0=no options,no ext options>");
540 1.10 rillig h_snprintb(
541 1.10 rillig "\177\020"
542 1.10 rillig "f\010\004std options\0"
543 1.10 rillig "*=other std options\0"
544 1.10 rillig "F\020\004ext\toptions\0"
545 1.10 rillig "*other\text\toptions\0",
546 1.10 rillig 0x000001,
547 1.10 rillig "0x1<std options=0=other std options,other\text\toptions>");
548 1.10 rillig
549 1.9 rillig // It is possible but cumbersome to implement a reduced variant of
550 1.9 rillig // rot13 using snprintb, shown here for lowercase letters only.
551 1.9 rillig for (char ch = 'A'; ch <= '~'; ch++) {
552 1.9 rillig char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
553 1.9 rillig : ch >= 'n' && ch <= 'z' ? ch - 13
554 1.9 rillig : '?';
555 1.9 rillig char expected[8];
556 1.9 rillig ATF_REQUIRE_EQ(7,
557 1.9 rillig snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
558 1.9 rillig h_snprintb(
559 1.9 rillig "\177\020"
560 1.9 rillig "F\000\010\0"
561 1.9 rillig ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
562 1.9 rillig ":iv\0:jw\0:kx\0:ly\0:mz\0"
563 1.9 rillig ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
564 1.9 rillig ":vi\0:wj\0:xk\0:yl\0:zm\0"
565 1.9 rillig // If snprintf accepted "%jc", it would be possible to
566 1.9 rillig // echo the non-alphabetic characters instead of a
567 1.9 rillig // catchall question mark.
568 1.9 rillig "*?\0",
569 1.9 rillig ch,
570 1.9 rillig expected);
571 1.9 rillig }
572 1.1 jmmv }
573 1.1 jmmv
574 1.2 pgoyette static void
575 1.10 rillig h_snprintb_m_loc(const char *file, size_t line,
576 1.13 rillig size_t bufsize, const char *fmt, size_t fmtlen, uint64_t val, size_t max,
577 1.13 rillig size_t exp_rv, const char *res, size_t reslen)
578 1.2 pgoyette {
579 1.2 pgoyette char buf[1024];
580 1.2 pgoyette
581 1.13 rillig ATF_REQUIRE(bufsize > 1);
582 1.13 rillig ATF_REQUIRE(bufsize <= sizeof(buf));
583 1.2 pgoyette
584 1.13 rillig memset(buf, 'Z', sizeof(buf));
585 1.13 rillig int rv = snprintb_m(buf, bufsize, fmt, val, max);
586 1.13 rillig ATF_REQUIRE_MSG(rv >= 0,
587 1.13 rillig "formatting %jx with '%s' returns error %d",
588 1.10 rillig (uintmax_t)val, vis_arr(fmt, fmtlen), rv);
589 1.9 rillig
590 1.13 rillig size_t total = rv;
591 1.9 rillig ATF_CHECK_MSG(
592 1.13 rillig total == exp_rv && memcmp(buf, res, reslen) == 0,
593 1.9 rillig "failed:\n"
594 1.9 rillig "\ttest case: %s:%zu\n"
595 1.9 rillig "\tformat: %s\n"
596 1.9 rillig "\tvalue: %#jx\n"
597 1.13 rillig "\tmax: %zu\n"
598 1.9 rillig "\twant: %zu bytes %s\n"
599 1.9 rillig "\thave: %zu bytes %s\n",
600 1.9 rillig file, line,
601 1.11 rillig vis_arr(fmt, fmtlen),
602 1.11 rillig (uintmax_t)val,
603 1.13 rillig max,
604 1.13 rillig exp_rv, vis_arr(res, reslen),
605 1.13 rillig total, vis_arr(buf, reslen));
606 1.2 pgoyette }
607 1.2 pgoyette
608 1.13 rillig #define h_snprintb_m_len(bufsize, fmt, val, line_max, exp_rv, res) \
609 1.10 rillig h_snprintb_m_loc(__FILE__, __LINE__, \
610 1.13 rillig bufsize, fmt, sizeof(fmt) - 1, val, line_max, \
611 1.13 rillig exp_rv, res, sizeof(res) - 1)
612 1.13 rillig #define h_snprintb_m(fmt, val, max, res) \
613 1.13 rillig h_snprintb_m_len(1024, fmt, val, max, sizeof(res) - 1, res)
614 1.9 rillig
615 1.2 pgoyette ATF_TC(snprintb_m);
616 1.2 pgoyette ATF_TC_HEAD(snprintb_m, tc)
617 1.2 pgoyette {
618 1.2 pgoyette atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
619 1.2 pgoyette }
620 1.2 pgoyette ATF_TC_BODY(snprintb_m, tc)
621 1.2 pgoyette {
622 1.13 rillig // old-style format, small maximum line length
623 1.13 rillig h_snprintb_m_len(
624 1.13 rillig 68,
625 1.13 rillig "\020"
626 1.13 rillig "\001bit1"
627 1.13 rillig "\002bit2"
628 1.13 rillig "\003bit3",
629 1.13 rillig 0xffff,
630 1.13 rillig 6,
631 1.13 rillig 143,
632 1.13 rillig /* 0 */ "0xffff>\0"
633 1.13 rillig /* 8 */ "0xffff<>\0"
634 1.13 rillig /* 17 */ "0xffffb>\0"
635 1.13 rillig /* 26 */ "0xffffi>\0"
636 1.13 rillig /* 35 */ "0xfffft>\0"
637 1.13 rillig /* 44 */ "0xffff1>\0"
638 1.13 rillig /* 53 */ "0xffff<>\0"
639 1.13 rillig /* 62 */ "0xff\0"
640 1.13 rillig /* 67 */ "ZZZ"
641 1.13 rillig /* 70 */ "ZZZZZZZZZZ"
642 1.13 rillig /* 80 */ "ZZZZZZZZZZ"
643 1.13 rillig /* 90 */ "ZZZZZZZZZZ"
644 1.13 rillig /* 100 */ "ZZZZZZZZZZ"
645 1.13 rillig /* 110 */ "ZZZZZZ"
646 1.13 rillig /* 116 */ "\0\0" /* FIXME: out-of-bounds write */
647 1.13 rillig /* 118 */ "ZZ"
648 1.13 rillig /* 120 */ "ZZZZZZZZZZ"
649 1.13 rillig /* 130 */ "ZZZZZZZZZZ"
650 1.13 rillig /* 140 */ "ZZZZZZZZZZ"
651 1.13 rillig );
652 1.13 rillig
653 1.13 rillig // new-style format, small maximum line length
654 1.13 rillig h_snprintb_m_len(
655 1.13 rillig 68,
656 1.13 rillig "\177\020"
657 1.13 rillig "b\000bit1\0"
658 1.13 rillig "b\001bit2\0"
659 1.13 rillig "b\002bit3\0",
660 1.13 rillig 0xffff,
661 1.13 rillig 6,
662 1.13 rillig 143,
663 1.13 rillig /* 0 */ "0xffff>\0"
664 1.13 rillig /* 8 */ "0xffff<>\0"
665 1.13 rillig /* 17 */ "0xffffb>\0"
666 1.13 rillig /* 26 */ "0xffffi>\0"
667 1.13 rillig /* 35 */ "0xfffft>\0"
668 1.13 rillig /* 44 */ "0xffff1>\0"
669 1.13 rillig /* 53 */ "0xffff<>\0"
670 1.13 rillig /* 62 */ "0xff\0"
671 1.13 rillig /* 67 */ "ZZZ"
672 1.13 rillig /* 70 */ "ZZZZZZZZZZ"
673 1.13 rillig /* 80 */ "ZZZZZZZZZZ"
674 1.13 rillig /* 90 */ "ZZZZZZZZZZ"
675 1.13 rillig /* 100 */ "ZZZZZZZZZZ"
676 1.13 rillig /* 110 */ "ZZZZZZ"
677 1.13 rillig /* 116 */ "\0\0" /* FIXME: out-of-bounds write */
678 1.13 rillig /* 118 */ "ZZ"
679 1.13 rillig /* 120 */ "ZZZZZZZZZZ"
680 1.13 rillig /* 130 */ "ZZZZZZZZZZ"
681 1.13 rillig /* 140 */ "ZZZZZZZZZZ"
682 1.13 rillig );
683 1.13 rillig
684 1.9 rillig h_snprintb_m(
685 1.9 rillig "\177\020"
686 1.9 rillig "b\0LSB\0"
687 1.9 rillig "b\1_BITONE\0"
688 1.9 rillig "f\4\4NIBBLE2\0"
689 1.9 rillig "f\x10\4BURST\0"
690 1.9 rillig "=\04FOUR\0"
691 1.9 rillig "=\17FIFTEEN\0"
692 1.9 rillig "b\x1fMSB\0",
693 1.9 rillig 0x800f0701,
694 1.9 rillig 33,
695 1.9 rillig "0x800f0701<LSB,NIBBLE2=0>\0"
696 1.9 rillig "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
697 1.9 rillig
698 1.9 rillig h_snprintb_m(
699 1.9 rillig "\177\020"
700 1.9 rillig "b\0LSB\0"
701 1.9 rillig "b\1_BITONE\0"
702 1.9 rillig "f\4\4NIBBLE2\0"
703 1.9 rillig "f\x10\4BURST\0"
704 1.9 rillig "=\04FOUR\0"
705 1.9 rillig "=\17FIFTEEN\0"
706 1.9 rillig "b\x1fMSB\0",
707 1.9 rillig 0x800f0701,
708 1.9 rillig 32,
709 1.9 rillig "0x800f0701<LSB,NIBBLE2=0>\0"
710 1.9 rillig "0x800f0701<BURST=0xf=FIFTEEN>\0"
711 1.9 rillig "0x800f0701<MSB>\0");
712 1.2 pgoyette }
713 1.2 pgoyette
714 1.1 jmmv ATF_TP_ADD_TCS(tp)
715 1.1 jmmv {
716 1.1 jmmv
717 1.1 jmmv ATF_TP_ADD_TC(tp, snprintb);
718 1.2 pgoyette ATF_TP_ADD_TC(tp, snprintb_m);
719 1.1 jmmv
720 1.1 jmmv return atf_no_error();
721 1.1 jmmv }
722