Home | History | Annotate | Line # | Download | only in libutil
      1 /* $NetBSD: t_snprintb.c,v 1.39 2025/10/09 18:51:41 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.39 2025/10/09 18:51:41 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
    682 	// commas in a row, which looks confusing. The ':' conversions should
    683 	// either be exhaustive, or there should be a '*' catch-all
    684 	// conversion.
    685 	h_snprintb(
    686 	    "\177\020"
    687 	    "b\000bit0\0"
    688 	    "F\000\004\0"
    689 		":\1one\0"
    690 		":\2two\0"
    691 	    "b\001bit1\0",
    692 	    0x3,
    693 	    "0x3<bit0,,bit1>");
    694 
    695 	// new style bit-field, '=', can never match
    696 	//
    697 	// The extracted value from the bit-field has 7 bits and is thus less
    698 	// than 128, therefore it can neither match 128 nor 255.
    699 	h_snprintb(
    700 	    "\177\020"
    701 	    "f\000\007f\0"
    702 		"=\200never\0"
    703 		"=\377never\0",
    704 	    0xff,
    705 	    "0xff<f=0x7f>");
    706 
    707 	// new style, two separate bit-fields
    708 	h_snprintb(
    709 	    "\177\020"
    710 	    "f\000\004f1\0"
    711 		"=\001one\0"
    712 		"=\002two\0"
    713 	    "f\004\004f2\0"
    714 		"=\001one\0"
    715 		"=\002two\0",
    716 	    0x12,
    717 	    "0x12<f1=0x2=two,f2=0x1=one>");
    718 
    719 	// new style, mixed named and unnamed bit-fields
    720 	h_snprintb(
    721 	    "\177\020"
    722 	    "f\000\004f1\0"
    723 		"=\001one\0"
    724 		"=\002two\0"
    725 	    "F\010\004\0"
    726 		":\015thirteen\0"
    727 	    "f\004\004f2\0"
    728 		"=\001one\0"
    729 		"=\002two\0",
    730 	    0x0d12,
    731 	    "0xd12<f1=0x2=two,thirteen,f2=0x1=one>");
    732 
    733 	// new style bit-field, overlapping
    734 	h_snprintb(
    735 	    "\177\020"
    736 	    "f\000\004lo\0"
    737 	    "f\002\004mid\0"
    738 	    "f\004\004hi\0"
    739 	    "f\000\010all\0",
    740 	    0x18,
    741 	    "0x18<lo=0x8,mid=0x6,hi=0x1,all=0x18>");
    742 
    743 	// new style bit-field, difference between '=' and ':'
    744 	//
    745 	// The ':' conversion can almost emulate the '=' conversion by
    746 	// starting its description with '=', excluding the numeric value of
    747 	// the field. The 'f' and '=' conversions mix well, and so do 'F' and
    748 	// ':'. Other combinations don't mix well and are thus erroneous.
    749 	h_snprintb(
    750 	    "\177\020"
    751 	    "f\000\004field\0"
    752 		"=\010f-value\0"
    753 	    "F\000\000\0"		// Use an empty bit-field
    754 		":\000separator\0"	// to generate a separator.
    755 	    "F\000\004\0"
    756 		":\010F-value\0",
    757 	    0x18,
    758 	    "0x18<field=0x8=f-value,separator,F-value>");
    759 
    760 	// new style bit-field default, fixed string
    761 	//
    762 	// When used with the 'f' conversion, the '*' conversion should
    763 	// start with '=' to match the rest of the format.
    764 	//
    765 	// When used with the 'F' conversion, the '*' conversion should not
    766 	// start with '=' to avoid the wrong punctuation ',=' in the output.
    767 	h_snprintb(
    768 	    "\177\020"
    769 	    "f\030\010f1\0"
    770 		"*default-f\0"
    771 	    "f\020\010f2\0"
    772 		"*=default-f\0"
    773 	    "F\010\010\0"
    774 		"*default-F\0"
    775 	    "F\010\010\0"
    776 		"*=default-F\0",
    777 	    0x11223344,
    778 	    "0x11223344<f1=0x11default-f,f2=0x22=default-f,default-F,=default-F>");
    779 
    780 	// new style bit-field default, numeric conversion specifier
    781 	h_snprintb(
    782 	    "\177\020"
    783 	    "f\010\010f\0"
    784 		"*=f(%ju)\0"
    785 	    "F\000\010F\0"
    786 		"*F(%ju)\0",
    787 	    0x1122,
    788 	    "0x1122<f=0x11=f(17),F(34)>");
    789 
    790 	// new style bit-field default, can never match
    791 	//
    792 	// The '=' conversions are exhaustive, making the '*' redundant.
    793 	h_snprintb(
    794 	    "\177\020"
    795 	    "f\010\002f\0"
    796 		"=\000zero\0"
    797 		"=\001one\0"
    798 		"=\002two\0"
    799 		"=\003three\0"
    800 		"*default\0",
    801 	    0xff00,
    802 	    "0xff00<f=0x3=three>");
    803 
    804 	// new style bit-field default, invalid conversion specifier
    805 	//
    806 	// There is no reliable way to make snprintf return an error, as such
    807 	// errors are defined as undefined behavior in the C standard.
    808 	// Instead, here's a conversion specifier that produces a literal '%'.
    809 	h_snprintb(
    810 	    "\177\020"
    811 	    "f\000\010f\0"
    812 		"*=%030ju%%\0",
    813 	    0xff,
    814 	    "0xff<f=0xff=000000000000000000000000000255%>");
    815 
    816 	// new style unknown conversion, at the beginning
    817 	h_snprintb_val_error(
    818 	    "\177\020"
    819 	    "unknown\0",
    820 	    0xff,
    821 	    "0xff#");
    822 
    823 	// new style unknown conversion, after a known conversion
    824 	h_snprintb_val_error(
    825 	    "\177\020"
    826 	    "b\007msb\0"
    827 	    "unknown\0",
    828 	    0xff,
    829 	    "0xff<msb#");
    830 
    831 	// new style combinations, 'b' '='
    832 	//
    833 	// A '=' conversion requires a preceding 'f' conversion.
    834 	h_snprintb_val_error(
    835 	    "\177\020"
    836 	    "b\004bit4\0"
    837 		"=\000clear\0"
    838 		"=\001set\0"
    839 		"=\245complete\0"
    840 	    "b\000bit0\0"
    841 		"=\000clear\0"
    842 		"=\001set\0"
    843 		"=\245complete\0",
    844 	    0xa5,
    845 	    "0xa5#");
    846 
    847 	// new style combinations, 'b' ':'
    848 	//
    849 	// A ':' conversion requires a preceding 'f' or 'F' conversion.
    850 	h_snprintb_val_error(
    851 	    "\177\020"
    852 	    "b\004bit4\0"
    853 		":\000clear\0"
    854 		":\001set\0"
    855 		":\245complete\0"
    856 	    "b\000bit0\0"
    857 		":\000clear\0"
    858 		":\001set\0"
    859 		":\245complete\0",
    860 	    0xa5,
    861 	    "0xa5#");
    862 
    863 	// new style combinations, 'b' '*'
    864 	//
    865 	// A '*' conversion requires a preceding 'f' or 'F' conversion.
    866 	h_snprintb_val_error(
    867 	    "\177\020"
    868 	    "b\004bit4\0"
    869 		"*default(%ju)\0"
    870 	    "b\000bit0\0"
    871 		"*default(%ju)\0",
    872 	    0xa5,
    873 	    "0xa5#");
    874 
    875 	// new style combinations, 'f' 'b' '='
    876 	//
    877 	// A '=' conversion requires a preceding 'f' conversion, there must
    878 	// not be a 'b' conversion in between.
    879 	h_snprintb_val_error(
    880 	    "\177\020"
    881 	    "f\000\010f\0"
    882 	    "b\005bit5\0"
    883 		"=\245match\0",
    884 	    0xa5,
    885 	    "0xa5<f=0xa5,bit5#");
    886 
    887 	// new style combinations, 'F' 'b' ':'
    888 	//
    889 	// A ':' conversion requires a preceding 'F' conversion, there must
    890 	// not be a 'b' conversion in between.
    891 	//
    892 	// The isolated leading comma is produced by the non-exhaustive 'F'
    893 	// conversion. Detecting these at runtime would be too costly.
    894 	h_snprintb_val_error(
    895 	    "\177\020"
    896 	    "F\000\010f\0"
    897 	    "b\005bit5\0"
    898 		":\245match\0",
    899 	    0xa5,
    900 	    "0xa5<,bit5#");
    901 
    902 	// new style combinations, 'f' ':'
    903 	//
    904 	// The ':' conversion requires a preceding 'F' conversion, not 'f'.
    905 	// Otherwise, the output would be "0x1<nibble=0x1one>", missing a
    906 	// separator between the number and the description "one".
    907 	h_snprintb_val_error(
    908 	    "\177\20"
    909 	    "f\000\004nibble\0"
    910 		":\001one\0",
    911 	    0x01,
    912 	    "0x1<nibble=0x1#");
    913 
    914 	// new style combinations, 'f' ':' with punctuation
    915 	//
    916 	// When the description starts with punctuation, in this case round
    917 	// parentheses, the resulting string is easily readable.
    918 	h_snprintb(
    919 	    "\177\20"
    920 	    "f\000\002field\0" ":\0(zero)\0"
    921 	    "f\000\002field\0" "*(catch-all)\0",
    922 	    0x0000,
    923 	    "0<field=0(zero),field=0(catch-all)>");
    924 
    925 	// new style combinations, 'F' '='
    926 	//
    927 	// A '=' conversion requires a preceding 'f' conversion, not 'F'.
    928 	h_snprintb_val_error(
    929 	    "\177\20"
    930 	    "F\000\004\0"
    931 		"=\001one\0",
    932 	    0x01,
    933 	    "0x1<#");
    934 
    935 	// new style combinations, '='
    936 	//
    937 	// A '=' conversion requires a preceding 'f' or 'F' conversion.
    938 	h_snprintb_val_error(
    939 	    "\177\020"
    940 		"=\245match\0",
    941 	    0xa5,
    942 	    "0xa5#");
    943 
    944 	// new style combinations, ':'
    945 	//
    946 	// A ':' conversion requires a preceding 'f' or 'F' conversion.
    947 	h_snprintb_val_error(
    948 	    "\177\020"
    949 		":\245match\0",
    950 	    0xa5,
    951 	    "0xa5#");
    952 
    953 	// new style combinations, '*'
    954 	//
    955 	// A '*' conversion requires a preceding 'f' or 'F' conversion.
    956 	h_snprintb_val_error(
    957 	    "\177\020"
    958 		"*match\0",
    959 	    0xa5,
    960 	    "0xa5#");
    961 
    962 	// new style combinations, 'f' '*' '='
    963 	//
    964 	// After a catch-all '*' conversion, there must not be further '='
    965 	// conversions.
    966 	h_snprintb_val_error(
    967 	    "\177\020"
    968 	    "f\000\010f\0"
    969 		"*=default\0"
    970 		"=\245match\0",
    971 	    0xa5,
    972 	    "0xa5<f=0xa5=default#");
    973 
    974 	// new style combinations, 'F' '*' ':'
    975 	//
    976 	// After a catch-all '*' conversion, there must not be further ':'
    977 	// conversions.
    978 	h_snprintb_val_error(
    979 	    "\177\020"
    980 	    "F\000\010F\0"
    981 		"*default\0"
    982 		":\245-match\0",
    983 	    0xa5,
    984 	    "0xa5<default#");
    985 
    986 	// new style combinations, 'f' '*' '*'
    987 	//
    988 	// After a catch-all '*' conversion, there must not be further '=' or
    989 	// '*' conversions.
    990 	h_snprintb_val_error(
    991 	    "\177\020"
    992 	    "f\000\010f\0"
    993 		"*=default-f\0"
    994 		"*ignored\0",
    995 	    0xa5,
    996 	    "0xa5<f=0xa5=default-f#");
    997 
    998 	// new style combinations, 'F' '*' '*'
    999 	//
   1000 	// After a catch-all '*' conversion, there must not be further ':' or
   1001 	// '*' conversions.
   1002 	h_snprintb_val_error(
   1003 	    "\177\020"
   1004 	    "F\000\010\0"
   1005 		"*default-F\0"
   1006 		"*ignored\0",
   1007 	    0xa5,
   1008 	    "0xa5<default-F#");
   1009 
   1010 	// example from the manual page, old style octal
   1011 	h_snprintb(
   1012 	    "\010\002BITTWO\001BITONE",
   1013 	    0x03,
   1014 	    "03<BITTWO,BITONE>");
   1015 
   1016 	// example from the manual page, old style hexadecimal
   1017 	//
   1018 	// When using a hexadecimal escape sequence to encode a bit number,
   1019 	// the description must not start with a hexadecimal digit, or that
   1020 	// digit is interpreted as part of the bit number. To prevent this,
   1021 	// the bit number and the description need to be written as separate
   1022 	// string literals.
   1023 	h_snprintb(
   1024 	    "\x10"
   1025 	    "\x10" "NOTBOOT"
   1026 	    "\x0f" "FPP"
   1027 	    "\x0e" "SDVMA"
   1028 	    "\x0c" "VIDEO"
   1029 	    "\x0b" "LORES"
   1030 	    "\x0a" "FPA"
   1031 	    "\x09" "DIAG"
   1032 	    "\x07" "CACHE"
   1033 	    "\x06" "IOCACHE"
   1034 	    "\x05" "LOOPBACK"
   1035 	    "\x04" "DBGCACHE",
   1036 	    0xe860,
   1037 	    "0xe860<NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
   1038 
   1039 	// example from the manual page, new style bits and fields
   1040 	h_snprintb(
   1041 	    "\177\020"
   1042 	    "b\000" "LSB\0"
   1043 	    "b\001" "BITONE\0"
   1044 	    "f\004\004" "NIBBLE2\0"
   1045 	    "f\020\004" "BURST\0"
   1046 		"=\x04" "FOUR\0"
   1047 		"=\x0f" "FIFTEEN\0"
   1048 	    "b\037" "MSB\0",
   1049 	    0x800f0701,
   1050 	    "0x800f0701<LSB,NIBBLE2=0,BURST=0xf=FIFTEEN,MSB>");
   1051 
   1052 	// example from the manual page, new style mmap
   1053 #define	MAP_FMT				\
   1054 	"\177\020"			\
   1055 	"b\0"  "SHARED\0"		\
   1056 	"b\1"  "PRIVATE\0"		\
   1057 	"b\2"  "COPY\0"			\
   1058 	"b\4"  "FIXED\0"		\
   1059 	"b\5"  "RENAME\0"		\
   1060 	"b\6"  "NORESERVE\0"		\
   1061 	"b\7"  "INHERIT\0"		\
   1062 	"b\11" "HASSEMAPHORE\0"		\
   1063 	"b\12" "TRYFIXED\0"		\
   1064 	"b\13" "WIRED\0"		\
   1065 	"F\14\1\0"			\
   1066 		":\0" "FILE\0"		\
   1067 		":\1" "ANONYMOUS\0"	\
   1068 	"b\15" "STACK\0"		\
   1069 	"F\30\010\0"			\
   1070 		":\000" "ALIGN=NONE\0"	\
   1071 		":\015" "ALIGN=8KB\0"	\
   1072 		"*"     "ALIGN=2^%ju\0"
   1073 	h_snprintb(
   1074 	    MAP_FMT,
   1075 	    0x0d001234,
   1076 	    "0xd001234<COPY,FIXED,RENAME,HASSEMAPHORE,ANONYMOUS,ALIGN=8KB>");
   1077 	h_snprintb(
   1078 	    MAP_FMT,
   1079 	    0x2e000000,
   1080 	    "0x2e000000<FILE,ALIGN=2^46>");
   1081 
   1082 	// It is possible but cumbersome to implement a reduced variant of
   1083 	// rot13 using snprintb, shown here for lowercase letters only.
   1084 	for (char ch = 'A'; ch <= '~'; ch++) {
   1085 		char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
   1086 		    : ch >= 'n' && ch <= 'z' ? ch - 13
   1087 		    : '?';
   1088 		char expected[8];
   1089 		ATF_REQUIRE_EQ(7,
   1090 		    snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
   1091 		h_snprintb(
   1092 		    "\177\020"
   1093 		    "F\000\010\0"
   1094 		    ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
   1095 		    ":iv\0:jw\0:kx\0:ly\0:mz\0"
   1096 		    ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
   1097 		    ":vi\0:wj\0:xk\0:yl\0:zm\0"
   1098 		    // If snprintf accepted "%jc", it would be possible to
   1099 		    // echo the non-alphabetic characters instead of a
   1100 		    // catchall question mark.
   1101 		    "*?\0",
   1102 		    ch,
   1103 		    expected);
   1104 	}
   1105 
   1106 	// new style, small buffers
   1107 	h_snprintb_len(
   1108 	    0, "\177\020", 0x00,
   1109 	    1, "");
   1110 	h_snprintb_len(
   1111 	    1, "\177\020", 0x00,
   1112 	    1, "");
   1113 	h_snprintb_len(
   1114 	    2, "\177\020", 0x00,
   1115 	    1, "0");
   1116 	h_snprintb_len(
   1117 	    3, "\177\020", 0x00,
   1118 	    1, "0");
   1119 	h_snprintb_len(
   1120 	    3, "\177\020", 0x07,
   1121 	    3, "0#");
   1122 	h_snprintb_len(
   1123 	    4, "\177\020", 0x07,
   1124 	    3, "0x7");
   1125 	h_snprintb_len(
   1126 	    7, "\177\020b\000lsb\0", 0x07,
   1127 	    8, "0x7<l#");
   1128 	h_snprintb_len(
   1129 	    8, "\177\020b\000lsb\0", 0x07,
   1130 	    8, "0x7<ls#");
   1131 	h_snprintb_len(
   1132 	    9, "\177\020b\000lsb\0", 0x07,
   1133 	    8, "0x7<lsb>");
   1134 	h_snprintb_len(
   1135 	    9, "\177\020b\000one\0b\001two\0", 0x07,
   1136 	    12, "0x7<one#");
   1137 	h_snprintb_len(
   1138 	    10, "\177\020b\000one\0b\001two\0", 0x07,
   1139 	    12, "0x7<one,#");
   1140 	h_snprintb_len(
   1141 	    12, "\177\020b\000one\0b\001two\0", 0x07,
   1142 	    12, "0x7<one,tw#");
   1143 	h_snprintb_len(
   1144 	    13, "\177\020b\000one\0b\001two\0", 0x07,
   1145 	    12, "0x7<one,two>");
   1146 }
   1147 
   1148 ATF_TC(snprintb_m);
   1149 ATF_TC_HEAD(snprintb_m, tc)
   1150 {
   1151 	atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
   1152 }
   1153 ATF_TC_BODY(snprintb_m, tc)
   1154 {
   1155 
   1156 	// old style, line_max exceeded by number in line 1
   1157 	h_snprintb_m(
   1158 	    "\020",
   1159 	    0xff,
   1160 	    1,
   1161 	    "#\0");
   1162 
   1163 	// old style, line_max exceeded by '<' in line 1
   1164 	h_snprintb_m(
   1165 	    "\020"
   1166 	    "\001lsb",
   1167 	    0xff,
   1168 	    4,
   1169 	    "0xf#\0");
   1170 
   1171 	// old style, line_max exceeded by description
   1172 	h_snprintb_m(
   1173 	    "\020"
   1174 	    "\001bit1"
   1175 	    "\002bit2",
   1176 	    0xff,
   1177 	    7,
   1178 	    "0xff<b#\0"
   1179 	    "0xff<b#\0");
   1180 
   1181 	// old style, line_max exceeded by '>' in line 1
   1182 	h_snprintb_m(
   1183 	    "\020"
   1184 	    "\001bit1"
   1185 	    "\0022",
   1186 	    0xff,
   1187 	    9,
   1188 	    "0xff<bit#\0"
   1189 	    "0xff<2>\0");
   1190 
   1191 	// old style, line_max exceeded by description in line 2
   1192 	h_snprintb_m(
   1193 	    "\020"
   1194 	    "\0011"
   1195 	    "\002bit2",
   1196 	    0xff,
   1197 	    8,
   1198 	    "0xff<1>\0"
   1199 	    "0xff<bi#\0");
   1200 
   1201 	// old style, line_max exceeded by '>' in line 2
   1202 	h_snprintb_m(
   1203 	    "\020"
   1204 	    "\0011"
   1205 	    "\002bit2",
   1206 	    0xff,
   1207 	    9,
   1208 	    "0xff<1>\0"
   1209 	    "0xff<bit#\0");
   1210 
   1211 	// old style, complete
   1212 	h_snprintb_m(
   1213 	    "\020"
   1214 	    "\0011"
   1215 	    "\002bit2",
   1216 	    0xff,
   1217 	    10,
   1218 	    "0xff<1>\0"
   1219 	    "0xff<bit2>\0");
   1220 
   1221 	// new style, line_max exceeded by value in line 1
   1222 	h_snprintb_m(
   1223 	    "\177\020",
   1224 	    0xff,
   1225 	    3,
   1226 	    "0x#\0");
   1227 
   1228 	// new style, line_max exceeded by single-bit '<' in line 1
   1229 	h_snprintb_m(
   1230 	    "\177\020"
   1231 	    "b\000bit\0",
   1232 	    0xff,
   1233 	    4,
   1234 	    "0xf#\0");
   1235 
   1236 	// new style, line_max exceeded by single-bit description in line 1
   1237 	h_snprintb_m(
   1238 	    "\177\020"
   1239 	    "b\000bit0\0"
   1240 	    "b\001two\0",
   1241 	    0xff,
   1242 	    8,
   1243 	    "0xff<bi#\0"
   1244 	    "0xff<tw#\0");
   1245 
   1246 	// new style, line_max exceeded by single-bit '>' in line 1
   1247 	h_snprintb_m(
   1248 	    "\177\020"
   1249 	    "b\000bit0\0"
   1250 	    "b\001two\0",
   1251 	    0xff,
   1252 	    9,
   1253 	    "0xff<bit#\0"
   1254 	    "0xff<two>\0");
   1255 
   1256 	// new style, line_max exceeded by single-bit description in line 2
   1257 	h_snprintb_m(
   1258 	    "\177\020"
   1259 	    "b\000one\0"
   1260 	    "b\001three\0",
   1261 	    0xff,
   1262 	    9,
   1263 	    "0xff<one>\0"
   1264 	    "0xff<thr#\0");
   1265 
   1266 	// new style, line_max exceeded by single-bit '>' in line 2
   1267 	h_snprintb_m(
   1268 	    "\177\020"
   1269 	    "b\000one\0"
   1270 	    "b\001three\0",
   1271 	    0xff,
   1272 	    10,
   1273 	    "0xff<one>\0"
   1274 	    "0xff<thre#\0");
   1275 
   1276 	// new style, single-bit complete
   1277 	h_snprintb_m(
   1278 	    "\177\020"
   1279 	    "b\000one\0"
   1280 	    "b\001three\0",
   1281 	    0xff,
   1282 	    11,
   1283 	    "0xff<one>\0"
   1284 	    "0xff<three>\0");
   1285 
   1286 	// new style, line_max exceeded by named bit-field number in line 1
   1287 	h_snprintb_m(
   1288 	    "\177\020"
   1289 	    "f\000\004lo\0",
   1290 	    0xff,
   1291 	    3,
   1292 	    "0x#\0");
   1293 
   1294 	// new style, line_max exceeded by named bit-field '<' in line 1
   1295 	h_snprintb_m(
   1296 	    "\177\020"
   1297 	    "f\000\004lo\0",
   1298 	    0xff,
   1299 	    4,
   1300 	    "0xf#\0");
   1301 
   1302 	// new style, line_max exceeded by bit-field description in line 1
   1303 	h_snprintb_m(
   1304 	    "\177\020"
   1305 	    "f\000\004lo\0",
   1306 	    0xff,
   1307 	    6,
   1308 	    "0xff<#\0");
   1309 
   1310 	// new style, line_max exceeded by named bit-field '=' in line 1
   1311 	h_snprintb_m(
   1312 	    "\177\020"
   1313 	    "f\000\004lo\0",
   1314 	    0xff,
   1315 	    7,
   1316 	    "0xff<l#\0");
   1317 
   1318 	// new style, line_max exceeded by named bit-field value in line 1
   1319 	h_snprintb_m(
   1320 	    "\177\020"
   1321 	    "f\000\004lo\0",
   1322 	    0xff,
   1323 	    10,
   1324 	    "0xff<lo=0#\0");
   1325 
   1326 	// new style, line_max exceeded by named bit-field '=' in line 1
   1327 	h_snprintb_m(
   1328 	    "\177\020"
   1329 	    "f\000\004lo\0"
   1330 		"=\017match\0",
   1331 	    0xff,
   1332 	    12,
   1333 	    "0xff<lo=0xf#\0");
   1334 
   1335 	// new style, line_max exceeded by named bit-field value description in
   1336 	// line 1
   1337 	h_snprintb_m(
   1338 	    "\177\020"
   1339 	    "f\000\004lo\0"
   1340 		"=\017match\0",
   1341 	    0xff,
   1342 	    16,
   1343 	    "0xff<lo=0xf=mat#\0");
   1344 
   1345 	// new style, line_max exceeded by named bit-field '>' in line 1
   1346 	h_snprintb_m(
   1347 	    "\177\020"
   1348 	    "f\000\004lo\0"
   1349 		"=\017match\0",
   1350 	    0xff,
   1351 	    17,
   1352 	    "0xff<lo=0xf=matc#\0");
   1353 
   1354 	// new style, line_max exceeded by named bit-field description in
   1355 	// line 2
   1356 	h_snprintb_m(
   1357 	    "\177\020"
   1358 	    "f\000\004lo\0"
   1359 	    "f\000\004low-bits\0"
   1360 		"=\017match\0",
   1361 	    0xff,
   1362 	    12,
   1363 	    "0xff<lo=0xf>\0"
   1364 	    "0xff<low-bi#\0");
   1365 
   1366 	// new style, line_max exceeded by named bit-field '=' in line 2
   1367 	h_snprintb_m(
   1368 	    "\177\020"
   1369 	    "f\000\004lo\0"
   1370 	    "f\000\004low-bits\0"
   1371 		"=\017match\0",
   1372 	    0xff,
   1373 	    13,
   1374 	    "0xff<lo=0xf>\0"
   1375 	    "0xff<low-bit#\0");
   1376 
   1377 	// new style, line_max exceeded by named bit-field value in line 2
   1378 	h_snprintb_m(
   1379 	    "\177\020"
   1380 	    "f\000\004lo\0"
   1381 	    "f\000\004low-bits\0"
   1382 		"=\017match\0",
   1383 	    0xff,
   1384 	    16,
   1385 	    "0xff<lo=0xf>\0"
   1386 	    "0xff<low-bits=0#\0");
   1387 
   1388 	// new style, line_max exceeded by named bit-field '=' in line 2
   1389 	h_snprintb_m(
   1390 	    "\177\020"
   1391 	    "f\000\004lo\0"
   1392 	    "f\000\004low-bits\0"
   1393 		"=\017match\0",
   1394 	    0xff,
   1395 	    18,
   1396 	    "0xff<lo=0xf>\0"
   1397 	    "0xff<low-bits=0xf#\0");
   1398 
   1399 	// new style, line_max exceeded by named bit-field value description
   1400 	// in line 2
   1401 	h_snprintb_m(
   1402 	    "\177\020"
   1403 	    "f\000\004lo\0"
   1404 	    "f\000\004low-bits\0"
   1405 		"=\017match\0",
   1406 	    0xff,
   1407 	    22,
   1408 	    "0xff<lo=0xf>\0"
   1409 	    "0xff<low-bits=0xf=mat#\0");
   1410 
   1411 	// new style, line_max exceeded by named bit-field '>' in line 2
   1412 	h_snprintb_m(
   1413 	    "\177\020"
   1414 	    "f\000\004lo\0"
   1415 	    "f\000\004low-bits\0"
   1416 		"=\017match\0",
   1417 	    0xff,
   1418 	    23,
   1419 	    "0xff<lo=0xf>\0"
   1420 	    "0xff<low-bits=0xf=matc#\0");
   1421 
   1422 	// new style, named bit-field complete
   1423 	h_snprintb_m(
   1424 	    "\177\020"
   1425 	    "f\000\004lo\0"
   1426 	    "f\000\004low-bits\0"
   1427 		"=\017match\0",
   1428 	    0xff,
   1429 	    24,
   1430 	    "0xff<lo=0xf>\0"
   1431 	    "0xff<low-bits=0xf=match>\0");
   1432 
   1433 	// new style, line_max exceeded by unnamed bit-field number in line 1
   1434 	h_snprintb_m(
   1435 	    "\177\020"
   1436 	    "F\000\004\0",
   1437 	    0xff,
   1438 	    3,
   1439 	    "0x#\0");
   1440 
   1441 	// new style, line_max exceeded by unnamed bit-field '<' in line 1
   1442 	h_snprintb_m(
   1443 	    "\177\020"
   1444 	    "F\000\004\0",
   1445 	    0xff,
   1446 	    4,
   1447 	    "0xf#\0");
   1448 
   1449 	// new style, line_max exceeded by unnamed bit-field value description
   1450 	// in line 1
   1451 	h_snprintb_m(
   1452 	    "\177\020"
   1453 	    "F\000\004\0"
   1454 		":\017match\0",
   1455 	    0xff,
   1456 	    9,
   1457 	    "0xff<mat#\0");
   1458 
   1459 	// new style, line_max exceeded by unnamed bit-field '>' in line 1
   1460 	h_snprintb_m(
   1461 	    "\177\020"
   1462 	    "F\000\004\0"
   1463 		":\017match\0",
   1464 	    0xff,
   1465 	    10,
   1466 	    "0xff<matc#\0");
   1467 
   1468 	// new style, line_max exceeded by unnamed bit-field value description
   1469 	// in line 2
   1470 	h_snprintb_m(
   1471 	    "\177\020"
   1472 	    "F\000\004\0"
   1473 		":\017m1\0"
   1474 		":\017match\0",
   1475 	    0xff,
   1476 	    10,
   1477 	    "0xff<m1ma#\0");
   1478 
   1479 	// new style, line_max exceeded by unnamed bit-field '>' in line 2
   1480 	h_snprintb_m(
   1481 	    "\177\020"
   1482 	    "F\000\004\0"
   1483 		":\017m1\0"
   1484 		":\017match\0",
   1485 	    0xff,
   1486 	    10,
   1487 	    "0xff<m1ma#\0");
   1488 
   1489 	// new style unnamed bit-field complete
   1490 	h_snprintb_m(
   1491 	    "\177\020"
   1492 	    "F\000\004\0"
   1493 		":\017m1\0"
   1494 		":\017match\0",
   1495 	    0xff,
   1496 	    13,
   1497 	    "0xff<m1match>\0");
   1498 
   1499 	// new style, line_max exceeded by bit-field default
   1500 	h_snprintb_m(
   1501 	    "\177\020"
   1502 	    "f\000\004f\0"
   1503 		"*=default\0",
   1504 	    0xff,
   1505 	    17,
   1506 	    "0xff<f=0xf=defau#\0");
   1507 
   1508 	// new style, line_max exceeded by unmatched field value
   1509 	h_snprintb_m(
   1510 	    "\177\020"
   1511 	    "f\000\004bits\0"
   1512 		"=\000zero\0",
   1513 	    0xff,
   1514 	    11,
   1515 	    "0xff<bits=#\0");
   1516 
   1517 	// example from the manual page, new style bits and fields
   1518 	h_snprintb_m(
   1519 	    "\177\020"
   1520 	    "b\000" "LSB\0"
   1521 	    "b\001" "BITONE\0"
   1522 	    "f\004\004" "NIBBLE2\0"
   1523 	    "f\020\004" "BURST\0"
   1524 		"=\x04" "FOUR\0"
   1525 		"=\x0f" "FIFTEEN\0"
   1526 	    "b\037" "MSB\0",
   1527 	    0x800f0701,
   1528 	    34,
   1529 	    "0x800f0701<LSB,NIBBLE2=0>\0"
   1530 	    "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
   1531 
   1532 	// new style, missing number base
   1533 	h_snprintb_m_len(
   1534 	    1024,
   1535 	    "\177",
   1536 	    0xff,
   1537 	    128,
   1538 	    -1,
   1539 	    "#\0");
   1540 
   1541 	// new style, buffer too small for complete number in line 2
   1542 	h_snprintb_m_len(
   1543 	    15,
   1544 	    "\177\020"
   1545 	    "b\000lsb\0"
   1546 	    "b\001two\0",
   1547 	    0xff,
   1548 	    11,
   1549 	    20,
   1550 	    "0xff<lsb>\0"
   1551 	    "0x#\0");
   1552 
   1553 	// new-style format, buffer too small for '<' in line 2
   1554 	h_snprintb_m_len(
   1555 	    16,
   1556 	    "\177\020"
   1557 	    "b\000lsb\0"
   1558 	    "b\001two\0",
   1559 	    0xff,
   1560 	    11,
   1561 	    20,
   1562 	    "0xff<lsb>\0"
   1563 	    "0xf#\0");
   1564 
   1565 	// new-style format, buffer too small for textual fallback
   1566 	h_snprintb_m_len(
   1567 	    24,
   1568 	    "\177\020"
   1569 	    "f\000\004bits\0"
   1570 		"*=fallback\0"
   1571 	    "b\0024\0",
   1572 	    0xff,
   1573 	    64,
   1574 	    26,
   1575 	    "0xff<bits=0xf=fallbac#\0");
   1576 
   1577 	// new-style format, buffer too small for numeric fallback
   1578 	h_snprintb_m_len(
   1579 	    20,
   1580 	    "\177\020"
   1581 	    "F\000\004\0"
   1582 		"*fallback(%040jd)\0",
   1583 	    0xff,
   1584 	    64,
   1585 	    57,
   1586 	    "0xff<fallback(000#\0");
   1587 
   1588 	// new-style format, buffer too small for numeric fallback past buffer
   1589 	h_snprintb_m_len(
   1590 	    15,
   1591 	    "\177\020"
   1592 	    "F\000\004\0"
   1593 		"*fallback(%010jd)\0"
   1594 	    "F\004\004\0"
   1595 		"*fallback(%010jd)\0",
   1596 	    0xff,
   1597 	    64,
   1598 	    48,
   1599 	    "0xff<fallbac#\0");
   1600 
   1601 	// new style, bits and fields, line break between fields
   1602 	h_snprintb_m(
   1603 	    "\177\020"
   1604 	    "b\0LSB\0"
   1605 	    "b\1_BITONE\0"
   1606 	    "f\4\4NIBBLE2\0"
   1607 	    "f\x10\4BURST\0"
   1608 		"=\04FOUR\0"
   1609 		"=\17FIFTEEN\0"
   1610 	    "b\x1fMSB\0",
   1611 	    0x800f0701,
   1612 	    33,
   1613 	    "0x800f0701<LSB,NIBBLE2=0>\0"
   1614 	    "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
   1615 
   1616 	// new style, bits and fields, line break after field description
   1617 	h_snprintb_m(
   1618 	    "\177\020"
   1619 	    "b\0LSB\0"
   1620 	    "b\1_BITONE\0"
   1621 	    "f\4\4NIBBLE2\0"
   1622 	    "f\020\4BURST\0"
   1623 		"=\04FOUR\0"
   1624 		"=\17FIFTEEN\0"
   1625 	    "b\037MSB\0",
   1626 	    0x800f0701,
   1627 	    32,
   1628 	    "0x800f0701<LSB,NIBBLE2=0>\0"
   1629 	    "0x800f0701<BURST=0xf=FIFTEEN>\0"
   1630 	    "0x800f0701<MSB>\0");
   1631 }
   1632 
   1633 ATF_TP_ADD_TCS(tp)
   1634 {
   1635 
   1636 	ATF_TP_ADD_TC(tp, snprintb);
   1637 	ATF_TP_ADD_TC(tp, snprintb_m);
   1638 
   1639 	return atf_no_error();
   1640 }
   1641