static int parse(EVP_TEST *t)
{
    KEY_LIST *key, **klist;
    EVP_PKEY *pkey;
    PAIR *pp;
    int i;

top:
    do {
        if (BIO_eof(t->s.fp))
            return EOF;
        clear_test(t);
        if (!test_readstanza(&t->s))
            return 0;
    } while (t->s.numpairs == 0);
    pp = &t->s.pairs[0];

    /* Are we adding a key? */
    klist = NULL;
    pkey = NULL;
    if (strcmp(pp->key, "PrivateKey") == 0) {
        pkey = PEM_read_bio_PrivateKey(t->s.key, NULL, 0, NULL);
        if (pkey == NULL && !key_unsupported()) {
            TEST_info("Can't read private key %s", pp->value);
            ERR_print_errors_fp(stderr);
            return 0;
        }
        klist = &private_keys;
    }
    else if (strcmp(pp->key, "PublicKey") == 0) {
        pkey = PEM_read_bio_PUBKEY(t->s.key, NULL, 0, NULL);
        if (pkey == NULL && !key_unsupported()) {
            TEST_info("Can't read public key %s", pp->value);
            ERR_print_errors_fp(stderr);
            return 0;
        }
        klist = &public_keys;
    }

    /* If we have a key add to list */
    if (klist != NULL) {
        if (find_key(NULL, pp->value, *klist)) {
            TEST_info("Duplicate key %s", pp->value);
            return 0;
        }
        if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key))))
            return 0;
        key->name = take_value(pp);
        key->key = pkey;
        key->next = *klist;
        *klist = key;

        /* Go back and start a new stanza. */
        if (t->s.numpairs != 1)
            TEST_info("Line %d: missing blank line\n", t->s.curr);
        goto top;
    }

    /* Find the test, based on first keyword. */
    if (!TEST_ptr(t->meth = find_test(pp->key)))
        return 0;
    if (!t->meth->init(t, pp->value)) {
        TEST_error("unknown %s: %s\n", pp->key, pp->value);
        return 0;
    }
    if (t->skip == 1) {
        /* TEST_info("skipping %s %s", pp->key, pp->value); */
        return 0;
    }

    for (pp++, i = 1; i < t->s.numpairs; pp++, i++) {
        if (strcmp(pp->key, "Result") == 0) {
            if (t->expected_err != NULL) {
                TEST_info("Line %d: multiple result lines", t->s.curr);
                return 0;
            }
            t->expected_err = take_value(pp);
        } else if (strcmp(pp->key, "Function") == 0) {
            if (t->func != NULL) {
                TEST_info("Line %d: multiple function lines\n", t->s.curr);
                return 0;
            }
            t->func = take_value(pp);
        } else if (strcmp(pp->key, "Reason") == 0) {
            if (t->reason != NULL) {
                TEST_info("Line %d: multiple reason lines", t->s.curr);
                return 0;
            }
            t->reason = take_value(pp);
        } else {
            /* Must be test specific line: try to parse it */
            int rv = t->meth->parse(t, pp->key, pp->value);

            if (rv == 0) {
                TEST_info("Line %d: unknown keyword %s", t->s.curr, pp->key);
                return 0;
            }
            if (rv < 0) {
                TEST_info("Line %d: error processing keyword %s\n",
                        t->s.curr, pp->key);
                return 0;
            }
        }
    }

    return 1;
}