3 * Test-vector framework basic register types
5 * (c) 2024 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the mLib utilities library.
12 * mLib is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU Library General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or (at
15 * your option) any later version.
17 * mLib is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
20 * License for more details.
22 * You should have received a copy of the GNU Library General Public
23 * License along with mLib. If not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
28 #ifndef MLIB_TVEC_TYPES_H
29 #define MLIB_TVEC_TYPES_H
35 /*----- Header files ------------------------------------------------------*/
41 /*----- Integer types: signed and unsigned --------------------------------*/
43 /* Integers may be input in decimal, hex, binary, or octal, following
44 * approximately usual conventions.
46 * * Signed integers may be preceded with a `+' or `-' sign.
48 * * Decimal integers are just a sequence of decimal digits `0' ... `9'.
50 * * Octal integers are a sequence of digits `0' ... `7', preceded by `0o'
53 * * Hexadecimal integers are a sequence of digits `0' ... `9', `a'
54 * ... `f', or `A' ... `F', preceded by `0x' or `0X'.
56 * * Radix-B integers are a sequence of digits `0' ... `9', `a' ... `f', or
57 * `A' ... `F', each with value less than B, preceded by `Br' or `BR',
58 * where 0 < B < 36 is expressed in decimal without any leading `0' or
59 * internal underscores `_'.
61 * * A digit sequence may contain internal underscore `_' separators, but
62 * not before or after all of the digits; and two consecutive `_'
63 * characters are not permitted.
66 extern const struct tvec_regty tvty_int, tvty_uint;
68 /* The @arg.p@ slot may be null or a pointer to @struct tvec_irange@ or
69 * @struct tvec_urange@ as appropriate. The bounds are inclusive; use, e.g.,
70 * @LONG_MAX@ explicitly if one or the other bound is logically inapplicable.
71 * If %$m$% is nonzero, then the value must additionally be congruent to
74 struct tvec_irange { long min, max, a, m; };
75 struct tvec_urange { unsigned long min, max, a, m; };
77 /* Bounds corresponding to common integer types. */
78 extern const struct tvec_irange
79 tvrange_schar, tvrange_short, tvrange_int, tvrange_long,
80 tvrange_sbyte, tvrange_i16, tvrange_i32;
81 extern const struct tvec_urange
82 tvrange_uchar, tvrange_ushort, tvrange_uint, tvrange_ulong, tvrange_size,
83 tvrange_byte, tvrange_u16, tvrange_u32;
85 /* --- @tvec_claimeq_int@, @TVEC_CLAIMEQ_INT@ --- *
87 * Arguments: @struct tvec_state *tv@ = test-vector state
88 * @long i0, i1@ = two signed integers
89 * @const char *file@, @unsigned @lno@ = calling file and line
90 * @const char *expr@ = the expression to quote on failure
92 * Returns: Nonzero if @i0@ and @i1@ are equal, otherwise zero.
94 * Use: Check that values of @i0@ and @i1@ are equal. As for
95 * @tvec_claim@ above, a test case is automatically begun and
96 * ended if none is already underway. If the values are
97 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
98 * mismatched values are dumped: @i0@ is printed as the output
99 * value and @i1@ is printed as the input reference.
101 * The @TVEC_CLAIM_INT@ macro is similar, only it (a) identifies
102 * the file and line number of the call site automatically, and
103 * (b) implicitly quotes the source text of the @i0@ and @i1@
104 * arguments in the failure message.
107 extern int tvec_claimeq_int(struct tvec_state */*tv*/,
108 long /*i0*/, long /*i1*/,
109 const char */*file*/, unsigned /*lno*/,
110 const char */*expr*/);
111 #define TVEC_CLAIMEQ_INT(tv, i0, i1) \
112 (tvec_claimeq_int(tv, i0, i1, __FILE__, __LINE__, #i0 " /= " #i1))
114 /* --- @tvec_claimeq_uint@, @TVEC_CLAIMEQ_UINT@ --- *
116 * Arguments: @struct tvec_state *tv@ = test-vector state
117 * @unsigned long u0, u1@ = two unsigned integers
118 * @const char *file@, @unsigned @lno@ = calling file and line
119 * @const char *expr@ = the expression to quote on failure
121 * Returns: Nonzero if @u0@ and @u1@ are equal, otherwise zero.
123 * Use: Check that values of @u0@ and @u1@ are equal. As for
124 * @tvec_claim@ above, a test case is automatically begun and
125 * ended if none is already underway. If the values are
126 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
127 * mismatched values are dumped: @u0@ is printed as the output
128 * value and @u1@ is printed as the input reference.
130 * The @TVEC_CLAIM_UINT@ macro is similar, only it (a)
131 * identifies the file and line number of the call site
132 * automatically, and (b) implicitly quotes the source text of
133 * the @u0@ and @u1@ arguments in the failure message.
136 extern int tvec_claimeq_uint(struct tvec_state */*tv*/,
137 unsigned long /*u0*/, unsigned long /*u1*/,
138 const char */*file*/, unsigned /*lno*/,
139 const char */*expr*/);
140 #define TVEC_CLAIMEQ_UINT(tv, u0, u1) \
141 (tvec_claimeq_uint(tv, u0, u1, __FILE__, __LINE__, #u0 " /= " #u1))
143 /*----- Size type ---------------------------------------------------------*/
145 /* A size is an unsigned integer followed by an optional unit specifier
146 * consisting of an SI unit prefix and (optionally) the letter `B'.
149 extern const struct tvec_regty tvty_size;
151 /* --- @tvec_claimeq_size@ --- *
153 * Arguments: @struct tvec_state *tv@ = test-vector state
154 * @unsigned long sz0, sz1@ = two sizes
155 * @const char *file@, @unsigned @lno@ = calling file and line
156 * @const char *expr@ = the expression to quote on failure
158 * Returns: Nonzero if @sz0@ and @sz1@ are equal, otherwise zero.
160 * Use: Check that values of @u0@ and @u1@ are equal. As for
161 * @tvec_claim@ above, a test case is automatically begun and
162 * ended if none is already underway. If the values are
163 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
164 * mismatched values are dumped: @u0@ is printed as the output
165 * value and @u1@ is printed as the input reference.
167 * The @TVEC_CLAIM_SIZE@ macro is similar, only it (a)
168 * identifies the file and line number of the call site
169 * automatically, and (b) implicitly quotes the source text of
170 * the @u0@ and @u1@ arguments in the failure message.
173 int tvec_claimeq_size(struct tvec_state *tv,
174 unsigned long sz0, unsigned long sz1,
175 const char *file, unsigned lno, const char *expr);
176 #define TVEC_CLAIMEQ_UINT(tv, u0, u1) \
177 (tvec_claimeq_uint(tv, u0, u1, __FILE__, __LINE__, #u0 " /= " #u1))
179 /*----- Floating-point type -----------------------------------------------*/
181 /* Floating-point values are either NaN (%|#nan|%, if supported by the
182 * platform); positive or negative infinity (%|#inf|%, %|+#inf|%, or
183 * %|#+inf|% (preferring the last), and %|-#inf|% or %|#-inf|% (preferring
184 * the latter), if supported by the platform); or a number in strtod(3)
187 * The comparison rules for floating-point numbers are complex: see
188 * @tvec_claimeqish_float@ for details.
191 extern const struct tvec_regty tvty_float;
193 struct tvec_floatinfo {
194 /* Details about acceptable floating-point values. */
196 unsigned f; /* flags (@TVFF_...@ bits) */
197 #define TVFF_NOMIN 0x0001 /* ignore @min@ (allow -∞) */
198 #define TVFF_NOMAX 0x0002 /* ignore @max@ (allow +∞) */
199 #define TVFF_NANOK 0x0004 /* permit NaN */
200 #define TVFF_NEGINFOK 0x0008 /* permit -∞, check finite */
201 #define TVFF_POSINFOK 0x0010 /* permit +∞, check finite */
202 #define TVFF_INFOK (TVFF_NEGINFOK | TVFF_POSINFOK) /* permit ±∞ */
203 #define TVFF_EQMASK 0x0f00 /* how to compare */
204 #define TVFF_EXACT 0x0000 /* must equal exactly */
205 #define TVFF_ABSDELTA 0x0100 /* must be within @delta@ */
206 #define TVFF_RELDELTA 0x0200 /* diff < @delta@ fraction */
207 double min, max; /* smallest/largest value allowed */
208 double delta; /* maximum tolerable difference */
211 extern const struct tvec_floatinfo
212 tvflt_float, tvflt_double, tvflt_finite, tvflt_nonneg;
214 /* --- @tvec_claimeqish_float@, @TVEC_CLAIMEQISH_FLOAT@ --- *
216 * Arguments: @struct tvec_state *tv@ = test-vector state
217 * @double f0, f1@ = two floating-point numbers
218 * @unsigned f@ = flags (@TVFF_...@)
219 * @double delta@ = maximum tolerable difference
220 * @const char *file@, @unsigned @lno@ = calling file and line
221 * @const char *expr@ = the expression to quote on failure
223 * Returns: Nonzero if @f0@ and @f1@ are sufficiently close, otherwise
226 * Use: Check that values of @f0@ and @f1@ are sufficiently close.
227 * As for @tvec_claim@ above, a test case is automatically begun
228 * and ended if none is already underway. If the values are
229 * too far apart, then @tvec_fail@ is called, quoting @expr@,
230 * and the mismatched values are dumped: @f0@ is printed as the
231 * output value and @f1@ is printed as the input reference.
233 * The details for the comparison are as follows.
235 * * A NaN value matches any other NaN, and nothing else.
237 * * An infinity matches another infinity of the same sign,
240 * * If @f&TVFF_EQMASK@ is @TVFF_EXACT@, then any
241 * representable number matches only itself: in particular,
242 * positive and negative zero are considered distinct.
243 * (This allows tests to check that they land on the correct
244 * side of branch cuts, for example.)
246 * * If @f&TVFF_EQMASK@ is @TVFF_ABSDELTA@, then %$x$% matches
247 * %$y$% when %$|x - y| < \delta$%.
249 * * If @f&TVFF_EQMASK@ is @TVFF_RELDELTA@, then %$x$% matches
250 * %$y$% when %$|1 - x/y| < \delta$%. (Note that this
251 * criterion is asymmetric. Write %$x \approx_\delta y$%
252 * if and only if %$|1 - x/y < \delta$%. Then, for example,
253 * if %$y/(1 + \delta) < x < y (1 - \delta)$%, then
254 * %$x \approx_\delta y$%, but %$y \not\approx_\delta x$%.)
256 * The @TVEC_CLAIM_FLOAT@ macro is similar, only it (a)
257 * identifies the file and line number of the call site
258 * automatically, and (b) implicitly quotes the source text of
259 * the @f0@ and @f1@ arguments (and @delta@) in the failure
263 extern int tvec_claimeqish_float(struct tvec_state */*tv*/,
264 double /*f0*/, double /*f1*/,
265 unsigned /*f*/, double /*delta*/,
266 const char */*file*/, unsigned /*lno*/,
267 const char */*expr*/);
268 #define TVEC_CLAIMEQISH_FLOAT(tv, f0, f1, f, delta) \
269 (tvec_claimeqish_float(tv, f0, f1, f, delta, __FILE__, __LINE__, \
270 #f0 " /= " #f1 " (+/- " #delta ")"))
272 /* --- @tvec_claimeq_float@, @TVEC_CLAIMEQ_FLOAT@ --- *
274 * Arguments: @struct tvec_state *tv@ = test-vector state
275 * @double f0, f1@ = two floating-point numbers
276 * @const char *file@, @unsigned @lno@ = calling file and line
277 * @const char *expr@ = the expression to quote on failure
279 * Returns: Nonzero if @f0@ and @u1@ are identical, otherwise zero.
281 * Use: Check that values of @f0@ and @f1@ are identical. The
282 * function is exactly equivalent to @tvec_claimeqish_float@
283 * with @f == TVFF_EXACT@; the macro is similarly like
284 * @TVEC_CLAIMEQISH_FLOAT@ with @f == TVFF_EXACT@, except that
285 * it doesn't bother to quote a delta.
288 extern int tvec_claimeq_float(struct tvec_state */*tv*/,
289 double /*f0*/, double /*f1*/,
290 const char */*file*/, unsigned /*lno*/,
291 const char */*expr*/);
292 #define TVEC_CLAIMEQ_FLOAT(tv, f0, f1) \
293 (tvec_claimeq_float(tv, f0, f1, __FILE__, __LINE__, #f0 " /= " #f1))
295 /*----- Durations ---------------------------------------------------------*/
297 /* A duration measures a time interval in seconds. The input format consists
298 * of a nonnegative decimal floating-point number in @strtod@ format followed
299 * by an optional unit specification.
302 extern const struct tvec_regty tvty_duration;
304 /* --- @tvec_parsedurunit@ --- *
306 * Arguments: @double *scale_out@ = where to leave the scale
307 * @const char **p_inout@ = input unit string, updated
309 * Returns: Zero on success, %$-1$% on error.
311 * Use: If @*p_inout@ begins with a unit string followed by the end
312 * of the string or some non-alphanumeric character, then store
313 * the corresponding scale factor in @*scale_out@, advance
314 * @*p_inout@ past the unit string, and return zero. Otherwise,
318 extern int tvec_parsedurunit(double */*scale_out*/,
319 const char **/*p_inout*/);
321 /* --- @tvec_claimeqish_duration@, @TVEC_CLAIMEQISH_DURATION@ --- *
323 * Arguments: @struct tvec_state *tv@ = test-vector state
324 * @double t0, t1@ = two durations
325 * @unsigned f@ = flags (@TVFF_...@)
326 * @double delta@ = maximum tolerable difference
327 * @const char *file@, @unsigned @lno@ = calling file and line
328 * @const char *expr@ = the expression to quote on failure
330 * Returns: Nonzero if @t0@ and @t1@ are sufficiently close, otherwise
333 * Use: Check that values of @t0@ and @t1@ are sufficiently close.
334 * This is essentially the same as @tvec_claimeqish_float@, only
335 * it dumps the values as durations on a mismatch.
337 * The @TVEC_CLAIM_FLOAT@ macro is similar, only it (a)
338 * identifies the file and line number of the call site
339 * automatically, and (b) implicitly quotes the source text of
340 * the @t0@ and @t1@ arguments (and @delta@) in the failure
344 extern int tvec_claimeqish_duration(struct tvec_state */*tv*/,
345 double /*t0*/, double /*t1*/,
346 unsigned /*f*/, double /*delta*/,
347 const char */*file*/, unsigned /*lno*/,
348 const char */*expr*/);
349 #define TVEC_CLAIMEQISH_DURATION(tv, t0, t1, f, delta) \
350 (tvec_claimeqish_duration(tv, t0, t1, f, delta, __FILE__, __LINE__, \
351 #t0 " /= " #t1 " (+/- " #delta ")"))
353 /* --- @tvec_claimeq_duration@, @TVEC_CLAIMEQ_DURATION@ --- *
355 * Arguments: @struct tvec_state *tv@ = test-vector state
356 * @double t0, t1@ = two durations
357 * @const char *file@, @unsigned @lno@ = calling file and line
358 * @const char *expr@ = the expression to quote on failure
360 * Returns: Nonzero if @t0@ and @t1@ are identical, otherwise zero.
362 * Use: Check that values of @t0@ and @t1@ are identical. The
363 * function is exactly equivalent to @tvec_claimeqish_duration@
364 * with @f == TVFF_EXACT@; the macro is similarly like
365 * @TVEC_CLAIMEQISH_DURATION@ with @f == TVFF_EXACT@, except
366 * that it doesn't bother to quote a delta.
369 int tvec_claimeq_duration(struct tvec_state */*tv*/,
370 double /*t0*/, double /*t1*/,
371 const char */*file*/, unsigned /*lno*/,
372 const char */*expr*/);
373 #define TVEC_CLAIMEQ_DURATION(tv, t0, t1) \
374 (tvec_claimeq_float(tv, t0, t1, __FILE__, __LINE__, #t0 " /= " #t1))
376 /*----- Enumerated types --------------------------------------------------*/
378 /* An enumeration describes a set of values of some underlying type, each of
379 * which has a symbolic name. Values outside of the defined set can occur --
380 * on output, because of bugs in the tested code, or on input to test
381 * handling of unexpected values.
383 * There is a distinct enumerated type for each of the branches of
384 * @tvec_misc@. In the following, we write @t@ for the type code, which is
385 * @i@ for signed integer, @u@ for unsigned integer, @f@ for floating-point,
386 * and @p@ for pointer.
388 * On input, an enumerated value may be given by name or as a literal value.
389 * For enumerations based on numeric types, the literal values can be written
390 * in the same syntax as the underlying values. For enumerations based on
391 * pointers, the only permitted literal is %|#nil|%, which denotes a null
392 * pointer. On output, names are preferred (with the underlying value given
396 #define DEFENUMTY(tag, ty, slot) \
397 extern const struct tvec_regty tvty_##slot##enum;
398 TVEC_MISCSLOTS(DEFENUMTY)
401 /* A @struct tvec_tassoc@ associates a string tag with a value. */
402 #define DEFASSOC(tag_, ty, slot) \
403 struct tvec_##slot##assoc { const char *tag; ty slot; };
404 TVEC_MISCSLOTS(DEFASSOC)
407 #define TVEC_ENDENUM { 0, 0 }
409 /* Information about an enumerated type. */
410 #define DEFINFO(tag, ty, slot) \
411 struct tvec_##slot##enuminfo { \
412 const char *name; /* type name for diagnostics */ \
413 const struct tvec_##slot##assoc *av; /* name/value mappings */ \
414 EXTRA_##tag##_INFOSLOTS /* type-specific extra info */ \
417 #define EXTRA_INT_INFOSLOTS \
418 const struct tvec_irange *ir; /* allowed range of raw values */
420 #define EXTRA_UINT_INFOSLOTS \
421 const struct tvec_urange *ur; /* allowed range of raw values */
423 #define EXTRA_FLT_INFOSLOTS \
424 const struct tvec_floatinfo *fi; /* range and matching policy */
426 #define EXTRA_PTR_INFOSLOTS /* (nothing) */
428 TVEC_MISCSLOTS(DEFINFO)
430 #undef EXTRA_INT_INFOSLOTS
431 #undef EXTRA_UINT_INFOSLOTS
432 #undef EXTRA_FLT_INFOSLOTS
433 #undef EXTRA_PTR_INFOSLOTS
437 /* Standard enumerations. */
438 extern const struct tvec_ienuminfo tvenum_bool;
439 extern const struct tvec_ienuminfo tvenum_cmp;
441 /* --- @tvec_claimeq_tenum@, @TVEC_CLAIMEQ_TENUM@, @TVEC_CLAIMEQ_PTR@ --- *
443 * Arguments: @struct tvec_state *tv@ = test-vector state
444 * @const struct tvec_typeenuminfo *ei@ = enumeration type info
445 * @ty t0, t1@ = two values
446 * @const char *file@, @unsigned @lno@ = calling file and line
447 * @const char *expr@ = the expression to quote on failure
449 * Returns: Nonzero if @t0@ and @t1@ are equal, otherwise zero.
451 * Use: Check that values of @t0@ and @t1@ are equal. As for
452 * @tvec_claim@ above, a test case is automatically begun and
453 * ended if none is already underway. If the values are
454 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
455 * mismatched values are dumped: @t0@ is printed as the output
456 * value and @t1@ is printed as the input reference.
458 * The @ei@ argument to @tvec_claimeq_penum@ (but not the other
459 * functions) may be null, as a hack for comparing two plain
462 * The @TVEC_CLAIM_TENUM@ macro is similar, only it (a)
463 * identifies the file and line number of the call site
464 * automatically, and (b) implicitly quotes the source text of
465 * the @t0@ and @t1@ arguments in the failure message. The
466 * @TVEC_CLAIMEQ_PTR@ macro simply compares two pointers in the
470 #define DECLCLAIM(tag, ty, slot) \
471 extern int tvec_claimeq_##slot##enum \
472 (struct tvec_state */*tv*/, \
473 const struct tvec_##slot##enuminfo */*ei*/, \
474 ty /*t0*/, ty /*t1*/, \
475 const char */*file*/, unsigned /*lno*/, const char */*expr*/);
476 TVEC_MISCSLOTS(DECLCLAIM)
478 #define TVEC_CLAIMEQ_IENUM(tv, ei, i0, i1) \
479 (tvec_claimeq_ienum(tv, ei, i0, i1, \
480 __FILE__, __LINE__, #i0 " /= " #i1))
481 #define TVEC_CLAIMEQ_UENUM(tv, ei, u0, u1) \
482 (tvec_claimeq_uenum(tv, ei, u0, u1, \
483 __FILE__, __LINE__, #u0 " /= " #u1))
484 #define TVEC_CLAIMEQ_FENUM(tv, ei, f0, f1) \
485 (tvec_claimeq_fenum(tv, ei, f0, f1, \
486 __FILE__, __LINE__, #f0 " /= " #f1))
487 #define TVEC_CLAIMEQ_PENUM(tv, ei, p0, p1) \
488 (tvec_claimeq_penum(tv, ei, p0, p1, \
489 __FILE__, __LINE__, #p0 " /= " #p1))
490 #define TVEC_CLAIMEQ_PTR(tv, p0, p1) \
491 (tvec_claimeq_penum(tv, 0, p0, p1, \
492 __FILE__, __LINE__, #p0 " /= " #p1))
494 /*----- Flags type --------------------------------------------------------*/
496 /* A flags value packs a number of fields into a single nonnegative integer.
497 * Symbolic names are associated with the possible values of the various
498 * fields; more precisely, each name is associated with a value and a
501 * The input syntax is a sequence of items separated by `%|||%' signs. Each
502 * item may be the symbolic name of a field value, or a literal unsigned
503 * integer. The masks associated with the given symbolic names must be
504 * disjoint. The resulting numerical value is simply the bitwise OR of the
507 * On output, the table of symbolic names and their associated values and
508 * masks is repeatedly scanned, in order, to find disjoint matches -- i.e.,
509 * entries whose value matches the target value in the bit positions
510 * indicated by the mask, and whose mask doesn't overlap with any previously
511 * found matches; the names are then output, separated by `%|||%'. Any
512 * remaining nonzero bits not covered by any of the matching masks are output
513 * as a single literal integer, in hex.
516 extern const struct tvec_regty tvty_flags;
519 /* Definition of a single flag or bitfield value.
521 * Each named setting comes with a value @v@ and a mask @m@; the mask
522 * should cover all of the value bits, i.e., @(v&~m) == 0@.
525 const char *tag; /* name */
526 unsigned long m, v; /* mask and value */
529 #define TVEC_ENDFLAGS { 0, 0, 0 }
531 struct tvec_flaginfo {
532 /* Information about a flags type. */
534 const char *name; /* type name for diagnostics */
535 const struct tvec_flag *fv; /* name/mask/value mappings */
536 const struct tvec_urange *range; /* permitted range for literals */
539 /* --- @tvec_claimeq_flags@, @TVEC_CLAIMEQ_FLAGS@ --- *
541 * Arguments: @struct tvec_state *tv@ = test-vector state
542 * @const struct tvec_flaginfo *fi@ = flags type info
543 * @unsigned long f0, f1@ = two values
544 * @const char *file@, @unsigned @lno@ = calling file and line
545 * @const char *expr@ = the expression to quote on failure
547 * Returns: Nonzero if @f0@ and @f1@ are equal, otherwise zero.
549 * Use: Check that values of @f0@ and @f1@ are equal. As for
550 * @tvec_claim@ above, a test case is automatically begun and
551 * ended if none is already underway. If the values are
552 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
553 * mismatched values are dumped: @f0@ is printed as the output
554 * value and @f1@ is printed as the input reference.
556 * The @TVEC_CLAIM_FLAGS@ macro is similar, only it (a)
557 * identifies the file and line number of the call site
558 * automatically, and (b) implicitly quotes the source text of
559 * the @f0@ and @f1@ arguments in the failure message.
562 extern int tvec_claimeq_flags(struct tvec_state */*tv*/,
563 const struct tvec_flaginfo */*fi*/,
564 unsigned long /*f0*/, unsigned long /*f1*/,
565 const char */*file*/, unsigned /*lno*/,
566 const char */*expr*/);
567 #define TVEC_CLAIMEQ_FLAGS(tv, fi, f0, f1) \
568 (tvec_claimeq_flags(tv, fi, f0, f1, \
569 __FILE__, __LINE__, #f0 " /= " #f1))
571 /*----- Character type ----------------------------------------------------*/
573 /* A character value holds a character, as read by @fgetc@. The special
574 * @EOF@ value can also be represented.
576 * On input, a character value can be given by symbolic name, with a leading
577 * `%|#|%'; or a character or `%|\|%'-escape sequence, optionally in single
580 * The following escape sequences and character names are recognized.
582 * * `%|#eof|%' is the special end-of-file marker.
584 * * `%|#nul|%' is the NUL character, sometimes used to terminate strings.
586 * * `%|bell|%', `%|bel|%', `%|ding|%', or `%|\a|%' is the BEL character
587 * used to ring the terminal bell (or do some other thing to attract the
590 * * %|#backspace|%, %|#bs|%, or %|\b|% is the backspace character, used to
591 * move the cursor backwords by one cell.
593 * * %|#escape|% %|#esc|%, or%|\e|% is the escape character, used to
594 * introduce special terminal commands.
596 * * %|#formfeed|%, %|#ff|%, or %|\f|% is the formfeed character, used to
597 * separate pages of text.
599 * * %|#newline|%, %|#linefeed|%, %|#lf|%, %|#nl|%, or %|\n|% is the
600 * newline character, used to terminate lines of text or advance the
601 * cursor to the next line (perhaps without returning it to the start of
604 * * %|#return|%, %|#carriage-return|%, %|#cr|%, or %|\r|% is the
605 * carriage-return character, used to return the cursor to the start of
608 * * %|#tab|%, %|#horizontal-tab|%, %|#ht|%, or %|\t|% is the tab
609 * character, used to advance the cursor to the next tab stop on the
612 * * %|#vertical-tab|%, %|#vt|%, %|\v|% is the vertical tab character.
614 * * %|#space|%, %|#spc|% is the space character.
616 * * %|#delete|%, %|#del|% is the delete character, used to erase the most
619 * * %|\'|% is the single-quote character.
621 * * %|\\|% is the backslash character.
623 * * %|\"|% is the double-quote character.
625 * * %|\NNN|% or %|\{NNN}|% is the character with code NNN in octal. The
626 * NNN may be up to three digits long.
628 * * %|\xNN|% or %|\x{NN}|% is the character with code NNN in hexadecimal.
631 extern const struct tvec_regty tvty_char;
633 /* --- @tvec_claimeq_char@, @TVEC_CLAIMEQ_CHAR@ --- *
635 * Arguments: @struct tvec_state *tv@ = test-vector state
636 * @int ch0, ch1@ = two character codes
637 * @const char *file@, @unsigned @lno@ = calling file and line
638 * @const char *expr@ = the expression to quote on failure
640 * Returns: Nonzero if @ch0@ and @ch1@ are equal, otherwise zero.
642 * Use: Check that values of @ch0@ and @ch1@ are equal. As for
643 * @tvec_claim@ above, a test case is automatically begun and
644 * ended if none is already underway. If the values are
645 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
646 * mismatched values are dumped: @ch0@ is printed as the output
647 * value and @ch1@ is printed as the input reference.
649 * The @TVEC_CLAIM_CHAR@ macro is similar, only it (a)
650 * identifies the file and line number of the call site
651 * automatically, and (b) implicitly quotes the source text of
652 * the @ch0@ and @ch1@ arguments in the failure message.
655 extern int tvec_claimeq_char(struct tvec_state */*tv*/,
656 int /*ch0*/, int /*ch1*/,
657 const char */*file*/, unsigned /*lno*/,
658 const char */*expr*/);
659 #define TVEC_CLAIMEQ_CHAR(tv, c0, c1) \
660 (tvec_claimeq_char(tv, c0, c1, __FILE__, __LINE__, #c0 " /= " #c1))
662 /*----- Text and binary string types --------------------------------------*/
664 /* A string is a sequence of octets. Text and binary strings differ
665 * primarily in presentation: text strings are shown as raw characters where
666 * possible; binary strings are shown as hex dumps with an auxiliary text
667 * display. Storage for strings always uses the standard C library
668 * allocator, though applications will probably need to call @malloc@ or
669 * @free@ only rarely.
671 * The input format for both kinds of strings is basically the same: a
672 * `compound string', consisting of
674 * * single-quoted strings, which are interpreted entirely literally, but
675 * can't contain single quotes or newlines;
677 * * double-quoted strings, in which `%|\|%'-escapes are interpreted as for
680 * * character names, marked by an initial `%|#|%' sign;
682 * * special tokens marked by an initial `%|!|%' sign; or
684 * * barewords interpreted according to the current coding scheme.
686 * The special tokens are
688 * * `%|!bare|%', which causes subsequent sequences of barewords to be
689 * treated as plain text;
691 * * `%|!hex|%', `%|!base32|%', `%|!base64|%', which cause subsequent
692 * barewords to be decoded in the requested manner.
694 * * `%|!repeat|% %$n$% %|{|% %%\textit{string}%% %|}|%', which includes
695 * %$n$% copies of the (compound) string.
697 * The only difference between text and binary strings is that the initial
698 * coding scheme is %|bare|% for text strings and %|hex|% for binary strings.
700 * Either kind of string can contain internal nul characters. A trailing nul
701 * is appended -- beyond the stated input length -- to input strings as a
702 * convenience to test functions. Test functions may include such a nul
703 * character on output but this is not checked by the equality test.
705 * A @struct tvec_urange@ may be supplied as an argument: the length of the
706 * string (in bytes) will be checked against the permitted range.
709 extern const struct tvec_regty tvty_text, tvty_bytes;
711 /* --- @tvec_alloctext@, @tvec_allocbytes@ --- *
713 * Arguments: @union tvec_regval *rv@ = register value
714 * @size_t sz@ = required size
718 * Use: Allocated space in a text or binary string register. If the
719 * current register size is sufficient, its buffer is left
720 * alone; otherwise, the old buffer, if any, is freed and a
721 * fresh buffer allocated. These functions are not intended to
722 * be used to adjust a buffer repeatedly, e.g., while building
723 * output incrementally: (a) they will perform badly, and (b)
724 * the old buffer contents are simply discarded if reallocation
725 * is necessary. Instead, use a @dbuf@ or @dstr@.
727 * The @tvec_alloctext@ function sneakily allocates an extra
728 * byte for a terminating zero. The @tvec_allocbytes@ function
732 extern void tvec_alloctext(union tvec_regval */*rv*/, size_t /*sz*/);
733 extern void tvec_allocbytes(union tvec_regval */*rv*/, size_t /*sz*/);
735 /* --- @tvec_claimeq_text@, @TVEC_CLAIMEQ_TEXT@ --- *
737 * Arguments: @struct tvec_state *tv@ = test-vector state
738 * @const char *p0@, @size_t sz0@ = first string with length
739 * @const char *p1@, @size_t sz1@ = second string with length
740 * @const char *file@, @unsigned @lno@ = calling file and line
741 * @const char *expr@ = the expression to quote on failure
743 * Returns: Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
746 * Use: Check that strings at @p0@ and @p1@ are equal. As for
747 * @tvec_claim@ above, a test case is automatically begun and
748 * ended if none is already underway. If the values are
749 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
750 * mismatched values are dumped: @p0@ is printed as the output
751 * value and @p1@ is printed as the input reference.
753 * The @TVEC_CLAIM_TEXT@ macro is similar, only it (a)
754 * identifies the file and line number of the call site
755 * automatically, and (b) implicitly quotes the source text of
756 * the @ch0@ and @ch1@ arguments in the failure message.
759 extern int tvec_claimeq_text(struct tvec_state */*tv*/,
760 const char */*p0*/, size_t /*sz0*/,
761 const char */*p1*/, size_t /*sz1*/,
762 const char */*file*/, unsigned /*lno*/,
763 const char */*expr*/);
764 #define TVEC_CLAIMEQ_TEXT(tv, p0, sz0, p1, sz1) \
765 (tvec_claimeq_text(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \
766 #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
768 /* --- @tvec_claimeq_textz@, @TVEC_CLAIMEQ_TEXTZ@ --- *
770 * Arguments: @struct tvec_state *tv@ = test-vector state
771 * @const char *p0, *p1@ = two strings to compare
772 * @const char *file@, @unsigned @lno@ = calling file and line
773 * @const char *expr@ = the expression to quote on failure
775 * Returns: Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
778 * Use: Check that strings at @p0@ and @p1@ are equal, as for
779 * @tvec_claimeq_string@, except that the strings are assumed
780 * null-terminated, so their lengths don't need to be supplied
781 * explicitly. The macro is similarly like @TVEC_CLAIMEQ_TEXT@.
784 extern int tvec_claimeq_textz(struct tvec_state */*tv*/,
785 const char */*p0*/, const char */*p1*/,
786 const char */*file*/, unsigned /*lno*/,
787 const char */*expr*/);
788 #define TVEC_CLAIMEQ_TEXTZ(tv, p0, p1) \
789 (tvec_claimeq_textz(tv, p0, p1, __FILE__, __LINE__, #p0 " /= " #p1))
791 /* --- @tvec_claimeq_bytes@, @TVEC_CLAIMEQ_BYTES@ --- *
793 * Arguments: @struct tvec_state *tv@ = test-vector state
794 * @const void *p0@, @size_t sz0@ = first string with length
795 * @const void *p1@, @size_t sz1@ = second string with length
796 * @const char *file@, @unsigned @lno@ = calling file and line
797 * @const char *expr@ = the expression to quote on failure
799 * Returns: Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
802 * Use: Check that binary strings at @p0@ and @p1@ are equal. As for
803 * @tvec_claim@ above, a test case is automatically begun and
804 * ended if none is already underway. If the values are
805 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
806 * mismatched values are dumped: @p0@ is printed as the output
807 * value and @p1@ is printed as the input reference.
809 * The @TVEC_CLAIM_STRING@ macro is similar, only it (a)
810 * identifies the file and line number of the call site
811 * automatically, and (b) implicitly quotes the source text of
812 * the @ch0@ and @ch1@ arguments in the failure message.
815 extern int tvec_claimeq_bytes(struct tvec_state */*tv*/,
816 const void */*p0*/, size_t /*sz0*/,
817 const void */*p1*/, size_t /*sz1*/,
818 const char */*file*/, unsigned /*lno*/,
819 const char */*expr*/);
820 #define TVEC_CLAIMEQ_BYTES(tv, p0, sz0, p1, sz1) \
821 (tvec_claimeq(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \
822 #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
824 /*----- Buffer type -------------------------------------------------------*/
826 /* Buffer registers are primarily used for benchmarking. Only a buffer's
827 * allocation parameters are significant: its contents are ignored on
828 * comparison and output, and unspecified on input.
830 * The input format gives the buffer's size, and an optional alignment
831 * specification, in the form %|SZ [`@' M [`+' A]]|%. Each of %|SZ|%, %|M|%
832 * and %|A|% are sizes, as an integer, optionally suffixed with a unit `kB',
833 * `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or without the `B')
834 * denoting a power of 1024. The %|SZ|% gives the (effective) buffer size.
835 * %|M|% is the `alignment quantum' and %|A|% is the `alignment offset'; both
836 * default to zero, but if %|M|% is nonzero then the start of the buffer is
837 * aligned such that it is %|A|% more than a multiple of %|M|% bytes. Note
838 * that %|M|% need not be a power of two, though this is common.
840 * Units other than `B' are used on output only when the size would be
843 * Buffers are %%\emph{not}%% allocated by default. In benchmarks, this is
844 * best done in a @before@ function.
846 * No @claimeq@ functions or macros are provided for buffers because they
847 * don't seem very useful.
850 extern const struct tvec_regty tvty_buffer;
852 /* --- @tvec_initbuffer@ --- *
854 * Arguments: @union tvec_regval *rv@ = register value
855 * @const union tvec_regval *ref@ = reference buffer
856 * @size_t sz@ = size to allocate
860 * Use: Initialize the alignment parameters in @rv@ to match @ref@,
861 * and the size to @sz@.
864 extern void tvec_initbuffer(union tvec_regval */*rv*/,
865 const union tvec_regval */*ref*/, size_t /*sz*/);
867 /* --- @tvec_allocbuffer@ --- *
869 * Arguments: @union tvec_regval *rv@ = register value
873 * Use: Allocate @sz@ bytes to the buffer and fill the space with a
874 * distinctive pattern.
877 extern void tvec_allocbuffer(union tvec_regval */*rv*/);
879 /*----- That's all, folks -------------------------------------------------*/