diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-10-18 08:53:40 +0000 |
commit | d6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch) | |
tree | ece253b876159b39c620e62b6c9b1174642e070e /regress/lib/libc |
initial import of NetBSD tree
Diffstat (limited to 'regress/lib/libc')
26 files changed, 3765 insertions, 0 deletions
diff --git a/regress/lib/libc/Makefile b/regress/lib/libc/Makefile new file mode 100644 index 00000000000..7b65e2c1c56 --- /dev/null +++ b/regress/lib/libc/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.6 1995/04/24 05:52:15 cgd Exp $ + +SUBDIR+= _setjmp db regex setjmp sigsetjmp +.if (${MACHINE_ARCH} != "vax") +SUBDIR+= ieeefp +.endif + +.if exists(arch/${MACHINE_ARCH}) +SUBDIR+= arch/${MACHINE_ARCH} +.endif + +regress: _SUBDIRUSE + +install: + +.include <bsd.subdir.mk> diff --git a/regress/lib/libc/_setjmp/Makefile b/regress/lib/libc/_setjmp/Makefile new file mode 100644 index 00000000000..c2b9dc1aae3 --- /dev/null +++ b/regress/lib/libc/_setjmp/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.2 1995/04/20 22:38:44 cgd Exp $ + +PROG= _setjmptest +SRCS= jmptest.c +NOMAN= noman, no way, man + +CFLAGS+= -DTEST_U_SETJMP + +.PATH: ${.CURDIR}/../setjmp + +install: + +regress: ${PROG} + ./${PROG} + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/arch/alpha/Makefile b/regress/lib/libc/arch/alpha/Makefile new file mode 100644 index 00000000000..b79a82b0e2e --- /dev/null +++ b/regress/lib/libc/arch/alpha/Makefile @@ -0,0 +1,10 @@ +# $NetBSD: Makefile,v 1.1 1995/04/24 05:53:31 cgd Exp $ + +# do nothing here; none of the tests here can be run automatically +SUBDIR= + +regress: _SUBDIRUSE + +install: + +.include <bsd.subdir.mk> diff --git a/regress/lib/libc/arch/alpha/divremtest/Makefile b/regress/lib/libc/arch/alpha/divremtest/Makefile new file mode 100644 index 00000000000..bd3b12f5373 --- /dev/null +++ b/regress/lib/libc/arch/alpha/divremtest/Makefile @@ -0,0 +1,29 @@ +# $NetBSD: Makefile,v 1.1 1995/04/24 05:53:34 cgd Exp $ + +PROG= divremtest +NOMAN= + +CLEANFILES+= mkcases cases.c mktestcases testcases + +divremtest.c: cases.c + +cases.c: mkcases + /bin/rm -f cases.c + mkcases > cases.c + +# a typical strategy to use this: +# compile a NetBSD divremtest binary, an OSF/1 divremtest binary, and an +# OSF/1 mktestcases binary. You then run mktestecases | divremtest -g +# on an OSF/1 machine, and pipe the output to an rsh to a NetBSD machine +# which then runs divremtest. You can test an infinite number of random +# values that way; I like to put a 'dd' in, so I can see how much I've done. + +testcases: mktestcases divremtest + /bin/rm -f testcases + mktestcases | divremtest -g > testcases + +regress: + @echo THIS TEST CANNOT BE RUN AUTOMATICALLY. + @false + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/arch/alpha/divremtest/divremtest.c b/regress/lib/libc/arch/alpha/divremtest/divremtest.c new file mode 100644 index 00000000000..fcf64c93845 --- /dev/null +++ b/regress/lib/libc/arch/alpha/divremtest/divremtest.c @@ -0,0 +1,183 @@ +/* $NetBSD: divremtest.c,v 1.1 1995/04/24 05:53:35 cgd Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <unistd.h> +#include <signal.h> + +void testfile(); +void usage(); + +int generate; + +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + + signal(SIGFPE, SIG_IGN); + + while ((c = getopt(argc, argv, "g")) != -1) + switch (c) { + case 'g': + generate = 1; + break; + + default: + usage(); + break; + } + + argc -= optind; + argv += optind; + + if (argc == 0) + testfile(); + else + for (; argc != 0; argc--, argv++) { + if (freopen(argv[0], "r", stdin) == NULL) { + fprintf(stderr, + "divremtest: couldn't open %s\n", + argv[0]); + exit(1); + } + + testfile(); + } + + exit(0); +} + +void +testfile() +{ + union operand { + unsigned long input; + int op_int; + unsigned int op_u_int; + long op_long; + unsigned long op_u_long; + } op1, op2, divres, modres, divwant, modwant; + char opspec[6]; + int encoded, i; + + while (scanf("%6c %lx %lx %lx %lx\n", opspec, &op1.input, + &op2.input, &divwant.input, &modwant.input) != EOF) { + + encoded = 0; + + for (i = 0; i < 6; i += 2) { + int posval; + + switch (opspec[i]) { + case '.': + posval = 0; + break; + case '-': + posval = 1; + break; + default: + fprintf(stderr, + "unknown signedness spec %c\n", + opspec[i]); + exit(1); + } + encoded |= posval << ((5 - i) * 4); + } + + for (i = 1; i < 6; i += 2) { + int posval; + + switch (opspec[i]) { + case 'i': + posval = 0; + break; + case 'l': + posval = 1; + break; + default: + fprintf(stderr, "unknown length spec %c\n", + opspec[i]); + exit(1); + } + encoded |= posval << ((5 - i) * 4); + } + + /* KILL ME!!! */ + switch (encoded) { + +#define TRY_IT(a, b, c) \ + divres.a = op1.b / op2.c; \ + modres.a = op1.b % op2.c; \ + if (generate) { \ + printf("%6s 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n", \ + opspec, op1.input, op2.input, \ + divres.a, modres.a); \ + } else { \ + if ((divres.a != divwant.a) || \ + (modres.a != modwant.a)) { \ + fprintf(stderr, "%6s 0x%016lx 0x%016lx\n", \ + opspec, op1.input, op2.input); \ + fprintf(stderr, "FAILED:\n"); \ + fprintf(stderr, \ + "div:\twanted 0x%16lx, got 0x%16lx\n", \ + divwant.a, divres.a); \ + fprintf(stderr, \ + "mod:\twanted 0x%16lx, got 0x%16lx\n", \ + modwant.a, modres.a); \ + \ + exit(1); \ + } \ + } + +#include "cases.c" + +#undef TRY_IT + + default: + fprintf(stderr, + "INTERNAL ERROR: unknown encoding %x\n", encoded); + exit(1); + } + } +} + +void +usage() +{ + + fprintf(stderr, "usage: divremtest [-v] [testfile ...]\n"); + exit(1); +} diff --git a/regress/lib/libc/arch/alpha/divremtest/mkcases.c b/regress/lib/libc/arch/alpha/divremtest/mkcases.c new file mode 100644 index 00000000000..65ca17af4c6 --- /dev/null +++ b/regress/lib/libc/arch/alpha/divremtest/mkcases.c @@ -0,0 +1,63 @@ +/* $NetBSD: mkcases.c,v 1.1 1995/04/24 05:53:36 cgd Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +char *tab[4] = { "u_int", "int", "u_long", "long" }; + +int +main() +{ + int i; + + for (i = 0; i < 64; i++) { + printf( +" case 0x%d%d%d%d%d%d: /* %s <= %s op %s */\n", + (i >> 5) & 1, + (i >> 4) & 1, + (i >> 3) & 1, + (i >> 2) & 1, + (i >> 1) & 1, + (i >> 0) & 1, + tab[(i >> 4) & 0x3], + tab[(i >> 2) & 0x3], + tab[(i >> 0) & 0x3]); + printf( +" TRY_IT(op_%s, op_%s, op_%s);\n", + tab[(i >> 4) & 0x3], + tab[(i >> 2) & 0x3], + tab[(i >> 0) & 0x3]); + printf( +" break;\n\n"); + } + + exit(0); +} diff --git a/regress/lib/libc/arch/alpha/divremtest/mktestcases.c b/regress/lib/libc/arch/alpha/divremtest/mktestcases.c new file mode 100644 index 00000000000..ef02d61d701 --- /dev/null +++ b/regress/lib/libc/arch/alpha/divremtest/mktestcases.c @@ -0,0 +1,67 @@ +/* $NetBSD: mktestcases.c,v 1.1 1995/04/24 05:53:37 cgd Exp $ */ + +/* + * Copyright (c) 1995 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> + +int +main() +{ + int i, j; + unsigned long n1, n2; + + srandom(time(NULL)); + + for (i = 1; /* i < 10240 */ 1; i++) { + n1 = (unsigned) + (random() & ((random() & random()) | 0x80000000)); + n1 <<= 32; + n1 |= (unsigned)(random() & random() & random()); + + n2 = (unsigned) + (random() & ((random() & random()) | 0x80000000)); + n2 <<= 32; + n2 |= (unsigned)(random() & random() & random()); + + for (j = 0; j < 64; j++) { + char *tab[] = { ".i", ".l", "-i", "-l" }; + + printf("%s%s%s 0x%lx 0x%lx 0 0\n", + tab[(j >> 4) & 0x3], + tab[(j >> 2) & 0x3], + tab[(j >> 0) & 0x3], + n1, n2); + } + } + + exit(0); +} diff --git a/regress/lib/libc/db/Makefile b/regress/lib/libc/db/Makefile new file mode 100644 index 00000000000..5bf343bf647 --- /dev/null +++ b/regress/lib/libc/db/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.10 1995/04/20 22:39:11 cgd Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 + +PROG= dbtest + +# add -DSTATISTICS to CFLAGS to get usage statistics. Note that +# for this to work, libc must be compiled with -DSTATISTICS as well +CFLAGS= -g -D__DBINTERFACE_PRIVATE -DDEBUG +NOMAN= noman +CLEANFILES+= t1 t2 t3 + +install: + +regress: + sh ${.CURDIR}/run.test + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/db/README b/regress/lib/libc/db/README new file mode 100644 index 00000000000..3b290b09d81 --- /dev/null +++ b/regress/lib/libc/db/README @@ -0,0 +1,54 @@ +# $NetBSD: README,v 1.4 1995/04/20 22:39:18 cgd Exp $ +# @(#)README 8.4 (Berkeley) 6/20/94 + +To run the tests, enter "make regress". + +Fairly large files (the command files) are built in this directory during +the test runs, and even larger files (the database files) are created in +"/var/tmp". If the latter directory doesn't exist, set the environmental +variable TMPDIR to a directory where the files can be built. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +The script file consists of lines with a initial character which is +the "command" for that line. Legal characters are as follows: + +c: compare a record + + must be followed by [kK][dD]; the data value in the database + associated with the specified key is compared to the specified + data value. +e: echo a string + + writes out the rest of the line into the output file; if the + last character is not a carriage-return, a newline is appended. +g: do a get command + + must be followed by [kK] + + writes out the retrieved data DBT. +p: do a put command + + must be followed by [kK][dD] +r: do a del command + + must be followed by [kK] +s: do a seq command + + writes out the retrieved data DBT. +f: set the flags for the next command + + no value zero's the flags +D [file]: data file + + set the current data value to the contents of the file +d [data]: + + set the current key value to the contents of the line. +K [file]: key file + + set the current key value to the contents of the file +k [data]: + + set the current key value to the contents of the line. +o [r]: dump [reverse] + + dump the database out, if 'r' is set, in reverse order. + +Options to dbtest are as follows: + + -f: Use the file argument as the database file. + -i: Use the rest of the argument to set elements in the info + structure. If the type is btree, then "-i cachesize=10240" + will set BTREEINFO.cachesize to 10240. + -o: The rest of the argument is the output file instead of + using stdout. + +Dbtest requires two arguments, the type of access "hash", "recno" or +"btree", and the script name. diff --git a/regress/lib/libc/db/dbtest.c b/regress/lib/libc/db/dbtest.c new file mode 100644 index 00000000000..1fcf09af97f --- /dev/null +++ b/regress/lib/libc/db/dbtest.c @@ -0,0 +1,672 @@ +/* $NetBSD: dbtest.c,v 1.7 1995/04/20 22:39:22 cgd Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)dbtest.c 8.8 (Berkeley) 2/21/94"; +#else +static char rcsid[] = "$NetBSD: dbtest.c,v 1.7 1995/04/20 22:39:22 cgd Exp $"; +#endif +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <db.h> + +enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA }; + +void compare __P((DBT *, DBT *)); +DBTYPE dbtype __P((char *)); +void dump __P((DB *, int)); +void err __P((const char *, ...)); +void get __P((DB *, DBT *)); +void getdata __P((DB *, DBT *, DBT *)); +void put __P((DB *, DBT *, DBT *)); +void rem __P((DB *, DBT *)); +void *rfile __P((char *, size_t *)); +void seq __P((DB *, DBT *)); +u_int setflags __P((char *)); +void *setinfo __P((DBTYPE, char *)); +void usage __P((void)); +void *xmalloc __P((char *, size_t)); + +DBTYPE type; +void *infop; +u_long lineno; +u_int flags; +int ofd = STDOUT_FILENO; + +DB *XXdbp; /* Global for gdb. */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + extern char *optarg; + enum S command, state; + DB *dbp; + DBT data, key, keydata; + size_t len; + int ch, oflags; + char *fname, *infoarg, *p, buf[8 * 1024]; + + infoarg = NULL; + fname = NULL; + oflags = O_CREAT | O_RDWR; + while ((ch = getopt(argc, argv, "f:i:lo:")) != EOF) + switch(ch) { + case 'f': + fname = optarg; + break; + case 'i': + infoarg = optarg; + break; + case 'l': + oflags |= DB_LOCK; + break; + case 'o': + if ((ofd = open(optarg, + O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + err("%s: %s", optarg, strerror(errno)); + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 2) + usage(); + + /* Set the type. */ + type = dbtype(*argv++); + + /* Open the descriptor file. */ + if (freopen(*argv, "r", stdin) == NULL) + err("%s: %s", *argv, strerror(errno)); + + /* Set up the db structure as necessary. */ + if (infoarg == NULL) + infop = NULL; + else + for (p = strtok(infoarg, ",\t "); p != NULL; + p = strtok(0, ",\t ")) + if (*p != '\0') + infop = setinfo(type, p); + + /* Open the DB. */ + if (fname == NULL) { + p = getenv("TMPDIR"); + if (p == NULL) + p = "/var/tmp"; + (void)sprintf(buf, "%s/__dbtest", p); + fname = buf; + (void)unlink(buf); + } + if ((dbp = dbopen(fname, + oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) + err("dbopen: %s", strerror(errno)); + XXdbp = dbp; + + state = COMMAND; + for (lineno = 1; + (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { + len = strlen(buf); + switch(*p) { + case 'c': /* compare */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = COMPARE; + break; + case 'e': /* echo */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + /* Don't display the newline, if CR at EOL. */ + if (p[len - 2] == '\r') + --len; + if (write(ofd, p + 1, len - 1) != len - 1) + err("write: %s", strerror(errno)); + break; + case 'g': /* get */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = GET; + break; + case 'p': /* put */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = PUT; + break; + case 'r': /* remove */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = REMOVE; + break; + case 's': /* seq */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + if (flags == R_CURSOR) { + state = KEY; + command = SEQ; + } else + seq(dbp, &key); + break; + case 'f': + flags = setflags(p + 1); + break; + case 'D': /* data file */ + if (state != DATA) + err("line %lu: not expecting data", lineno); + data.data = rfile(p + 1, &data.size); + goto ldata; + case 'd': /* data */ + if (state != DATA) + err("line %lu: not expecting data", lineno); + data.data = xmalloc(p + 1, len - 1); + data.size = len - 1; +ldata: switch(command) { + case COMPARE: + compare(&keydata, &data); + break; + case PUT: + put(dbp, &key, &data); + break; + default: + err("line %lu: command doesn't take data", + lineno); + } + if (type != DB_RECNO) + free(key.data); + free(data.data); + state = COMMAND; + break; + case 'K': /* key file */ + if (state != KEY) + err("line %lu: not expecting a key", lineno); + if (type == DB_RECNO) + err("line %lu: 'K' not available for recno", + lineno); + key.data = rfile(p + 1, &key.size); + goto lkey; + case 'k': /* key */ + if (state != KEY) + err("line %lu: not expecting a key", lineno); + if (type == DB_RECNO) { + static recno_t recno; + recno = atoi(p + 1); + key.data = &recno; + key.size = sizeof(recno); + } else { + key.data = xmalloc(p + 1, len - 1); + key.size = len - 1; + } +lkey: switch(command) { + case COMPARE: + getdata(dbp, &key, &keydata); + state = DATA; + break; + case GET: + get(dbp, &key); + if (type != DB_RECNO) + free(key.data); + state = COMMAND; + break; + case PUT: + state = DATA; + break; + case REMOVE: + rem(dbp, &key); + if (type != DB_RECNO) + free(key.data); + state = COMMAND; + break; + case SEQ: + seq(dbp, &key); + if (type != DB_RECNO) + free(key.data); + state = COMMAND; + break; + default: + err("line %lu: command doesn't take a key", + lineno); + } + break; + case 'o': + dump(dbp, p[1] == 'r'); + break; + default: + err("line %lu: %s: unknown command character", + p, lineno); + } + } +#ifdef STATISTICS + if (type == DB_BTREE) + __bt_stat(dbp); +#endif + if (dbp->close(dbp)) + err("db->close: %s", strerror(errno)); + (void)close(ofd); + exit(0); +} + +#define NOOVERWRITE "put failed, would overwrite key\n" +#define NOSUCHKEY "get failed, no such key\n" + +void +compare(db1, db2) + DBT *db1, *db2; +{ + register size_t len; + register u_char *p1, *p2; + + if (db1->size != db2->size) + printf("compare failed: key->data len %lu != data len %lu\n", + db1->size, db2->size); + + len = MIN(db1->size, db2->size); + for (p1 = db1->data, p2 = db2->data; len--;) + if (*p1++ != *p2++) { + printf("compare failed at offset %d\n", + p1 - (u_char *)db1->data); + break; + } +} + +void +get(dbp, kp) + DB *dbp; + DBT *kp; +{ + DBT data; + + switch(dbp->get(dbp, kp, &data, flags)) { + case 0: + (void)write(ofd, data.data, data.size); + break; + case -1: + err("line %lu: get: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); + (void)fprintf(stderr, "%d: %.*s: %s\n", + lineno, kp->size, kp->data, NOSUCHKEY); + break; + } +} + +void +getdata(dbp, kp, dp) + DB *dbp; + DBT *kp, *dp; +{ + switch(dbp->get(dbp, kp, dp, flags)) { + case 0: + return; + case -1: + err("line %lu: getdata: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + err("line %lu: get failed, no such key", lineno); + /* NOTREACHED */ + } +} + +void +put(dbp, kp, dp) + DB *dbp; + DBT *kp, *dp; +{ + switch(dbp->put(dbp, kp, dp, flags)) { + case 0: + break; + case -1: + err("line %lu: put: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1); + break; + } +} + +void +rem(dbp, kp) + DB *dbp; + DBT *kp; +{ + switch(dbp->del(dbp, kp, flags)) { + case 0: + break; + case -1: + err("line %lu: get: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); + break; + } +} + +void +seq(dbp, kp) + DB *dbp; + DBT *kp; +{ + DBT data; + + switch(dbp->seq(dbp, kp, &data, flags)) { + case 0: + (void)write(ofd, data.data, data.size); + break; + case -1: + err("line %lu: seq: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1); + break; + } +} + +void +dump(dbp, rev) + DB *dbp; + int rev; +{ + DBT key, data; + int flags, nflags; + + if (rev) { + flags = R_LAST; + nflags = R_PREV; + } else { + flags = R_FIRST; + nflags = R_NEXT; + } + for (;; flags = nflags) + switch(dbp->seq(dbp, &key, &data, flags)) { + case 0: + (void)write(ofd, data.data, data.size); + break; + case 1: + goto done; + case -1: + err("line %lu: (dump) seq: %s", + lineno, strerror(errno)); + /* NOTREACHED */ + } +done: return; +} + +u_int +setflags(s) + char *s; +{ + char *p, *index(); + + for (; isspace(*s); ++s); + if (*s == '\n') + return (0); + if ((p = index(s, '\n')) != NULL) + *p = '\0'; + if (!strcmp(s, "R_CURSOR")) + return (R_CURSOR); + if (!strcmp(s, "R_FIRST")) + return (R_FIRST); + if (!strcmp(s, "R_IAFTER")) + return (R_IAFTER); + if (!strcmp(s, "R_IBEFORE")) + return (R_IBEFORE); + if (!strcmp(s, "R_LAST")) + return (R_LAST); + if (!strcmp(s, "R_NEXT")) + return (R_NEXT); + if (!strcmp(s, "R_NOOVERWRITE")) + return (R_NOOVERWRITE); + if (!strcmp(s, "R_PREV")) + return (R_PREV); + if (!strcmp(s, "R_SETCURSOR")) + return (R_SETCURSOR); + err("line %lu: %s: unknown flag", lineno, s); + /* NOTREACHED */ +} + +DBTYPE +dbtype(s) + char *s; +{ + if (!strcmp(s, "btree")) + return (DB_BTREE); + if (!strcmp(s, "hash")) + return (DB_HASH); + if (!strcmp(s, "recno")) + return (DB_RECNO); + err("%s: unknown type (use btree, hash or recno)", s); + /* NOTREACHED */ +} + +void * +setinfo(type, s) + DBTYPE type; + char *s; +{ + static BTREEINFO ib; + static HASHINFO ih; + static RECNOINFO rh; + char *eq, *index(); + + if ((eq = index(s, '=')) == NULL) + err("%s: illegal structure set statement", s); + *eq++ = '\0'; + if (!isdigit(*eq)) + err("%s: structure set statement must be a number", s); + + switch(type) { + case DB_BTREE: + if (!strcmp("flags", s)) { + ib.flags = atoi(eq); + return (&ib); + } + if (!strcmp("cachesize", s)) { + ib.cachesize = atoi(eq); + return (&ib); + } + if (!strcmp("maxkeypage", s)) { + ib.maxkeypage = atoi(eq); + return (&ib); + } + if (!strcmp("minkeypage", s)) { + ib.minkeypage = atoi(eq); + return (&ib); + } + if (!strcmp("lorder", s)) { + ib.lorder = atoi(eq); + return (&ib); + } + if (!strcmp("psize", s)) { + ib.psize = atoi(eq); + return (&ib); + } + break; + case DB_HASH: + if (!strcmp("bsize", s)) { + ih.bsize = atoi(eq); + return (&ih); + } + if (!strcmp("ffactor", s)) { + ih.ffactor = atoi(eq); + return (&ih); + } + if (!strcmp("nelem", s)) { + ih.nelem = atoi(eq); + return (&ih); + } + if (!strcmp("cachesize", s)) { + ih.cachesize = atoi(eq); + return (&ih); + } + if (!strcmp("lorder", s)) { + ih.lorder = atoi(eq); + return (&ih); + } + break; + case DB_RECNO: + if (!strcmp("flags", s)) { + rh.flags = atoi(eq); + return (&rh); + } + if (!strcmp("cachesize", s)) { + rh.cachesize = atoi(eq); + return (&rh); + } + if (!strcmp("lorder", s)) { + rh.lorder = atoi(eq); + return (&rh); + } + if (!strcmp("reclen", s)) { + rh.reclen = atoi(eq); + return (&rh); + } + if (!strcmp("bval", s)) { + rh.bval = atoi(eq); + return (&rh); + } + if (!strcmp("psize", s)) { + rh.psize = atoi(eq); + return (&rh); + } + break; + } + err("%s: unknown structure value", s); + /* NOTREACHED */ +} + +void * +rfile(name, lenp) + char *name; + size_t *lenp; +{ + struct stat sb; + void *p; + int fd; + char *np, *index(); + + for (; isspace(*name); ++name); + if ((np = index(name, '\n')) != NULL) + *np = '\0'; + if ((fd = open(name, O_RDONLY, 0)) < 0 || + fstat(fd, &sb)) + err("%s: %s\n", name, strerror(errno)); +#ifdef NOT_PORTABLE + if (sb.st_size > (off_t)SIZE_T_MAX) + err("%s: %s\n", name, strerror(E2BIG)); +#endif + if ((p = (void *)malloc((u_int)sb.st_size)) == NULL) + err("%s", strerror(errno)); + (void)read(fd, p, (int)sb.st_size); + *lenp = sb.st_size; + (void)close(fd); + return (p); +} + +void * +xmalloc(text, len) + char *text; + size_t len; +{ + void *p; + + if ((p = (void *)malloc(len)) == NULL) + err("%s", strerror(errno)); + memmove(p, text, len); + return (p); +} + +void +usage() +{ + (void)fprintf(stderr, + "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n"); + exit(1); +} + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +void +#if __STDC__ +err(const char *fmt, ...) +#else +err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "dbtest: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(1); + /* NOTREACHED */ +} diff --git a/regress/lib/libc/db/run.test b/regress/lib/libc/db/run.test new file mode 100644 index 00000000000..4073310a311 --- /dev/null +++ b/regress/lib/libc/db/run.test @@ -0,0 +1,699 @@ +#!/bin/sh - +# $NetBSD: run.test,v 1.7 1995/04/20 22:39:27 cgd Exp $ +# +# @(#)run.test 8.8 (Berkeley) 6/16/94 +# + +# db regression tests +main() +{ + +DICT=/usr/share/dict/web2 +PROG=./dbtest +TMP1=t1 +TMP2=t2 +TMP3=t3 + + if [ $# -eq 0 ]; then + for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do + test$t + done + else + while [ $# -gt 0 ] + do case "$1" in + test*) + $1;; + [0-9]*) + test$1;; + btree) + for t in 1 2 3 7 8 9 10 12 13; do + test$t + done;; + hash) + for t in 1 2 3 8 13 20; do + test$t + done;; + recno) + for t in 1 2 3 4 5 6 7 10 11; do + test$t + done;; + *) + echo "run.test: unknown test $1" + echo "usage: run.test test# | type" + exit 1 + esac + shift + done + fi + rm -f $TMP1 $TMP2 $TMP3 + exit 0 +} + +# Take the first hundred entries in the dictionary, and make them +# be key/data pairs. +test1() +{ + echo "Test 1: btree, hash: small key, small data pairs" + sed 200q $DICT > $TMP1 + for type in btree hash; do + rm -f $TMP2 $TMP3 + for i in `sed 200q $DICT`; do + echo p + echo k$i + echo d$i + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test1: type $type: failed" + exit 1 + fi + done + echo "Test 1: recno: small key, small data pairs" + rm -f $TMP2 $TMP3 + sed 200q $DICT | + awk '{ + ++i; + printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test1: type recno: failed" + exit 1 + fi +} + +# Take the first 200 entries in the dictionary, and give them +# each a medium size data entry. +test2() +{ + echo "Test 2: btree, hash: small key, medium data pairs" + mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz + echo $mdata | + awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1 + for type in hash btree; do + rm -f $TMP2 $TMP3 + for i in `sed 200q $DICT`; do + echo p + echo k$i + echo d$mdata + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test2: type $type: failed" + exit 1 + fi + done + echo "Test 2: recno: small key, medium data pairs" + rm -f $TMP2 $TMP3 + echo $mdata | + awk '{ for (i = 1; i < 201; ++i) + printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test2: type recno: failed" + exit 1 + fi +} + +# Insert the programs in /bin with their paths as their keys. +test3() +{ + echo "Test 3: hash: small key, big data pairs" + rm -f $TMP1 + (find /bin -type f -print | xargs cat) > $TMP1 + for type in hash; do + rm -f $TMP2 $TMP3 + for i in `find /bin -type f -print`; do + echo p + echo k$i + echo D$i + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: $type: failed" + exit 1 + fi + done + echo "Test 3: btree: small key, big data pairs" + for psize in 512 16384 65536; do + echo " page size $psize" + for type in btree; do + rm -f $TMP2 $TMP3 + for i in `find /bin -type f -print`; do + echo p + echo k$i + echo D$i + echo g + echo k$i + done > $TMP2 + $PROG -i psize=$psize -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: $type: page size $psize: failed" + exit 1 + fi + done + done + echo "Test 3: recno: big data pairs" + rm -f $TMP2 $TMP3 + find /bin -type f -print | + awk '{ + ++i; + printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i); + }' > $TMP2 + for psize in 512 16384 65536; do + echo " page size $psize" + $PROG -i psize=$psize -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: recno: page size $psize: failed" + exit 1 + fi + done +} + +# Do random recno entries. +test4() +{ + echo "Test 4: recno: random entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 37; i <= 37 + 88 * 17; i += 17) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 1; i <= 15; ++i) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 19234; i <= 19234 + 61 * 27; i += 27) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 37; + incr = 17; + } + { + printf("p\nk%d\nd%s\n", i, $0); + if (i == 19234 + 61 * 27) + exit; + if (i == 37 + 88 * 17) { + i = 1; + incr = 1; + } else if (i == 15) { + i = 19234; + incr = 27; + } else + i += incr; + } + END { + for (i = 37; i <= 37 + 88 * 17; i += 17) + printf("g\nk%d\n", i); + for (i = 1; i <= 15; ++i) + printf("g\nk%d\n", i); + for (i = 19234; i <= 19234 + 61 * 27; i += 27) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test4: type recno: failed" + exit 1 + fi +} + +# Do reverse order recno entries. +test5() +{ + echo "Test 5: recno: reverse order entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk ' { + for (i = 1500; i; --i) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 1500; + } + { + printf("p\nk%d\nd%s\n", i, $0); + --i; + } + END { + for (i = 1500; i; --i) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test5: type recno: failed" + exit 1 + fi +} + +# Do alternating order recno entries. +test6() +{ + echo "Test 6: recno: alternating order entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk ' { + for (i = 1; i < 1200; i += 2) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 2; i < 1200; i += 2) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 1; + even = 0; + } + { + printf("p\nk%d\nd%s\n", i, $0); + i += 2; + if (i >= 1200) { + if (even == 1) + exit; + even = 1; + i = 2; + } + } + END { + for (i = 1; i < 1200; ++i) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + sort -o $TMP1 $TMP1 + sort -o $TMP3 $TMP3 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test6: type recno: failed" + exit 1 + fi +} + +# Delete cursor record +test7() +{ + echo "Test 7: btree, recno: delete cursor record" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 120; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + printf("%05d: input key %d: %s\n", 120, 120, $0); + printf("get failed, no such key\n"); + printf("%05d: input key %d: %s\n", 1, 1, $0); + printf("%05d: input key %d: %s\n", 2, 2, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 120) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_NEXT\n"); + for (i = 1; i <= 120; ++i) + printf("s\n"); + printf("fR_CURSOR\ns\nk120\n"); + printf("r\nk120\n"); + printf("fR_NEXT\ns\n"); + printf("fR_CURSOR\ns\nk1\n"); + printf("r\nk1\n"); + printf("fR_FIRST\ns\n"); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test7: type $type: failed" + exit 1 + fi + done +} + +# Make sure that overflow pages are reused. +test8() +{ + echo "Test 8: btree, hash: repeated small key, big data pairs" + rm -f $TMP1 + echo "" | + awk 'BEGIN { + for (i = 1; i <= 10; ++i) { + printf("p\nkkey1\nD/bin/sh\n"); + printf("p\nkkey2\nD/bin/csh\n"); + if (i % 8 == 0) { + printf("c\nkkey2\nD/bin/csh\n"); + printf("c\nkkey1\nD/bin/sh\n"); + printf("e\t%d of 10 (comparison)\n", i); + } else + printf("e\t%d of 10 \n", i); + printf("r\nkkey1\nr\nkkey2\n"); + } + printf("e\n"); + printf("eend of test8 run\n"); + }' > $TMP1 + $PROG btree $TMP1 +# $PROG hash $TMP1 + # No explicit test for success. +} + +# Test btree duplicate keys +test9() +{ + echo "Test 9: btree: duplicate keys" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 543; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in btree; do + cat $TMP1 | + awk '{ + if (i++ % 2) + printf("p\nkduplicatekey\nd%s\n", $0); + else + printf("p\nkunique%dkey\nd%s\n", i, $0); + } + END { + printf("o\n"); + }' > $TMP2 + $PROG -iflags=1 -o $TMP3 $type $TMP2 + sort -o $TMP3 $TMP3 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test9: type $type: failed" + exit 1 + fi + done +} + +# Test use of cursor flags without initialization +test10() +{ + echo "Test 10: btree, recno: test cursor flag use" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 20; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + # Test that R_CURSOR doesn't succeed before cursor initialized + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 10) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_CURSOR\nr\nk1\n"); + printf("eR_CURSOR SHOULD HAVE FAILED\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1 + if [ -s $TMP3 ] ; then + echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED" + exit 1 + fi + done + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 10) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_CURSOR\np\nk1\ndsome data\n"); + printf("eR_CURSOR SHOULD HAVE FAILED\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1 + if [ -s $TMP3 ] ; then + echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED" + exit 1 + fi + done +} + +# Test insert in reverse order. +test11() +{ + echo "Test 11: recno: reverse order insert" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 779; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in recno; do + cat $TMP1 | + awk '{ + if (i == 0) { + i = 1; + printf("p\nk1\nd%s\n", $0); + printf("%s\n", "fR_IBEFORE"); + } else + printf("p\nk1\nd%s\n", $0); + } + END { + printf("or\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test11: type $type: failed" + exit 1 + fi + done +} + +# Take the first 20000 entries in the dictionary, reverse them, and give +# them each a small size data entry. Use a small page size to make sure +# the btree split code gets hammered. +test12() +{ + echo "Test 12: btree: lots of keys, small page size" + mdata=abcdefghijklmnopqrstuvwxy + echo $mdata | + awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1 + for type in btree; do + rm -f $TMP2 $TMP3 + for i in `sed 20000q $DICT | rev`; do + echo p + echo k$i + echo d$mdata + echo g + echo k$i + done > $TMP2 + $PROG -i psize=512 -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test12: type $type: failed" + exit 1 + fi + done +} + +# Test different byte orders. +test13() +{ + echo "Test 13: btree, hash: differing byte orders" + sed 50q $DICT > $TMP1 + for order in 1234 4321; do + for type in btree hash; do + rm -f byte.file $TMP2 $TMP3 + for i in `sed 50q $DICT`; do + echo p + echo k$i + echo d$i + echo g + echo k$i + done > $TMP2 + $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test13: $type/$order put failed" + exit 1 + fi + for i in `sed 50q $DICT`; do + echo g + echo k$i + done > $TMP2 + $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test13: $type/$order get failed" + exit 1 + fi + done + done + rm -f byte.file +} + +# Try a variety of bucketsizes and fill factors for hashing +test20() +{ + echo\ + "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 10000; ++i) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("%s\n", s); + } + exit; + }' > $TMP1 + sed 10000q $DICT | + awk 'BEGIN { + ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" + } + { + if (++i % 34) + s = substr(ds, 1, i % 34); + else + s = substr(ds, 1); + printf("p\nk%s\nd%s\n", $0, s); + }' > $TMP2 + sed 10000q $DICT | + awk '{ + ++i; + printf("g\nk%s\n", $0); + }' >> $TMP2 + bsize=256 + for ffactor in 11 14 21; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=512 + for ffactor in 21 28 43; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=1024 + for ffactor in 43 57 85; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=2048 + for ffactor in 85 114 171; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=4096 + for ffactor in 171 228 341; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=8192 + for ffactor in 341 455 683; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done +} + +main $* diff --git a/regress/lib/libc/ieeefp/Makefile b/regress/lib/libc/ieeefp/Makefile new file mode 100644 index 00000000000..4e2e517b038 --- /dev/null +++ b/regress/lib/libc/ieeefp/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.4 1995/10/03 21:59:36 phil Exp $ + +.if ${MACHINE} == "pc532" +SUBDIR+= round +.else +SUBDIR+= except round +.endif + +regress: _SUBDIRUSE + +install: + +.include <bsd.subdir.mk> diff --git a/regress/lib/libc/ieeefp/except/Makefile b/regress/lib/libc/ieeefp/except/Makefile new file mode 100644 index 00000000000..91f24f15f68 --- /dev/null +++ b/regress/lib/libc/ieeefp/except/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 1995/04/26 00:27:25 jtc Exp $ + +PROG= except +SRCS= except.c +NOMAN= + +install: + +regress: ${PROG} + ./${PROG} + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/ieeefp/except/except.c b/regress/lib/libc/ieeefp/except/except.c new file mode 100644 index 00000000000..0ffdcdd468f --- /dev/null +++ b/regress/lib/libc/ieeefp/except/except.c @@ -0,0 +1,87 @@ +#include <stdio.h> +#include <signal.h> +#include <assert.h> +#include <ieeefp.h> +#include <float.h> + +void sigfpe(); +volatile sig_atomic_t signal_cought; + +static volatile const double one = 1.0; +static volatile const double zero = 0.0; +static volatile const double huge = DBL_MAX; +static volatile const double tiny = DBL_MIN; + +main() +{ + volatile double x; + + /* + * check to make sure that all exceptions are masked and + * that the accumulated exception status is clear. + */ + assert(fpgetmask() == 0); + assert(fpgetsticky() == 0); + + /* set up signal handler */ + signal (SIGFPE, sigfpe); + signal_cought = 0; + + /* trip divide by zero */ + x = one / zero; + assert (fpgetsticky() & FP_X_DZ); + assert (signal_cought == 0); + fpsetsticky(0); + + /* trip invalid operation */ + x = zero / zero; + assert (fpgetsticky() & FP_X_INV); + assert (signal_cought == 0); + fpsetsticky(0); + + /* trip overflow */ + x = huge * huge; + assert (fpgetsticky() & FP_X_OFL); + assert (signal_cought == 0); + fpsetsticky(0); + + /* trip underflow */ + x = tiny * tiny; + assert (fpgetsticky() & FP_X_UFL); + assert (signal_cought == 0); + fpsetsticky(0); + +#if 0 + /* unmask and then trip divide by zero */ + fpsetmask(FP_X_DZ); + x = one / zero; + assert (signal_cought == 1); + signal_cought = 0; + + /* unmask and then trip invalid operation */ + fpsetmask(FP_X_INV); + x = zero / zero; + assert (signal_cought == 1); + signal_cought = 0; + + /* unmask and then trip overflow */ + fpsetmask(FP_X_OFL); + x = huge * huge; + assert (signal_cought == 1); + signal_cought = 0; + + /* unmask and then trip underflow */ + fpsetmask(FP_X_UFL); + x = tiny * tiny; + assert (signal_cought == 1); + signal_cought = 0; +#endif + + exit(0); +} + +void +sigfpe() +{ + signal_cought = 1; +} diff --git a/regress/lib/libc/ieeefp/round/Makefile b/regress/lib/libc/ieeefp/round/Makefile new file mode 100644 index 00000000000..571133436cb --- /dev/null +++ b/regress/lib/libc/ieeefp/round/Makefile @@ -0,0 +1,12 @@ +# $NetBSD: Makefile,v 1.1 1995/04/26 00:27:27 jtc Exp $ + +PROG= round +SRCS= round.c +NOMAN= + +install: + +regress: ${PROG} + ./${PROG} + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/ieeefp/round/round.c b/regress/lib/libc/ieeefp/round/round.c new file mode 100644 index 00000000000..b9fcd9771e8 --- /dev/null +++ b/regress/lib/libc/ieeefp/round/round.c @@ -0,0 +1,44 @@ +/* $NetBSD: round.c,v 1.1 1995/04/26 00:27:28 jtc Exp $ */ + +/* + * Written by J.T. Conklin, Apr 18, 1995 + * Public domain. + */ + +#include <assert.h> +#include <stdlib.h> +#include <ieeefp.h> +#include <float.h> + +int +main() +{ + /* + * This test would be better if it actually performed some + * calculations to verify the selected rounding mode. But + * this is probably acceptable since the fp{get,set}round + * functions usually just get or set the processors fpu + * control word. + */ + + assert(fpgetround() == FP_RN); + assert(FLT_ROUNDS == 1); + + assert(fpsetround(FP_RP) == FP_RN); + assert(fpgetround() == FP_RP); + assert(FLT_ROUNDS == 2); + + assert(fpsetround(FP_RM) == FP_RP); + assert(fpgetround() == FP_RM); + assert(FLT_ROUNDS == 3); + + assert(fpsetround(FP_RZ) == FP_RM); + assert(fpgetround() == FP_RZ); + assert(FLT_ROUNDS == 0); + + assert(fpsetround(FP_RN) == FP_RZ); + assert(fpgetround() == FP_RN); + assert(FLT_ROUNDS == 1); + + exit(0); +} diff --git a/regress/lib/libc/regex/Makefile b/regress/lib/libc/regex/Makefile new file mode 100644 index 00000000000..93b7bb90525 --- /dev/null +++ b/regress/lib/libc/regex/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.2 1995/02/16 19:38:45 cgd Exp $ + +PROG= re +SRCS= main.c split.c debug.c +NOMAN= + +CFLAGS+= -I${.CURDIR}/../../../../lib/libc/regex + +TESTS= ${.CURDIR}/tests + +regress: + ./re < ${TESTS} + ./re -el < ${TESTS} + ./re -er < ${TESTS} + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/regex/debug.c b/regress/lib/libc/regex/debug.c new file mode 100644 index 00000000000..861f550611e --- /dev/null +++ b/regress/lib/libc/regex/debug.c @@ -0,0 +1,244 @@ +/* $NetBSD: debug.c,v 1.2 1995/04/20 22:39:42 cgd Exp $ */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> +#include <stdlib.h> +#include <sys/types.h> +#include <regex.h> + +#include "utils.h" +#include "regex2.h" +#include "debug.ih" + +/* + - regprint - print a regexp for debugging + == void regprint(regex_t *r, FILE *d); + */ +void +regprint(r, d) +regex_t *r; +FILE *d; +{ + register struct re_guts *g = r->re_g; + register int i; + register int c; + register int last; + int nincat[NC]; + + fprintf(d, "%ld states, %d categories", (long)g->nstates, + g->ncategories); + fprintf(d, ", first %ld last %ld", (long)g->firststate, + (long)g->laststate); + if (g->iflags&USEBOL) + fprintf(d, ", USEBOL"); + if (g->iflags&USEEOL) + fprintf(d, ", USEEOL"); + if (g->iflags&BAD) + fprintf(d, ", BAD"); + if (g->nsub > 0) + fprintf(d, ", nsub=%ld", (long)g->nsub); + if (g->must != NULL) + fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen, + g->must); + if (g->backrefs) + fprintf(d, ", backrefs"); + if (g->nplus > 0) + fprintf(d, ", nplus %ld", (long)g->nplus); + fprintf(d, "\n"); + s_print(g, d); + for (i = 0; i < g->ncategories; i++) { + nincat[i] = 0; + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (g->categories[c] == i) + nincat[i]++; + } + fprintf(d, "cc0#%d", nincat[0]); + for (i = 1; i < g->ncategories; i++) + if (nincat[i] == 1) { + for (c = CHAR_MIN; c <= CHAR_MAX; c++) + if (g->categories[c] == i) + break; + fprintf(d, ", %d=%s", i, regchar(c)); + } + fprintf(d, "\n"); + for (i = 1; i < g->ncategories; i++) + if (nincat[i] != 1) { + fprintf(d, "cc%d\t", i); + last = -1; + for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */ + if (c <= CHAR_MAX && g->categories[c] == i) { + if (last < 0) { + fprintf(d, "%s", regchar(c)); + last = c; + } + } else { + if (last >= 0) { + if (last != c-1) + fprintf(d, "-%s", + regchar(c-1)); + last = -1; + } + } + fprintf(d, "\n"); + } +} + +/* + - s_print - print the strip for debugging + == static void s_print(register struct re_guts *g, FILE *d); + */ +static void +s_print(g, d) +register struct re_guts *g; +FILE *d; +{ + register sop *s; + register cset *cs; + register int i; + register int done = 0; + register sop opnd; + register int col = 0; + register int last; + register sopno offset = 2; +# define GAP() { if (offset % 5 == 0) { \ + if (col > 40) { \ + fprintf(d, "\n\t"); \ + col = 0; \ + } else { \ + fprintf(d, " "); \ + col++; \ + } \ + } else \ + col++; \ + offset++; \ + } + + if (OP(g->strip[0]) != OEND) + fprintf(d, "missing initial OEND!\n"); + for (s = &g->strip[1]; !done; s++) { + opnd = OPND(*s); + switch (OP(*s)) { + case OEND: + fprintf(d, "\n"); + done = 1; + break; + case OCHAR: + if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL) + fprintf(d, "\\%c", (char)opnd); + else + fprintf(d, "%s", regchar((char)opnd)); + break; + case OBOL: + fprintf(d, "^"); + break; + case OEOL: + fprintf(d, "$"); + break; + case OBOW: + fprintf(d, "\\{"); + break; + case OEOW: + fprintf(d, "\\}"); + break; + case OANY: + fprintf(d, "."); + break; + case OANYOF: + fprintf(d, "[(%ld)", (long)opnd); + cs = &g->sets[opnd]; + last = -1; + for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */ + if (CHIN(cs, i) && i < g->csetsize) { + if (last < 0) { + fprintf(d, "%s", regchar(i)); + last = i; + } + } else { + if (last >= 0) { + if (last != i-1) + fprintf(d, "-%s", + regchar(i-1)); + last = -1; + } + } + fprintf(d, "]"); + break; + case OBACK_: + fprintf(d, "(\\<%ld>", (long)opnd); + break; + case O_BACK: + fprintf(d, "<%ld>\\)", (long)opnd); + break; + case OPLUS_: + fprintf(d, "(+"); + if (OP(*(s+opnd)) != O_PLUS) + fprintf(d, "<%ld>", (long)opnd); + break; + case O_PLUS: + if (OP(*(s-opnd)) != OPLUS_) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, "+)"); + break; + case OQUEST_: + fprintf(d, "(?"); + if (OP(*(s+opnd)) != O_QUEST) + fprintf(d, "<%ld>", (long)opnd); + break; + case O_QUEST: + if (OP(*(s-opnd)) != OQUEST_) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, "?)"); + break; + case OLPAREN: + fprintf(d, "((<%ld>", (long)opnd); + break; + case ORPAREN: + fprintf(d, "<%ld>))", (long)opnd); + break; + case OCH_: + fprintf(d, "<"); + if (OP(*(s+opnd)) != OOR2) + fprintf(d, "<%ld>", (long)opnd); + break; + case OOR1: + if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, "|"); + break; + case OOR2: + fprintf(d, "|"); + if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH) + fprintf(d, "<%ld>", (long)opnd); + break; + case O_CH: + if (OP(*(s-opnd)) != OOR1) + fprintf(d, "<%ld>", (long)opnd); + fprintf(d, ">"); + break; + default: + fprintf(d, "!%d(%d)!", OP(*s), opnd); + break; + } + if (!done) + GAP(); + } +} + +/* + - regchar - make a character printable + == static char *regchar(int ch); + */ +static char * /* -> representation */ +regchar(ch) +int ch; +{ + static char buf[10]; + + if (isprint(ch) || ch == ' ') + sprintf(buf, "%c", ch); + else + sprintf(buf, "\\%o", ch); + return(buf); +} diff --git a/regress/lib/libc/regex/debug.ih b/regress/lib/libc/regex/debug.ih new file mode 100644 index 00000000000..fb9bac0c756 --- /dev/null +++ b/regress/lib/libc/regex/debug.ih @@ -0,0 +1,16 @@ +/* $NetBSD: debug.ih,v 1.2 1995/04/20 22:39:47 cgd Exp $ */ + +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === debug.c === */ +void regprint __P((regex_t *r, FILE *d)); +static void s_print __P((register struct re_guts *g, FILE *d)); +static char *regchar __P((int ch)); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/regress/lib/libc/regex/main.c b/regress/lib/libc/regex/main.c new file mode 100644 index 00000000000..8d88a8b9b81 --- /dev/null +++ b/regress/lib/libc/regex/main.c @@ -0,0 +1,512 @@ +/* $NetBSD: main.c,v 1.2 1995/04/20 22:39:51 cgd Exp $ */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <regex.h> +#include <assert.h> + +#include "main.ih" + +char *progname; +int debug = 0; +int line = 0; +int status = 0; + +int copts = REG_EXTENDED; +int eopts = 0; +regoff_t startoff = 0; +regoff_t endoff = 0; + + +extern int split(); +extern void regprint(); + +/* + - main - do the simple case, hand off to regress() for regression + */ +main(argc, argv) +int argc; +char *argv[]; +{ + regex_t re; +# define NS 10 + regmatch_t subs[NS]; + char erbuf[100]; + int err; + size_t len; + int c; + int errflg = 0; + register int i; + extern int optind; + extern char *optarg; + + progname = argv[0]; + + while ((c = getopt(argc, argv, "c:e:S:E:x")) != EOF) + switch (c) { + case 'c': /* compile options */ + copts = options('c', optarg); + break; + case 'e': /* execute options */ + eopts = options('e', optarg); + break; + case 'S': /* start offset */ + startoff = (regoff_t)atoi(optarg); + break; + case 'E': /* end offset */ + endoff = (regoff_t)atoi(optarg); + break; + case 'x': /* Debugging. */ + debug++; + break; + case '?': + default: + errflg++; + break; + } + if (errflg) { + fprintf(stderr, "usage: %s ", progname); + fprintf(stderr, "[-c copt][-C][-d] [re]\n"); + exit(2); + } + + if (optind >= argc) { + regress(stdin); + exit(status); + } + + err = regcomp(&re, argv[optind++], copts); + if (err) { + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "error %s, %d/%d `%s'\n", + eprint(err), len, sizeof(erbuf), erbuf); + exit(status); + } + regprint(&re, stdout); + + if (optind >= argc) { + regfree(&re); + exit(status); + } + + if (eopts®_STARTEND) { + subs[0].rm_so = startoff; + subs[0].rm_eo = strlen(argv[optind]) - endoff; + } + err = regexec(&re, argv[optind], (size_t)NS, subs, eopts); + if (err) { + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "error %s, %d/%d `%s'\n", + eprint(err), len, sizeof(erbuf), erbuf); + exit(status); + } + if (!(copts®_NOSUB)) { + len = (int)(subs[0].rm_eo - subs[0].rm_so); + if (subs[0].rm_so != -1) { + if (len != 0) + printf("match `%.*s'\n", len, + argv[optind] + subs[0].rm_so); + else + printf("match `'@%.1s\n", + argv[optind] + subs[0].rm_so); + } + for (i = 1; i < NS; i++) + if (subs[i].rm_so != -1) + printf("(%d) `%.*s'\n", i, + (int)(subs[i].rm_eo - subs[i].rm_so), + argv[optind] + subs[i].rm_so); + } + exit(status); +} + +/* + - regress - main loop of regression test + == void regress(FILE *in); + */ +void +regress(in) +FILE *in; +{ + char inbuf[1000]; +# define MAXF 10 + char *f[MAXF]; + int nf; + int i; + char erbuf[100]; + size_t ne; + char *badpat = "invalid regular expression"; +# define SHORT 10 + char *bpname = "REG_BADPAT"; + regex_t re; + + while (fgets(inbuf, sizeof(inbuf), in) != NULL) { + line++; + if (inbuf[0] == '#' || inbuf[0] == '\n') + continue; /* NOTE CONTINUE */ + inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */ + if (debug) + fprintf(stdout, "%d:\n", line); + nf = split(inbuf, f, MAXF, "\t\t"); + if (nf < 3) { + fprintf(stderr, "bad input, line %d\n", line); + exit(1); + } + for (i = 0; i < nf; i++) + if (strcmp(f[i], "\"\"") == 0) + f[i] = ""; + if (nf <= 3) + f[3] = NULL; + if (nf <= 4) + f[4] = NULL; + try(f[0], f[1], f[2], f[3], f[4], options('c', f[1])); + if (opt('&', f[1])) /* try with either type of RE */ + try(f[0], f[1], f[2], f[3], f[4], + options('c', f[1]) &~ REG_EXTENDED); + } + + ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf)); + if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) { + fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n", + erbuf, badpat); + status = 1; + } + ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT); + if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' || + ne != strlen(badpat)+1) { + fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n", + erbuf, SHORT-1, badpat); + status = 1; + } + ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf)); + if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) { + fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n", + erbuf, bpname); + status = 1; + } + re.re_endp = bpname; + ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf)); + if (atoi(erbuf) != (int)REG_BADPAT) { + fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n", + erbuf, (long)REG_BADPAT); + status = 1; + } else if (ne != strlen(erbuf)+1) { + fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n", + erbuf, (long)REG_BADPAT); + status = 1; + } +} + +/* + - try - try it, and report on problems + == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts); + */ +void +try(f0, f1, f2, f3, f4, opts) +char *f0; +char *f1; +char *f2; +char *f3; +char *f4; +int opts; /* may not match f1 */ +{ + regex_t re; +# define NSUBS 10 + regmatch_t subs[NSUBS]; +# define NSHOULD 15 + char *should[NSHOULD]; + int nshould; + char erbuf[100]; + int err; + int len; + char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE"; + register int i; + char *grump; + char f0copy[1000]; + char f2copy[1000]; + + strcpy(f0copy, f0); + re.re_endp = (opts®_PEND) ? f0copy + strlen(f0copy) : NULL; + fixstr(f0copy); + err = regcomp(&re, f0copy, opts); + if (err != 0 && (!opt('C', f1) || err != efind(f2))) { + /* unexpected error or wrong error */ + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n", + line, type, eprint(err), len, + sizeof(erbuf), erbuf); + status = 1; + } else if (err == 0 && opt('C', f1)) { + /* unexpected success */ + fprintf(stderr, "%d: %s should have given REG_%s\n", + line, type, f2); + status = 1; + err = 1; /* so we won't try regexec */ + } + + if (err != 0) { + regfree(&re); + return; + } + + strcpy(f2copy, f2); + fixstr(f2copy); + + if (options('e', f1)®_STARTEND) { + if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL) + fprintf(stderr, "%d: bad STARTEND syntax\n", line); + subs[0].rm_so = strchr(f2, '(') - f2 + 1; + subs[0].rm_eo = strchr(f2, ')') - f2; + } + err = regexec(&re, f2copy, NSUBS, subs, options('e', f1)); + + if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) { + /* unexpected error or wrong error */ + len = regerror(err, &re, erbuf, sizeof(erbuf)); + fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n", + line, type, eprint(err), len, + sizeof(erbuf), erbuf); + status = 1; + } else if (err != 0) { + /* nothing more to check */ + } else if (f3 == NULL) { + /* unexpected success */ + fprintf(stderr, "%d: %s exec should have failed\n", + line, type); + status = 1; + err = 1; /* just on principle */ + } else if (opts®_NOSUB) { + /* nothing more to check */ + } else if ((grump = check(f2, subs[0], f3)) != NULL) { + fprintf(stderr, "%d: %s %s\n", line, type, grump); + status = 1; + err = 1; + } + + if (err != 0 || f4 == NULL) { + regfree(&re); + return; + } + + for (i = 1; i < NSHOULD; i++) + should[i] = NULL; + nshould = split(f4, should+1, NSHOULD-1, ","); + if (nshould == 0) { + nshould = 1; + should[1] = ""; + } + for (i = 1; i < NSUBS; i++) { + grump = check(f2, subs[i], should[i]); + if (grump != NULL) { + fprintf(stderr, "%d: %s $%d %s\n", line, + type, i, grump); + status = 1; + err = 1; + } + } + + regfree(&re); +} + +/* + - options - pick options out of a regression-test string + == int options(int type, char *s); + */ +int +options(type, s) +int type; /* 'c' compile, 'e' exec */ +char *s; +{ + register char *p; + register int o = (type == 'c') ? copts : eopts; + register char *legal = (type == 'c') ? "bisnmp" : "^$#tl"; + + for (p = s; *p != '\0'; p++) + if (strchr(legal, *p) != NULL) + switch (*p) { + case 'b': + o &= ~REG_EXTENDED; + break; + case 'i': + o |= REG_ICASE; + break; + case 's': + o |= REG_NOSUB; + break; + case 'n': + o |= REG_NEWLINE; + break; + case 'm': + o &= ~REG_EXTENDED; + o |= REG_NOSPEC; + break; + case 'p': + o |= REG_PEND; + break; + case '^': + o |= REG_NOTBOL; + break; + case '$': + o |= REG_NOTEOL; + break; + case '#': + o |= REG_STARTEND; + break; + case 't': /* trace */ + o |= REG_TRACE; + break; + case 'l': /* force long representation */ + o |= REG_LARGE; + break; + case 'r': /* force backref use */ + o |= REG_BACKR; + break; + } + return(o); +} + +/* + - opt - is a particular option in a regression string? + == int opt(int c, char *s); + */ +int /* predicate */ +opt(c, s) +int c; +char *s; +{ + return(strchr(s, c) != NULL); +} + +/* + - fixstr - transform magic characters in strings + == void fixstr(register char *p); + */ +void +fixstr(p) +register char *p; +{ + if (p == NULL) + return; + + for (; *p != '\0'; p++) + if (*p == 'N') + *p = '\n'; + else if (*p == 'T') + *p = '\t'; + else if (*p == 'S') + *p = ' '; + else if (*p == 'Z') + *p = '\0'; +} + +/* + - check - check a substring match + == char *check(char *str, regmatch_t sub, char *should); + */ +char * /* NULL or complaint */ +check(str, sub, should) +char *str; +regmatch_t sub; +char *should; +{ + register int len; + register int shlen; + register char *p; + static char grump[500]; + register char *at = NULL; + + if (should != NULL && strcmp(should, "-") == 0) + should = NULL; + if (should != NULL && should[0] == '@') { + at = should + 1; + should = ""; + } + + /* check rm_so and rm_eo for consistency */ + if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) || + (sub.rm_so != -1 && sub.rm_eo == -1) || + (sub.rm_so != -1 && sub.rm_so < 0) || + (sub.rm_eo != -1 && sub.rm_eo < 0) ) { + sprintf(grump, "start %ld end %ld", (long)sub.rm_so, + (long)sub.rm_eo); + return(grump); + } + + /* check for no match */ + if (sub.rm_so == -1 && should == NULL) + return(NULL); + if (sub.rm_so == -1) + return("did not match"); + + /* check for in range */ + if (sub.rm_eo > strlen(str)) { + sprintf(grump, "start %ld end %ld, past end of string", + (long)sub.rm_so, (long)sub.rm_eo); + return(grump); + } + + len = (int)(sub.rm_eo - sub.rm_so); + shlen = (int)strlen(should); + p = str + sub.rm_so; + + /* check for not supposed to match */ + if (should == NULL) { + sprintf(grump, "matched `%.*s'", len, p); + return(grump); + } + + /* check for wrong match */ + if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) { + sprintf(grump, "matched `%.*s' instead", len, p); + return(grump); + } + if (shlen > 0) + return(NULL); + + /* check null match in right place */ + if (at == NULL) + return(NULL); + shlen = strlen(at); + if (shlen == 0) + shlen = 1; /* force check for end-of-string */ + if (strncmp(p, at, shlen) != 0) { + sprintf(grump, "matched null at `%.20s'", p); + return(grump); + } + return(NULL); +} + +/* + - eprint - convert error number to name + == static char *eprint(int err); + */ +static char * +eprint(err) +int err; +{ + static char epbuf[100]; + size_t len; + + len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf)); + assert(len <= sizeof(epbuf)); + return(epbuf); +} + +/* + - efind - convert error name to number + == static int efind(char *name); + */ +static int +efind(name) +char *name; +{ + static char efbuf[100]; + size_t n; + regex_t re; + + sprintf(efbuf, "REG_%s", name); + assert(strlen(efbuf) < sizeof(efbuf)); + re.re_endp = efbuf; + (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf)); + return(atoi(efbuf)); +} diff --git a/regress/lib/libc/regex/main.ih b/regress/lib/libc/regex/main.ih new file mode 100644 index 00000000000..135e3e792d6 --- /dev/null +++ b/regress/lib/libc/regex/main.ih @@ -0,0 +1,21 @@ +/* $NetBSD: main.ih,v 1.2 1995/04/20 22:39:55 cgd Exp $ */ + +/* ========= begin header generated by ./mkh ========= */ +#ifdef __cplusplus +extern "C" { +#endif + +/* === main.c === */ +void regress __P((FILE *in)); +void try __P((char *f0, char *f1, char *f2, char *f3, char *f4, int opts)); +int options __P((int type, char *s)); +int opt __P((int c, char *s)); +void fixstr __P((register char *p)); +char *check __P((char *str, regmatch_t sub, char *should)); +static char *eprint __P((int err)); +static int efind __P((char *name)); + +#ifdef __cplusplus +} +#endif +/* ========= end header generated by ./mkh ========= */ diff --git a/regress/lib/libc/regex/split.c b/regress/lib/libc/regex/split.c new file mode 100644 index 00000000000..dd1ca144800 --- /dev/null +++ b/regress/lib/libc/regex/split.c @@ -0,0 +1,318 @@ +/* $NetBSD: split.c,v 1.2 1995/04/20 22:39:57 cgd Exp $ */ + +#include <stdio.h> +#include <string.h> + +/* + - split - divide a string into fields, like awk split() + = int split(char *string, char *fields[], int nfields, char *sep); + */ +int /* number of fields, including overflow */ +split(string, fields, nfields, sep) +char *string; +char *fields[]; /* list is not NULL-terminated */ +int nfields; /* number of entries available in fields[] */ +char *sep; /* "" white, "c" single char, "ab" [ab]+ */ +{ + register char *p = string; + register char c; /* latest character */ + register char sepc = sep[0]; + register char sepc2; + register int fn; + register char **fp = fields; + register char *sepp; + register int trimtrail; + + /* white space */ + if (sepc == '\0') { + while ((c = *p++) == ' ' || c == '\t') + continue; + p--; + trimtrail = 1; + sep = " \t"; /* note, code below knows this is 2 long */ + sepc = ' '; + } else + trimtrail = 0; + sepc2 = sep[1]; /* now we can safely pick this up */ + + /* catch empties */ + if (*p == '\0') + return(0); + + /* single separator */ + if (sepc2 == '\0') { + fn = nfields; + for (;;) { + *fp++ = p; + fn--; + if (fn == 0) + break; + while ((c = *p++) != sepc) + if (c == '\0') + return(nfields - fn); + *(p-1) = '\0'; + } + /* we have overflowed the fields vector -- just count them */ + fn = nfields; + for (;;) { + while ((c = *p++) != sepc) + if (c == '\0') + return(fn); + fn++; + } + /* not reached */ + } + + /* two separators */ + if (sep[2] == '\0') { + fn = nfields; + for (;;) { + *fp++ = p; + fn--; + while ((c = *p++) != sepc && c != sepc2) + if (c == '\0') { + if (trimtrail && **(fp-1) == '\0') + fn++; + return(nfields - fn); + } + if (fn == 0) + break; + *(p-1) = '\0'; + while ((c = *p++) == sepc || c == sepc2) + continue; + p--; + } + /* we have overflowed the fields vector -- just count them */ + fn = nfields; + while (c != '\0') { + while ((c = *p++) == sepc || c == sepc2) + continue; + p--; + fn++; + while ((c = *p++) != '\0' && c != sepc && c != sepc2) + continue; + } + /* might have to trim trailing white space */ + if (trimtrail) { + p--; + while ((c = *--p) == sepc || c == sepc2) + continue; + p++; + if (*p != '\0') { + if (fn == nfields+1) + *p = '\0'; + fn--; + } + } + return(fn); + } + + /* n separators */ + fn = 0; + for (;;) { + if (fn < nfields) + *fp++ = p; + fn++; + for (;;) { + c = *p++; + if (c == '\0') + return(fn); + sepp = sep; + while ((sepc = *sepp++) != '\0' && sepc != c) + continue; + if (sepc != '\0') /* it was a separator */ + break; + } + if (fn < nfields) + *(p-1) = '\0'; + for (;;) { + c = *p++; + sepp = sep; + while ((sepc = *sepp++) != '\0' && sepc != c) + continue; + if (sepc == '\0') /* it wasn't a separator */ + break; + } + p--; + } + + /* not reached */ +} + +#ifdef TEST_SPLIT + + +/* + * test program + * pgm runs regression + * pgm sep splits stdin lines by sep + * pgm str sep splits str by sep + * pgm str sep n splits str by sep n times + */ +int +main(argc, argv) +int argc; +char *argv[]; +{ + char buf[512]; + register int n; +# define MNF 10 + char *fields[MNF]; + + if (argc > 4) + for (n = atoi(argv[3]); n > 0; n--) { + (void) strcpy(buf, argv[1]); + } + else if (argc > 3) + for (n = atoi(argv[3]); n > 0; n--) { + (void) strcpy(buf, argv[1]); + (void) split(buf, fields, MNF, argv[2]); + } + else if (argc > 2) + dosplit(argv[1], argv[2]); + else if (argc > 1) + while (fgets(buf, sizeof(buf), stdin) != NULL) { + buf[strlen(buf)-1] = '\0'; /* stomp newline */ + dosplit(buf, argv[1]); + } + else + regress(); + + exit(0); +} + +dosplit(string, seps) +char *string; +char *seps; +{ +# define NF 5 + char *fields[NF]; + register int nf; + + nf = split(string, fields, NF, seps); + print(nf, NF, fields); +} + +print(nf, nfp, fields) +int nf; +int nfp; +char *fields[]; +{ + register int fn; + register int bound; + + bound = (nf > nfp) ? nfp : nf; + printf("%d:\t", nf); + for (fn = 0; fn < bound; fn++) + printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n"); +} + +#define RNF 5 /* some table entries know this */ +struct { + char *str; + char *seps; + int nf; + char *fi[RNF]; +} tests[] = { + "", " ", 0, { "" }, + " ", " ", 2, { "", "" }, + "x", " ", 1, { "x" }, + "xy", " ", 1, { "xy" }, + "x y", " ", 2, { "x", "y" }, + "abc def g ", " ", 5, { "abc", "def", "", "g", "" }, + " a bcd", " ", 4, { "", "", "a", "bcd" }, + "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" }, + " a b c d ", " ", 6, { "", "a", "b", "c", "d " }, + + "", " _", 0, { "" }, + " ", " _", 2, { "", "" }, + "x", " _", 1, { "x" }, + "x y", " _", 2, { "x", "y" }, + "ab _ cd", " _", 2, { "ab", "cd" }, + " a_b c ", " _", 5, { "", "a", "b", "c", "" }, + "a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" }, + " a b c d ", " _", 6, { "", "a", "b", "c", "d " }, + + "", " _~", 0, { "" }, + " ", " _~", 2, { "", "" }, + "x", " _~", 1, { "x" }, + "x y", " _~", 2, { "x", "y" }, + "ab _~ cd", " _~", 2, { "ab", "cd" }, + " a_b c~", " _~", 5, { "", "a", "b", "c", "" }, + "a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" }, + "~a b c d ", " _~", 6, { "", "a", "b", "c", "d " }, + + "", " _~-", 0, { "" }, + " ", " _~-", 2, { "", "" }, + "x", " _~-", 1, { "x" }, + "x y", " _~-", 2, { "x", "y" }, + "ab _~- cd", " _~-", 2, { "ab", "cd" }, + " a_b c~", " _~-", 5, { "", "a", "b", "c", "" }, + "a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" }, + "~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " }, + + "", " ", 0, { "" }, + " ", " ", 2, { "", "" }, + "x", " ", 1, { "x" }, + "xy", " ", 1, { "xy" }, + "x y", " ", 2, { "x", "y" }, + "abc def g ", " ", 4, { "abc", "def", "g", "" }, + " a bcd", " ", 3, { "", "a", "bcd" }, + "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" }, + " a b c d ", " ", 6, { "", "a", "b", "c", "d " }, + + "", "", 0, { "" }, + " ", "", 0, { "" }, + "x", "", 1, { "x" }, + "xy", "", 1, { "xy" }, + "x y", "", 2, { "x", "y" }, + "abc def g ", "", 3, { "abc", "def", "g" }, + "\t a bcd", "", 2, { "a", "bcd" }, + " a \tb\t c ", "", 3, { "a", "b", "c" }, + "a b c d e ", "", 5, { "a", "b", "c", "d", "e" }, + "a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" }, + " a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " }, + + NULL, NULL, 0, { NULL }, +}; + +regress() +{ + char buf[512]; + register int n; + char *fields[RNF+1]; + register int nf; + register int i; + register int printit; + register char *f; + + for (n = 0; tests[n].str != NULL; n++) { + (void) strcpy(buf, tests[n].str); + fields[RNF] = NULL; + nf = split(buf, fields, RNF, tests[n].seps); + printit = 0; + if (nf != tests[n].nf) { + printf("split `%s' by `%s' gave %d fields, not %d\n", + tests[n].str, tests[n].seps, nf, tests[n].nf); + printit = 1; + } else if (fields[RNF] != NULL) { + printf("split() went beyond array end\n"); + printit = 1; + } else { + for (i = 0; i < nf && i < RNF; i++) { + f = fields[i]; + if (f == NULL) + f = "(NULL)"; + if (strcmp(f, tests[n].fi[i]) != 0) { + printf("split `%s' by `%s', field %d is `%s', not `%s'\n", + tests[n].str, tests[n].seps, + i, fields[i], tests[n].fi[i]); + printit = 1; + } + } + } + if (printit) + print(nf, RNF, fields); + } +} +#endif diff --git a/regress/lib/libc/regex/tests b/regress/lib/libc/regex/tests new file mode 100644 index 00000000000..8e89f161b1c --- /dev/null +++ b/regress/lib/libc/regex/tests @@ -0,0 +1,477 @@ +# $NetBSD: tests,v 1.5 1995/04/20 22:40:00 cgd Exp $ + +# regular expression test set +# Lines are at least three fields, separated by one or more tabs. "" stands +# for an empty field. First field is an RE. Second field is flags. If +# C flag given, regcomp() is expected to fail, and the third field is the +# error name (minus the leading REG_). +# +# Otherwise it is expected to succeed, and the third field is the string to +# try matching it against. If there is no fourth field, the match is +# expected to fail. If there is a fourth field, it is the substring that +# the RE is expected to match. If there is a fifth field, it is a comma- +# separated list of what the subexpressions should match, with - indicating +# no match for that one. In both the fourth and fifth fields, a (sub)field +# starting with @ indicates that the (sub)expression is expected to match +# a null string followed by the stuff after the @; this provides a way to +# test where null strings match. The character `N' in REs and strings +# is newline, `S' is space, `T' is tab, `Z' is NUL. +# +# The full list of flags: +# - placeholder, does nothing +# b RE is a BRE, not an ERE +# & try it as both an ERE and a BRE +# C regcomp() error expected, third field is error name +# i REG_ICASE +# m ("mundane") REG_NOSPEC +# s REG_NOSUB (not really testable) +# n REG_NEWLINE +# ^ REG_NOTBOL +# $ REG_NOTEOL +# # REG_STARTEND (see below) +# p REG_PEND +# +# For REG_STARTEND, the start/end offsets are those of the substring +# enclosed in (). + +# basics +a & a a +abc & abc abc +abc|de - abc abc +a|b|c - abc a + +# parentheses and perversions thereof +a(b)c - abc abc +a\(b\)c b abc abc +a( C EPAREN +a( b a( a( +a\( - a( a( +a\( bC EPAREN +a\(b bC EPAREN +a(b C EPAREN +a(b b a(b a(b +# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly) +a) - a) a) +) - ) ) +# end gagging (in a just world, those *should* give EPAREN) +a) b a) a) +a\) bC EPAREN +\) bC EPAREN +a()b - ab ab +a\(\)b b ab ab + +# anchoring and REG_NEWLINE +^abc$ & abc abc +a^b - a^b +a^b b a^b a^b +a$b - a$b +a$b b a$b a$b +^ & abc @abc +$ & abc @ +^$ & "" @ +$^ - "" @ +\($\)\(^\) b "" @ +# stop retching, those are legitimate (although disgusting) +^^ - "" @ +$$ - "" @ +b$ & abNc +b$ &n abNc b +^b$ & aNbNc +^b$ &n aNbNc b +^$ &n aNNb @Nb +^$ n abc +^$ n abcN @ +$^ n aNNb @Nb +\($\)\(^\) bn aNNb @Nb +^^ n^ aNNb @Nb +$$ n aNNb @NN +^a ^ a +a$ $ a +^a ^n aNb +^b ^n aNb b +a$ $n bNa +b$ $n bNa b +a*(^b$)c* - b b +a*\(^b$\)c* b b b + +# certain syntax errors and non-errors +| C EMPTY +| b | | +* C BADRPT +* b * * ++ C BADRPT +? C BADRPT +"" &C EMPTY +() - abc @abc +\(\) b abc @abc +a||b C EMPTY +|ab C EMPTY +ab| C EMPTY +(|a)b C EMPTY +(a|)b C EMPTY +(*a) C BADRPT +(+a) C BADRPT +(?a) C BADRPT +({1}a) C BADRPT +\(\{1\}a\) bC BADRPT +(a|*b) C BADRPT +(a|+b) C BADRPT +(a|?b) C BADRPT +(a|{1}b) C BADRPT +^* C BADRPT +^* b * * +^+ C BADRPT +^? C BADRPT +^{1} C BADRPT +^\{1\} bC BADRPT + +# metacharacters, backslashes +a.c & abc abc +a[bc]d & abd abd +a\*c & a*c a*c +a\\b & a\b a\b +a\\\*b & a\*b a\*b +a\bc & abc abc +a\ &C EESCAPE +a\\bc & a\bc a\bc +\{ bC BADRPT +a\[b & a[b a[b +a[b &C EBRACK +# trailing $ is a peculiar special case for the BRE code +a$ & a a +a$ & a$ +a\$ & a +a\$ & a$ a$ +a\\$ & a +a\\$ & a$ +a\\$ & a\$ +a\\$ & a\ a\ + +# back references, ugh +a\(b\)\2c bC ESUBREG +a\(b\1\)c bC ESUBREG +a\(b*\)c\1d b abbcbbd abbcbbd bb +a\(b*\)c\1d b abbcbd +a\(b*\)c\1d b abbcbbbd +^\(.\)\1 b abc +a\([bc]\)\1d b abcdabbd abbd b +a\(\([bc]\)\2\)*d b abbccd abbccd +a\(\([bc]\)\2\)*d b abbcbd +# actually, this next one probably ought to fail, but the spec is unclear +a\(\(b\)*\2\)*d b abbbd abbbd +# here is a case that no NFA implementation does right +\(ab*\)[ab]*\1 b ababaaa ababaaa a +# check out normal matching in the presence of back refs +\(a\)\1bcd b aabcd aabcd +\(a\)\1bc*d b aabcd aabcd +\(a\)\1bc*d b aabd aabd +\(a\)\1bc*d b aabcccd aabcccd +\(a\)\1bc*[ce]d b aabcccd aabcccd +^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd + +# ordinary repetitions +ab*c & abc abc +ab+c - abc abc +ab?c - abc abc +a\(*\)b b a*b a*b +a\(**\)b b ab ab +a\(***\)b bC BADRPT +*a b *a *a +**a b a a +***a bC BADRPT + +# the dreaded bounded repetitions +{ & { { +{abc & {abc {abc +{1 C BADRPT +{1} C BADRPT +a{b & a{b a{b +a{1}b - ab ab +a\{1\}b b ab ab +a{1,}b - ab ab +a\{1,\}b b ab ab +a{1,2}b - aab aab +a\{1,2\}b b aab aab +a{1 C EBRACE +a\{1 bC EBRACE +a{1a C EBRACE +a\{1a bC EBRACE +a{1a} C BADBR +a\{1a\} bC BADBR +a{,2} - a{,2} a{,2} +a\{,2\} bC BADBR +a{,} - a{,} a{,} +a\{,\} bC BADBR +a{1,x} C BADBR +a\{1,x\} bC BADBR +a{1,x C EBRACE +a\{1,x bC EBRACE +a{300} C BADBR +a\{300\} bC BADBR +a{1,0} C BADBR +a\{1,0\} bC BADBR +ab{0,0}c - abcac ac +ab\{0,0\}c b abcac ac +ab{0,1}c - abcac abc +ab\{0,1\}c b abcac abc +ab{0,3}c - abbcac abbc +ab\{0,3\}c b abbcac abbc +ab{1,1}c - acabc abc +ab\{1,1\}c b acabc abc +ab{1,3}c - acabc abc +ab\{1,3\}c b acabc abc +ab{2,2}c - abcabbc abbc +ab\{2,2\}c b abcabbc abbc +ab{2,4}c - abcabbc abbc +ab\{2,4\}c b abcabbc abbc +((a{1,10}){1,10}){1,10} - a a a,a + +# multiple repetitions +a** &C BADRPT +a++ C BADRPT +a?? C BADRPT +a*+ C BADRPT +a*? C BADRPT +a+* C BADRPT +a+? C BADRPT +a?* C BADRPT +a?+ C BADRPT +a{1}{1} C BADRPT +a*{1} C BADRPT +a+{1} C BADRPT +a?{1} C BADRPT +a{1}* C BADRPT +a{1}+ C BADRPT +a{1}? C BADRPT +a*{b} - a{b} a{b} +a\{1\}\{1\} bC BADRPT +a*\{1\} bC BADRPT +a\{1\}* bC BADRPT + +# brackets, and numerous perversions thereof +a[b]c & abc abc +a[ab]c & abc abc +a[^ab]c & adc adc +a[]b]c & a]c a]c +a[[b]c & a[c a[c +a[-b]c & a-c a-c +a[^]b]c & adc adc +a[^-b]c & adc adc +a[b-]c & a-c a-c +a[b &C EBRACK +a[] &C EBRACK +a[1-3]c & a2c a2c +a[3-1]c &C ERANGE +a[1-3-5]c &C ERANGE +a[[.-.]--]c & a-c a-c +a[1- &C ERANGE +a[[. &C EBRACK +a[[.x &C EBRACK +a[[.x. &C EBRACK +a[[.x.] &C EBRACK +a[[.x.]] & ax ax +a[[.x,.]] &C ECOLLATE +a[[.one.]]b & a1b a1b +a[[.notdef.]]b &C ECOLLATE +a[[.].]]b & a]b a]b +a[[:alpha:]]c & abc abc +a[[:notdef:]]c &C ECTYPE +a[[: &C EBRACK +a[[:alpha &C EBRACK +a[[:alpha:] &C EBRACK +a[[:alpha,:] &C ECTYPE +a[[:]:]]b &C ECTYPE +a[[:-:]]b &C ECTYPE +a[[:alph:]] &C ECTYPE +a[[:alphabet:]] &C ECTYPE +[[:alnum:]]+ - -%@a0X- a0X +[[:alpha:]]+ - -%@aX0- aX +[[:blank:]]+ - aSSTb SST +[[:cntrl:]]+ - aNTb NT +[[:digit:]]+ - a019b 019 +[[:graph:]]+ - Sa%bS a%b +[[:lower:]]+ - AabC ab +[[:print:]]+ - NaSbN aSb +[[:punct:]]+ - S%-&T %-& +[[:space:]]+ - aSNTb SNT +[[:upper:]]+ - aBCd BC +[[:xdigit:]]+ - p0f3Cq 0f3C +a[[=b=]]c & abc abc +a[[= &C EBRACK +a[[=b &C EBRACK +a[[=b= &C EBRACK +a[[=b=] &C EBRACK +a[[=b,=]] &C ECOLLATE +a[[=one=]]b & a1b a1b + +# complexities +a(((b)))c - abc abc +a(b|(c))d - abd abd +a(b*|c)d - abbd abbd +# just gotta have one DFA-buster, of course +a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab +# and an inline expansion in case somebody gets tricky +a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab +# and in case somebody just slips in an NFA... +a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights +# fish for anomalies as the number of states passes 32 +12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789 +123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890 +1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901 +12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012 +123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123 +# and one really big one, beyond any plausible word width +1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890 +# fish for problems as brackets go past 8 +[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm +[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo +[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq +[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq + +# subtleties of matching +abc & xabcy abc +a\(b\)?c\1d b acd +aBc i Abc Abc +a[Bc]*d i abBCcd abBCcd +0[[:upper:]]1 &i 0a1 0a1 +0[[:lower:]]1 &i 0A1 0A1 +a[^b]c &i abc +a[^b]c &i aBc +a[^b]c &i adc adc +[a]b[c] - abc abc +[a]b[a] - aba aba +[abc]b[abc] - abc abc +[abc]b[abd] - abd abd +a(b?c)+d - accd accd +(wee|week)(knights|night) - weeknights weeknights +(we|wee|week|frob)(knights|night|day) - weeknights weeknights +a[bc]d - xyzaaabcaababdacd abd +a[ab]c - aaabc abc +abc s abc abc +a* & b @b + +# Let's have some fun -- try to match a C comment. +# first the obvious, which looks okay at first glance... +/\*.*\*/ - /*x*/ /*x*/ +# but... +/\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/ +# okay, we must not match */ inside; try to do that... +/\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/ +/\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/ +# but... +/\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/ +# and a still fancier version, which does it right (I think)... +/\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/ +/\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/ +/\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/ +/\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/ + +# subexpressions +a(b)(c)d - abcd abcd b,c +a(((b)))c - abc abc b,b,b +a(b|(c))d - abd abd b,- +a(b*|c|e)d - abbd abbd bb +a(b*|c|e)d - acd acd c +a(b*|c|e)d - ad ad @d +a(b?)c - abc abc b +a(b?)c - ac ac @c +a(b+)c - abc abc b +a(b+)c - abbbc abbbc bbb +a(b*)c - ac ac @c +(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de +# the regression tester only asks for 9 subexpressions +a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j +a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k +a([bc]?)c - abc abc b +a([bc]?)c - ac ac @c +a([bc]+)c - abc abc b +a([bc]+)c - abcc abcc bc +a([bc]+)bc - abcbc abcbc bc +a(bb+|b)b - abb abb b +a(bbb+|bb+|b)b - abb abb b +a(bbb+|bb+|b)b - abbb abbb bb +a(bbb+|bb+|b)bb - abbb abbb b +(.*).* - abcdef abcdef abcdef +(a*)* - bc @b @b + +# do we get the right subexpression when it is used more than once? +a(b|c)*d - ad ad - +a(b|c)*d - abcd abcd c +a(b|c)+d - abd abd b +a(b|c)+d - abcd abcd c +a(b|c?)+d - ad ad @d +a(b|c?)+d - abcd abcd @d +a(b|c){0,0}d - ad ad - +a(b|c){0,1}d - ad ad - +a(b|c){0,1}d - abd abd b +a(b|c){0,2}d - ad ad - +a(b|c){0,2}d - abcd abcd c +a(b|c){0,}d - ad ad - +a(b|c){0,}d - abcd abcd c +a(b|c){1,1}d - abd abd b +a(b|c){1,1}d - acd acd c +a(b|c){1,2}d - abd abd b +a(b|c){1,2}d - abcd abcd c +a(b|c){1,}d - abd abd b +a(b|c){1,}d - abcd abcd c +a(b|c){2,2}d - acbd acbd b +a(b|c){2,2}d - abcd abcd c +a(b|c){2,4}d - abcd abcd c +a(b|c){2,4}d - abcbd abcbd b +a(b|c){2,4}d - abcbcd abcbcd c +a(b|c){2,}d - abcd abcd c +a(b|c){2,}d - abcbd abcbd b +a(b+|((c)*))+d - abd abd @d,@d,- +a(b+|((c)*))+d - abcd abcd @d,@d,- + +# check out the STARTEND option +[abc] &# a(b)c b +[abc] &# a(d)c +[abc] &# a(bc)d b +[abc] &# a(dc)d c +. &# a()c +b.*c &# b(bc)c bc +b.* &# b(bc)c bc +.*c &# b(bc)c bc + +# plain strings, with the NOSPEC flag +abc m abc abc +abc m xabcy abc +abc m xyz +a*b m aba*b a*b +a*b m ab +"" mC EMPTY + +# cases involving NULs +aZb & a a +aZb &p a +aZb &p# (aZb) aZb +aZ*b &p# (ab) ab +a.b &# (aZb) aZb +a.* &# (aZb)c aZb + +# word boundaries (ick) +[[:<:]]a & a a +[[:<:]]a & ba +[[:<:]]a & -a a +a[[:>:]] & a a +a[[:>:]] & ab +a[[:>:]] & a- a +[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc +[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc +[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc +[[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc +[[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_ +[[:<:]]a_b[[:>:]] & x_a_b + +# past problems, and suspected problems +(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1 +abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop +abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv +(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11 +CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11 +Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz +a?b - ab ab +-\{0,1\}[0-9]*$ b -5 -5 diff --git a/regress/lib/libc/setjmp/Makefile b/regress/lib/libc/setjmp/Makefile new file mode 100644 index 00000000000..25bf99d4cb7 --- /dev/null +++ b/regress/lib/libc/setjmp/Makefile @@ -0,0 +1,16 @@ +# $NetBSD: Makefile,v 1.2 1995/04/20 22:40:13 cgd Exp $ + +PROG= setjmptest +SRCS= jmptest.c +NOMAN= noman, no way, man + +CFLAGS+= -DTEST_SETJMP + +.PATH: ${.CURDIR}/../setjmp + +install: + +regress: ${PROG} + ./${PROG} + +.include <bsd.prog.mk> diff --git a/regress/lib/libc/setjmp/jmptest.c b/regress/lib/libc/setjmp/jmptest.c new file mode 100644 index 00000000000..f2cecc9178e --- /dev/null +++ b/regress/lib/libc/setjmp/jmptest.c @@ -0,0 +1,134 @@ +/* $NetBSD: jmptest.c,v 1.2 1995/01/01 20:55:35 jtc Exp $ */ + +/* + * Copyright (c) 1994 Christopher G. Demetriou + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <setjmp.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#if (TEST_SETJMP + TEST_U_SETJMP + TEST_SIGSETJMP) != 1 +#error one of TEST_SETJMP, TEST_U_SETJMP, or TEST_SIGSETJMP must be defined +#endif + +#ifdef TEST_SETJMP +#define BUF jmp_buf +#define SET(b, m) setjmp(b) +#define JMP(b, v) longjmp(b, v) +#endif + +#ifdef TEST_U_SETJMP +#define BUF jmp_buf +#define SET(b, m) _setjmp(b) +#define JMP(b, v) _longjmp(b, v) +#endif + +#ifdef TEST_SIGSETJMP +#define BUF sigjmp_buf +#define SET(b, m) sigsetjmp(b, m) +#define JMP(b, v) siglongjmp(b, v) +#endif + +int expectsignal; + +void +aborthandler(signo) + int signo; +{ + + if (expectsignal) + exit(0); + else + errx(1, "kill(SIGABRT) succeeded"); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct sigaction sa; + BUF jb; + sigset_t ss; + int i, x; + + i = getpid(); + +#ifdef TEST_SETJMP + expectsignal = 0; +#endif +#ifdef TEST_U_SETJMP + expectsignal = 1; +#endif +#ifdef TEST_SIGSETJMP + if (argc != 2 || + (strcmp(argv[1], "save") && strcmp(argv[1], "nosave"))) { + fprintf(stderr, "usage: %s [save|nosave]\n", argv[0]); + exit(1); + } + expectsignal = (strcmp(argv[1], "save") != 0); +#endif + + sa.sa_handler = aborthandler; + sa.sa_mask = 0; + sa.sa_flags = 0; + if (sigaction(SIGABRT, &sa, NULL) == -1) + err(1, "sigaction failed"); + + if (sigemptyset(&ss) == -1) + err(1, "sigemptyset failed"); + if (sigaddset(&ss, SIGABRT) == -1) + err(1, "sigaddset failed"); + if (sigprocmask(SIG_BLOCK, &ss, NULL) == -1) + err(1, "sigprocmask (1) failed"); + + x = SET(jb, !expectsignal); + if (x != 0) { + if (x != i) + errx(1, "setjmp returned wrong value"); + + kill(i, SIGABRT); + if (expectsignal) + errx(1, "kill(SIGABRT) failed"); + else + exit(0); + } + + if (sigprocmask(SIG_UNBLOCK, &ss, NULL) == -1) + err(1, "sigprocmask (2) failed"); + + JMP(jb, i); + + errx(1, "jmp failed"); +} diff --git a/regress/lib/libc/sigsetjmp/Makefile b/regress/lib/libc/sigsetjmp/Makefile new file mode 100644 index 00000000000..41682fcb661 --- /dev/null +++ b/regress/lib/libc/sigsetjmp/Makefile @@ -0,0 +1,17 @@ +# $NetBSD: Makefile,v 1.2 1995/04/20 22:40:40 cgd Exp $ + +PROG= sigsetjmptest +SRCS= jmptest.c +NOMAN= noman, no way, man + +CFLAGS+= -DTEST_SIGSETJMP + +.PATH: ${.CURDIR}/../setjmp + +install: + +regress: ${PROG} + ./${PROG} save + ./${PROG} nosave + +.include <bsd.prog.mk> |