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@ --- *
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 @TVEC_CLAIM_TENUM@ macro is similar, only it (a)
459 * identifies the file and line number of the call site
460 * automatically, and (b) implicitly quotes the source text of
461 * the @t0@ and @t1@ arguments in the failure message.
464 #define DECLCLAIM(tag, ty, slot) \
465 extern int tvec_claimeq_##slot##enum \
466 (struct tvec_state */*tv*/, \
467 const struct tvec_##slot##enuminfo */*ei*/, \
468 ty /*t0*/, ty /*t1*/, \
469 const char */*file*/, unsigned /*lno*/, const char */*expr*/);
470 TVEC_MISCSLOTS(DECLCLAIM)
472 #define TVEC_CLAIMEQ_IENUM(tv, ei, i0, i1) \
473 (tvec_claimeq_ienum(tv, ei, i0, i1, \
474 __FILE__, __LINE__, #i0 " /= " #i1))
475 #define TVEC_CLAIMEQ_UENUM(tv, ei, u0, u1) \
476 (tvec_claimeq_uenum(tv, ei, u0, u1, \
477 __FILE__, __LINE__, #u0 " /= " #u1))
478 #define TVEC_CLAIMEQ_FENUM(tv, ei, f0, f1) \
479 (tvec_claimeq_fenum(tv, ei, f0, f1, \
480 __FILE__, __LINE__, #f0 " /= " #f1))
481 #define TVEC_CLAIMEQ_PENUM(tv, ei, p0, p1) \
482 (tvec_claimeq_penum(tv, ei, p0, p1, \
483 __FILE__, __LINE__, #p0 " /= " #p1))
485 /*----- Flags type --------------------------------------------------------*/
487 /* A flags value packs a number of fields into a single nonnegative integer.
488 * Symbolic names are associated with the possible values of the various
489 * fields; more precisely, each name is associated with a value and a
492 * The input syntax is a sequence of items separated by `%|||%' signs. Each
493 * item may be the symbolic name of a field value, or a literal unsigned
494 * integer. The masks associated with the given symbolic names must be
495 * disjoint. The resulting numerical value is simply the bitwise OR of the
498 * On output, the table of symbolic names and their associated values and
499 * masks is repeatedly scanned, in order, to find disjoint matches -- i.e.,
500 * entries whose value matches the target value in the bit positions
501 * indicated by the mask, and whose mask doesn't overlap with any previously
502 * found matches; the names are then output, separated by `%|||%'. Any
503 * remaining nonzero bits not covered by any of the matching masks are output
504 * as a single literal integer, in hex.
507 extern const struct tvec_regty tvty_flags;
510 /* Definition of a single flag or bitfield value.
512 * Each named setting comes with a value @v@ and a mask @m@; the mask
513 * should cover all of the value bits, i.e., @(v&~m) == 0@.
516 const char *tag; /* name */
517 unsigned long m, v; /* mask and value */
520 #define TVEC_ENDFLAGS { 0, 0, 0 }
522 struct tvec_flaginfo {
523 /* Information about a flags type. */
525 const char *name; /* type name for diagnostics */
526 const struct tvec_flag *fv; /* name/mask/value mappings */
527 const struct tvec_urange *range; /* permitted range for literals */
530 /* --- @tvec_claimeq_flags@, @TVEC_CLAIMEQ_FLAGS@ --- *
532 * Arguments: @struct tvec_state *tv@ = test-vector state
533 * @const struct tvec_flaginfo *fi@ = flags type info
534 * @unsigned long f0, f1@ = two values
535 * @const char *file@, @unsigned @lno@ = calling file and line
536 * @const char *expr@ = the expression to quote on failure
538 * Returns: Nonzero if @f0@ and @f1@ are equal, otherwise zero.
540 * Use: Check that values of @f0@ and @f1@ are equal. As for
541 * @tvec_claim@ above, a test case is automatically begun and
542 * ended if none is already underway. If the values are
543 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
544 * mismatched values are dumped: @f0@ is printed as the output
545 * value and @f1@ is printed as the input reference.
547 * The @TVEC_CLAIM_FLAGS@ macro is similar, only it (a)
548 * identifies the file and line number of the call site
549 * automatically, and (b) implicitly quotes the source text of
550 * the @f0@ and @f1@ arguments in the failure message.
553 extern int tvec_claimeq_flags(struct tvec_state */*tv*/,
554 const struct tvec_flaginfo */*fi*/,
555 unsigned long /*f0*/, unsigned long /*f1*/,
556 const char */*file*/, unsigned /*lno*/,
557 const char */*expr*/);
558 #define TVEC_CLAIMEQ_FLAGS(tv, fi, f0, f1) \
559 (tvec_claimeq_flags(tv, fi, f0, f1, \
560 __FILE__, __LINE__, #f0 " /= " #f1))
562 /*----- Character type ----------------------------------------------------*/
564 /* A character value holds a character, as read by @fgetc@. The special
565 * @EOF@ value can also be represented.
567 * On input, a character value can be given by symbolic name, with a leading
568 * `%|#|%'; or a character or `%|\|%'-escape sequence, optionally in single
571 * The following escape sequences and character names are recognized.
573 * * `%|#eof|%' is the special end-of-file marker.
575 * * `%|#nul|%' is the NUL character, sometimes used to terminate strings.
577 * * `%|bell|%', `%|bel|%', `%|ding|%', or `%|\a|%' is the BEL character
578 * used to ring the terminal bell (or do some other thing to attract the
581 * * %|#backspace|%, %|#bs|%, or %|\b|% is the backspace character, used to
582 * move the cursor backwords by one cell.
584 * * %|#escape|% %|#esc|%, or%|\e|% is the escape character, used to
585 * introduce special terminal commands.
587 * * %|#formfeed|%, %|#ff|%, or %|\f|% is the formfeed character, used to
588 * separate pages of text.
590 * * %|#newline|%, %|#linefeed|%, %|#lf|%, %|#nl|%, or %|\n|% is the
591 * newline character, used to terminate lines of text or advance the
592 * cursor to the next line (perhaps without returning it to the start of
595 * * %|#return|%, %|#carriage-return|%, %|#cr|%, or %|\r|% is the
596 * carriage-return character, used to return the cursor to the start of
599 * * %|#tab|%, %|#horizontal-tab|%, %|#ht|%, or %|\t|% is the tab
600 * character, used to advance the cursor to the next tab stop on the
603 * * %|#vertical-tab|%, %|#vt|%, %|\v|% is the vertical tab character.
605 * * %|#space|%, %|#spc|% is the space character.
607 * * %|#delete|%, %|#del|% is the delete character, used to erase the most
610 * * %|\'|% is the single-quote character.
612 * * %|\\|% is the backslash character.
614 * * %|\"|% is the double-quote character.
616 * * %|\NNN|% or %|\{NNN}|% is the character with code NNN in octal. The
617 * NNN may be up to three digits long.
619 * * %|\xNN|% or %|\x{NN}|% is the character with code NNN in hexadecimal.
622 extern const struct tvec_regty tvty_char;
624 /* --- @tvec_claimeq_char@, @TVEC_CLAIMEQ_CHAR@ --- *
626 * Arguments: @struct tvec_state *tv@ = test-vector state
627 * @int ch0, ch1@ = two character codes
628 * @const char *file@, @unsigned @lno@ = calling file and line
629 * @const char *expr@ = the expression to quote on failure
631 * Returns: Nonzero if @ch0@ and @ch1@ are equal, otherwise zero.
633 * Use: Check that values of @ch0@ and @ch1@ are equal. As for
634 * @tvec_claim@ above, a test case is automatically begun and
635 * ended if none is already underway. If the values are
636 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
637 * mismatched values are dumped: @ch0@ is printed as the output
638 * value and @ch1@ is printed as the input reference.
640 * The @TVEC_CLAIM_CHAR@ macro is similar, only it (a)
641 * identifies the file and line number of the call site
642 * automatically, and (b) implicitly quotes the source text of
643 * the @ch0@ and @ch1@ arguments in the failure message.
646 extern int tvec_claimeq_char(struct tvec_state */*tv*/,
647 int /*ch0*/, int /*ch1*/,
648 const char */*file*/, unsigned /*lno*/,
649 const char */*expr*/);
650 #define TVEC_CLAIMEQ_CHAR(tv, c0, c1) \
651 (tvec_claimeq_char(tv, c0, c1, __FILE__, __LINE__, #c0 " /= " #c1))
653 /*----- Text and binary string types --------------------------------------*/
655 /* A string is a sequence of octets. Text and binary strings differ
656 * primarily in presentation: text strings are shown as raw characters where
657 * possible; binary strings are shown as hex dumps with an auxiliary text
658 * display. Storage for strings always uses the standard C library
659 * allocator, though applications will probably need to call @malloc@ or
660 * @free@ only rarely.
662 * The input format for both kinds of strings is basically the same: a
663 * `compound string', consisting of
665 * * single-quoted strings, which are interpreted entirely literally, but
666 * can't contain single quotes or newlines;
668 * * double-quoted strings, in which `%|\|%'-escapes are interpreted as for
671 * * character names, marked by an initial `%|#|%' sign;
673 * * special tokens marked by an initial `%|!|%' sign; or
675 * * barewords interpreted according to the current coding scheme.
677 * The special tokens are
679 * * `%|!bare|%', which causes subsequent sequences of barewords to be
680 * treated as plain text;
682 * * `%|!hex|%', `%|!base32|%', `%|!base64|%', which cause subsequent
683 * barewords to be decoded in the requested manner.
685 * * `%|!repeat|% %$n$% %|{|% %%\textit{string}%% %|}|%', which includes
686 * %$n$% copies of the (compound) string.
688 * The only difference between text and binary strings is that the initial
689 * coding scheme is %|bare|% for text strings and %|hex|% for binary strings.
691 * Either kind of string can contain internal nul characters. A trailing nul
692 * is appended -- beyond the stated input length -- to input strings as a
693 * convenience to test functions. Test functions may include such a nul
694 * character on output but this is not checked by the equality test.
696 * A @struct tvec_urange@ may be supplied as an argument: the length of the
697 * string (in bytes) will be checked against the permitted range.
700 extern const struct tvec_regty tvty_text, tvty_bytes;
702 /* --- @tvec_alloctext@, @tvec_allocbytes@ --- *
704 * Arguments: @union tvec_regval *rv@ = register value
705 * @size_t sz@ = required size
709 * Use: Allocated space in a text or binary string register. If the
710 * current register size is sufficient, its buffer is left
711 * alone; otherwise, the old buffer, if any, is freed and a
712 * fresh buffer allocated. These functions are not intended to
713 * be used to adjust a buffer repeatedly, e.g., while building
714 * output incrementally: (a) they will perform badly, and (b)
715 * the old buffer contents are simply discarded if reallocation
716 * is necessary. Instead, use a @dbuf@ or @dstr@.
718 * The @tvec_alloctext@ function sneakily allocates an extra
719 * byte for a terminating zero. The @tvec_allocbytes@ function
723 extern void tvec_alloctext(union tvec_regval */*rv*/, size_t /*sz*/);
724 extern void tvec_allocbytes(union tvec_regval */*rv*/, size_t /*sz*/);
726 /* --- @tvec_claimeq_text@, @TVEC_CLAIMEQ_TEXT@ --- *
728 * Arguments: @struct tvec_state *tv@ = test-vector state
729 * @const char *p0@, @size_t sz0@ = first string with length
730 * @const char *p1@, @size_t sz1@ = second string with length
731 * @const char *file@, @unsigned @lno@ = calling file and line
732 * @const char *expr@ = the expression to quote on failure
734 * Returns: Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
737 * Use: Check that strings at @p0@ and @p1@ are equal. As for
738 * @tvec_claim@ above, a test case is automatically begun and
739 * ended if none is already underway. If the values are
740 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
741 * mismatched values are dumped: @p0@ is printed as the output
742 * value and @p1@ is printed as the input reference.
744 * The @TVEC_CLAIM_TEXT@ macro is similar, only it (a)
745 * identifies the file and line number of the call site
746 * automatically, and (b) implicitly quotes the source text of
747 * the @ch0@ and @ch1@ arguments in the failure message.
750 extern int tvec_claimeq_text(struct tvec_state */*tv*/,
751 const char */*p0*/, size_t /*sz0*/,
752 const char */*p1*/, size_t /*sz1*/,
753 const char */*file*/, unsigned /*lno*/,
754 const char */*expr*/);
755 #define TVEC_CLAIMEQ_TEXT(tv, p0, sz0, p1, sz1) \
756 (tvec_claimeq_text(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \
757 #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
759 /* --- @tvec_claimeq_textz@, @TVEC_CLAIMEQ_TEXTZ@ --- *
761 * Arguments: @struct tvec_state *tv@ = test-vector state
762 * @const char *p0, *p1@ = two strings to compare
763 * @const char *file@, @unsigned @lno@ = calling file and line
764 * @const char *expr@ = the expression to quote on failure
766 * Returns: Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
769 * Use: Check that strings at @p0@ and @p1@ are equal, as for
770 * @tvec_claimeq_string@, except that the strings are assumed
771 * null-terminated, so their lengths don't need to be supplied
772 * explicitly. The macro is similarly like @TVEC_CLAIMEQ_TEXT@.
775 extern int tvec_claimeq_textz(struct tvec_state */*tv*/,
776 const char */*p0*/, const char */*p1*/,
777 const char */*file*/, unsigned /*lno*/,
778 const char */*expr*/);
779 #define TVEC_CLAIMEQ_TEXTZ(tv, p0, p1) \
780 (tvec_claimeq_textz(tv, p0, p1, __FILE__, __LINE__, #p0 " /= " #p1))
782 /* --- @tvec_claimeq_bytes@, @TVEC_CLAIMEQ_BYTES@ --- *
784 * Arguments: @struct tvec_state *tv@ = test-vector state
785 * @const void *p0@, @size_t sz0@ = first string with length
786 * @const void *p1@, @size_t sz1@ = second string with length
787 * @const char *file@, @unsigned @lno@ = calling file and line
788 * @const char *expr@ = the expression to quote on failure
790 * Returns: Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
793 * Use: Check that binary strings at @p0@ and @p1@ are equal. As for
794 * @tvec_claim@ above, a test case is automatically begun and
795 * ended if none is already underway. If the values are
796 * unequal, then @tvec_fail@ is called, quoting @expr@, and the
797 * mismatched values are dumped: @p0@ is printed as the output
798 * value and @p1@ is printed as the input reference.
800 * The @TVEC_CLAIM_STRING@ macro is similar, only it (a)
801 * identifies the file and line number of the call site
802 * automatically, and (b) implicitly quotes the source text of
803 * the @ch0@ and @ch1@ arguments in the failure message.
806 extern int tvec_claimeq_bytes(struct tvec_state */*tv*/,
807 const void */*p0*/, size_t /*sz0*/,
808 const void */*p1*/, size_t /*sz1*/,
809 const char */*file*/, unsigned /*lno*/,
810 const char */*expr*/);
811 #define TVEC_CLAIMEQ_BYTES(tv, p0, sz0, p1, sz1) \
812 (tvec_claimeq(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \
813 #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
815 /*----- Buffer type -------------------------------------------------------*/
817 /* Buffer registers are primarily used for benchmarking. Only a buffer's
818 * allocation parameters are significant: its contents are ignored on
819 * comparison and output, and unspecified on input.
821 * The input format gives the buffer's size, and an optional alignment
822 * specification, in the form %|SZ [`@' M [`+' A]]|%. Each of %|SZ|%, %|M|%
823 * and %|A|% are sizes, as an integer, optionally suffixed with a unit `kB',
824 * `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or without the `B')
825 * denoting a power of 1024. The %|SZ|% gives the (effective) buffer size.
826 * %|M|% is the `alignment quantum' and %|A|% is the `alignment offset'; both
827 * default to zero, but if %|M|% is nonzero then the start of the buffer is
828 * aligned such that it is %|A|% more than a multiple of %|M|% bytes. Note
829 * that %|M|% need not be a power of two, though this is common.
831 * Units other than `B' are used on output only when the size would be
834 * Buffers are %%\emph{not}%% allocated by default. In benchmarks, this is
835 * best done in a @before@ function.
837 * No @claimeq@ functions or macros are provided for buffers because they
838 * don't seem very useful.
841 extern const struct tvec_regty tvty_buffer;
843 /* --- @tvec_initbuffer@ --- *
845 * Arguments: @union tvec_regval *rv@ = register value
846 * @const union tvec_regval *ref@ = reference buffer
847 * @size_t sz@ = size to allocate
851 * Use: Initialize the alignment parameters in @rv@ to match @ref@,
852 * and the size to @sz@.
855 extern void tvec_initbuffer(union tvec_regval */*rv*/,
856 const union tvec_regval */*ref*/, size_t /*sz*/);
858 /* --- @tvec_allocbuffer@ --- *
860 * Arguments: @union tvec_regval *rv@ = register value
864 * Use: Allocate @sz@ bytes to the buffer and fill the space with a
865 * distinctive pattern.
868 extern void tvec_allocbuffer(union tvec_regval */*rv*/);
870 /*----- That's all, folks -------------------------------------------------*/