X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=miniexpect.c;h=9e9cc0ee3b0cbdc30723ac1ed48fd0287c636abb;hb=329575032af72a3155bcc2640231e603604cd253;hp=f525b68630a7f15fa6b9d97abb7e9b2d634ff4af;hpb=5cac23de1963880d8fb3aed4be47ec2894cf520c;p=miniexpect.git diff --git a/miniexpect.c b/miniexpect.c index f525b68..9e9cc0e 100644 --- a/miniexpect.c +++ b/miniexpect.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -50,8 +51,10 @@ create_handle (void) h->pid = 0; h->timeout = 60000; h->read_size = 1024; + h->pcre_error = 0; h->buffer = NULL; h->len = h->alloc = 0; + h->next_match = -1; h->user1 = h->user2 = h->user3 = NULL; return h; @@ -63,6 +66,7 @@ clear_buffer (mexp_h *h) free (h->buffer); h->buffer = NULL; h->alloc = h->len = 0; + h->next_match = -1; } int @@ -79,6 +83,8 @@ mexp_close (mexp_h *h) return -1; } + free (h); + return status; } @@ -196,10 +202,7 @@ mexp_spawnv (const char *file, char **argv) } enum mexp_status -mexp_expect (mexp_h *h, const pcre *code, - const pcre_extra *extra, - int options, int *ovector, int ovecsize, - int *pcre_ret) +mexp_expect (mexp_h *h, const mexp_regexp *regexps, int *ovector, int ovecsize) { time_t start_t, now_t; int timeout; @@ -209,10 +212,19 @@ mexp_expect (mexp_h *h, const pcre *code, time (&start_t); - options |= PCRE_PARTIAL_SOFT; - - /* Clear the read buffer. */ - clear_buffer (h); + if (h->next_match == -1) { + /* Fully clear the buffer, then read. */ + clear_buffer (h); + } else { + /* See the comment in the manual about h->next_match. We have + * some data remaining in the buffer, so begin by matching that. + */ + memmove (&h->buffer[0], &h->buffer[h->next_match], h->len - h->next_match); + h->len -= h->next_match; + h->buffer[h->len] = '\0'; + h->next_match = -1; + goto try_match; + } for (;;) { /* If we've got a timeout then work out how many seconds are left. @@ -277,34 +289,55 @@ mexp_expect (mexp_h *h, const pcre *code, fprintf (stderr, "DEBUG: buffer content: %s\n", h->buffer); #endif - /* See if there is a full or partial match against the regular expression. */ - if (code) { + try_match: + /* See if there is a full or partial match against any regexp. */ + if (regexps) { + size_t i; + int can_clear_buffer = 1; + assert (h->buffer != NULL); - r = pcre_exec (code, extra, h->buffer, (int)h->len, 0, - options, ovector, ovecsize); - if (pcre_ret) - *pcre_ret = r; - - if (r >= 0) { - /* A full match. */ - return MEXP_MATCHED; - } - else if (r == PCRE_ERROR_NOMATCH) { - /* No match at all, so we can dump the input buffer. */ - clear_buffer (h); + for (i = 0; regexps[i].r > 0; ++i) { + int options = regexps[i].options | PCRE_PARTIAL_SOFT; + + r = pcre_exec (regexps[i].re, regexps[i].extra, + h->buffer, (int)h->len, 0, + options, + ovector, ovecsize); + h->pcre_error = r; + + if (r >= 0) { + /* A full match. */ + if (ovector != NULL && ovecsize >= 1 && ovector[1] >= 0) + h->next_match = ovector[1]; + else + h->next_match = -1; + return regexps[i].r; + } + + else if (r == PCRE_ERROR_NOMATCH) { + /* No match at all. */ + /* (nothing here) */ + } + + else if (r == PCRE_ERROR_PARTIAL) { + /* Partial match. Keep the buffer and keep reading. */ + can_clear_buffer = 0; + } + + else { + /* An actual PCRE error. */ + return MEXP_PCRE_ERROR; + } } - else if (r == PCRE_ERROR_PARTIAL) { - /* Partial match. Keep the buffer and keep reading. */ - /* (nothing here) */ - } + /* If none of the regular expressions matched (not partially) + * then we can clear the buffer. This is an optimization. + */ + if (can_clear_buffer) + clear_buffer (h); - else { - /* An actual PCRE error. */ - return MEXP_PCRE_ERROR; - } - } /* if (code) */ + } /* if (regexps) */ } }