@@@ adjust bench timings
[mLib] / test / tvec.h
CommitLineData
b64eb60f
MW
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
69union tvec_misc {
70#define TVEC_DEFSLOT(tag, ty, slot) ty slot;
71 TVEC_MISCSLOTS(TVEC_DEFSLOT)
72#undef TVEC_DEFSLOT
73};
74enum {
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
102union 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
124struct 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
149struct 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
167extern 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
172extern 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
179enum { TVOUT_LOSE, TVOUT_SKIP, TVOUT_WIN, TVOUT_LIMIT };
180
181struct 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 */
882a39c1 186#define TVSF_ERROR 8u /* an error occurred */
b64eb60f
MW
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
882a39c1 206typedef int tvec_hookfn(struct tvec_state */*tv*/);
b64eb60f
MW
207typedef void tvec_testfn(const struct tvec_reg */*in*/,
208 struct tvec_reg */*out*/,
209 void */*ctx*/);
210
211struct 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
220extern void PRINTF_LIKE(2, 3)
221 tvec_check(struct tvec_state */*tv*/, const char */*detail*/, ...);
222extern void tvec_check_v(struct tvec_state */*tv*/,
223 const char */*detail*/, va_list */*ap*/);
224
882a39c1 225extern int tvec_runtest(struct tvec_state */*tv*/);
b64eb60f
MW
226
227/*----- Input utilities ---------------------------------------------------*/
228
229extern void tvec_skipspc(struct tvec_state */*tv*/);
230
231#define TVFF_ALLOWANY 1u
882a39c1 232extern int tvec_flushtoeol(struct tvec_state */*tv*/, unsigned /*f*/);
b64eb60f
MW
233
234extern int PRINTF_LIKE(4, 5)
235 tvec_readword(struct tvec_state */*tv*/, dstr */*d*/,
236 const char */*delims*/, const char */*expect*/, ...);
237extern int tvec_readword_v(struct tvec_state */*tv*/, dstr */*d*/,
238 const char */*delims*/, const char */*expect*/,
239 va_list */*ap*/);
240
241extern int tvec_nexttoken(struct tvec_state */*tv*/);
242
243/*----- Session lifecycle -------------------------------------------------*/
244
245struct tvec_info {
246 const struct tvec_test *tests;
247 unsigned nrout, nreg;
248 size_t regsz;
249};
250
251extern void tvec_begin(struct tvec_state */*tv_out*/,
252 const struct tvec_info */*info*/,
253 struct tvec_output */*o*/);
254extern int tvec_end(struct tvec_state */*tv*/);
255
882a39c1
MW
256extern int tvec_read(struct tvec_state */*tv*/,
257 const char */*infile*/, FILE */*fp*/);
b64eb60f
MW
258
259/*----- Benchmarking ------------------------------------------------------*/
260
261struct 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
272extern struct bench_state *tvec_benchstate;
273
274extern int tvec_ensurebench(struct tvec_state */*tv*/,
275 struct bench_state **/*b_out*/);
882a39c1 276extern int tvec_bench(struct tvec_state */*tv*/);
b64eb60f
MW
277
278/*----- Ad-hoc testing ----------------------------------------------------*/
279
280extern void tvec_adhoc(struct tvec_state */*tv*/, struct tvec_test */*t*/);
281
282extern void tvec_begingroup(struct tvec_state */*tv*/, const char */*name*/,
283 const char */*file*/, unsigned /*lno*/);
284extern void tvec_reportgroup(struct tvec_state */*tv*/);
285extern 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
297extern void tvec_begintest(struct tvec_state */*tv*/,
298 const char */*file*/, unsigned /*lno*/);
299extern 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
311extern 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
319extern 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
327extern const struct tvec_info tvec_adhocinfo;
328
329extern void tvec_parseargs(int /*argc*/, char */*argv*/[],
330 struct tvec_state */*tv_out*/,
331 int */*argpos_out*/,
332 const struct tvec_info */*info*/);
333
882a39c1
MW
334extern int tvec_readstdin(struct tvec_state */*tv*/);
335extern int tvec_readfile(struct tvec_state */*tv*/, const char */*file*/);
336extern int tvec_readdflt(struct tvec_state */*tv*/, const char */*file*/);
337extern int tvec_readarg(struct tvec_state */*tv*/, const char */*arg*/);
b64eb60f 338
882a39c1
MW
339extern int tvec_readargs(int /*argc*/, char */*argv*/[],
340 struct tvec_state */*tv*/,
341 int */*argpos_inout*/, const char */*dflt*/);
b64eb60f
MW
342
343extern int tvec_main(int /*argc*/, char */*argv*/[],
344 const struct tvec_info */*info*/,
345 const char */*dflt*/);
346
347/*----- Output formatting -------------------------------------------------*/
348
349struct tvec_output {
350 const struct tvec_outops *ops;
351 struct tvec_state *tv;
352};
353
354struct bench_timing;
355
356struct 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
882a39c1 386extern int PRINTF_LIKE(2, 3)
b64eb60f 387 tvec_error(struct tvec_state */*tv*/, const char */*msg*/, ...);
882a39c1
MW
388extern int tvec_error_v(struct tvec_state */*tv*/,
389 const char */*msg*/, va_list */*ap*/);
b64eb60f
MW
390
391extern void PRINTF_LIKE(2, 3)
392 tvec_notice(struct tvec_state */*tv*/, const char */*msg*/, ...);
393extern void tvec_notice_v(struct tvec_state */*tv*/,
394 const char */*msg*/, va_list */*ap*/);
395
882a39c1 396extern int PRINTF_LIKE(3, 4)
b64eb60f
MW
397 tvec_syntax(struct tvec_state */*tv*/, int /*ch*/,
398 const char */*expect*/, ...);
882a39c1
MW
399extern int tvec_syntax_v(struct tvec_state */*tv*/, int /*ch*/,
400 const char */*expect*/, va_list */*ap*/);
b64eb60f
MW
401
402extern void PRINTF_LIKE(2, 3)
403 tvec_skipgroup(struct tvec_state */*tv*/, const char */*note*/, ...);
404extern void tvec_skipgroup_v(struct tvec_state */*tv*/,
405 const char */*note*/, va_list */*ap*/);
406
407extern void PRINTF_LIKE(2, 3)
408 tvec_skip(struct tvec_state */*tv*/, const char */*excuse*/, ...);
409extern void tvec_skip_v(struct tvec_state */*tv*/,
410 const char */*excuse*/, va_list */*ap*/);
411
412extern void PRINTF_LIKE(2, 3)
413 tvec_fail(struct tvec_state */*tv*/, const char */*detail*/, ...);
414extern void tvec_fail_v(struct tvec_state */*tv*/,
415 const char */*detail*/, va_list */*ap*/);
416
417extern void tvec_mismatch(struct tvec_state */*tv*/);
418
419extern void PRINTF_LIKE(2, 3)
420 tvec_write(struct tvec_state */*tv*/, const char */*p*/, ...);
421extern void tvec_write_v(struct tvec_state */*tv*/,
422 const char */*p*/, va_list */*ap*/);
423
424extern struct tvec_output *tvec_humanoutput(FILE */*fp*/);
425extern struct tvec_output *tvec_tapoutput(FILE */*fp*/);
426extern struct tvec_output *tvec_dfltout(FILE */*fp*/);
427
428/*----- Register types ----------------------------------------------------*/
429
430struct 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*/);
882a39c1
MW
443 int (*parse)(union tvec_regval */*rv*/, const struct tvec_regdef */*rd*/,
444 struct tvec_state */*tv*/);
b64eb60f
MW
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
451extern const struct tvec_regty tvty_int, tvty_uint;
452struct tvec_irange { long min, max; };
453struct tvec_urange { unsigned long min, max; };
454
455extern const struct tvec_irange
456 tvrange_schar, tvrange_short, tvrange_int, tvrange_long,
457 tvrange_sbyte, tvrange_i16, tvrange_i32;
458extern const struct tvec_urange
459 tvrange_uchar, tvrange_ushort, tvrange_uint, tvrange_ulong, tvrange_size,
460 tvrange_byte, tvrange_u16, tvrange_u32;
461
462extern int tvec_claimeq_int(struct tvec_state */*tv*/,
463 long /*i0*/, long /*i1*/,
464 const char */*file*/, unsigned /*lno*/,
465 const char */*expr*/);
466extern 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
475extern const struct tvec_regty tvty_enum;
476
477#define DEFASSOC(tag_, ty, slot) \
478 struct tvec_##slot##assoc { const char *tag; ty slot; };
479TVEC_MISCSLOTS(DEFASSOC)
480#undef DEFASSOC
481
482struct 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*/);
505TVEC_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
517extern const struct tvec_regty tvty_flags;
518struct tvec_flag { const char *tag; unsigned long m, v; };
519struct tvec_flaginfo {
520 const char *name;
521 const struct tvec_flag *fv;
522 const struct tvec_urange *range;
523};
524
525extern 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
534extern const struct tvec_regty tvty_string, tvty_bytes;
535
536extern 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*/);
541extern 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*/);
545extern 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
560extern const struct tvec_regty tvty_buffer;
561
562extern void tvec_allocstring(union tvec_regval */*rv*/, size_t /*sz*/);
563extern 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