/*
 * Simple timing program for regcomp().
 *
 *      Copyright (c) 1986 by University of Toronto.
 *      Written by Henry Spencer.  Not derived from licensed software.
 *
 *      Permission is granted to anyone to use this software for any
 *      purpose on any computer system, and to redistribute it freely,
 *      subject to the following restrictions:
 *
 *      1. The author is not responsible for the consequences of use of
 *              this software, no matter how awful, even if they arise
 *              from defects in it.
 *
 *      2. The origin of this software must not be misrepresented, either
 *              by explicit claim or by omission.
 *
 *      3. Altered versions must be plainly marked as such, and must not
 *              be misrepresented as being the original software.
 *
 * Usage: timer ncomp nexec nsub
 *      or
 *      timer ncomp nexec nsub regexp string [ answer [ sub ] ]
 *
 * The second form is for timing repetitions of a single test case.
 * The first form's test data is a compiled-in copy of the "tests" file.
 * Ncomp, nexec, nsub are how many times to do each regcomp, regexec,
 * and regsub.  The way to time an operation individually is to do something
 * like "timer 1 50 1".
 */
#include <stdio.h>

struct try {
        char *re, *str, *ans, *src, *dst;
} tests[] = {
#include "timer.t.h"
{ NULL, NULL, NULL, NULL, NULL }
};

#include "regexp.h"

int errreport = 0;              /* Report errors via errseen? */
char *errseen = NULL;           /* Error message. */

char *progname;

/* ARGSUSED */
main(argc, argv)
int argc;
char *argv[];
{
        int ncomp, nexec, nsub;
        struct try one;
        char dummy[512];

        if (argc < 4) {
                ncomp = 1;
                nexec = 1;
                nsub = 1;
        } else {
                ncomp = atoi(argv[1]);
                nexec = atoi(argv[2]);
                nsub = atoi(argv[3]);
        }
        
        progname = argv[0];
        if (argc > 5) {
                one.re = argv[4];
                one.str = argv[5];
                if (argc > 6)
                        one.ans = argv[6];
                else
                        one.ans = "y";
                if (argc > 7) { 
                        one.src = argv[7];
                        one.dst = "xxx";
                } else {
                        one.src = "x";
                        one.dst = "x";
                }
                errreport = 1;
                try(one, ncomp, nexec, nsub);
        } else
                multiple(ncomp, nexec, nsub);
        exit(0);
}

void
regerror(s)
char *s;
{
        if (errreport)
                errseen = s;
        else
                error(s, "");
}

#ifndef ERRAVAIL
error(s1, s2)
char *s1;
char *s2;
{
        fprintf(stderr, "regexp: ");
        fprintf(stderr, s1, s2);
        fprintf(stderr, "\n");
        exit(1);
}
#endif

int lineno = 0;

multiple(ncomp, nexec, nsub)
int ncomp, nexec, nsub;
{
        register int i;
        extern char *strchr();

        errreport = 1;
        for (i = 0; tests[i].re != NULL; i++) {
                lineno++;
                try(tests[i], ncomp, nexec, nsub);
        }
}

try(fields, ncomp, nexec, nsub)
struct try fields;
int ncomp, nexec, nsub;
{
        regexp *r;
        char dbuf[BUFSIZ];
        register int i;

        errseen = NULL;
        r = regcomp(fields.re);
        if (r == NULL) {
                if (*fields.ans != 'c')
                        complain("regcomp failure in `%s'", fields.re);
                return;
        }
        if (*fields.ans == 'c') {
                complain("unexpected regcomp success in `%s'", fields.re);
                free((char *)r);
                return;
        }
        for (i = ncomp-1; i > 0; i--) {
                free((char *)r);
                r = regcomp(fields.re);
        }
        if (!regexec(r, fields.str)) {
                if (*fields.ans != 'n')
                        complain("regexec failure in `%s'", "");
                free((char *)r);
                return;
        }
        if (*fields.ans == 'n') {
                complain("unexpected regexec success", "");
                free((char *)r);
                return;
        }
        for (i = nexec-1; i > 0; i--)
                (void) regexec(r, fields.str);
        errseen = NULL;
        for (i = nsub; i > 0; i--)
                regsub(r, fields.src, dbuf);
        if (errseen != NULL) {  
                complain("regsub complaint", "");
                free((char *)r);
                return;
        }
        if (strcmp(dbuf, fields.dst) != 0)
                complain("regsub result `%s' wrong", dbuf);
        free((char *)r);
}

complain(s1, s2)
char *s1;
char *s2;
{
        fprintf(stderr, "try: %d: ", lineno);
        fprintf(stderr, s1, s2);
        fprintf(stderr, " (%s)\n", (errseen != NULL) ? errseen : "");
}
