chiark / gitweb /
2309edf744da022fad2a28c993690e5b3ced03c8
[mLib] / test / tvec.h
1 /* -*-c-*-
2  *
3  * Test vector processing framework
4  *
5  * (c) 2023 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_H
29 #define MLIB_TVEC_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stdarg.h>
38 #include <stddef.h>
39 #include <stdio.h>
40 #include <string.h>
41
42 #ifndef MLIB_BUF_H
43 #  include "buf.h"
44 #endif
45
46 #ifndef MLIB_CONTROL_H
47 #  include "control.h"
48 #endif
49
50 #ifndef MLIB_BUF_H
51 #  include "dstr.h"
52 #endif
53
54 #ifndef MLIB_MACROS_H
55 #  include "macros.h"
56 #endif
57
58 /*----- Miscellaneous values ----------------------------------------------*/
59
60 /* These are attached to structures which represent extension points, as a
61  * way to pass an opaque parameter to whatever things are hooked onto them.
62  */
63
64 #define TVEC_MISCSLOTS(_)                                               \
65         _(PTR, const void *, p)         /* arbitrary pointer */         \
66         _(INT, long, i)                 /* signed integer */            \
67         _(UINT, unsigned long, u)       /* signed integer */
68
69 union tvec_misc {
70 #define TVEC_DEFSLOT(tag, ty, slot) ty slot;
71   TVEC_MISCSLOTS(TVEC_DEFSLOT)
72 #undef TVEC_DEFSLOT
73 };
74 enum {
75 #define TVEC_DEFCONST(tag, ty, slot) TVMISC_##tag,
76   TVEC_MISCSLOTS(TVEC_DEFCONST)
77   TVMISC_LIMIT
78 };
79
80 /*----- Register values ---------------------------------------------------*/
81
82 /* The framework doesn't have a preconceived idea about what's in a register
83  * value: it just allocates them and accesses them through the register type
84  * functions.  It doesn't even have a baked-in idea of how big a register
85  * value is: instead, it gets that via the `regsz' slot in `struct
86  * tvec_testinfo'.  So, as far as the framework is concerned, it's safe to
87  * add new slots to this union, even if they make the overall union larger.
88  * This can be done by defining the preprocessor macro `TVEC_REGSLOTS' to be
89  * a `union' fragment defining any additional union members.
90  *
91  * This creates a distinction between code which does and doesn't know the
92  * size of a register value.  Code which does, which typically means the test
93  * functions, benchmarking setup and teardown functions, and tightly-bound
94  * runner functions, is free to index the register vectors directly.  Code
95  * which doesn't, which means the framework core itself and output formatting
96  * machinery, must use the `TVEC_REG' macro (or its more general `TVEC_GREG'
97  * companion) for indexing register vectors.  (In principle, register type
98  * handlers also fit into this category, but they have no business peering
99  * into register values other than the one's they're given.)
100  */
101
102 union tvec_regval {
103         /* The actual register value.  This is what the type handler sees.
104          * Additional members can be added by setting `TVEC_REGSLOTS' before
105          * including this file.
106          *
107          * A register value can be /initialized/, which simply means that its
108          * contents represent a valid value according to its type -- the
109          * register can be compared, dumped, serialized, parsed into, etc.
110          * You can't do anything safely to an uninitialized register value
111          * other than initialize it.
112          */
113
114   long i;                               /* signed integer */
115   unsigned long u;                      /* unsigned integer */
116   void *p;                              /* pointer */
117   struct { unsigned char *p; size_t sz; } bytes; /* binary string of bytes */
118   struct { char *p; size_t sz; } str;   /* text string */
119 #ifdef TVEC_REGSLOTS
120   TVEC_REGSLOTS
121 #endif
122 };
123
124 struct tvec_reg {
125         /* A register.
126          *
127          * Note that all of the registers listed as being used by a
128          * particular test group are initialized at all times[1] while that
129          * test group is being processed.  (The other register slots don't
130          * even have types associated with them, so there's nothing useful we
131          * could do with them.)
132          *
133          * The `TVRF_LIVE' flag indicates that the register was assigned a
134          * value by the test vector file: it's the right thing to use to
135          * check whether an optional register is actually present.  Even
136          * `dead' registers are still initialized, though.
137          *
138          * [1] This isn't quite true.  Between individual tests, the
139          *     registers are released and reinitialized in order to reset
140          *     them to known values ready for the next test.  But you won't
141          *     see them at this point.
142          */
143
144   unsigned f;                           /* flags */
145 #define TVRF_LIVE 1u                    /*   used in current test  */
146   union tvec_regval v;                  /* register value */
147 };
148
149 struct tvec_regdef {
150         /* A register definition.  Register definitions list the registers
151          * which are used by a particular test group (see `struct tvec_test'
152          * below).
153          *
154          * A vector of register definitions is terminated by a definition
155          * whose `name' slot is null.
156          */
157
158   const char *name;                     /* register name (for input files) */
159   unsigned i;                           /* register index */
160   const struct tvec_regty *ty;          /* register type descriptor */
161   unsigned f;                           /* flags */
162 #define TVRF_OPT 1u                     /*   optional register */
163 #define TVRF_ID 2u                      /*   part of test identity  */
164   union tvec_misc arg;                  /* extra detail for the type */
165 };
166
167 extern int tvec_serialize(const struct tvec_reg */*rv*/,
168                           const struct tvec_regdef */*regs*/,
169                           unsigned /*nr*/, size_t /*regsz*/,
170                           void **/*p_out*/, size_t */*sz_out*/);
171
172 extern int tvec_deserialize(struct tvec_reg */*rv*/,
173                             const struct tvec_regdef */*regs*/,
174                             unsigned /*nr*/, size_t /*regsz*/,
175                             const void */*p*/, size_t /*sz*/);
176
177 /*----- Test state --------------------------------------------------------*/
178
179 enum { TVOUT_LOSE, TVOUT_SKIP, TVOUT_WIN, TVOUT_LIMIT };
180
181 struct tvec_state {
182   unsigned f;                           /* flags */
183 #define TVSF_SKIP 1u                    /*   skip this test group */
184 #define TVSF_OPEN 2u                    /*   test is open */
185 #define TVSF_ACTIVE 4u                  /*   test is active */
186 #define TVSF_ERROR 8u                   /*   an error occurred */
187 #define TVSF_OUTMASK 0xf0               /*   test outcome */
188 #define TVSF_OUTSHIFT 4
189   unsigned nrout, nreg;                /* number of output/total registers */
190   size_t regsz;                         /* size of register entry */
191   struct tvec_reg *in, *out;            /* register vectors */
192   char expst, st;                       /* progress status codes */
193   const struct tvec_test *tests, *test; /* all tests and current test */
194   unsigned curr[TVOUT_LIMIT], all[TVOUT_LIMIT], grps[TVOUT_LIMIT];
195   struct tvec_output *output;           /* output formatter */
196   const char *infile; unsigned lno, test_lno; /* input file name, line */
197   FILE *fp;                             /* input file stream */
198 };
199
200 #define TVEC_GREG(vec, i, regsz)                                        \
201         ((struct tvec_reg *)((unsigned char *)(vec) + (i)*(regsz)))
202 #define TVEC_REG(tv, vec, i) TVEC_GREG((tv)->vec, (i), (tv)->regsz)
203
204 /*----- Test descriptions -------------------------------------------------*/
205
206 typedef int tvec_hookfn(struct tvec_state */*tv*/);
207 typedef void tvec_testfn(const struct tvec_reg */*in*/,
208                          struct tvec_reg */*out*/,
209                          void */*ctx*/);
210
211 struct tvec_test {
212   const char *name;                     /* name of the test */
213   const struct tvec_regdef *regs;       /* descriptions of the registers */
214   tvec_hookfn *preflight;               /* check before starting */
215   tvec_hookfn *run;                     /* test runner */
216   tvec_testfn *fn;                      /* test function */
217   union tvec_misc arg;                  /* additional parameter to `run' */
218 };
219
220 extern void PRINTF_LIKE(2, 3)
221   tvec_check(struct tvec_state */*tv*/, const char */*detail*/, ...);
222 extern void tvec_check_v(struct tvec_state */*tv*/,
223                          const char */*detail*/, va_list */*ap*/);
224
225 extern int tvec_runtest(struct tvec_state */*tv*/);
226
227 /*----- Input utilities ---------------------------------------------------*/
228
229 extern void tvec_skipspc(struct tvec_state */*tv*/);
230
231 #define TVFF_ALLOWANY 1u
232 extern int tvec_flushtoeol(struct tvec_state */*tv*/, unsigned /*f*/);
233
234 extern int PRINTF_LIKE(4, 5)
235   tvec_readword(struct tvec_state */*tv*/, dstr */*d*/,
236                 const char */*delims*/, const char */*expect*/, ...);
237 extern int tvec_readword_v(struct tvec_state */*tv*/, dstr */*d*/,
238                            const char */*delims*/, const char */*expect*/,
239                            va_list */*ap*/);
240
241 extern int tvec_nexttoken(struct tvec_state */*tv*/);
242
243 /*----- Session lifecycle -------------------------------------------------*/
244
245 struct tvec_info {
246   const struct tvec_test *tests;
247   unsigned nrout, nreg;
248   size_t regsz;
249 };
250
251 extern void tvec_begin(struct tvec_state */*tv_out*/,
252                        const struct tvec_info */*info*/,
253                        struct tvec_output */*o*/);
254 extern int tvec_end(struct tvec_state */*tv*/);
255
256 extern int tvec_read(struct tvec_state */*tv*/,
257                      const char */*infile*/, FILE */*fp*/);
258
259 /*----- Benchmarking ------------------------------------------------------*/
260
261 struct tvec_bench {
262   unsigned long niter;                  /* iterations done per unit */
263   int riter, rbuf;                      /* iterations and buffer registers */
264   size_t ctxsz;                         /* size of context */
265   int (*setup)(const struct tvec_reg */*in*/, struct tvec_reg */*out*/,
266                const union tvec_misc */*arg*/, void */*ctx*/); /* setup fn */
267   void (*teardown)(void */*ctx*/);      /* teardown function, or null */
268   struct bench_state **b;               /* benchmark state anchor or null */
269   union tvec_misc arg;                  /* argument to setup */
270 };
271
272 extern struct bench_state *tvec_benchstate;
273
274 extern int tvec_ensurebench(struct tvec_state */*tv*/,
275                             struct bench_state **/*b_out*/);
276 extern int tvec_bench(struct tvec_state */*tv*/);
277
278 /*----- Ad-hoc testing ----------------------------------------------------*/
279
280 extern void tvec_adhoc(struct tvec_state */*tv*/, struct tvec_test */*t*/);
281
282 extern void tvec_begingroup(struct tvec_state */*tv*/, const char */*name*/,
283                             const char */*file*/, unsigned /*lno*/);
284 extern void tvec_reportgroup(struct tvec_state */*tv*/);
285 extern void tvec_endgroup(struct tvec_state */*tv*/);
286
287 #define TVEC_BEGINGROUP(tv, name)                                       \
288         do tvec_begingroup(tv, name, __FILE__, __LINE__); while (0)
289
290 #define TVEC_TESTGROUP(tag, tv, name)                                   \
291         MC_WRAP(tag##__around,                                          \
292           { TVEC_BEGINGROUP(tv, name); },                               \
293           { tvec_endgroup(tv); },                                       \
294           { if (!((tv)->f&TVSF_SKIP)) tvec_skipgroup(tv, 0);            \
295             tvec_endgroup(tv); })
296
297 extern void tvec_begintest(struct tvec_state */*tv*/,
298                            const char */*file*/, unsigned /*lno*/);
299 extern void tvec_endtest(struct tvec_state */*tv*/);
300
301 #define TVEC_BEGINTEST(tv)                                              \
302         do tvec_begintest(tv, __FILE__, __LINE__); while (0)
303
304 #define TVEC_TEST(tag, tv)                                              \
305         MC_WRAP(tag##__around,                                          \
306           { TVEC_BEGINTEST(tv); },                                      \
307           { tvec_endtest(tv); },                                        \
308           { if ((tv)->f&TVSF_ACTIVE) tvec_skipgroup((tv), 0);           \
309             tvec_endtest(tv); })
310
311 extern int PRINTF_LIKE(5, 6)
312   tvec_claim(struct tvec_state */*tv*/, int /*ok*/,
313              const char */*file*/, unsigned /*lno*/,
314              const char */*expr*/, ...);
315
316 #define TVEC_CLAIM(tv, cond)                                            \
317         (tvec_claim(tv, !!(cond), __FILE__, __LINE__, #cond " untrue"))
318
319 extern int tvec_claimeq(struct tvec_state */*tv*/,
320                         const struct tvec_regty */*ty*/,
321                         const union tvec_misc */*arg*/,
322                         const char */*file*/, unsigned /*lno*/,
323                         const char */*expr*/);
324
325 /*----- Command-line interface --------------------------------------------*/
326
327 extern const struct tvec_info tvec_adhocinfo;
328
329 extern void tvec_parseargs(int /*argc*/, char */*argv*/[],
330                            struct tvec_state */*tv_out*/,
331                            int */*argpos_out*/,
332                            const struct tvec_info */*info*/);
333
334 extern int tvec_readstdin(struct tvec_state */*tv*/);
335 extern int tvec_readfile(struct tvec_state */*tv*/, const char */*file*/);
336 extern int tvec_readdflt(struct tvec_state */*tv*/, const char */*file*/);
337 extern int tvec_readarg(struct tvec_state */*tv*/, const char */*arg*/);
338
339 extern int tvec_readargs(int /*argc*/, char */*argv*/[],
340                          struct tvec_state */*tv*/,
341                          int */*argpos_inout*/, const char */*dflt*/);
342
343 extern int tvec_main(int /*argc*/, char */*argv*/[],
344                      const struct tvec_info */*info*/,
345                      const char */*dflt*/);
346
347 /*----- Output formatting -------------------------------------------------*/
348
349 struct tvec_output {
350   const struct tvec_outops *ops;
351   struct tvec_state *tv;
352 };
353
354 struct bench_timing;
355
356 struct tvec_outops {
357   void (*error)(struct tvec_output */*o*/,
358                 const char */*msg*/, va_list */*ap*/);
359   void (*notice)(struct tvec_output */*o*/,
360                  const char */*msg*/, va_list */*ap*/);
361   void (*write)(struct tvec_output */*o*/, const char */*p*/, size_t /*sz*/);
362
363   void (*bsession)(struct tvec_output */*o*/);
364   int (*esession)(struct tvec_output */*o*/);
365
366   void (*bgroup)(struct tvec_output */*o*/);
367   void (*egroup)(struct tvec_output */*o*/, unsigned /*outcome*/);
368   void (*skipgroup)(struct tvec_output */*o*/,
369                     const char */*excuse*/, va_list */*ap*/);
370
371   void (*btest)(struct tvec_output */*o*/);
372   void (*skip)(struct tvec_output */*o*/,
373                const char */*excuse*/, va_list */*ap*/);
374   void (*fail)(struct tvec_output */*o*/,
375                const char */*detail*/, va_list */*ap*/);
376   void (*mismatch)(struct tvec_output */*o*/);
377   void (*etest)(struct tvec_output */*o*/, unsigned /*outcome*/);
378
379   void (*bbench)(struct tvec_output */*o*/);
380   void (*ebench)(struct tvec_output */*o*/,
381                  const struct bench_timing */*tm*/);
382
383   void (*destroy)(struct tvec_output */*o*/);
384 };
385
386 extern int PRINTF_LIKE(2, 3)
387   tvec_error(struct tvec_state */*tv*/, const char */*msg*/, ...);
388 extern int tvec_error_v(struct tvec_state */*tv*/,
389                         const char */*msg*/, va_list */*ap*/);
390
391 extern void PRINTF_LIKE(2, 3)
392   tvec_notice(struct tvec_state */*tv*/, const char */*msg*/, ...);
393 extern void tvec_notice_v(struct tvec_state */*tv*/,
394                           const char */*msg*/, va_list */*ap*/);
395
396 extern int PRINTF_LIKE(3, 4)
397   tvec_syntax(struct tvec_state */*tv*/, int /*ch*/,
398               const char */*expect*/, ...);
399 extern int tvec_syntax_v(struct tvec_state */*tv*/, int /*ch*/,
400                          const char */*expect*/, va_list */*ap*/);
401
402 extern void PRINTF_LIKE(2, 3)
403   tvec_skipgroup(struct tvec_state */*tv*/, const char */*note*/, ...);
404 extern void tvec_skipgroup_v(struct tvec_state */*tv*/,
405                              const char */*note*/, va_list */*ap*/);
406
407 extern void PRINTF_LIKE(2, 3)
408   tvec_skip(struct tvec_state */*tv*/, const char */*excuse*/, ...);
409 extern void tvec_skip_v(struct tvec_state */*tv*/,
410                         const char */*excuse*/, va_list */*ap*/);
411
412 extern void PRINTF_LIKE(2, 3)
413   tvec_fail(struct tvec_state */*tv*/, const char */*detail*/, ...);
414 extern void tvec_fail_v(struct tvec_state */*tv*/,
415                         const char */*detail*/, va_list */*ap*/);
416
417 extern void tvec_mismatch(struct tvec_state */*tv*/);
418
419 extern void PRINTF_LIKE(2, 3)
420   tvec_write(struct tvec_state */*tv*/, const char */*p*/, ...);
421 extern void tvec_write_v(struct tvec_state */*tv*/,
422                          const char */*p*/, va_list */*ap*/);
423
424 extern struct tvec_output *tvec_humanoutput(FILE */*fp*/);
425 extern struct tvec_output *tvec_tapoutput(FILE */*fp*/);
426 extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
427
428 /*----- Register types ----------------------------------------------------*/
429
430 struct tvec_regty {
431   void (*init)(union tvec_regval */*rv*/, const struct tvec_regdef */*rd*/);
432   void (*release)(union tvec_regval */*rv*/,
433                   const struct tvec_regdef */*rd*/);
434   int (*eq)(const union tvec_regval */*rv0*/,
435             const union tvec_regval */*rv1*/,
436             const struct tvec_regdef */*rd*/);
437   size_t (*measure)(const union tvec_regval */*rv*/,
438                     const struct tvec_regdef */*rd*/);
439   int (*tobuf)(buf */*b*/, const union tvec_regval */*rv*/,
440                const struct tvec_regdef */*rd*/);
441   int (*frombuf)(buf */*b*/, union tvec_regval */*rv*/,
442                  const struct tvec_regdef */*rd*/);
443   int (*parse)(union tvec_regval */*rv*/, const struct tvec_regdef */*rd*/,
444                struct tvec_state */*tv*/);
445   void (*dump)(const union tvec_regval */*rv*/,
446                const struct tvec_regdef */*rd*/,
447                struct tvec_state */*tv*/, unsigned /*style*/);
448 #define TVSF_COMPACT 1u
449 };
450
451 extern const struct tvec_regty tvty_int, tvty_uint;
452 struct tvec_irange { long min, max; };
453 struct tvec_urange { unsigned long min, max; };
454
455 extern const struct tvec_irange
456   tvrange_schar, tvrange_short, tvrange_int, tvrange_long,
457   tvrange_sbyte, tvrange_i16, tvrange_i32;
458 extern const struct tvec_urange
459   tvrange_uchar, tvrange_ushort, tvrange_uint, tvrange_ulong, tvrange_size,
460   tvrange_byte, tvrange_u16, tvrange_u32;
461
462 extern int tvec_claimeq_int(struct tvec_state */*tv*/,
463                             long /*i0*/, long /*i1*/,
464                             const char */*file*/, unsigned /*lno*/,
465                             const char */*expr*/);
466 extern int tvec_claimeq_uint(struct tvec_state */*tv*/,
467                             unsigned long /*u0*/, unsigned long /*u1*/,
468                             const char */*file*/, unsigned /*lno*/,
469                             const char */*expr*/);
470 #define TVEC_CLAIMEQ_INT(tv, i0, i1)                                    \
471         (tvec_claimeq_int(tv, i0, i1, __FILE__, __LINE__, #i0 " /= " #i1))
472 #define TVEC_CLAIMEQ_UINT(tv, u0, u1)                                   \
473         (tvec_claimeq_uint(tv, u0, u1, __FILE__, __LINE__, #u0 " /= " #u1))
474
475 extern const struct tvec_regty tvty_enum;
476
477 #define DEFASSOC(tag_, ty, slot)                                        \
478         struct tvec_##slot##assoc { const char *tag; ty slot; };
479 TVEC_MISCSLOTS(DEFASSOC)
480 #undef DEFASSOC
481
482 struct tvec_enuminfo {
483   const char *name; unsigned mv;
484   union {
485 #define DEFENUMINFO(tag, ty, slot) struct {                             \
486           const struct tvec_##slot##assoc *av;                          \
487           RANGESLOT_##tag                                               \
488         } slot;
489 #define RANGESLOT_INT const struct tvec_irange *ir;
490 #define RANGESLOT_UINT const struct tvec_urange *ur;
491 #define RANGESLOT_PTR
492     TVEC_MISCSLOTS(DEFENUMINFO)
493 #undef DEFENUMINFO
494 #undef RANGESLOT_INT
495 #undef RANGESLOT_UINT
496 #undef RANGESLOT_PTR
497   } u;
498 };
499
500 #define DECLCLAIM(tag, ty, slot)                                        \
501         extern int tvec_claimeq_##slot##enum                            \
502           (struct tvec_state */*tv*/,                                   \
503            const struct tvec_enuminfo */*ei*/, ty /*e0*/, ty /*e1*/,    \
504            const char */*file*/, unsigned /*lno*/, const char */*expr*/);
505 TVEC_MISCSLOTS(DECLCLAIM)
506 #undef DECLCLAIM
507 #define TVEC_CLAIMEQ_IENUM(tv, ei, e0, e1)                              \
508         (tvec_claimeq_ienum(tv, ei, e0, e1,                             \
509                             __FILE__, __LINE__, #e0 " /= " #e1))
510 #define TVEC_CLAIMEQ_UENUM(tv, ei, e0, e1)                              \
511         (tvec_claimeq_uenum(tv, ei, e0, e1,                             \
512                             __FILE__, __LINE__, #e0 " /= " #e1))
513 #define TVEC_CLAIMEQ_PENUM(tv, ei, e0, e1)                              \
514         (tvec_claimeq_penum(tv, ei, e0, e1,                             \
515                             __FILE__, __LINE__, #e0 " /= " #e1))
516
517 extern const struct tvec_regty tvty_flags;
518 struct tvec_flag { const char *tag; unsigned long m, v; };
519 struct tvec_flaginfo {
520   const char *name;
521   const struct tvec_flag *fv;
522   const struct tvec_urange *range;
523 };
524
525 extern int tvec_claimeq_flags(struct tvec_state */*tv*/,
526                               const struct tvec_flaginfo */*fi*/,
527                               unsigned long /*f0*/, unsigned long /*f1*/,
528                               const char */*file*/, unsigned /*lno*/,
529                               const char */*expr*/);
530 #define TVEC_CLAIMEQ_FLAGS(tv, fi, f0, f1)                              \
531         (tvec_claimeq_flags(tv, fi, f0, f1,                             \
532                             __FILE__, __LINE__, #f0 " /= " #f1))
533
534 extern const struct tvec_regty tvty_string, tvty_bytes;
535
536 extern int tvec_claimeq_string(struct tvec_state */*tv*/,
537                                const char */*p0*/, size_t /*sz0*/,
538                                const char */*p1*/, size_t /*sz1*/,
539                                const char */*file*/, unsigned /*lno*/,
540                                const char */*expr*/);
541 extern int tvec_claimeq_strz(struct tvec_state */*tv*/,
542                              const char */*p0*/, const char */*p1*/,
543                              const char */*file*/, unsigned /*lno*/,
544                              const char */*expr*/);
545 extern int tvec_claimeq_bytes(struct tvec_state */*tv*/,
546                                const void */*p0*/, size_t /*sz0*/,
547                                const void */*p1*/, size_t /*sz1*/,
548                                const char */*file*/, unsigned /*lno*/,
549                                const char */*expr*/);
550
551 #define TVEC_CLAIMEQ_STRING(tv, p0, sz0, p1, sz1)                       \
552         (tvec_claimeq_string(tv, p0, sz0, p1, sz1, __FILE__, __LINE__,  \
553                              #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
554 #define TVEC_CLAIMEQ_STRZ(tv, p0, p1)                                   \
555         (tvec_claimeq_strz(tv, p0, p1, __FILE__, __LINE__, #p0 " /= " #p1))
556 #define TVEC_CLAIMEQ_BYTES(tv, p0, sz0, p1, sz1)                        \
557         (tvec_claimeq(tv, p0, sz0, p1, sz1, __FILE__, __LINE__,         \
558                       #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]"))
559
560 extern const struct tvec_regty tvty_buffer;
561
562 extern void tvec_allocstring(union tvec_regval */*rv*/, size_t /*sz*/);
563 extern void tvec_allocbytes(union tvec_regval */*rv*/, size_t /*sz*/);
564
565 /*----- That's all, folks -------------------------------------------------*/
566
567 #ifdef __cplusplus
568   }
569 #endif
570
571 #endif