X-Git-Url: https://git.distorted.org.uk/~mdw/mLib/blobdiff_plain/31d0247cc58abc0b0720aa7e9972011c5a66995c..0335afec2c33fefcd6d3cb2c39d014ab2519b2c2:/test/tvec.h diff --git a/test/tvec.h b/test/tvec.h index 38c462b..b2ae674 100644 --- a/test/tvec.h +++ b/test/tvec.h @@ -193,7 +193,12 @@ union tvec_regval { void *p; /* pointer */ double f; /* floating point */ struct { unsigned char *p; size_t sz; } bytes; /* binary string of bytes */ - struct { char *p; size_t sz; } str; /* text string */ + struct { char *p; size_t sz; } text; /* text string */ + struct { /* buffer */ + unsigned char *p; size_t sz; /* binary string */ + size_t a, m; /* residue and modulus */ + size_t off; /* offset into full buffer */ + } buf; #ifdef TVEC_REGSLOTS TVEC_REGSLOTS #endif @@ -337,6 +342,18 @@ typedef void tvec_testfn(const struct tvec_reg */*in*/, struct tvec_env; +typedef int tvec_setvarfn(struct tvec_state */*tv*/, const char */*var*/, + const union tvec_regval */*rv*/, void */*ctx*/); + /* Called after a variable is read. Return zero on success or %$-1$% on + * error. This function is never called if the test group is skipped. + */ + +struct tvec_vardef { + size_t regsz; /* (minimum) register size */ + tvec_setvarfn *setvar; /* function to set variable */ + struct tvec_regdef def; /* register definition */ +}; + typedef void tvec_envsetupfn(struct tvec_state */*tv*/, const struct tvec_env */*env*/, void */*pctx*/, void */*ctx*/); @@ -348,18 +365,23 @@ typedef void tvec_envsetupfn(struct tvec_state */*tv*/, * will not. */ -typedef int tvec_envsetfn(struct tvec_state */*tv*/, - const char */*var*/, void */*ctx*/); - /* Called when the parser finds a %|@var|%' setting to parse and store the - * value. If @setup@ failed, this is still called (so as to skip the - * value), but @ctx@ is null. +typedef const struct tvec_vardef *tvec_envfindvarfn + (struct tvec_state */*tv*/, const char */*name*/, + void **/*ctx_out*/, void */*ctx*/); + /* Called when the parser finds a %|@var|%' special variable. If a + * suitable variable was found, set @*ctx_out@ to a suitable context and + * return the variable definition; the context will be passed to the + * variable definition's @setvar@ function. If no suitable variable was + * found, then return null. */ typedef void tvec_envbeforefn(struct tvec_state */*tv*/, void */*ctx*/); /* Called prior to running a test. This is the right place to act on any * `%|@var|%' settings. If preparation fails, the function should call * @tvec_skip@ with a suitable excuse. This function is never called if - * the test group is skipped. + * the test group is skipped. It %%\emph{is}%% called if the test will be + * skipped due to erroneous test data. It should check the @TVSF_ACTIVE@ + * flag if necessary. */ typedef void tvec_envrunfn(struct tvec_state */*tv*/, @@ -375,9 +397,9 @@ typedef void tvec_envrunfn(struct tvec_state */*tv*/, typedef void tvec_envafterfn(struct tvec_state */*tv*/, void */*ctx*/); /* Called after running or skipping a test. Typical actions involve * resetting whatever things were established by @set@. This function - * %%\emph{is}%% called if the test group is skipped, so that the test - * environment can reset variables set by the @set@ entry point. It should - * check the @TVSF_SKIP@ flag if necessary. + * %%\emph{is}%% called if the test group is skipped or the test data is + * erroneous, so that the test environment can reset variables set by the + * @set@ entry point. It should check the @TVSF_SKIP@ flag if necessary. */ typedef void tvec_envteardownfn(struct tvec_state */*tv*/, void */*ctx*/); @@ -396,7 +418,7 @@ struct tvec_env { size_t ctxsz; /* environment context size */ tvec_envsetupfn *setup; /* setup for group */ - tvec_envsetfn *set; /* set variable */ + tvec_envfindvarfn *findvar; /* find variable */ tvec_envbeforefn *before; /* prepare for test */ tvec_envrunfn *run; /* run test function */ tvec_envafterfn *after; /* clean up after test */ @@ -497,7 +519,7 @@ enum { TVBU_BYTE, /* counting bytes (@rbuf >= 0@) */ TVBU_LIMIT /* (number of units) */ }; -struct bench_timing; /* forward declaration */ +struct bench_timing; /* include for the real definition */ struct tvec_outops { /* Output operations. */ @@ -1146,7 +1168,7 @@ extern struct bench_state *tvec_benchstate; */ extern tvec_envsetupfn tvec_benchsetup; -extern tvec_envsetfn tvec_benchset; +extern tvec_envfindvarfn tvec_benchfindvar; extern tvec_envbeforefn tvec_benchbefore; extern tvec_envrunfn tvec_benchrun; extern tvec_envafterfn tvec_benchafter; @@ -1155,7 +1177,7 @@ extern tvec_envteardownfn tvec_benchteardown; #define TVEC_BENCHENV \ { sizeof(struct tvec_benchctx), \ tvec_benchsetup, \ - tvec_benchset, \ + tvec_benchfindvar, \ tvec_benchbefore, \ tvec_benchrun, \ tvec_benchafter, \ @@ -1197,6 +1219,8 @@ struct tvec_remotectx { struct tvec_state *tv; /* test vector state */ struct tvec_remotecomms rc; /* communication state */ const struct tvec_remoteenv *re; /* environment configuration */ + void *subctx; /* subenvironment context */ + struct tvec_vardef vd; /* temporary variable definition */ unsigned ver; /* protocol version */ pid_t kid; /* child process id */ int errfd; /* child stderr descriptor */ @@ -1204,8 +1228,8 @@ struct tvec_remotectx { dstr prgwant, progress; /* progress: wanted/reported */ unsigned exwant, exit; /* exit status wanted/reported */ #define TVRF_RCNMASK 0x0300u /* reconnection behaviour: */ -#define TVRCN_SKIP 0x0000u /* skip unless connected */ -#define TVRCN_DEMAND 0x0100u /* connect on demand */ +#define TVRCN_DEMAND 0x0000u /* connect on demand */ +#define TVRCN_SKIP 0x0100u /* skip unless connected */ #define TVRCN_FORCE 0x0200u /* force reconnection */ #define TVRF_MUFFLE 0x0400u /* muffle child stderr */ #define TVRF_SETEXIT 0x0800u /* set `@exit' */ @@ -1219,10 +1243,24 @@ typedef int tvec_connectfn(pid_t */*kid_out*/, int */*infd_out*/, int */*outfd_out*/, int */*errfd_out*/, struct tvec_state */*tv*/, const struct tvec_remoteenv */*env*/); + /* A connection function. On entry, @tv@ holds the test-vector state, and + * @env@ is the test group's remote environment structure, which will + * typically really be some subclass of @struct tvec_remoteenv@ containing + * additional parameters for establishing the child process. + * + * On successful completion, the function stores input and output + * descriptors (which need not be distinct) in @*infd_out@ and + * @*outfd_out@, and returns zero; if it creates a child process, it should + * additionally store the child's process-id in @*kid_out@ and store in + * @*errfd_out@ a descriptor from which the child's error output can be + * read. On error, the function should report an appropriate message via + * @tvec_error@ and return %$-1$%. + */ struct tvec_remoteenv_slots { tvec_connectfn *connect; /* connection function */ const struct tvec_env *env; /* subsidiary environment */ + unsigned dflt_reconn; /* default reconnection */ }; struct tvec_remoteenv { @@ -1257,23 +1295,93 @@ union tvec_remoteenv_subclass_kludge { struct tvec_remoteexec exec; }; +/* Exit status. + * + * We don't use the conventional encoding returned by the @wait@(2) family of + * system calls because it's too hard for our flags type to decode. Instead, + * we use our own encoding. + * + * The exit code or signal number ends up in the `value' field in the low 12 + * bits; bit 12 is set if the value field holds a signal, and it if holds an + * exit code. Bits 13--15 hold a code which describes the status of a child + * process or connection. + */ +#define TVXF_VALMASK 0x0fffu /* value (exit code or signal) */ +#define TVXF_SIG 0x1000u /* value is signal, not exit code */ +#define TVXF_CAUSEMASK 0xe000u /* mask for cause bits */ +#define TVXST_RUN 0x0000u /* still running */ +#define TVXST_EXIT 0x2000u /* child exited */ +#define TVXST_KILL 0x4000u /* child killed by signal */ +#define TVXST_CONT 0x6000u /* child continued (?) */ +#define TVXST_STOP 0x8000u /* child stopped (?) */ +#define TVXST_DISCONN 0xa000u /* disconnected */ +#define TVXST_UNK 0xc000u /* unknown */ +#define TVXST_ERR 0xe000u /* local error prevented diagnosis */ + +/* Remote environment. */ extern tvec_envsetupfn tvec_remotesetup; -extern tvec_envsetfn tvec_remoteset; +extern tvec_envfindvarfn tvec_remotefindvar; +extern tvec_envbeforefn tvec_remotebefore; extern tvec_envrunfn tvec_remoterun; extern tvec_envafterfn tvec_remoteafter; extern tvec_envteardownfn tvec_remoteteardown; #define TVEC_REMOTEENV \ { sizeof(struct tvec_remotectx), \ tvec_remotesetup, \ - tvec_remoteset, \ - 0, \ + tvec_remotefindvar, \ + tvec_remotebefore, \ tvec_remoterun, \ tvec_remoteafter, \ tvec_remoteteardown } +/* --- @tvec_setprogress@, @tvec_setprogress_v@ --- * + * + * Arguments: @const char *status@ = progress status token format + * @va_list ap@ = argument tail + * + * Returns: --- + * + * Use: Reports the progress of a test execution to the client. + * + * The framework makes use of tokens beginning with %|%|%: + * + * * %|%IDLE|%: during the top-level server code; + * + * * %|%SETUP|%: during the enclosing environment's @before@ + * function; + * + * * %|%RUN|%: during the environment's @run@ function, or the + * test function; and + * + * * %|%DONE|%: during the enclosing environment's @after@ + * function. + * + * The intent is that a test can use the progress token to check + * that a function which is expected to crash does so at the + * correct point, so it's expected that more complex test + * functions and/or environments will set their own progress + * tokens to reflect what's going on. + */ + extern PRINTF_LIKE(1, 2) int tvec_setprogress(const char */*status*/, ...); extern int tvec_setprogress_v(const char */*status*/, va_list */*ap*/); +/* --- @tvec_remoteserver@ --- * + * + * Arguments: @int infd@, @int outfd@ = input and output file descriptors + * @const struct tvec_config *config@ = test configuration + * + * Returns: Suggested exit code. + * + * Use: Run a test server, reading packets from @infd@ and writing + * responses and notifications to @outfd@, and invoking tests as + * described by @config@. + * + * This function is not particularly general purpose. It + * expects to `take over' the process, and makes use of private + * global variables. + */ + extern int tvec_remoteserver(int /*infd*/, int /*outfd*/, const struct tvec_config */*config*/); @@ -1289,23 +1397,25 @@ extern tvec_connectfn tvec_fork, tvec_exec; struct tvec_timeoutenv { struct tvec_env _env; - unsigned timer; - double t; - const struct tvec_env *env; + int timer; /* the timer (@ITIMER_...@) */ + double t; /* time to wait (in seconds) */ + const struct tvec_env *env; /* subsidiary environment */ }; struct tvec_timeoutctx { - const struct tvec_timeoutenv *te; - unsigned timer; - double t; + const struct tvec_timeoutenv *te; /* saved environment description */ + int timer; /* timer code (as overridden) */ + double t; /* time to wait (as overridden) */ unsigned f; /* flags */ #define TVTF_SETTMO 1u /* set `@timeout' */ -#define TVTF_SETMASK (TVTF_SETTMO) /* mask of @TVTF_SET...@ */ +#define TVTF_SETTMR 2u /* set `@timer' */ +#define TVTF_SETMASK (TVTF_SETTMO | TVTF_SETTMR) + /* mask of @TVTF_SET...@ */ void *subctx; }; extern tvec_envsetupfn tvec_timeoutsetup; -extern tvec_envsetfn tvec_timeoutset; +extern tvec_envfindvarfn tvec_timeoutfindvar; extern tvec_envbeforefn tvec_timeoutbefore; extern tvec_envrunfn tvec_timeoutrun; extern tvec_envafterfn tvec_timeoutafter; @@ -1313,7 +1423,7 @@ extern tvec_envteardownfn tvec_timeoutteardown; #define TVEC_TIMEOUTENV \ { sizeof(struct tvec_timeoutctx), \ tvec_timeoutsetup, \ - tvec_timeoutset, \ + tvec_timeoutfindvar, \ tvec_timeoutbefore, \ tvec_timeoutrun, \ tvec_timeoutafter, \ @@ -1533,6 +1643,19 @@ extern PRINTF_LIKE(3, 4) extern int tvec_syntax_v(struct tvec_state */*tv*/, int /*ch*/, const char */*expect*/, va_list */*ap*/); +/* --- @tvec_unkreg@ --- * + * + * Arguments: @struct tvec_state *tv@ = test-vector state + * @const char *name@ = register or pseudoregister name + * + * Returns: %$-1$%. + * + * Use: Reports an error that the register or pseudoregister is + * unrecognized. + */ + +extern int tvec_unkreg(struct tvec_state */*tv*/, const char */*name*/); + /* --- @tvec_dupreg@ --- * * * Arguments: @struct tvec_state *tv@ = test-vector state @@ -1609,6 +1732,7 @@ extern int tvec_nexttoken(struct tvec_state */*tv*/); * * Arguments: @struct tvec_state *tv@ = test-vector state * @dstr *d@ = string to append the word to + * @const char **p_inout@ = pointer into string, updated * @const char *delims@ = additional delimiters to stop at * @const char *expect@, @va_list ap@ = what was expected * @@ -1631,14 +1755,23 @@ extern int tvec_nexttoken(struct tvec_state */*tv*/); * word constituents, a null terminator is written to @d@, and * it is safe to treat the string in @d@ as being null- * terminated. + * + * If @p_inout@ is not null, then @*p_inout@ must be a pointer + * into @d->buf@, which will be adjusted so that it will + * continue to point at the same position even if the buffer is + * reallocated. As a subtle tweak, if @*p_inout@ initially + * points at the end of the buffer, then it will be adjusted to + * point at the beginning of the next word, rather than at the + * additional intervening space. */ -extern PRINTF_LIKE(4, 5) +extern PRINTF_LIKE(5, 6) int tvec_readword(struct tvec_state */*tv*/, dstr */*d*/, - const char */*delims*/, const char */*expect*/, ...); + const char **/*p_inout*/, const char */*delims*/, + const char */*expect*/, ...); extern int tvec_readword_v(struct tvec_state */*tv*/, dstr */*d*/, - const char */*delims*/, const char */*expect*/, - va_list */*ap*/); + const char **/*p_inout*/, const char */*delims*/, + const char */*expect*/, va_list */*ap*/); /*----- Integer types: signed and unsigned --------------------------------*/ @@ -1742,10 +1875,11 @@ extern int tvec_claimeq_uint(struct tvec_state */*tv*/, /*----- Floating-point type -----------------------------------------------*/ -/* Floating-point are either NaN (`#nan', if supported by the platform); - * positive or negative infinity (`#inf', `+#inf', or, preferred, `#+inf', - * and `-#inf' or, preferred, `#-inf', if supported by the platform), or a - * number in strtod(3) syntax. +/* Floating-point values are either NaN (%|#nan|%, if supported by the + * platform); positive or negative infinity (%|#inf|%, %|+#inf|%, or + * %|#+inf|% (preferring the last), and %|-#inf|% or %|#-inf|% (preferring + * the latter), if supported by the platform); or a number in strtod(3) + * syntax. * * The comparison rules for floating-point numbers are complex: see * @tvec_claimeqish_float@ for details. @@ -1848,6 +1982,18 @@ extern int tvec_claimeq_float(struct tvec_state */*tv*/, extern const struct tvec_floatinfo tvflt_finite, tvflt_nonneg; +/*----- Durations ---------------------------------------------------------*/ + +/* A duration measures a time interval in seconds. The input format consists + * of a nonnegative decimal floating-point number in @strtod@ format followed + * by an optional unit specification. + * + * No @tvec_claimeq_...@ function is provided for durations: use + * @tvec_claimeq_float@. + */ + +extern const struct tvec_regty tvty_duration; + /*----- Enumerated types --------------------------------------------------*/ /* An enumeration describes a set of values of some underlying type, each of @@ -1863,7 +2009,7 @@ extern const struct tvec_floatinfo tvflt_finite, tvflt_nonneg; * On input, an enumerated value may be given by name or as a literal value. * For enumerations based on numeric types, the literal values can be written * in the same syntax as the underlying values. For enumerations based on - * pointers, the only permitted literal is `#nil', which denotes a null + * pointers, the only permitted literal is %|#nil|%, which denotes a null * pointer. On output, names are preferred (with the underlying value given * in a comment). */ @@ -1964,18 +2110,19 @@ TVEC_MISCSLOTS(DECLCLAIM) * fields; more precisely, each name is associated with a value and a * covering bitmask. * - * The input syntax is a sequence of items separated by `|' signs. Each item - * may be the symbolic name of a field value, or a literal unsigned integer. - * The masks associated with the given symbolic names must be disjoint. The - * resulting numerical value is simply the bitwise OR of the given values. + * The input syntax is a sequence of items separated by `%|||%' signs. Each + * item may be the symbolic name of a field value, or a literal unsigned + * integer. The masks associated with the given symbolic names must be + * disjoint. The resulting numerical value is simply the bitwise OR of the + * given values. * * On output, the table of symbolic names and their associated values and * masks is repeatedly scanned, in order, to find disjoint matches -- i.e., * entries whose value matches the target value in the bit positions * indicated by the mask, and whose mask doesn't overlap with any previously - * found matches; the names are then output, separated by `|'. Any remaining - * nonzero bits not covered by any of the matching masks are output as a - * single literal integer, in hex. + * found matches; the names are then output, separated by `%|||%'. Any + * remaining nonzero bits not covered by any of the matching masks are output + * as a single literal integer, in hex. */ extern const struct tvec_regty tvty_flags; @@ -2038,8 +2185,9 @@ extern int tvec_claimeq_flags(struct tvec_state */*tv*/, /* A character value holds a character, as read by @fgetc@. The special * @EOF@ value can also be represented. * - * On input, a character value can be given by name, with a leading `%|#|%'; - * or a character or `%|\|%'-escape sequence, optionally in single quotes. + * On input, a character value can be given by symbolic name, with a leading + * `%|#|%'; or a character or `%|\|%'-escape sequence, optionally in single + * quotes. * * The following escape sequences and character names are recognized. * @@ -2156,6 +2304,9 @@ extern int tvec_claimeq_char(struct tvec_state */*tv*/, * * `%|!repeat|% %$n$% %|{|% %%\textit{string}%% %|}|%', which includes * %$n$% copies of the (compound) string. * + * The only difference between text and binary strings is that the initial + * coding scheme is %|bare|% for text strings and %|hex|% for binary strings. + * * Either kind of string can contain internal nul characters. A trailing nul * is appended -- beyond the stated input length -- to input strings as a * convenience to test functions. Test functions may include such a nul @@ -2165,9 +2316,9 @@ extern int tvec_claimeq_char(struct tvec_state */*tv*/, * string (in bytes) will be checked against the permitted range. */ -extern const struct tvec_regty tvty_string, tvty_bytes; +extern const struct tvec_regty tvty_text, tvty_bytes; -/* --- @tvec_claimeq_string@, @TVEC_CLAIMEQ_STRING@ --- * +/* --- @tvec_claimeq_text@, @TVEC_CLAIMEQ_TEXT@ --- * * * Arguments: @struct tvec_state *tv@ = test-vector state * @const char *p0@, @size_t sz0@ = first string with length @@ -2185,22 +2336,22 @@ extern const struct tvec_regty tvty_string, tvty_bytes; * mismatched values are dumped: @p0@ is printed as the output * value and @p1@ is printed as the input reference. * - * The @TVEC_CLAIM_STRING@ macro is similar, only it (a) + * The @TVEC_CLAIM_TEXT@ macro is similar, only it (a) * identifies the file and line number of the call site * automatically, and (b) implicitly quotes the source text of * the @ch0@ and @ch1@ arguments in the failure message. */ -extern int tvec_claimeq_string(struct tvec_state */*tv*/, - const char */*p0*/, size_t /*sz0*/, - const char */*p1*/, size_t /*sz1*/, - const char */*file*/, unsigned /*lno*/, - const char */*expr*/); -#define TVEC_CLAIMEQ_STRING(tv, p0, sz0, p1, sz1) \ - (tvec_claimeq_string(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \ - #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]")) +extern int tvec_claimeq_text(struct tvec_state */*tv*/, + const char */*p0*/, size_t /*sz0*/, + const char */*p1*/, size_t /*sz1*/, + const char */*file*/, unsigned /*lno*/, + const char */*expr*/); +#define TVEC_CLAIMEQ_TEXT(tv, p0, sz0, p1, sz1) \ + (tvec_claimeq_text(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \ + #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]")) -/* --- @tvec_claimeq_strz@, @TVEC_CLAIMEQ_STRZ@ --- * +/* --- @tvec_claimeq_textz@, @TVEC_CLAIMEQ_TEXTZ@ --- * * * Arguments: @struct tvec_state *tv@ = test-vector state * @const char *p0, *p1@ = two strings to compare @@ -2213,16 +2364,15 @@ extern int tvec_claimeq_string(struct tvec_state */*tv*/, * Use: Check that strings at @p0@ and @p1@ are equal, as for * @tvec_claimeq_string@, except that the strings are assumed * null-terminated, so their lengths don't need to be supplied - * explicitly. The macro is similarly like - * @TVEC_CLAIMEQ_STRING@. + * explicitly. The macro is similarly like @TVEC_CLAIMEQ_TEXT@. */ -extern int tvec_claimeq_strz(struct tvec_state */*tv*/, - const char */*p0*/, const char */*p1*/, - const char */*file*/, unsigned /*lno*/, - const char */*expr*/); -#define TVEC_CLAIMEQ_STRZ(tv, p0, p1) \ - (tvec_claimeq_strz(tv, p0, p1, __FILE__, __LINE__, #p0 " /= " #p1)) +extern int tvec_claimeq_textz(struct tvec_state */*tv*/, + const char */*p0*/, const char */*p1*/, + const char */*file*/, unsigned /*lno*/, + const char */*expr*/); +#define TVEC_CLAIMEQ_TEXTZ(tv, p0, p1) \ + (tvec_claimeq_textz(tv, p0, p1, __FILE__, __LINE__, #p0 " /= " #p1)) /* --- @tvec_claimeq_bytes@, @TVEC_CLAIMEQ_BYTES@ --- * * @@ -2257,7 +2407,7 @@ extern int tvec_claimeq_bytes(struct tvec_state */*tv*/, (tvec_claimeq(tv, p0, sz0, p1, sz1, __FILE__, __LINE__, \ #p0 "[" #sz0 "] /= " #p1 "[" #sz1 "]")) -/* --- @tvec_allocstring@, @tvec_allocbytes@ --- * +/* --- @tvec_alloctext@, @tvec_allocbytes@ --- * * * Arguments: @union tvec_regval *rv@ = register value * @size_t sz@ = required size @@ -2273,28 +2423,69 @@ extern int tvec_claimeq_bytes(struct tvec_state */*tv*/, * the old buffer contents are simply discarded if reallocation * is necessary. Instead, use a @dbuf@ or @dstr@. * - * The @tvec_allocstring@ function sneakily allocates an extra + * The @tvec_alloctext@ function sneakily allocates an extra * byte for a terminating zero. The @tvec_allocbytes@ function * doesn't do this. */ -extern void tvec_allocstring(union tvec_regval */*rv*/, size_t /*sz*/); +extern void tvec_alloctext(union tvec_regval */*rv*/, size_t /*sz*/); extern void tvec_allocbytes(union tvec_regval */*rv*/, size_t /*sz*/); /*----- Buffer type -------------------------------------------------------*/ /* Buffer registers are primarily used for benchmarking. Only a buffer's - * size is significant: its contents are ignored on comparison and output, - * and unspecified on input. + * allocation parameters are significant: its contents are ignored on + * comparison and output, and unspecified on input. + * + * The input format gives the buffer's size, and an optional alignment + * specification, in the form %|SZ [`@' M [`+' A]]|%. Each of %|SZ|%, %|M|% + * and %|A|% are sizes, as an integer, optionally suffixed with a unit `kB', + * `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or without the `B') + * denoting a power of 1024. The %|SZ|% gives the (effective) buffer size. + * %|M|% is the `alignment quantum' and %|A|% is the `alignment offset'; both + * default to zero, but if %|M|% is nonzero then the start of the buffer is + * aligned such that it is %|A|% more than a multiple of %|M|% bytes. Note + * that %|M|% need not be a power of two, though this is common. * - * The input is simply the buffer size, as an integer, optionally suffixed - * with a unit `kB', `MB', `GB', `TB', `PB', `EB', `ZB', `YB' (with or - * without the `B') denoting a power of 1024. Units are used on output only - * when the size would be expressed exactly. + * Units other than `B' are used on output only when the size would be + * expressed exactly. + * + * Buffers are %%\emph{not}%% allocated by default. In benchmarks, this is + * best done in a @before@ function. + * + * No @claimeq@ functions or macros are provided for buffers because they + * don't seem very useful. */ extern const struct tvec_regty tvty_buffer; +/* --- @tvec_initbuffer@ --- * + * + * Arguments: @union tvec_regval *rv@ = register value + * @const union tvec_regval *src@ = source buffer + * @size_t sz@ = size to allocate + * + * Returns: --- + * + * Use: Initialize the alignment parameters in @rv@ to match @src@, + * and the size to @sz@. + */ + +extern void tvec_initbuffer(union tvec_regval */*rv*/, + const union tvec_regval */*src*/, size_t /*sz*/); + +/* --- @tvec_allocbuffer@ --- * + * + * Arguments: @union tvec_regval *rv@ = register value + * + * Returns: --- + * + * Use: Allocate @sz@ bytes to the buffer and fill the space with a + * distinctive pattern. + */ + +extern void tvec_allocbuffer(union tvec_regval */*rv*/); + /*----- That's all, folks -------------------------------------------------*/ #ifdef __cplusplus