head 1.3; access; symbols FSL_1_7_0:1.3 LMTP2NNTP_1_4_1:1.3 LMTP2NNTP_1_4_0:1.3 FSL_1_6_1:1.3 FSL_1_6_0:1.3 FSL_1_6b2:1.3 FSL_1_6b1:1.3 LMTP2NNTP_1_3_0:1.3 LMTP2NNTP_1_3b2:1.3 LMTP2NNTP_1_3b1:1.3 LMTP2NNTP_1_3a3:1.3 FSL_1_5_0:1.3 LMTP2NNTP_1_3a2:1.3 FSL_1_5a3:1.3 LMTP2NNTP_1_3a1:1.3 FSL_1_5a2:1.3 FSL_1_5a1:1.3 FSL_1_4_0:1.3 FSL_1_4b1:1.3 FSL_1_4a1:1.3 FSL_1_3_0:1.3 FSL_1_3b1:1.3 FSL_1_2_1:1.3 FSL_1_2_0:1.3 FSL_1_1_0:1.3 FSL_1_1b1:1.3 FSL_1_0_8:1.3 LMTP2NNTP_1_2_0:1.3 LMTP2NNTP_1_2b4:1.3 LMTP2NNTP_1_2b3:1.3 LMTP2NNTP_1_2b2:1.3 LMTP2NNTP_1_2b1:1.3 LMTP2NNTP_1_2a8:1.3 LMTP2NNTP_1_2a7:1.3 FSL_1_0_7:1.3 FSL_1_0_6:1.3 FSL_1_0_5:1.3 FSL_1_0_4:1.3 FSL_1_0_3:1.3 LMTP2NNTP_1_2a6:1.3 FSL_1_0_2:1.3 FSL_1_0_1:1.3 FSL_1_0_0:1.3 FSL_0_9_0:1.3 FSL_0_1_12:1.3 FSL_0_1_11:1.3 FSL_0_1_10:1.3 FSL_0_1_9:1.3 FSL_0_1_8:1.3 FSL_0_1_7:1.3 FSL_0_1_6:1.3 FSL_0_1_5:1.3 FSL_0_1_1:1.3 LMTP2NNTP_1_2a5:1.3 LMTP2NNTP_1_2a4:1.3 LMTP2NNTP_1_2a3:1.3 OSSP_PCRE_2_07:1.1.1.1 ossp:1.1.1; locks; strict; comment @ * @; 1.3 date 99.11.17.11.53.57; author rse; state Exp; branches; next 1.2; 1.2 date 99.11.17.11.39.03; author rse; state Exp; branches; next 1.1; 1.1 date 99.08.26.08.15.20; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 99.08.26.08.15.20; author rse; state Exp; branches; next ; desc @@ 1.3 log @*** empty log message *** @ text @/* ==================================================================== * Copyright (c) 1999 Ralf S. Engelschall. 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. * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY * EXPRESSED 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 RALF S. ENGELSCHALL OR * ITS 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. * ==================================================================== */ #include #include "pcre_internal.h" static char *strrspn(const char *string, const char *charset) { char *cp; int i, n; int oneof; if (string == NULL || charset == NULL) return NULL; cp = (char *)string+strlen(string)-1; n = strlen(charset); while (cp >= string) { oneof = FALSE; for (i = 0; i < n; i++) { if (*cp == charset[i]) { oneof = TRUE; break; } } if (!oneof) break; cp--; } return cp; } static int pattern_compile(const char *ptr, int len, int opt, pcre **p_pcre, pcre_extra **p_pcre_extra) { const char *err_str; int err_pos; char *cp; /* compile pattern */ if (ptr[len] == '\0') { /* plain pattern, so we can speed up processing */ if ((*p_pcre = pcre_compile(ptr, opt, &err_str, &err_pos, NULL)) == NULL) return FALSE; } else { /* else we have to create a temporary string */ if ((cp = pcre_malloc(len+1)) == NULL) return FALSE; memcpy(cp, ptr, len); cp[len] = '\0'; *p_pcre = pcre_compile(cp, opt, &err_str, &err_pos, NULL); pcre_free(cp); if (*p_pcre == NULL) return FALSE; } /* optionally study pattern */ if (p_pcre_extra != NULL) { *p_pcre_extra = pcre_study(*p_pcre, 0, &err_str); if (err_str != NULL) { pcre_free(p_pcre); return FALSE; } } return TRUE; } struct hash_entry { struct hash_entry *next; char *key; int keylen; pcre *p_pcre; pcre_extra *p_pcre_extra; }; #define HASH_SIZE 101 /* prime */ static struct hash_entry *pattern_hash[HASH_SIZE]; static int hash_initialized = FALSE; static void hash_init(void) { int i; for (i = 0; i < HASH_SIZE; i++) pattern_hash[i] = NULL; return; } static void hash_destroy(void) { int i; struct hash_entry *he, *ohe; for (i = 0; i < HASH_SIZE; i++) { he = pattern_hash[i]; pattern_hash[i] = NULL; while (he != NULL) { ohe = he; he = he->next; pcre_free(ohe); } } return; } static int hash_func(const char *key, int keylen) { int h, i; h = key[0]; for (i = 1; key[i] != '\0'; i++) h = ((((h<<5)+h)+key[i]) % HASH_SIZE); return h; } static void pattern_cache(const char *key, int keylen, pcre *p_pcre, pcre_extra *p_pcre_extra) { int h; struct hash_entry *he, *che; if ((he = pcre_malloc(sizeof(struct hash_entry))) == NULL) return; if ((he->key = pcre_malloc(keylen)) == NULL) { pcre_free(he); return; } he->next = NULL; memcpy(he->key, key, keylen); he->keylen = keylen; he->p_pcre = p_pcre; he->p_pcre_extra = p_pcre_extra; h = hash_func(key, keylen); if (pattern_hash[h] == NULL) pattern_hash[h] = he; else { che = pattern_hash[h]; while (che->next != NULL) che = che->next; che->next = he; } return; } static void pattern_lookup(const char *key, int keylen, pcre **p_pcre, pcre_extra **p_pcre_extra) { int h; struct hash_entry *he; *p_pcre = NULL; *p_pcre_extra = NULL; h = hash_func(key, keylen); if ((he = pattern_hash[h]) == NULL) return; while (he->next != NULL) { if (he->keylen == keylen) if (memcmp(he->key, key, keylen)) break; he = he->next; } *p_pcre = he->p_pcre; *p_pcre_extra = he->p_pcre_extra; return; } /* the API function */ int pcre_match(const char *string, const char *pattern, ...) { pcre *p_pcre; pcre_extra *p_pcre_extra; const char *match_ptr; int match_len; int match_opt; int match_once; int *cap_vec; int cap_num; int cap_len; char *cp; char **cpp; int n; int i; int k; va_list ap; int ismop; /* hash initialization */ if (!hash_initialized) { hash_init(); atexit(hash_destroy); hash_initialized = TRUE; } /* hash destruction */ if (string == NULL && pattern == NULL) { hash_destroy(); return -1; } /* check input parameters */ if (string == NULL || pattern == NULL) return -1; /* parse pattern */ match_ptr = NULL; match_len = 0; match_opt = 0; match_once = FALSE; ismop = FALSE; cp = NULL; if (*pattern == 'm' && strlen(pattern) >= 3) if ((cp = strrspn(pattern, "imsxo")) > pattern+1) if (*(pattern+1) == *cp) ismop = TRUE; if (ismop) { match_ptr = pattern + 2; match_len = cp - match_ptr; cp++; for (i = 0; cp[i] != '\0'; i++) { switch (cp[i]) { case 'i': match_opt |= PCRE_CASELESS; break; case 'm': match_opt |= PCRE_MULTILINE; break; case 's': match_opt |= PCRE_DOTALL; break; case 'x': match_opt |= PCRE_EXTENDED; break; case 'o': match_once = TRUE; break; default: return -1; } } } else { match_ptr = pattern; match_len = strlen(pattern); } if (match_once) { /* optimized processing: up to factor 15(!) for complex regular expressions */ pattern_lookup(match_ptr, match_len, &p_pcre, &p_pcre_extra); fprintf(stderr, "hash lookup: %s\n", p_pcre == NULL ? "missed" : "found"); if (p_pcre == NULL) { if (!pattern_compile(match_ptr, match_len, match_opt, &p_pcre, &p_pcre_extra)) return -1; pattern_cache(match_ptr, match_len, p_pcre, p_pcre_extra); } } else { /* unoptimized processing */ p_pcre_extra = NULL; if (!pattern_compile(match_ptr, match_len, match_opt, &p_pcre, NULL)) return -1; } /* allocate storage for captured substrings */ cap_vec = NULL; cap_len = 0; cap_num = pcre_info(p_pcre, NULL, NULL); if (cap_num > 0) { cap_len = (cap_num+1)*3; if ((cap_vec = pcre_malloc(cap_len*sizeof(int))) == NULL) { if (!match_once) { pcre_free(p_pcre); pcre_free(p_pcre_extra); } return -1; } } /* perform the matching */ n = pcre_exec(p_pcre, p_pcre_extra, string, strlen(string), 0, 0, cap_vec, cap_len); /* error cases */ if (n < 0) { if (cap_vec != NULL) pcre_free(cap_vec); if (!match_once) { pcre_free(p_pcre); pcre_free(p_pcre_extra); } if (n == PCRE_ERROR_NOMATCH) return 0; return -1; } /* extract captured substrings into caller provided pointer variables */ if (cap_num > 0) { va_start(ap, pattern); for (i = 1; i <= cap_num; i++) { cpp = va_arg(ap, char **); if (cpp != NULL) { if (i <= (n-1)) { if (cap_vec[(i*2)] != -1 && cap_vec[(i*2)+1] != -1) { k = (cap_vec[(i*2)+1] - cap_vec[(i*2)]); if (k > 0) { if ((*cpp = pcre_malloc(k+1)) != NULL) { memcpy(*cpp, (char *)(string+cap_vec[(i*2)]), k); (*cpp)[k] = '\0'; continue; } } } } *cpp = strdup(""); } } va_end(ap); } /* cleanup */ if (cap_vec != NULL) pcre_free(cap_vec); if (!match_once) { pcre_free(p_pcre); pcre_free(p_pcre_extra); } /* return success */ return 1; } @ 1.2 log @*** empty log message *** @ text @d263 1 a263 1 /* optimized processing: factor 15(!) */ @ 1.1 log @Initial revision @ text @d139 1 a139 1 h = (((h*32)+key[i]) % HASH_SIZE); @ 1.1.1.1 log @Import OSSP pcre @ text @@