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