1 /* $NetBSD: t_snprintb.c,v 1.37 2024/12/31 08:56:21 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.37 2024/12/31 08:56:21 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 *
vis_arr(char * buf,size_t bufsize,const char * arr,size_t arrsize)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
check_snprintb_m(const char * file,size_t line,size_t bufsize,const char * bitfmt,size_t bitfmtlen,uint64_t val,size_t line_max,int want_rv,const char * want_buf,size_t want_bufsize)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);
ATF_TC_HEAD(snprintb,tc)134 ATF_TC_HEAD(snprintb, tc)
135 {
136           atf_tc_set_md_var(tc, "descr", "Checks snprintb(3)");
137 }
ATF_TC_BODY(snprintb,tc)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.
746           //
747           // The 'f' and '=' conversions are used together, the 'F' and ':'
748           // conversions are used together, but these two groups cannot be mixed.
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 '=' conversion 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           h_snprintb_val_error(
906               "\177\20"
907               "f\000\004nibble\0"
908                     ":\001one\0",
909               0x01,
910               "0x1<nibble=0x1#");
911 
912           // new style combinations, 'F' '='
913           //
914           // A '=' conversion requires a preceding 'f' conversion, not 'F'.
915           h_snprintb_val_error(
916               "\177\20"
917               "F\000\004\0"
918                     "=\001one\0",
919               0x01,
920               "0x1<#");
921 
922           // new style combinations, '='
923           //
924           // A '=' conversion requires a preceding 'f' or 'F' conversion.
925           h_snprintb_val_error(
926               "\177\020"
927                     "=\245match\0",
928               0xa5,
929               "0xa5#");
930 
931           // new style combinations, ':'
932           //
933           // A ':' conversion requires a preceding 'f' or 'F' conversion.
934           h_snprintb_val_error(
935               "\177\020"
936                     ":\245match\0",
937               0xa5,
938               "0xa5#");
939 
940           // new style combinations, '*'
941           //
942           // A '*' conversion requires a preceding 'f' or 'F' conversion.
943           h_snprintb_val_error(
944               "\177\020"
945                     "*match\0",
946               0xa5,
947               "0xa5#");
948 
949           // new style combinations, 'f' '*' '='
950           //
951           // After a catch-all '*' conversions, there must not be further '='
952           // conversions.
953           h_snprintb_val_error(
954               "\177\020"
955               "f\000\010f\0"
956                     "*=default\0"
957                     "=\245match\0",
958               0xa5,
959               "0xa5<f=0xa5=default#");
960 
961           // new style combinations, 'F' '*' ':'
962           //
963           // After a catch-all '*' conversion, there must not be further ':'
964           // conversions.
965           h_snprintb_val_error(
966               "\177\020"
967               "F\000\010F\0"
968                     "*default\0"
969                     ":\245-match\0",
970               0xa5,
971               "0xa5<default#");
972 
973           // new style combinations, 'f' '*' '*'
974           //
975           // After a catch-all '*' conversion, there must not be further '=' or
976           // '*' conversions.
977           h_snprintb_val_error(
978               "\177\020"
979               "f\000\010f\0"
980                     "*=default-f\0"
981                     "*ignored\0",
982               0xa5,
983               "0xa5<f=0xa5=default-f#");
984 
985           // new style combinations, 'F' '*' '*'
986           //
987           // After a catch-all '*' conversion, there must not be further ':' or
988           // '*' conversions.
989           h_snprintb_val_error(
990               "\177\020"
991               "F\000\010\0"
992                     "*default-F\0"
993                     "*ignored\0",
994               0xa5,
995               "0xa5<default-F#");
996 
997           // example from the manual page, old style octal
998           h_snprintb(
999               "\010\002BITTWO\001BITONE",
1000               0x03,
1001               "03<BITTWO,BITONE>");
1002 
1003           // example from the manual page, old style hexadecimal
1004           //
1005           // When using a hexadecimal escape sequence to encode a bit number,
1006           // the description must not start with a hexadecimal digit, or that
1007           // digit is interpreted as part of the bit number. To prevent this,
1008           // the bit number and the description need to be written as separate
1009           // string literals.
1010           h_snprintb(
1011               "\x10"
1012               "\x10" "NOTBOOT"
1013               "\x0f" "FPP"
1014               "\x0e" "SDVMA"
1015               "\x0c" "VIDEO"
1016               "\x0b" "LORES"
1017               "\x0a" "FPA"
1018               "\x09" "DIAG"
1019               "\x07" "CACHE"
1020               "\x06" "IOCACHE"
1021               "\x05" "LOOPBACK"
1022               "\x04" "DBGCACHE",
1023               0xe860,
1024               "0xe860<NOTBOOT,FPP,SDVMA,VIDEO,CACHE,IOCACHE>");
1025 
1026           // example from the manual page, new style bits and fields
1027           h_snprintb(
1028               "\177\020"
1029               "b\000" "LSB\0"
1030               "b\001" "BITONE\0"
1031               "f\004\004" "NIBBLE2\0"
1032               "f\020\004" "BURST\0"
1033                     "=\x04" "FOUR\0"
1034                     "=\x0f" "FIFTEEN\0"
1035               "b\037" "MSB\0",
1036               0x800f0701,
1037               "0x800f0701<LSB,NIBBLE2=0,BURST=0xf=FIFTEEN,MSB>");
1038 
1039           // example from the manual page, new style mmap
1040 #define   MAP_FMT                                 \
1041           "\177\020"                              \
1042           "b\0"  "SHARED\0"             \
1043           "b\1"  "PRIVATE\0"            \
1044           "b\2"  "COPY\0"                         \
1045           "b\4"  "FIXED\0"              \
1046           "b\5"  "RENAME\0"             \
1047           "b\6"  "NORESERVE\0"                    \
1048           "b\7"  "INHERIT\0"            \
1049           "b\11" "HASSEMAPHORE\0"                 \
1050           "b\12" "TRYFIXED\0"           \
1051           "b\13" "WIRED\0"              \
1052           "F\14\1\0"                              \
1053                     ":\0" "FILE\0"                \
1054                     ":\1" "ANONYMOUS\0" \
1055           "b\15" "STACK\0"              \
1056           "F\30\010\0"                            \
1057                     ":\000" "ALIGN=NONE\0"        \
1058                     ":\015" "ALIGN=8KB\0"         \
1059                     "*"     "ALIGN=2^%ju\0"
1060           h_snprintb(
1061               MAP_FMT,
1062               0x0d001234,
1063               "0xd001234<COPY,FIXED,RENAME,HASSEMAPHORE,ANONYMOUS,ALIGN=8KB>");
1064           h_snprintb(
1065               MAP_FMT,
1066               0x2e000000,
1067               "0x2e000000<FILE,ALIGN=2^46>");
1068 
1069           // It is possible but cumbersome to implement a reduced variant of
1070           // rot13 using snprintb, shown here for lowercase letters only.
1071           for (char ch = 'A'; ch <= '~'; ch++) {
1072                     char rot13 = ch >= 'a' && ch <= 'm' ? ch + 13
1073                         : ch >= 'n' && ch <= 'z' ? ch - 13
1074                         : '?';
1075                     char expected[8];
1076                     ATF_REQUIRE_EQ(7,
1077                         snprintf(expected, sizeof(expected), "%#x<%c>", ch, rot13));
1078                     h_snprintb(
1079                         "\177\020"
1080                         "F\000\010\0"
1081                         ":an\0:bo\0:cp\0:dq\0:er\0:fs\0:gt\0:hu\0"
1082                         ":iv\0:jw\0:kx\0:ly\0:mz\0"
1083                         ":na\0:ob\0:pc\0:qd\0:re\0:sf\0:tg\0:uh\0"
1084                         ":vi\0:wj\0:xk\0:yl\0:zm\0"
1085                         // If snprintf accepted "%jc", it would be possible to
1086                         // echo the non-alphabetic characters instead of a
1087                         // catchall question mark.
1088                         "*?\0",
1089                         ch,
1090                         expected);
1091           }
1092 
1093           // new style, small buffers
1094           h_snprintb_len(
1095               0, "\177\020", 0x00,
1096               1, "");
1097           h_snprintb_len(
1098               1, "\177\020", 0x00,
1099               1, "");
1100           h_snprintb_len(
1101               2, "\177\020", 0x00,
1102               1, "0");
1103           h_snprintb_len(
1104               3, "\177\020", 0x00,
1105               1, "0");
1106           h_snprintb_len(
1107               3, "\177\020", 0x07,
1108               3, "0#");
1109           h_snprintb_len(
1110               4, "\177\020", 0x07,
1111               3, "0x7");
1112           h_snprintb_len(
1113               7, "\177\020b\000lsb\0", 0x07,
1114               8, "0x7<l#");
1115           h_snprintb_len(
1116               8, "\177\020b\000lsb\0", 0x07,
1117               8, "0x7<ls#");
1118           h_snprintb_len(
1119               9, "\177\020b\000lsb\0", 0x07,
1120               8, "0x7<lsb>");
1121           h_snprintb_len(
1122               9, "\177\020b\000one\0b\001two\0", 0x07,
1123               12, "0x7<one#");
1124           h_snprintb_len(
1125               10, "\177\020b\000one\0b\001two\0", 0x07,
1126               12, "0x7<one,#");
1127           h_snprintb_len(
1128               12, "\177\020b\000one\0b\001two\0", 0x07,
1129               12, "0x7<one,tw#");
1130           h_snprintb_len(
1131               13, "\177\020b\000one\0b\001two\0", 0x07,
1132               12, "0x7<one,two>");
1133 }
1134 
1135 ATF_TC(snprintb_m);
ATF_TC_HEAD(snprintb_m,tc)1136 ATF_TC_HEAD(snprintb_m, tc)
1137 {
1138           atf_tc_set_md_var(tc, "descr", "Checks snprintb_m(3)");
1139 }
ATF_TC_BODY(snprintb_m,tc)1140 ATF_TC_BODY(snprintb_m, tc)
1141 {
1142 
1143           // old style, line_max exceeded by number in line 1
1144           h_snprintb_m(
1145               "\020",
1146               0xff,
1147               1,
1148               "#\0");
1149 
1150           // old style, line_max exceeded by '<' in line 1
1151           h_snprintb_m(
1152               "\020"
1153               "\001lsb",
1154               0xff,
1155               4,
1156               "0xf#\0");
1157 
1158           // old style, line_max exceeded by description
1159           h_snprintb_m(
1160               "\020"
1161               "\001bit1"
1162               "\002bit2",
1163               0xff,
1164               7,
1165               "0xff<b#\0"
1166               "0xff<b#\0");
1167 
1168           // old style, line_max exceeded by '>' in line 1
1169           h_snprintb_m(
1170               "\020"
1171               "\001bit1"
1172               "\0022",
1173               0xff,
1174               9,
1175               "0xff<bit#\0"
1176               "0xff<2>\0");
1177 
1178           // old style, line_max exceeded by description in line 2
1179           h_snprintb_m(
1180               "\020"
1181               "\0011"
1182               "\002bit2",
1183               0xff,
1184               8,
1185               "0xff<1>\0"
1186               "0xff<bi#\0");
1187 
1188           // old style, line_max exceeded by '>' in line 2
1189           h_snprintb_m(
1190               "\020"
1191               "\0011"
1192               "\002bit2",
1193               0xff,
1194               9,
1195               "0xff<1>\0"
1196               "0xff<bit#\0");
1197 
1198           // old style, complete
1199           h_snprintb_m(
1200               "\020"
1201               "\0011"
1202               "\002bit2",
1203               0xff,
1204               10,
1205               "0xff<1>\0"
1206               "0xff<bit2>\0");
1207 
1208           // new style, line_max exceeded by value in line 1
1209           h_snprintb_m(
1210               "\177\020",
1211               0xff,
1212               3,
1213               "0x#\0");
1214 
1215           // new style, line_max exceeded by single-bit '<' in line 1
1216           h_snprintb_m(
1217               "\177\020"
1218               "b\000bit\0",
1219               0xff,
1220               4,
1221               "0xf#\0");
1222 
1223           // new style, line_max exceeded by single-bit description in line 1
1224           h_snprintb_m(
1225               "\177\020"
1226               "b\000bit0\0"
1227               "b\001two\0",
1228               0xff,
1229               8,
1230               "0xff<bi#\0"
1231               "0xff<tw#\0");
1232 
1233           // new style, line_max exceeded by single-bit '>' in line 1
1234           h_snprintb_m(
1235               "\177\020"
1236               "b\000bit0\0"
1237               "b\001two\0",
1238               0xff,
1239               9,
1240               "0xff<bit#\0"
1241               "0xff<two>\0");
1242 
1243           // new style, line_max exceeded by single-bit description in line 2
1244           h_snprintb_m(
1245               "\177\020"
1246               "b\000one\0"
1247               "b\001three\0",
1248               0xff,
1249               9,
1250               "0xff<one>\0"
1251               "0xff<thr#\0");
1252 
1253           // new style, line_max exceeded by single-bit '>' in line 2
1254           h_snprintb_m(
1255               "\177\020"
1256               "b\000one\0"
1257               "b\001three\0",
1258               0xff,
1259               10,
1260               "0xff<one>\0"
1261               "0xff<thre#\0");
1262 
1263           // new style, single-bit complete
1264           h_snprintb_m(
1265               "\177\020"
1266               "b\000one\0"
1267               "b\001three\0",
1268               0xff,
1269               11,
1270               "0xff<one>\0"
1271               "0xff<three>\0");
1272 
1273           // new style, line_max exceeded by named bit-field number in line 1
1274           h_snprintb_m(
1275               "\177\020"
1276               "f\000\004lo\0",
1277               0xff,
1278               3,
1279               "0x#\0");
1280 
1281           // new style, line_max exceeded by named bit-field '<' in line 1
1282           h_snprintb_m(
1283               "\177\020"
1284               "f\000\004lo\0",
1285               0xff,
1286               4,
1287               "0xf#\0");
1288 
1289           // new style, line_max exceeded by bit-field description in line 1
1290           h_snprintb_m(
1291               "\177\020"
1292               "f\000\004lo\0",
1293               0xff,
1294               6,
1295               "0xff<#\0");
1296 
1297           // new style, line_max exceeded by named bit-field '=' in line 1
1298           h_snprintb_m(
1299               "\177\020"
1300               "f\000\004lo\0",
1301               0xff,
1302               7,
1303               "0xff<l#\0");
1304 
1305           // new style, line_max exceeded by named bit-field value in line 1
1306           h_snprintb_m(
1307               "\177\020"
1308               "f\000\004lo\0",
1309               0xff,
1310               10,
1311               "0xff<lo=0#\0");
1312 
1313           // new style, line_max exceeded by named bit-field '=' in line 1
1314           h_snprintb_m(
1315               "\177\020"
1316               "f\000\004lo\0"
1317                     "=\017match\0",
1318               0xff,
1319               12,
1320               "0xff<lo=0xf#\0");
1321 
1322           // new style, line_max exceeded by named bit-field value description in
1323           // line 1
1324           h_snprintb_m(
1325               "\177\020"
1326               "f\000\004lo\0"
1327                     "=\017match\0",
1328               0xff,
1329               16,
1330               "0xff<lo=0xf=mat#\0");
1331 
1332           // new style, line_max exceeded by named bit-field '>' in line 1
1333           h_snprintb_m(
1334               "\177\020"
1335               "f\000\004lo\0"
1336                     "=\017match\0",
1337               0xff,
1338               17,
1339               "0xff<lo=0xf=matc#\0");
1340 
1341           // new style, line_max exceeded by named bit-field description in
1342           // line 2
1343           h_snprintb_m(
1344               "\177\020"
1345               "f\000\004lo\0"
1346               "f\000\004low-bits\0"
1347                     "=\017match\0",
1348               0xff,
1349               12,
1350               "0xff<lo=0xf>\0"
1351               "0xff<low-bi#\0");
1352 
1353           // new style, line_max exceeded by named bit-field '=' in line 2
1354           h_snprintb_m(
1355               "\177\020"
1356               "f\000\004lo\0"
1357               "f\000\004low-bits\0"
1358                     "=\017match\0",
1359               0xff,
1360               13,
1361               "0xff<lo=0xf>\0"
1362               "0xff<low-bit#\0");
1363 
1364           // new style, line_max exceeded by named bit-field value in line 2
1365           h_snprintb_m(
1366               "\177\020"
1367               "f\000\004lo\0"
1368               "f\000\004low-bits\0"
1369                     "=\017match\0",
1370               0xff,
1371               16,
1372               "0xff<lo=0xf>\0"
1373               "0xff<low-bits=0#\0");
1374 
1375           // new style, line_max exceeded by named bit-field '=' in line 2
1376           h_snprintb_m(
1377               "\177\020"
1378               "f\000\004lo\0"
1379               "f\000\004low-bits\0"
1380                     "=\017match\0",
1381               0xff,
1382               18,
1383               "0xff<lo=0xf>\0"
1384               "0xff<low-bits=0xf#\0");
1385 
1386           // new style, line_max exceeded by named bit-field value description
1387           // in line 2
1388           h_snprintb_m(
1389               "\177\020"
1390               "f\000\004lo\0"
1391               "f\000\004low-bits\0"
1392                     "=\017match\0",
1393               0xff,
1394               22,
1395               "0xff<lo=0xf>\0"
1396               "0xff<low-bits=0xf=mat#\0");
1397 
1398           // new style, line_max exceeded by named bit-field '>' in line 2
1399           h_snprintb_m(
1400               "\177\020"
1401               "f\000\004lo\0"
1402               "f\000\004low-bits\0"
1403                     "=\017match\0",
1404               0xff,
1405               23,
1406               "0xff<lo=0xf>\0"
1407               "0xff<low-bits=0xf=matc#\0");
1408 
1409           // new style, named bit-field complete
1410           h_snprintb_m(
1411               "\177\020"
1412               "f\000\004lo\0"
1413               "f\000\004low-bits\0"
1414                     "=\017match\0",
1415               0xff,
1416               24,
1417               "0xff<lo=0xf>\0"
1418               "0xff<low-bits=0xf=match>\0");
1419 
1420           // new style, line_max exceeded by unnamed bit-field number in line 1
1421           h_snprintb_m(
1422               "\177\020"
1423               "F\000\004\0",
1424               0xff,
1425               3,
1426               "0x#\0");
1427 
1428           // new style, line_max exceeded by unnamed bit-field '<' in line 1
1429           h_snprintb_m(
1430               "\177\020"
1431               "F\000\004\0",
1432               0xff,
1433               4,
1434               "0xf#\0");
1435 
1436           // new style, line_max exceeded by unnamed bit-field value description
1437           // in line 1
1438           h_snprintb_m(
1439               "\177\020"
1440               "F\000\004\0"
1441                     ":\017match\0",
1442               0xff,
1443               9,
1444               "0xff<mat#\0");
1445 
1446           // new style, line_max exceeded by unnamed bit-field '>' in line 1
1447           h_snprintb_m(
1448               "\177\020"
1449               "F\000\004\0"
1450                     ":\017match\0",
1451               0xff,
1452               10,
1453               "0xff<matc#\0");
1454 
1455           // new style, line_max exceeded by unnamed bit-field value description
1456           // in line 2
1457           h_snprintb_m(
1458               "\177\020"
1459               "F\000\004\0"
1460                     ":\017m1\0"
1461                     ":\017match\0",
1462               0xff,
1463               10,
1464               "0xff<m1ma#\0");
1465 
1466           // new style, line_max exceeded by unnamed bit-field '>' in line 2
1467           h_snprintb_m(
1468               "\177\020"
1469               "F\000\004\0"
1470                     ":\017m1\0"
1471                     ":\017match\0",
1472               0xff,
1473               10,
1474               "0xff<m1ma#\0");
1475 
1476           // new style unnamed bit-field complete
1477           h_snprintb_m(
1478               "\177\020"
1479               "F\000\004\0"
1480                     ":\017m1\0"
1481                     ":\017match\0",
1482               0xff,
1483               13,
1484               "0xff<m1match>\0");
1485 
1486           // new style, line_max exceeded by bit-field default
1487           h_snprintb_m(
1488               "\177\020"
1489               "f\000\004f\0"
1490                     "*=default\0",
1491               0xff,
1492               17,
1493               "0xff<f=0xf=defau#\0");
1494 
1495           // new style, line_max exceeded by unmatched field value
1496           h_snprintb_m(
1497               "\177\020"
1498               "f\000\004bits\0"
1499                     "=\000zero\0",
1500               0xff,
1501               11,
1502               "0xff<bits=#\0");
1503 
1504           // example from the manual page, new style bits and fields
1505           h_snprintb_m(
1506               "\177\020"
1507               "b\000" "LSB\0"
1508               "b\001" "BITONE\0"
1509               "f\004\004" "NIBBLE2\0"
1510               "f\020\004" "BURST\0"
1511                     "=\x04" "FOUR\0"
1512                     "=\x0f" "FIFTEEN\0"
1513               "b\037" "MSB\0",
1514               0x800f0701,
1515               34,
1516               "0x800f0701<LSB,NIBBLE2=0>\0"
1517               "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
1518 
1519           // new style, missing number base
1520           h_snprintb_m_len(
1521               1024,
1522               "\177",
1523               0xff,
1524               128,
1525               -1,
1526               "#\0");
1527 
1528           // new style, buffer too small for complete number in line 2
1529           h_snprintb_m_len(
1530               15,
1531               "\177\020"
1532               "b\000lsb\0"
1533               "b\001two\0",
1534               0xff,
1535               11,
1536               20,
1537               "0xff<lsb>\0"
1538               "0x#\0");
1539 
1540           // new-style format, buffer too small for '<' in line 2
1541           h_snprintb_m_len(
1542               16,
1543               "\177\020"
1544               "b\000lsb\0"
1545               "b\001two\0",
1546               0xff,
1547               11,
1548               20,
1549               "0xff<lsb>\0"
1550               "0xf#\0");
1551 
1552           // new-style format, buffer too small for textual fallback
1553           h_snprintb_m_len(
1554               24,
1555               "\177\020"
1556               "f\000\004bits\0"
1557                     "*=fallback\0"
1558               "b\0024\0",
1559               0xff,
1560               64,
1561               26,
1562               "0xff<bits=0xf=fallbac#\0");
1563 
1564           // new-style format, buffer too small for numeric fallback
1565           h_snprintb_m_len(
1566               20,
1567               "\177\020"
1568               "F\000\004\0"
1569                     "*fallback(%040jd)\0",
1570               0xff,
1571               64,
1572               57,
1573               "0xff<fallback(000#\0");
1574 
1575           // new-style format, buffer too small for numeric fallback past buffer
1576           h_snprintb_m_len(
1577               15,
1578               "\177\020"
1579               "F\000\004\0"
1580                     "*fallback(%010jd)\0"
1581               "F\004\004\0"
1582                     "*fallback(%010jd)\0",
1583               0xff,
1584               64,
1585               48,
1586               "0xff<fallbac#\0");
1587 
1588           // new style, bits and fields, line break between fields
1589           h_snprintb_m(
1590               "\177\020"
1591               "b\0LSB\0"
1592               "b\1_BITONE\0"
1593               "f\4\4NIBBLE2\0"
1594               "f\x10\4BURST\0"
1595                     "=\04FOUR\0"
1596                     "=\17FIFTEEN\0"
1597               "b\x1fMSB\0",
1598               0x800f0701,
1599               33,
1600               "0x800f0701<LSB,NIBBLE2=0>\0"
1601               "0x800f0701<BURST=0xf=FIFTEEN,MSB>\0");
1602 
1603           // new style, bits and fields, line break after field description
1604           h_snprintb_m(
1605               "\177\020"
1606               "b\0LSB\0"
1607               "b\1_BITONE\0"
1608               "f\4\4NIBBLE2\0"
1609               "f\020\4BURST\0"
1610                     "=\04FOUR\0"
1611                     "=\17FIFTEEN\0"
1612               "b\037MSB\0",
1613               0x800f0701,
1614               32,
1615               "0x800f0701<LSB,NIBBLE2=0>\0"
1616               "0x800f0701<BURST=0xf=FIFTEEN>\0"
1617               "0x800f0701<MSB>\0");
1618 }
1619 
ATF_TP_ADD_TCS(tp)1620 ATF_TP_ADD_TCS(tp)
1621 {
1622 
1623           ATF_TP_ADD_TC(tp, snprintb);
1624           ATF_TP_ADD_TC(tp, snprintb_m);
1625 
1626           return atf_no_error();
1627 }
1628