xref: /netbsd-src/tests/lib/libutil/t_snprintb.c (revision 835080d5e678e165a8c64b1ec4e616adde88537c)
1 /* $NetBSD: t_snprintb.c,v 1.36 2024/04/08 21:28:35 rillig Exp $ */
2 
3 /*
4  * Copyright (c) 2002, 2004, 2008, 2010, 2024 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code was contributed to The NetBSD Foundation by Christos Zoulas and
8  * Roland Illig.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __COPYRIGHT("@(#) Copyright (c) 2008, 2010, 2024\
34  The NetBSD Foundation, inc. All rights reserved.");
35 __RCSID("$NetBSD: t_snprintb.c,v 1.36 2024/04/08 21:28:35 rillig Exp $");
36 
37 #include <stdio.h>
38 #include <string.h>
39 #include <util.h>
40 #include <vis.h>
41 
42 #include <atf-c.h>
43 
44 static const char *
45 vis_arr(char *buf, size_t bufsize, const char *arr, size_t arrsize)
46 {
47 	ATF_REQUIRE(bufsize >= 2);
48 	int rv = strnvisx(buf + 1, bufsize - 2, arr, arrsize,
49 	    VIS_WHITE | VIS_OCTAL);
50 	ATF_REQUIRE_MSG(rv >= 0, "buffer too small for size %zu", arrsize);
51 	buf[0] = '"';
52 	buf[1 + rv] = '"';
53 	buf[1 + rv + 1] = '\0';
54 	return buf;
55 }
56 
57 static void
58 check_snprintb_m(const char *file, size_t line,
59     size_t bufsize, const char *bitfmt, size_t bitfmtlen, uint64_t val,
60     size_t line_max,
61     int want_rv, const char *want_buf, size_t want_bufsize)
62 {
63 	char buf[1024], vis_bitfmt[1024], vis_want_buf[1024], vis_buf[1024];
64 
65 	ATF_REQUIRE(bufsize <= sizeof(buf));
66 	ATF_REQUIRE(want_bufsize <= sizeof(buf));
67 	if (bitfmtlen > 2 && bitfmt[0] == '\177')
68 		ATF_REQUIRE_MSG(
69 		    bitfmt[bitfmtlen - 1] == '\0',
70 		    "%s:%zu: missing trailing '\\0' in new-style bitfmt",
71 		    file, line);
72 	if (bufsize == 0)
73 		want_bufsize = 0;
74 	memset(buf, 0x5a, sizeof(buf));
75 
76 	int rv = snprintb_m(buf, bufsize, bitfmt, val, line_max);
77 
78 	size_t have_bufsize = sizeof(buf);
79 	while (have_bufsize > 0 && buf[have_bufsize - 1] == 0x5a)
80 		have_bufsize--;
81 	if (rv > 0 && (unsigned)rv < have_bufsize
82 	    && buf[rv - 1] == '\0' && buf[rv] == '\0')
83 		have_bufsize = rv + 1;
84 	if (rv < 0)
85 		for (size_t i = have_bufsize; i >= 2; i--)
86 			if (buf[i - 2] == '\0' && buf[i - 1] == '\0')
87 				have_bufsize = i;
88 
89 	ATF_CHECK_MSG(
90 	    rv == want_rv
91 	    && memcmp(buf, want_buf, want_bufsize) == 0
92 	    && (line_max == 0 || have_bufsize < 2
93 		|| buf[have_bufsize - 2] == '\0')
94 	    && (have_bufsize < 1 || buf[have_bufsize - 1] == '\0'),
95 	    "failed:\n"
96 	    "\ttest case: %s:%zu\n"
97 	    "\tformat: %s\n"
98 	    "\tvalue: %#jx\n"
99 	    "\tline_max: %zu\n"
100 	    "\twant: %d bytes %s\n"
101 	    "\thave: %d bytes %s\n",
102 	    file, line,
103 	    vis_arr(vis_bitfmt, sizeof(vis_bitfmt), bitfmt, bitfmtlen),
104 	    (uintmax_t)val,
105 	    line_max,
106 	    want_rv, vis_arr(vis_want_buf, sizeof(vis_want_buf),
107 		want_buf, want_bufsize),
108 	    rv, vis_arr(vis_buf, sizeof(vis_buf), buf, have_bufsize));
109 }
110 
111 #define	h_snprintb_m_len(bufsize, bitfmt, val, line_max,		\
112 	    want_rv, want_buf)						\
113 	check_snprintb_m(__FILE__, __LINE__,				\
114 	    bufsize, bitfmt, sizeof(bitfmt) - 1, val, line_max,		\
115 	    want_rv, want_buf, sizeof(want_buf))
116 
117 #define	h_snprintb(bitfmt, val, want_buf)				\
118 	h_snprintb_m_len(1024, bitfmt, val, 0, sizeof(want_buf) - 1, want_buf)
119 
120 #define	h_snprintb_len(bufsize, bitfmt, val, want_rv, want_buf)		\
121 	h_snprintb_m_len(bufsize, bitfmt, val, 0, want_rv, want_buf)
122 
123 #define	h_snprintb_error(bitfmt, want_buf)				\
124 	h_snprintb_m_len(1024, bitfmt, 0x00, 0, -1, want_buf)
125 
126 #define	h_snprintb_val_error(bitfmt, val, want_buf)			\
127 	h_snprintb_m_len(1024, bitfmt, val, 0, -1, want_buf)
128 
129 #define	h_snprintb_m(bitfmt, val, line_max, want_buf)			\
130 	h_snprintb_m_len(1024, bitfmt, val, line_max,			\
131 	    sizeof(want_buf) - 1, want_buf)
132 
133 ATF_TC(snprintb);
134 ATF_TC_HEAD(snprintb, tc)
135 {
136 	atf_tc_set_md_var(tc, "descr", "Checks snprintb(3)");
137 }
138 ATF_TC_BODY(snprintb, tc)
139 {
140 
141 	// style and number base, old style, octal, zero value
142 	//
143 	// The value 0 does not get a leading '0'.
144 	h_snprintb(
145 	    "\010",
146 	    0x00,
147 	    "0");
148 
149 	// style and number base, old style, octal, nonzero value
150 	//
151 	// Nonzero octal values get a leading '0'.
152 	h_snprintb(
153 	    "\010",
154 	    0xff,
155 	    "0377");
156 
157 	// style and number base, old style, decimal, zero value
158 	h_snprintb(
159 	    "\012",
160 	    0x00,
161 	    "0");
162 
163 	// style and number base, old style, decimal, nonzero value
164 	h_snprintb(
165 	    "\012",
166 	    0xff,
167 	    "255");
168 
169 	// style and number base, old style, hexadecimal, zero value
170 	//
171 	// The value 0 does not get a leading '0x'.
172 	h_snprintb(
173 	    "\020",
174 	    0x00,
175 	    "0");
176 
177 	// style and number base, old style, hexadecimal, nonzero value
178 	//
179 	// Nonzero hexadecimal values get a leading '0x'.
180 	h_snprintb(
181 	    "\177\020",
182 	    0xff,
183 	    "0xff");
184 
185 	// style and number base, old style, invalid base 0
186 	h_snprintb_error(
187 	    "",
188 	    "#");
189 
190 	// style and number base, old style, invalid base 2
191 	h_snprintb_error(
192 	    "\002",
193 	    "#");
194 
195 	// style and number base, old style, invalid base 255 or -1
196 	h_snprintb_error(
197 	    "\377",
198 	    "#");
199 
200 	// style and number base, new style, octal, zero value
201 	//
202 	// The value 0 does not get a leading '0'.
203 	h_snprintb(
204 	    "\177\010",
205 	    0x00,
206 	    "0");
207 
208 	// style and number base, new style, octal, nonzero value
209 	//
210 	// Nonzero octal values get a leading '0'.
211 	h_snprintb(
212 	    "\177\010",
213 	    0xff,
214 	    "0377");
215 
216 	// style and number base, new style, decimal, zero value
217 	h_snprintb(
218 	    "\177\012",
219 	    0x00,
220 	    "0");
221 
222 	// style and number base, new style, decimal, nonzero value
223 	h_snprintb(
224 	    "\177\012",
225 	    0xff,
226 	    "255");
227 
228 	// style and number base, new style, hexadecimal, zero value
229 	//
230 	// The value 0 does not get a leading '0x'.
231 	h_snprintb(
232 	    "\177\020",
233 	    0x00,
234 	    "0");
235 
236 	// style and number base, new style, hexadecimal, nonzero value
237 	//
238 	// Nonzero hexadecimal values get a leading '0x'.
239 	h_snprintb(
240 	    "\177\020",
241 	    0xff,
242 	    "0xff");
243 
244 	// style and number base, new style, invalid number base 0
245 	h_snprintb_error(
246 	    "\177",
247 	    "#");
248 
249 	// style and number base, new style, invalid number base 2
250 	h_snprintb_error(
251 	    "\177\002",
252 	    "#");
253 
254 	// style and number base, new style, invalid number base 255 or -1
255 	h_snprintb_error(
256 	    "\177\377",
257 	    "#");
258 
259 	// old style, from lsb to msb
260 	h_snprintb(
261 	    "\020"
262 	    "\001bit1"
263 	    "\002bit2"
264 	    "\037bit31"
265 	    "\040bit32",
266 	    0xffffffff80000001,
267 	    "0xffffffff80000001<bit1,bit32>");
268 
269 	// old style, invalid bit number, at the beginning
270 	h_snprintb_error(
271 	    "\020"
272 	    "\041invalid",
273 	    "0#");
274 
275 	// old style, invalid bit number, in the middle
276 	//
277 	// The old-style format supports only 32 bits, interpreting the
278 	// \041 as part of the text belonging to bit 1.
279 	h_snprintb(
280 	    "\020"
281 	    "\001bit1"
282 	    "\041bit33",
283 	    0x01,
284 	    "0x1<bit1!bit33>");
285 
286 	// old style, repeated bit numbers
287 	//
288 	// When a bit number is mentioned more than once,
289 	// this is most likely a typo.
290 	h_snprintb(
291 	    "\020"
292 	    "\001once"
293 	    "\001again",
294 	    0x01,
295 	    "0x1<once,again>");
296 
297 	// old style, non-printable description
298 	//
299 	// The characters ' ' and '\t' are interpreted as bit numbers,
300 	// not as part of the description; the visual arrangement in this
301 	// example is intentionally misleading.
302 	h_snprintb(
303 	    "\020"
304 	    "\001least significant"
305 	    "\002horizontal\ttab"
306 	    "\003\xC3\xA4",
307 	    0xff,
308 	    "0xff<least,horizontal,\xC3\xA4>");
309 
310 	// old style, empty description
311 	//
312 	// The description of a bit in the old format must not be empty,
313 	// to prevent multiple commas in a row.
314 	h_snprintb_val_error(
315 	    "\020"
316 	    "\001lsb"
317 	    "\004"
318 	    "\005"
319 	    "\010msb",
320 	    0xff,
321 	    "0xff<lsb#");
322 
323 	// old style, buffer size 0, null buffer
324 	//
325 	// If the buffer size is 0, the buffer is not accessed at all and
326 	// may be a null pointer.
327 	int null_rv_old = snprintb(NULL, 0, "\020\001lsb", 0x01);
328 	ATF_CHECK_MSG(
329 	    null_rv_old == 8,
330 	    "want length 8, have %d", null_rv_old);
331 
332 	// old style, buffer too small for value
333 	h_snprintb_len(
334 	    1, "\020", 0x00,
335 	    1, "");
336 
337 	// old style, buffer large enough for zero value
338 	h_snprintb_len(
339 	    2, "\020", 0x00,
340 	    1, "0");
341 
342 	// old style, buffer too small for nonzero value
343 	h_snprintb_len(
344 	    3, "\020", 0x07,
345 	    3, "0#");
346 
347 	// old style, buffer large enough for nonzero value
348 	h_snprintb_len(
349 	    4, "\020", 0x07,
350 	    3, "0x7");
351 
352 	// old style, buffer too small for '<'
353 	h_snprintb_len(
354 	    4, "\020\001lsb", 0x07,
355 	    8, "0x#");
356 
357 	// old style, buffer too small for description
358 	h_snprintb_len(
359 	    7, "\020\001lsb", 0x07,
360 	    8, "0x7<l#");
361 
362 	// old style, buffer too small for '>'
363 	h_snprintb_len(
364 	    8, "\020\001lsb", 0x07,
365 	    8, "0x7<ls#");
366 
367 	// old style, buffer large enough for '>'
368 	h_snprintb_len(
369 	    9, "\020\001lsb", 0x07,
370 	    8, "0x7<lsb>");
371 
372 	// old style, buffer too small for second description
373 	h_snprintb_len(
374 	    9, "\020\001one\002two", 0x07,
375 	    12, "0x7<one#");
376 
377 	// old style, buffer too small for second description
378 	h_snprintb_len(
379 	    10, "\020\001one\002two", 0x07,
380 	    12, "0x7<one,#");
381 
382 	// old style, buffer too small for '>' after second description
383 	h_snprintb_len(
384 	    12, "\020\001one\002two", 0x07,
385 	    12, "0x7<one,tw#");
386 
387 	// old style, buffer large enough for '>' after second description
388 	h_snprintb_len(
389 	    13, "\020\001one\002two", 0x07,
390 	    12, "0x7<one,two>");
391 
392 	// new style, buffer size 0, null buffer
393 	//
394 	// If the buffer size is 0, the buffer may be NULL.
395 	int null_rv_new = snprintb(NULL, 0, "\177\020b\000lsb\0", 0x01);
396 	ATF_CHECK_MSG(
397 	    null_rv_new == 8,
398 	    "want length 8, have %d", null_rv_new);
399 
400 	// new style single bits
401 	h_snprintb(
402 	    "\177\020"
403 	    "b\000lsb\0"
404 	    "b\001above-lsb\0"
405 	    "b\037bit31\0"
406 	    "b\040bit32\0"
407 	    "b\076below-msb\0"
408 	    "b\077msb\0",
409 	    0x8000000180000001,
410 	    "0x8000000180000001<lsb,bit31,bit32,msb>");
411 
412 	// new style single bits, duplicate bits
413 	h_snprintb(
414 	    "\177\020"
415 	    "b\000lsb\0"
416 	    "b\000lsb\0"
417 	    "b\000lsb\0",
418 	    0xff,
419 	    "0xff<lsb,lsb,lsb>");
420 
421 	// new style single bits, 'b' with empty description
422 	//
423 	// The description of a 'b' conversion must not be empty, as the
424 	// output would contain several commas in a row.
425 	h_snprintb_val_error(
426 	    "\177\020"
427 	    "b\000lsb\0"
428 	    "b\001\0"
429 	    "b\002\0"
430 	    "b\007msb\0",
431 	    0xff,
432 	    "0xff<lsb#");
433 
434 	// new style single bits, bit number too large
435 	h_snprintb_error(
436 	    "\177\020"
437 	    "b\100too-high\0",
438 	    "0#");
439 	h_snprintb_error(
440 	    "\177\020"
441 	    "b\377too-high\0",
442 	    "0#");
443 
444 	// new style single bits, non-printable description
445 	//
446 	// Contrary to the old-style format, the new-style format allows
447 	// arbitrary characters in the description, even control characters
448 	// and non-ASCII characters.
449 	h_snprintb(
450 	    "\177\020"
451 	    "b\000space \t \xC3\xA4\0",
452 	    0x1,
453 	    "0x1<space \t \xC3\xA4>");
454 
455 	// new style named bit-field, octal
456 	//
457 	// The bit-field value gets a leading '0' iff it is nonzero.
458 	h_snprintb(
459 	    "\177\010"
460 	    "f\000\010byte0\0"
461 	    "f\010\010byte1\0",
462 	    0x0100,
463 	    "0400<byte0=0,byte1=01>");
464 
465 	// new style named bit-field, decimal
466 	h_snprintb(
467 	    "\177\012"
468 	    "f\000\010byte0\0"
469 	    "f\010\010byte1\0",
470 	    0x0100,
471 	    "256<byte0=0,byte1=1>");
472 
473 	// new style named bit-field, hexadecimal
474 	//
475 	// The bit-field value gets a leading '0x' iff it is nonzero.
476 	h_snprintb(
477 	    "\177\020"
478 	    "f\000\010byte0\0"
479 	    "f\010\010byte1\0",
480 	    0x0100,
481 	    "0x100<byte0=0,byte1=0x1>");
482 
483 	// new style bit-field, from 0 width 0
484 	h_snprintb(
485 	    "\177\020"
486 	    "f\000\000zero-width\0"
487 		"=\000zero\0",
488 	    0xffff,
489 	    "0xffff<zero-width=0=zero>");
490 
491 	// new style bit-field, from 0 width 1
492 	h_snprintb(
493 	    "\177\020"
494 	    "f\000\001lsb\0"
495 		"=\000zero\0"
496 		"=\001one\0",
497 	    0x0,
498 	    "0<lsb=0=zero>");
499 	h_snprintb(
500 	    "\177\020"
501 	    "f\000\001lsb\0"
502 		"=\000zero\0"
503 		"=\001one\0",
504 	    0x1,
505 	    "0x1<lsb=0x1=one>");
506 
507 	// new style bit-field, from 0 width 63
508 	h_snprintb(
509 	    "\177\020"
510 	    "f\000\077uint63\0"
511 		"=\125match\0",
512 	    0xaaaa5555aaaa5555,
513 	    "0xaaaa5555aaaa5555<uint63=0x2aaa5555aaaa5555>");
514 
515 	// new style bit-field, from 0 width 64
516 	h_snprintb(
517 	    "\177\020"
518 	    "f\000\100uint64\0"
519 		"=\125match\0",
520 	    0xaaaa5555aaaa5555,
521 	    "0xaaaa5555aaaa5555<uint64=0xaaaa5555aaaa5555>");
522 
523 	// new style bit-field, from 0 width 65
524 	h_snprintb_error(
525 	    "\177\020"
526 	    "f\000\101uint65\0",
527 	    "0#");
528 
529 	// new style bit-field, from 1 width 8
530 	h_snprintb(
531 	    "\177\020"
532 	    "f\001\010uint8\0"
533 		"=\203match\0",
534 	    0x0106,
535 	    "0x106<uint8=0x83=match>");
536 
537 	// new style bit-field, from 1 width 9
538 	//
539 	// The '=' and ':' directives can match a bit-field value between
540 	// 0 and 255, independent of the bit-field's width.
541 	h_snprintb(
542 	    "\177\020"
543 	    "f\001\011uint9\0"
544 		"=\203match\0"
545 		"*=default-f\0"
546 	    "F\001\011\0"
547 		":\203match\0"
548 		"*default-F\0",
549 	    0x0306,
550 	    "0x306<uint9=0x183=default-f,default-F>");
551 
552 	// new style bit-field, from 24 width 32
553 	h_snprintb(
554 	    "\177\020"
555 	    "f\030\040uint32\0",
556 	    0xaaaa555500000000,
557 	    "0xaaaa555500000000<uint32=0xaa555500>");
558 
559 	// new style bit-field, from 60 width 4
560 	h_snprintb(
561 	    "\177\020"
562 	    "f\074\004uint4\0",
563 	    0xf555555555555555,
564 	    "0xf555555555555555<uint4=0xf>");
565 
566 	// new style bit-field, from 60 width 5
567 	//
568 	// The end of the bit-field is out of bounds.
569 	h_snprintb(
570 	    "\177\020"
571 	    "f\074\005uint5\0",
572 	    0xf555555555555555,
573 	    "0xf555555555555555<uint5=0xf>");
574 
575 	// new style bit-field, from 64 width 0
576 	//
577 	// The beginning of the bit-field is out of bounds, the end is fine.
578 	h_snprintb_error(
579 	    "\177\020"
580 	    "f\100\000uint0\0",
581 	    "0#");
582 
583 	// new style bit-field, from 65 width 0
584 	//
585 	// The beginning and end of the bit-field are out of bounds.
586 	h_snprintb_error(
587 	    "\177\020"
588 	    "f\101\000uint0\0",
589 	    "0#");
590 
591 	// new style bit-field, 'f' with empty description
592 	//
593 	// The description of an 'f' conversion must not be empty, as the
594 	// output would contain an isolated '='.
595 	h_snprintb_val_error(
596 	    "\177\020"
597 	    "f\000\004\0"
598 		"=\001one\0",
599 	    0x1,
600 	    "0x1#");
601 
602 	// new style bit-field, non-printable description
603 	//
604 	// Contrary to the old-style format, the new-style format allows
605 	// arbitrary characters in the description, even control characters
606 	// and non-ASCII characters.
607 	h_snprintb(
608 	    "\177\020"
609 	    "f\000\010\t \xC3\xA4\0"
610 		"=\001\t \xC3\xA4\0"
611 	    "F\000\010\0"
612 		":\001\t \xC3\xA4\0"
613 	    "F\000\010\0"
614 		"*\t \xC3\xA4\0",
615 	    0x1,
616 	    "0x1<\t \xC3\xA4=0x1=\t \xC3\xA4,\t \xC3\xA4,\t \xC3\xA4>");
617 
618 	// new style bit-field, '=' with empty description
619 	//
620 	// The description of a '=' conversion must not be empty, as the
621 	// output would contain several '=' in a row.
622 	h_snprintb_val_error(
623 	    "\177\020"
624 	    "f\000\004f\0"
625 		"=\001one\0"
626 		"=\001\0"
627 		"=\001\0",
628 	    0x1,
629 	    "0x1<f=0x1=one#");
630 
631 	// new style bit-field, 'F' followed by ':' with empty description
632 	//
633 	// The description of a ':' conversion must not be empty, as the
634 	// output would contain empty angle brackets.
635 	h_snprintb_val_error(
636 	    "\177\020"
637 	    "F\000\004\0"
638 		":\001\0"
639 		"*default\0",
640 	    0x1,
641 	    "0x1<#");
642 
643 	// new style bit-field, 'F', ':' with empty description, '*'
644 	//
645 	// The description of a ':' conversion must not be empty, as the
646 	// output would contain empty angle brackets. Not in this particular
647 	// test case, as the value is different, but the structural error is
648 	// detected nevertheless.
649 	h_snprintb_val_error(
650 	    "\177\020"
651 	    "F\000\004\0"
652 		":\001\0"
653 		"*default\0",
654 	    0x2,
655 	    "0x2<#");
656 
657 	// new style bit-field, 'f' with non-exhaustive '='
658 	h_snprintb(
659 	    "\177\020"
660 	    "f\000\004Field\0"
661 		"=\1one\0"
662 		"=\2two\0",
663 	    0x3,
664 	    "0x3<Field=0x3>");
665 
666 	// new style bit-field, 'F' with non-exhaustive ':'
667 	//
668 	// An unnamed bit-field that does not match any values generates empty
669 	// angle brackets, which looks confusing. The ':' directives should
670 	// either be exhaustive, or there should be a '*' catch-all directive.
671 	h_snprintb(
672 	    "\177\020"
673 	    "F\000\004\0"
674 		":\1one\0"
675 		":\2two\0",
676 	    0x3,
677 	    "0x3<>");
678 
679 	// new style bit-field, 'F' with non-exhaustive ':'
680 	//
681 	// A bit-field that does not match any values generates multiple commas
682 	// in a row, which looks confusing. The ':' conversions should either be
683 	// exhaustive, or there should be a '*' catch-all conversion.
684 	h_snprintb(
685 	    "\177\020"
686 	    "b\000bit0\0"
687 	    "F\000\004\0"
688 		":\1one\0"
689 		":\2two\0"
690 	    "b\001bit1\0",
691 	    0x3,
692 	    "0x3<bit0,,bit1>");
693 
694 	// new style bit-field, '=', can never match
695 	//
696 	// The extracted value from the bit-field has 7 bits and is thus less
697 	// than 128, therefore it can neither match 128 nor 255.
698 	h_snprintb(
699 	    "\177\020"
700 	    "f\000\007f\0"
701 		"=\200never\0"
702 		"=\377never\0",
703 	    0xff,
704 	    "0xff<f=0x7f>");
705 
706 	// new style, two separate bit-fields
707 	h_snprintb(
708 	    "\177\020"
709 	    "f\000\004f1\0"
710 		"=\001one\0"
711 		"=\002two\0"
712 	    "f\004\004f2\0"
713 		"=\001one\0"
714 		"=\002two\0",
715 	    0x12,
716 	    "0x12<f1=0x2=two,f2=0x1=one>");
717 
718 	// new style, mixed named and unnamed bit-fields
719 	h_snprintb(
720 	    "\177\020"
721 	    "f\000\004f1\0"
722 		"=\001one\0"
723 		"=\002two\0"
724 	    "F\010\004\0"
725 		":\015thirteen\0"
726 	    "f\004\004f2\0"
727 		"=\001one\0"
728 		"=\002two\0",
729 	    0x0d12,
730 	    "0xd12<f1=0x2=two,thirteen,f2=0x1=one>");
731 
732 	// new style bit-field, overlapping
733 	h_snprintb(
734 	    "\177\020"
735 	    "f\000\004lo\0"
736 	    "f\002\004mid\0"
737 	    "f\004\004hi\0"
738 	    "f\000\010all\0",
739 	    0x18,
740 	    "0x18<lo=0x8,mid=0x6,hi=0x1,all=0x18>");
741 
742 	// new style bit-field, difference between '=' and ':'
743 	//
744 	// The ':' conversion can almost emulate the '=' conversion, without the
745 	// numeric output and with a different separator. It's best to use
746 	// either 'f' with '=', or 'F' with ':', but not mix them.
747 	h_snprintb(
748 	    "\177\020"
749 	    "f\000\004field\0"
750 		"=\010f-value\0"
751 	    "F\000\000\0"		// Use an empty bit-field
752 		":\000separator\0"	// to generate a separator.
753 	    "F\000\004\0"
754 		":\010F-value\0",
755 	    0x18,
756 	    "0x18<field=0x8=f-value,separator,F-value>");
757 
758 	// new style bit-field default, fixed string
759 	//
760 	// The 'f' conversion pairs up with the '=' conversion,
761 	// the 'F' conversion pairs up with the ':' conversion,
762 	// but there's only one 'default' conversion for both variants,
763 	// so its description should include the '=' when used with 'f' but
764 	// not with 'F'.
765 	h_snprintb(
766 	    "\177\020"
767 	    "f\030\010f1\0"
768 		"*default\0"
769 	    "f\020\010f2\0"
770 		"*=default\0"
771 	    "F\010\010\0"
772 		"*default\0"
773 	    "F\010\010\0"
774 		"*=default\0",
775 	    0x11223344,
776 	    "0x11223344<f1=0x11default,f2=0x22=default,default,=default>");
777 
778 	// new style bit-field default, numeric conversion specifier
779 	h_snprintb(
780 	    "\177\020"
781 	    "f\010\010f\0"
782 		"*=f(%ju)\0"
783 	    "F\000\010F\0"
784 		"*F(%ju)\0",
785 	    0x1122,
786 	    "0x1122<f=0x11=f(17),F(34)>");
787 
788 	// new style bit-field default, can never match
789 	//
790 	// The '=' conversion are exhaustive, making the '*' redundant.
791 	h_snprintb(
792 	    "\177\020"
793 	    "f\010\002f\0"
794 		"=\000zero\0"
795 		"=\001one\0"
796 		"=\002two\0"
797 		"=\003three\0"
798 		"*default\0",
799 	    0xff00,
800 	    "0xff00<f=0x3=three>");
801 
802 	// new style bit-field default, invalid conversion specifier
803 	//
804 	// There is no reliable way to make snprintf return an error, as such
805 	// errors are defined as undefined behavior in the C standard.
806 	// Instead, here's a conversion specifier that produces a literal '%'.
807 	h_snprintb(
808 	    "\177\020"
809 	    "f\000\010f\0"
810 		"*=%030ju%%\0",
811 	    0xff,
812 	    "0xff<f=0xff=000000000000000000000000000255%>");
813 
814 	// new style unknown conversion, at the beginning
815 	h_snprintb_val_error(
816 	    "\177\020"
817 	    "unknown\0",
818 	    0xff,
819 	    "0xff#");
820 
821 	// new style unknown conversion, after a known conversion
822 	h_snprintb_val_error(
823 	    "\177\020"
824 	    "b\007msb\0"
825 	    "unknown\0",
826 	    0xff,
827 	    "0xff<msb#");
828 
829 	// new style combinations, 'b' '='
830 	//
831 	// A '=' conversion requires a preceding 'f' conversion.
832 	h_snprintb_val_error(
833 	    "\177\020"
834 	    "b\004bit4\0"
835 		"=\000clear\0"
836 		"=\001set\0"
837 		"=\245complete\0"
838 	    "b\000bit0\0"
839 		"=\000clear\0"
840 		"=\001set\0"
841 		"=\245complete\0",
842 	    0xa5,
843 	    "0xa5#");
844 
845 	// new style combinations, 'b' ':'
846 	//
847 	// A ':' conversion requires a preceding 'f' or 'F' conversion.
848 	h_snprintb_val_error(
849 	    "\177\020"
850 	    "b\004bit4\0"
851 		":\000clear\0"
852 		":\001set\0"
853 		":\245complete\0"
854 	    "b\000bit0\0"
855 		":\000clear\0"
856 		":\001set\0"
857 		":\245complete\0",
858 	    0xa5,
859 	    "0xa5#");
860 
861 	// new style combinations, 'b' '*'
862 	//
863 	// A '*' conversion requires a preceding 'f' or 'F' conversion.
864 	h_snprintb_val_error(
865 	    "\177\020"
866 	    "b\004bit4\0"
867 		"*default(%ju)\0"
868 	    "b\000bit0\0"
869 		"*default(%ju)\0",
870 	    0xa5,
871 	    "0xa5#");
872 
873 	// new style combinations, 'f' 'b' '='
874 	//
875 	// A '=' conversion requires a preceding 'f' conversion, there must
876 	// not be a 'b' conversion in between.
877 	h_snprintb_val_error(
878 	    "\177\020"
879 	    "f\000\010f\0"
880 	    "b\005bit5\0"
881 		"=\245match\0",
882 	    0xa5,
883 	    "0xa5<f=0xa5,bit5#");
884 
885 	// new style combinations, 'F' 'b' ':'
886 	//
887 	// A ':' conversion requires a preceding 'F' conversion, there must
888 	// not be a 'b' conversion in between.
889 	//
890 	// The isolated leading comma is produced by the non-exhaustive 'F'
891 	// conversion. Detecting these at runtime would be too costly.
892 	h_snprintb_val_error(
893 	    "\177\020"
894 	    "F\000\010f\0"
895 	    "b\005bit5\0"
896 		":\245match\0",
897 	    0xa5,
898 	    "0xa5<,bit5#");
899 
900 	// new style combinations, 'f' ':'
901 	//
902 	// The ':' conversion requires a preceding 'F' conversion, not 'f'.
903 	h_snprintb_val_error(
904 	    "\177\20"
905 	    "f\000\004nibble\0"
906 		":\001one\0",
907 	    0x01,
908 	    "0x1<nibble=0x1#");
909 
910 	// new style combinations, 'F' '='
911 	//
912 	// A '=' conversion requires a preceding 'f' conversion, not 'F'.
913 	h_snprintb_val_error(
914 	    "\177\20"
915 	    "F\000\004\0"
916 		"=\001one\0",
917 	    0x01,
918 	    "0x1<#");
919 
920 	// new style combinations, '='
921 	//
922 	// A '=' conversion requires a preceding 'f' or 'F' conversion.
923 	h_snprintb_val_error(
924 	    "\177\020"
925 		"=\245match\0",
926 	    0xa5,
927 	    "0xa5#");
928 
929 	// new style combinations, ':'
930 	//
931 	// A ':' conversion requires a preceding 'f' or 'F' conversion.
932 	h_snprintb_val_error(
933 	    "\177\020"
934 		":\245match\0",
935 	    0xa5,
936 	    "0xa5#");
937 
938 	// new style combinations, '*'
939 	//
940 	// A '*' conversion requires a preceding 'f' or 'F' conversion.
941 	h_snprintb_val_error(
942 	    "\177\020"
943 		"*match\0",
944 	    0xa5,
945 	    "0xa5#");
946 
947 	// new style combinations, 'f' '*' '='
948 	//
949 	// After a catch-all '*' conversions, there must not be further '='
950 	// conversions.
951 	h_snprintb_val_error(
952 	    "\177\020"
953 	    "f\000\010f\0"
954 		"*=default\0"
955 		"=\245match\0",
956 	    0xa5,
957 	    "0xa5<f=0xa5=default#");
958 
959 	// new style combinations, 'F' '*' ':'
960 	//
961 	// After a catch-all '*' conversion, there must not be further ':'
962 	// conversions.
963 	h_snprintb_val_error(
964 	    "\177\020"
965 	    "F\000\010F\0"
966 		"*default\0"
967 		":\245-match\0",
968 	    0xa5,
969 	    "0xa5<default#");
970 
971 	// new style combinations, 'f' '*' '*'
972 	//
973 	// After a catch-all '*' conversion, there must not be further '=' or
974 	// '*' conversions.
975 	h_snprintb_val_error(
976 	    "\177\020"
977 	    "f\000\010f\0"
978 		"*=default-f\0"
979 		"*ignored\0",
980 	    0xa5,
981 	    "0xa5<f=0xa5=default-f#");
982 
983 	// new style combinations, 'F' '*' '*'
984 	//
985 	// After a catch-all '*' conversion, there must not be further ':' or
986 	// '*' conversions.
987 	h_snprintb_val_error(
988 	    "\177\020"
989 	    "F\000\010\0"
990 		"*default-F\0"
991 		"*ignored\0",
992 	    0xa5,
993 	    "0xa5<default-F#");
994 
995 	// example from the manual page, old style octal
996 	h_snprintb(
997 	    "\010\002BITTWO\001BITONE",
998 	    0x03,
999 	    "03<BITTWO,BITONE>");
1000 
1001 	// example from the manual page, old style hexadecimal
1002 	//
1003 	// When using a hexadecimal escape sequence to encode a bit number,
1004 	// the description must not start with a hexadecimal digit, or that
1005 	// digit is interpreted as part of the bit number. To prevent this,
1006 	// the bit number and the description need to be written as separate
1007 	// string literals.
1008 	h_snprintb(
1009 	    "\x10"
1010 	    "\x10" "NOTBOOT"
1011 	    "\x0f" "FPP"
1012 	    "\x0e" "SDVMA"
1013 	    "\x0c" "VIDEO"
1014 	    "\x0b" "LORES"
1015 	    "\x0a" "FPA"
1016 	    "\x09" "DIAG"
1017 	    "\x07" "CACHE"
1018 	    "\x06" "IOCACHE"
1019 	    "\x05" "LOOPBACK"
1020 	    "\x04" "DBGCACHE",
1021 	    0xe860,
1022 	    "0xe860<NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
1023 
1024 	// example from the manual page, new style bits and fields
1025 	h_snprintb(
1026 	    "\177\020"
1027 	    "b\000" "LSB\0"
1028 	    "b\001" "BITONE\0"
1029 	    "f\004\004" "NIBBLE2\0"
1030 	    "f\020\004" "BURST\0"
1031 		"=\x04" "FOUR\0"
1032 		"=\x0f" "FIFTEEN\0"
1033 	    "b\037" "MSB\0",
1034 	    0x800f0701,
1035 	    "0x800f0701<LSB,NIBBLE2=0,BURST=0xf=FIFTEEN,MSB>");
1036 
1037 	// example from the manual page, new style mmap
1038 #define	MAP_FMT				\
1039 	"\177\020"			\
1040 	"b\0"  "SHARED\0"		\
1041 	"b\1"  "PRIVATE\0"		\
1042 	"b\2"  "COPY\0"			\
1043 	"b\4"  "FIXED\0"		\
1044 	"b\5"  "RENAME\0"		\
1045 	"b\6"  "NORESERVE\0"		\
1046 	"b\7"  "INHERIT\0"		\
1047 	"b\11" "HASSEMAPHORE\0"		\
1048 	"b\12" "TRYFIXED\0"		\
1049 	"b\13" "WIRED\0"		\
1050 	"F\14\1\0"			\
1051 		":\0" "FILE\0"		\
1052 		":\1" "ANONYMOUS\0"	\
1053 	"b\15" "STACK\0"		\
1054 	"F\30\010\0"			\
1055 		":\000" "ALIGN=NONE\0"	\
1056 		":\015" "ALIGN=8KB\0"	\
1057 		"*"     "ALIGN=2^%ju\0"
1058 	h_snprintb(
1059 	    MAP_FMT,
1060 	    0x0d001234,
1061 	    "0xd001234<COPY,FIXED,RENAME,HASSEMAPHORE,ANONYMOUS,ALIGN=8KB>");
1062 	h_snprintb(
1063 	    MAP_FMT,
1064 	    0x2e000000,
1065 	    "0x2e000000<FILE,ALIGN=2^46>");
1066 
1067 	// It is possible but cumbersome to implement a reduced variant of
1068 	// rot13 using snprintb, shown here for lowercase letters only.
1069 	for (char ch = 'A'; ch <= '~'; ch++) {
1070 		char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
1071 		    : ch >= 'n' && ch <= 'z' ? ch - 13
1072 		    : '?';
1073 		char expected[8];
1074 		ATF_REQUIRE_EQ(7,
1075 		    snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
1076 		h_snprintb(
1077 		    "\177\020"
1078 		    "F\000\010\0"
1079 		    ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
1080 		    ":iv\0:jw\0:kx\0:ly\0:mz\0"
1081 		    ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
1082 		    ":vi\0:wj\0:xk\0:yl\0:zm\0"
1083 		    // If snprintf accepted "%jc", it would be possible to
1084 		    // echo the non-alphabetic characters instead of a
1085 		    // catchall question mark.
1086 		    "*?\0",
1087 		    ch,
1088 		    expected);
1089 	}
1090 
1091 	// new style, small buffers
1092 	h_snprintb_len(
1093 	    0, "\177\020", 0x00,
1094 	    1, "");
1095 	h_snprintb_len(
1096 	    1, "\177\020", 0x00,
1097 	    1, "");
1098 	h_snprintb_len(
1099 	    2, "\177\020", 0x00,
1100 	    1, "0");
1101 	h_snprintb_len(
1102 	    3, "\177\020", 0x00,
1103 	    1, "0");
1104 	h_snprintb_len(
1105 	    3, "\177\020", 0x07,
1106 	    3, "0#");
1107 	h_snprintb_len(
1108 	    4, "\177\020", 0x07,
1109 	    3, "0x7");
1110 	h_snprintb_len(
1111 	    7, "\177\020b\000lsb\0", 0x07,
1112 	    8, "0x7<l#");
1113 	h_snprintb_len(
1114 	    8, "\177\020b\000lsb\0", 0x07,
1115 	    8, "0x7<ls#");
1116 	h_snprintb_len(
1117 	    9, "\177\020b\000lsb\0", 0x07,
1118 	    8, "0x7<lsb>");
1119 	h_snprintb_len(
1120 	    9, "\177\020b\000one\0b\001two\0", 0x07,
1121 	    12, "0x7<one#");
1122 	h_snprintb_len(
1123 	    10, "\177\020b\000one\0b\001two\0", 0x07,
1124 	    12, "0x7<one,#");
1125 	h_snprintb_len(
1126 	    12, "\177\020b\000one\0b\001two\0", 0x07,
1127 	    12, "0x7<one,tw#");
1128 	h_snprintb_len(
1129 	    13, "\177\020b\000one\0b\001two\0", 0x07,
1130 	    12, "0x7<one,two>");
1131 }
1132 
1133 ATF_TC(snprintb_m);
1134 ATF_TC_HEAD(snprintb_m, tc)
1135 {
1136 	atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
1137 }
1138 ATF_TC_BODY(snprintb_m, tc)
1139 {
1140 
1141 	// old style, line_max exceeded by number in line 1
1142 	h_snprintb_m(
1143 	    "\020",
1144 	    0xff,
1145 	    1,
1146 	    "#\0");
1147 
1148 	// old style, line_max exceeded by '<' in line 1
1149 	h_snprintb_m(
1150 	    "\020"
1151 	    "\001lsb",
1152 	    0xff,
1153 	    4,
1154 	    "0xf#\0");
1155 
1156 	// old style, line_max exceeded by description
1157 	h_snprintb_m(
1158 	    "\020"
1159 	    "\001bit1"
1160 	    "\002bit2",
1161 	    0xff,
1162 	    7,
1163 	    "0xff<b#\0"
1164 	    "0xff<b#\0");
1165 
1166 	// old style, line_max exceeded by '>' in line 1
1167 	h_snprintb_m(
1168 	    "\020"
1169 	    "\001bit1"
1170 	    "\0022",
1171 	    0xff,
1172 	    9,
1173 	    "0xff<bit#\0"
1174 	    "0xff<2>\0");
1175 
1176 	// old style, line_max exceeded by description in line 2
1177 	h_snprintb_m(
1178 	    "\020"
1179 	    "\0011"
1180 	    "\002bit2",
1181 	    0xff,
1182 	    8,
1183 	    "0xff<1>\0"
1184 	    "0xff<bi#\0");
1185 
1186 	// old style, line_max exceeded by '>' in line 2
1187 	h_snprintb_m(
1188 	    "\020"
1189 	    "\0011"
1190 	    "\002bit2",
1191 	    0xff,
1192 	    9,
1193 	    "0xff<1>\0"
1194 	    "0xff<bit#\0");
1195 
1196 	// old style, complete
1197 	h_snprintb_m(
1198 	    "\020"
1199 	    "\0011"
1200 	    "\002bit2",
1201 	    0xff,
1202 	    10,
1203 	    "0xff<1>\0"
1204 	    "0xff<bit2>\0");
1205 
1206 	// new style, line_max exceeded by value in line 1
1207 	h_snprintb_m(
1208 	    "\177\020",
1209 	    0xff,
1210 	    3,
1211 	    "0x#\0");
1212 
1213 	// new style, line_max exceeded by single-bit '<' in line 1
1214 	h_snprintb_m(
1215 	    "\177\020"
1216 	    "b\000bit\0",
1217 	    0xff,
1218 	    4,
1219 	    "0xf#\0");
1220 
1221 	// new style, line_max exceeded by single-bit description in line 1
1222 	h_snprintb_m(
1223 	    "\177\020"
1224 	    "b\000bit0\0"
1225 	    "b\001two\0",
1226 	    0xff,
1227 	    8,
1228 	    "0xff<bi#\0"
1229 	    "0xff<tw#\0");
1230 
1231 	// new style, line_max exceeded by single-bit '>' in line 1
1232 	h_snprintb_m(
1233 	    "\177\020"
1234 	    "b\000bit0\0"
1235 	    "b\001two\0",
1236 	    0xff,
1237 	    9,
1238 	    "0xff<bit#\0"
1239 	    "0xff<two>\0");
1240 
1241 	// new style, line_max exceeded by single-bit description in line 2
1242 	h_snprintb_m(
1243 	    "\177\020"
1244 	    "b\000one\0"
1245 	    "b\001three\0",
1246 	    0xff,
1247 	    9,
1248 	    "0xff<one>\0"
1249 	    "0xff<thr#\0");
1250 
1251 	// new style, line_max exceeded by single-bit '>' in line 2
1252 	h_snprintb_m(
1253 	    "\177\020"
1254 	    "b\000one\0"
1255 	    "b\001three\0",
1256 	    0xff,
1257 	    10,
1258 	    "0xff<one>\0"
1259 	    "0xff<thre#\0");
1260 
1261 	// new style, single-bit complete
1262 	h_snprintb_m(
1263 	    "\177\020"
1264 	    "b\000one\0"
1265 	    "b\001three\0",
1266 	    0xff,
1267 	    11,
1268 	    "0xff<one>\0"
1269 	    "0xff<three>\0");
1270 
1271 	// new style, line_max exceeded by named bit-field number in line 1
1272 	h_snprintb_m(
1273 	    "\177\020"
1274 	    "f\000\004lo\0",
1275 	    0xff,
1276 	    3,
1277 	    "0x#\0");
1278 
1279 	// new style, line_max exceeded by named bit-field '<' in line 1
1280 	h_snprintb_m(
1281 	    "\177\020"
1282 	    "f\000\004lo\0",
1283 	    0xff,
1284 	    4,
1285 	    "0xf#\0");
1286 
1287 	// new style, line_max exceeded by bit-field description in line 1
1288 	h_snprintb_m(
1289 	    "\177\020"
1290 	    "f\000\004lo\0",
1291 	    0xff,
1292 	    6,
1293 	    "0xff<#\0");
1294 
1295 	// new style, line_max exceeded by named bit-field '=' in line 1
1296 	h_snprintb_m(
1297 	    "\177\020"
1298 	    "f\000\004lo\0",
1299 	    0xff,
1300 	    7,
1301 	    "0xff<l#\0");
1302 
1303 	// new style, line_max exceeded by named bit-field value in line 1
1304 	h_snprintb_m(
1305 	    "\177\020"
1306 	    "f\000\004lo\0",
1307 	    0xff,
1308 	    10,
1309 	    "0xff<lo=0#\0");
1310 
1311 	// new style, line_max exceeded by named bit-field '=' in line 1
1312 	h_snprintb_m(
1313 	    "\177\020"
1314 	    "f\000\004lo\0"
1315 		"=\017match\0",
1316 	    0xff,
1317 	    12,
1318 	    "0xff<lo=0xf#\0");
1319 
1320 	// new style, line_max exceeded by named bit-field value description in
1321 	// line 1
1322 	h_snprintb_m(
1323 	    "\177\020"
1324 	    "f\000\004lo\0"
1325 		"=\017match\0",
1326 	    0xff,
1327 	    16,
1328 	    "0xff<lo=0xf=mat#\0");
1329 
1330 	// new style, line_max exceeded by named bit-field '>' in line 1
1331 	h_snprintb_m(
1332 	    "\177\020"
1333 	    "f\000\004lo\0"
1334 		"=\017match\0",
1335 	    0xff,
1336 	    17,
1337 	    "0xff<lo=0xf=matc#\0");
1338 
1339 	// new style, line_max exceeded by named bit-field description in
1340 	// line 2
1341 	h_snprintb_m(
1342 	    "\177\020"
1343 	    "f\000\004lo\0"
1344 	    "f\000\004low-bits\0"
1345 		"=\017match\0",
1346 	    0xff,
1347 	    12,
1348 	    "0xff<lo=0xf>\0"
1349 	    "0xff<low-bi#\0");
1350 
1351 	// new style, line_max exceeded by named bit-field '=' in line 2
1352 	h_snprintb_m(
1353 	    "\177\020"
1354 	    "f\000\004lo\0"
1355 	    "f\000\004low-bits\0"
1356 		"=\017match\0",
1357 	    0xff,
1358 	    13,
1359 	    "0xff<lo=0xf>\0"
1360 	    "0xff<low-bit#\0");
1361 
1362 	// new style, line_max exceeded by named bit-field value in line 2
1363 	h_snprintb_m(
1364 	    "\177\020"
1365 	    "f\000\004lo\0"
1366 	    "f\000\004low-bits\0"
1367 		"=\017match\0",
1368 	    0xff,
1369 	    16,
1370 	    "0xff<lo=0xf>\0"
1371 	    "0xff<low-bits=0#\0");
1372 
1373 	// new style, line_max exceeded by named bit-field '=' in line 2
1374 	h_snprintb_m(
1375 	    "\177\020"
1376 	    "f\000\004lo\0"
1377 	    "f\000\004low-bits\0"
1378 		"=\017match\0",
1379 	    0xff,
1380 	    18,
1381 	    "0xff<lo=0xf>\0"
1382 	    "0xff<low-bits=0xf#\0");
1383 
1384 	// new style, line_max exceeded by named bit-field value description
1385 	// in line 2
1386 	h_snprintb_m(
1387 	    "\177\020"
1388 	    "f\000\004lo\0"
1389 	    "f\000\004low-bits\0"
1390 		"=\017match\0",
1391 	    0xff,
1392 	    22,
1393 	    "0xff<lo=0xf>\0"
1394 	    "0xff<low-bits=0xf=mat#\0");
1395 
1396 	// new style, line_max exceeded by named bit-field '>' in line 2
1397 	h_snprintb_m(
1398 	    "\177\020"
1399 	    "f\000\004lo\0"
1400 	    "f\000\004low-bits\0"
1401 		"=\017match\0",
1402 	    0xff,
1403 	    23,
1404 	    "0xff<lo=0xf>\0"
1405 	    "0xff<low-bits=0xf=matc#\0");
1406 
1407 	// new style, named bit-field complete
1408 	h_snprintb_m(
1409 	    "\177\020"
1410 	    "f\000\004lo\0"
1411 	    "f\000\004low-bits\0"
1412 		"=\017match\0",
1413 	    0xff,
1414 	    24,
1415 	    "0xff<lo=0xf>\0"
1416 	    "0xff<low-bits=0xf=match>\0");
1417 
1418 	// new style, line_max exceeded by unnamed bit-field number in line 1
1419 	h_snprintb_m(
1420 	    "\177\020"
1421 	    "F\000\004\0",
1422 	    0xff,
1423 	    3,
1424 	    "0x#\0");
1425 
1426 	// new style, line_max exceeded by unnamed bit-field '<' in line 1
1427 	h_snprintb_m(
1428 	    "\177\020"
1429 	    "F\000\004\0",
1430 	    0xff,
1431 	    4,
1432 	    "0xf#\0");
1433 
1434 	// new style, line_max exceeded by unnamed bit-field value description
1435 	// in line 1
1436 	h_snprintb_m(
1437 	    "\177\020"
1438 	    "F\000\004\0"
1439 		":\017match\0",
1440 	    0xff,
1441 	    9,
1442 	    "0xff<mat#\0");
1443 
1444 	// new style, line_max exceeded by unnamed bit-field '>' in line 1
1445 	h_snprintb_m(
1446 	    "\177\020"
1447 	    "F\000\004\0"
1448 		":\017match\0",
1449 	    0xff,
1450 	    10,
1451 	    "0xff<matc#\0");
1452 
1453 	// new style, line_max exceeded by unnamed bit-field value description
1454 	// in line 2
1455 	h_snprintb_m(
1456 	    "\177\020"
1457 	    "F\000\004\0"
1458 		":\017m1\0"
1459 		":\017match\0",
1460 	    0xff,
1461 	    10,
1462 	    "0xff<m1ma#\0");
1463 
1464 	// new style, line_max exceeded by unnamed bit-field '>' in line 2
1465 	h_snprintb_m(
1466 	    "\177\020"
1467 	    "F\000\004\0"
1468 		":\017m1\0"
1469 		":\017match\0",
1470 	    0xff,
1471 	    10,
1472 	    "0xff<m1ma#\0");
1473 
1474 	// new style unnamed bit-field complete
1475 	h_snprintb_m(
1476 	    "\177\020"
1477 	    "F\000\004\0"
1478 		":\017m1\0"
1479 		":\017match\0",
1480 	    0xff,
1481 	    13,
1482 	    "0xff<m1match>\0");
1483 
1484 	// new style, line_max exceeded by bit-field default
1485 	h_snprintb_m(
1486 	    "\177\020"
1487 	    "f\000\004f\0"
1488 		"*=default\0",
1489 	    0xff,
1490 	    17,
1491 	    "0xff<f=0xf=defau#\0");
1492 
1493 	// new style, line_max exceeded by unmatched field value
1494 	h_snprintb_m(
1495 	    "\177\020"
1496 	    "f\000\004bits\0"
1497 		"=\000zero\0",
1498 	    0xff,
1499 	    11,
1500 	    "0xff<bits=#\0");
1501 
1502 	// example from the manual page, new style bits and fields
1503 	h_snprintb_m(
1504 	    "\177\020"
1505 	    "b\000" "LSB\0"
1506 	    "b\001" "BITONE\0"
1507 	    "f\004\004" "NIBBLE2\0"
1508 	    "f\020\004" "BURST\0"
1509 		"=\x04" "FOUR\0"
1510 		"=\x0f" "FIFTEEN\0"
1511 	    "b\037" "MSB\0",
1512 	    0x800f0701,
1513 	    34,
1514 	    "0x800f0701<LSB,NIBBLE2=0>\0"
1515 	    "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
1516 
1517 	// new style, missing number base
1518 	h_snprintb_m_len(
1519 	    1024,
1520 	    "\177",
1521 	    0xff,
1522 	    128,
1523 	    -1,
1524 	    "#\0");
1525 
1526 	// new style, buffer too small for complete number in line 2
1527 	h_snprintb_m_len(
1528 	    15,
1529 	    "\177\020"
1530 	    "b\000lsb\0"
1531 	    "b\001two\0",
1532 	    0xff,
1533 	    11,
1534 	    20,
1535 	    "0xff<lsb>\0"
1536 	    "0x#\0");
1537 
1538 	// new-style format, buffer too small for '<' in line 2
1539 	h_snprintb_m_len(
1540 	    16,
1541 	    "\177\020"
1542 	    "b\000lsb\0"
1543 	    "b\001two\0",
1544 	    0xff,
1545 	    11,
1546 	    20,
1547 	    "0xff<lsb>\0"
1548 	    "0xf#\0");
1549 
1550 	// new-style format, buffer too small for textual fallback
1551 	h_snprintb_m_len(
1552 	    24,
1553 	    "\177\020"
1554 	    "f\000\004bits\0"
1555 		"*=fallback\0"
1556 	    "b\0024\0",
1557 	    0xff,
1558 	    64,
1559 	    26,
1560 	    "0xff<bits=0xf=fallbac#\0");
1561 
1562 	// new-style format, buffer too small for numeric fallback
1563 	h_snprintb_m_len(
1564 	    20,
1565 	    "\177\020"
1566 	    "F\000\004\0"
1567 		"*fallback(%040jd)\0",
1568 	    0xff,
1569 	    64,
1570 	    57,
1571 	    "0xff<fallback(000#\0");
1572 
1573 	// new-style format, buffer too small for numeric fallback past buffer
1574 	h_snprintb_m_len(
1575 	    15,
1576 	    "\177\020"
1577 	    "F\000\004\0"
1578 		"*fallback(%010jd)\0"
1579 	    "F\004\004\0"
1580 		"*fallback(%010jd)\0",
1581 	    0xff,
1582 	    64,
1583 	    48,
1584 	    "0xff<fallbac#\0");
1585 
1586 	// new style, bits and fields, line break between fields
1587 	h_snprintb_m(
1588 	    "\177\020"
1589 	    "b\0LSB\0"
1590 	    "b\1_BITONE\0"
1591 	    "f\4\4NIBBLE2\0"
1592 	    "f\x10\4BURST\0"
1593 		"=\04FOUR\0"
1594 		"=\17FIFTEEN\0"
1595 	    "b\x1fMSB\0",
1596 	    0x800f0701,
1597 	    33,
1598 	    "0x800f0701<LSB,NIBBLE2=0>\0"
1599 	    "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
1600 
1601 	// new style, bits and fields, line break after field description
1602 	h_snprintb_m(
1603 	    "\177\020"
1604 	    "b\0LSB\0"
1605 	    "b\1_BITONE\0"
1606 	    "f\4\4NIBBLE2\0"
1607 	    "f\020\4BURST\0"
1608 		"=\04FOUR\0"
1609 		"=\17FIFTEEN\0"
1610 	    "b\037MSB\0",
1611 	    0x800f0701,
1612 	    32,
1613 	    "0x800f0701<LSB,NIBBLE2=0>\0"
1614 	    "0x800f0701<BURST=0xf=FIFTEEN>\0"
1615 	    "0x800f0701<MSB>\0");
1616 }
1617 
1618 ATF_TP_ADD_TCS(tp)
1619 {
1620 
1621 	ATF_TP_ADD_TC(tp, snprintb);
1622 	ATF_TP_ADD_TC(tp, snprintb_m);
1623 
1624 	return atf_no_error();
1625 }
1626