chiark / gitweb /
@@@ fltfmt wip
[mLib] / test / tvec-types.h
1 /* -*-c-*-
2  *
3  * Test-vector framework basic register types
4  *
5  * (c) 2024 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the mLib utilities library.
11  *
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.
16  *
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.
21  *
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,
25  * USA.
26  */
27
28 #ifndef MLIB_TVEC_TYPES_H
29 #define MLIB_TVEC_TYPES_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #ifndef MLIB_TVEC_H
38 #  include "tvec.h"
39 #endif
40
41 /*----- Integer types: signed and unsigned --------------------------------*/
42
43 /* Integers may be input in decimal, hex, binary, or octal, following
44  * approximately usual conventions.
45  *
46  *   * Signed integers may be preceded with a `+' or `-' sign.
47  *
48  *   * Decimal integers are just a sequence of decimal digits `0' ... `9'.
49  *
50  *   * Octal integers are a sequence of digits `0' ... `7', preceded by `0o'
51  *     or `0O'.
52  *
53  *   * Hexadecimal integers are a sequence of digits `0' ... `9', `a'
54  *     ... `f', or `A' ... `F', preceded by `0x' or `0X'.
55  *
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 `_'.
60  *
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.
64  */
65
66 extern const struct tvec_regty tvty_int, tvty_uint;
67
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
72  * %$a$% modulo %$m$%.
73  */
74 struct tvec_irange { long min, max, m, a; };
75 struct tvec_urange { unsigned long min, max, m, a; };
76
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;
84
85 /* --- @tvec_claimeq_int@, @TVEC_CLAIMEQ_INT@ --- *
86  *
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
91  *
92  * Returns:     Nonzero if @i0@ and @i1@ are equal, otherwise zero.
93  *
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.
100  *
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.
105  */
106
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))
113
114 /* --- @tvec_claimeq_uint@, @TVEC_CLAIMEQ_UINT@ --- *
115  *
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
120  *
121  * Returns:     Nonzero if @u0@ and @u1@ are equal, otherwise zero.
122  *
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.
129  *
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.
134  */
135
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))
142
143 /*----- Size type ---------------------------------------------------------*/
144
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'.
147  */
148
149 extern const struct tvec_regty tvty_size;
150
151 /* --- @tvec_claimeq_size@ --- *
152  *
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
157  *
158  * Returns:     Nonzero if @sz0@ and @sz1@ are equal, otherwise zero.
159  *
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.
166  *
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.
171  */
172
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))
178
179 /*----- Floating-point type -----------------------------------------------*/
180
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)
185  * syntax.
186  *
187  * The comparison rules for floating-point numbers are complex: see
188  * @tvec_claimeqish_float@ for details.
189  */
190
191 extern const struct tvec_regty tvty_float;
192
193 struct tvec_floatinfo {
194   /* Details about acceptable floating-point values. */
195
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 */
209 };
210
211 extern const struct tvec_floatinfo
212   tvflt_float, tvflt_double, tvflt_finite, tvflt_nonneg;
213
214 /* --- @tvec_claimeqish_float@, @TVEC_CLAIMEQISH_FLOAT@ --- *
215  *
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
222  *
223  * Returns:     Nonzero if @f0@ and @f1@ are sufficiently close, otherwise
224  *              zero.
225  *
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.
232  *
233  *              The details for the comparison are as follows.
234  *
235  *                * A NaN value matches any other NaN, and nothing else.
236  *
237  *                * An infinity matches another infinity of the same sign,
238  *                  and nothing else.
239  *
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.)
245  *
246  *                * If @f&TVFF_EQMASK@ is @TVFF_ABSDELTA@, then %$x$% matches
247  *                  %$y$% when %$|x - y| < \delta$%.
248  *
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$%.)
255  *
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
260  *              message.
261  */
262
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 ")"))
271
272 /* --- @tvec_claimeq_float@, @TVEC_CLAIMEQ_FLOAT@ --- *
273  *
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
278  *
279  * Returns:     Nonzero if @f0@ and @u1@ are identical, otherwise zero.
280  *
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.
286  */
287
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))
294
295 /*----- Durations ---------------------------------------------------------*/
296
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.
300  */
301
302 extern const struct tvec_regty tvty_duration;
303
304 /* --- @tvec_parsedurunit@ --- *
305  *
306  * Arguments:   @double *scale_out@ = where to leave the scale
307  *              @const char **p_inout@ = input unit string, updated
308  *
309  * Returns:     Zero on success, %$-1$% on error.
310  *
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,
315  *              return %$-1$%.
316  */
317
318 extern int tvec_parsedurunit(double */*scale_out*/,
319                              const char **/*p_inout*/);
320
321 /* --- @tvec_claimeqish_duration@, @TVEC_CLAIMEQISH_DURATION@ --- *
322  *
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
329  *
330  * Returns:     Nonzero if @t0@ and @t1@ are sufficiently close, otherwise
331  *              zero.
332  *
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.
336  *
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
341  *              message.
342  */
343
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 ")"))
352
353 /* --- @tvec_claimeq_duration@, @TVEC_CLAIMEQ_DURATION@ --- *
354  *
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
359  *
360  * Returns:     Nonzero if @t0@ and @t1@ are identical, otherwise zero.
361  *
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.
367  */
368
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))
375
376 /*----- Enumerated types --------------------------------------------------*/
377
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.
382  *
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.
387  *
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
393  * in a comment).
394  */
395
396 #define DEFENUMTY(tag, ty, slot)                                        \
397         extern const struct tvec_regty tvty_##slot##enum;
398 TVEC_MISCSLOTS(DEFENUMTY)
399 #undef DEFENUMTY
400
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)
405 #undef DEFASSOC
406
407 #define TVEC_ENDENUM { 0, 0 }
408
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 */  \
415         };
416
417 #define EXTRA_INT_INFOSLOTS                                             \
418         const struct tvec_irange *ir;   /* allowed range of raw values */
419
420 #define EXTRA_UINT_INFOSLOTS                                            \
421         const struct tvec_urange *ur;   /* allowed range of raw values */
422
423 #define EXTRA_FLT_INFOSLOTS                                             \
424         const struct tvec_floatinfo *fi; /* range and matching policy */
425
426 #define EXTRA_PTR_INFOSLOTS             /* (nothing) */
427
428 TVEC_MISCSLOTS(DEFINFO)
429
430 #undef EXTRA_INT_INFOSLOTS
431 #undef EXTRA_UINT_INFOSLOTS
432 #undef EXTRA_FLT_INFOSLOTS
433 #undef EXTRA_PTR_INFOSLOTS
434
435 #undef DEFINFO
436
437 /* Standard enumerations. */
438 extern const struct tvec_ienuminfo tvenum_bool;
439 extern const struct tvec_ienuminfo tvenum_cmp;
440
441 /* --- @tvec_claimeq_tenum@, @TVEC_CLAIMEQ_TENUM@ --- *
442  *
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
448  *
449  * Returns:     Nonzero if @t0@ and @t1@ are equal, otherwise zero.
450  *
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.
457  *
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.
462  */
463
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)
471 #undef 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))
484
485 /*----- Flags type --------------------------------------------------------*/
486
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
490  * covering bitmask.
491  *
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
496  * given values.
497  *
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.
505  */
506
507 extern const struct tvec_regty tvty_flags;
508
509 struct tvec_flag {
510   /* Definition of a single flag or bitfield value.
511    *
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@.
514    */
515
516   const char *tag;                      /* name */
517   unsigned long m, v;                   /* mask and value */
518 };
519
520 #define TVEC_ENDFLAGS { 0, 0, 0 }
521
522 struct tvec_flaginfo {
523   /* Information about a flags type. */
524
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 */
528 };
529
530 /* --- @tvec_claimeq_flags@, @TVEC_CLAIMEQ_FLAGS@ --- *
531  *
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
537  *
538  * Returns:     Nonzero if @f0@ and @f1@ are equal, otherwise zero.
539  *
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.
546  *
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.
551  */
552
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))
561
562 /*----- Character type ----------------------------------------------------*/
563
564 /* A character value holds a character, as read by @fgetc@.  The special
565  * @EOF@ value can also be represented.
566  *
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
569  * quotes.
570  *
571  * The following escape sequences and character names are recognized.
572  *
573  *   * `%|#eof|%' is the special end-of-file marker.
574  *
575  *   * `%|#nul|%' is the NUL character, sometimes used to terminate strings.
576  *
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
579  *     user's attention).
580  *
581  *   * %|#backspace|%, %|#bs|%, or %|\b|% is the backspace character, used to
582  *     move the cursor backwords by one cell.
583  *
584  *   * %|#escape|% %|#esc|%, or%|\e|% is the escape character, used to
585  *     introduce special terminal commands.
586  *
587  *   * %|#formfeed|%, %|#ff|%, or %|\f|% is the formfeed character, used to
588  *     separate pages of text.
589  *
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
593  *     the line).
594  *
595  *   * %|#return|%, %|#carriage-return|%, %|#cr|%, or %|\r|% is the
596  *     carriage-return character, used to return the cursor to the start of
597  *     the line.
598  *
599  *   * %|#tab|%, %|#horizontal-tab|%, %|#ht|%, or %|\t|% is the tab
600  *     character, used to advance the cursor to the next tab stop on the
601  *     current line.
602  *
603  *   * %|#vertical-tab|%, %|#vt|%, %|\v|% is the vertical tab character.
604  *
605  *   * %|#space|%, %|#spc|% is the space character.
606  *
607  *   * %|#delete|%, %|#del|% is the delete character, used to erase the most
608  *     recent character.
609  *
610  *   * %|\'|% is the single-quote character.
611  *
612  *   * %|\\|% is the backslash character.
613  *
614  *   * %|\"|% is the double-quote character.
615  *
616  *   * %|\NNN|% or %|\{NNN}|% is the character with code NNN in octal.  The
617  *     NNN may be up to three digits long.
618  *
619  *   * %|\xNN|% or %|\x{NN}|% is the character with code NNN in hexadecimal.
620  */
621
622 extern const struct tvec_regty tvty_char;
623
624 /* --- @tvec_claimeq_char@, @TVEC_CLAIMEQ_CHAR@ --- *
625  *
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
630  *
631  * Returns:     Nonzero if @ch0@ and @ch1@ are equal, otherwise zero.
632  *
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.
639  *
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.
644  */
645
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))
652
653 /*----- Text and binary string types --------------------------------------*/
654
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.
661  *
662  * The input format for both kinds of strings is basically the same: a
663  * `compound string', consisting of
664  *
665  *   * single-quoted strings, which are interpreted entirely literally, but
666  *     can't contain single quotes or newlines;
667  *
668  *   * double-quoted strings, in which `%|\|%'-escapes are interpreted as for
669  *     characters;
670  *
671  *   * character names, marked by an initial `%|#|%' sign;
672  *
673  *   * special tokens marked by an initial `%|!|%' sign; or
674  *
675  *   * barewords interpreted according to the current coding scheme.
676  *
677  * The special tokens are
678  *
679  *   * `%|!bare|%', which causes subsequent sequences of barewords to be
680  *     treated as plain text;
681  *
682  *   * `%|!hex|%', `%|!base32|%', `%|!base64|%', which cause subsequent
683  *     barewords to be decoded in the requested manner.
684  *
685  *   * `%|!repeat|% %$n$% %|{|% %%\textit{string}%% %|}|%', which includes
686  *     %$n$% copies of the (compound) string.
687  *
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.
690  *
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.
695  *
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.
698  */
699
700 extern const struct tvec_regty tvty_text, tvty_bytes;
701
702 /* --- @tvec_alloctext@, @tvec_allocbytes@ --- *
703  *
704  * Arguments:   @union tvec_regval *rv@ = register value
705  *              @size_t sz@ = required size
706  *
707  * Returns:     ---
708  *
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@.
717  *
718  *              The @tvec_alloctext@ function sneakily allocates an extra
719  *              byte for a terminating zero.  The @tvec_allocbytes@ function
720  *              doesn't do this.
721  */
722
723 extern void tvec_alloctext(union tvec_regval */*rv*/, size_t /*sz*/);
724 extern void tvec_allocbytes(union tvec_regval */*rv*/, size_t /*sz*/);
725
726 /* --- @tvec_claimeq_text@, @TVEC_CLAIMEQ_TEXT@ --- *
727  *
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
733  *
734  * Returns:     Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
735  *              zero.
736  *
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.
743  *
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.
748  */
749
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 "]"))
758
759 /* --- @tvec_claimeq_textz@, @TVEC_CLAIMEQ_TEXTZ@ --- *
760  *
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
765  *
766  * Returns:     Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
767  *              zero.
768  *
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@.
773  */
774
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))
781
782 /* --- @tvec_claimeq_bytes@, @TVEC_CLAIMEQ_BYTES@ --- *
783  *
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
789  *
790  * Returns:     Nonzero if the strings at @p0@ and @p1@ are equal, otherwise
791  *              zero.
792  *
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.
799  *
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.
804  */
805
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 "]"))
814
815 /*----- Buffer type -------------------------------------------------------*/
816
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.
820  *
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.
830  *
831  * Units other than `B' are used on output only when the size would be
832  * expressed exactly.
833  *
834  * Buffers are %%\emph{not}%% allocated by default.  In benchmarks, this is
835  * best done in a @before@ function.
836  *
837  * No @claimeq@ functions or macros are provided for buffers because they
838  * don't seem very useful.
839  */
840
841 extern const struct tvec_regty tvty_buffer;
842
843 /* --- @tvec_initbuffer@ --- *
844  *
845  * Arguments:   @union tvec_regval *rv@ = register value
846  *              @const union tvec_regval *ref@ = reference buffer
847  *              @size_t sz@ = size to allocate
848  *
849  * Returns:     ---
850  *
851  * Use:         Initialize the alignment parameters in @rv@ to match @ref@,
852  *              and the size to @sz@.
853  */
854
855 extern void tvec_initbuffer(union tvec_regval */*rv*/,
856                             const union tvec_regval */*ref*/, size_t /*sz*/);
857
858 /* --- @tvec_allocbuffer@ --- *
859  *
860  * Arguments:   @union tvec_regval *rv@ = register value
861  *
862  * Returns:     ---
863  *
864  * Use:         Allocate @sz@ bytes to the buffer and fill the space with a
865  *              distinctive pattern.
866  */
867
868 extern void tvec_allocbuffer(union tvec_regval */*rv*/);
869
870 /*----- That's all, folks -------------------------------------------------*/
871
872 #ifdef __cplusplus
873   }
874 #endif
875
876 #endif