📄 pcre_study.c
字号:
discard it. */ case OP_WHITESPACE: for (c = 0; c < 32; c++) { int d = cd->cbits[c+cbit_space]; if (c == 1) d &= ~0x08; start_bits[c] |= d; } try_next = FALSE; break; case OP_NOT_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_word]; try_next = FALSE; break; case OP_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_word]; try_next = FALSE; break; /* One or more character type fudges the pointer and restarts, knowing it will hit a single character type and stop there. */ case OP_TYPEPLUS: case OP_TYPEMINPLUS: tcode++; break; case OP_TYPEEXACT: tcode += 3; break; /* Zero or more repeats of character types set the bits and then try again. */ case OP_TYPEUPTO: case OP_TYPEMINUPTO: case OP_TYPEPOSUPTO: tcode += 2; /* Fall through */ case OP_TYPESTAR: case OP_TYPEMINSTAR: case OP_TYPEPOSSTAR: case OP_TYPEQUERY: case OP_TYPEMINQUERY: case OP_TYPEPOSQUERY: switch(tcode[1]) { case OP_ANY: return SSB_FAIL; case OP_NOT_DIGIT: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_digit]; break; case OP_DIGIT: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_digit]; break; /* The cbit_space table has vertical tab as whitespace; we have to discard it. */ case OP_NOT_WHITESPACE: for (c = 0; c < 32; c++) { int d = cd->cbits[c+cbit_space]; if (c == 1) d &= ~0x08; start_bits[c] |= ~d; } break; /* The cbit_space table has vertical tab as whitespace; we have to discard it. */ case OP_WHITESPACE: for (c = 0; c < 32; c++) { int d = cd->cbits[c+cbit_space]; if (c == 1) d &= ~0x08; start_bits[c] |= d; } break; case OP_NOT_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= ~cd->cbits[c+cbit_word]; break; case OP_WORDCHAR: for (c = 0; c < 32; c++) start_bits[c] |= cd->cbits[c+cbit_word]; break; } tcode += 2; break; /* Character class where all the information is in a bit map: set the bits and either carry on or not, according to the repeat count. If it was a negative class, and we are operating with UTF-8 characters, any byte with a value >= 0xc4 is a potentially valid starter because it starts a character with a value > 255. */ case OP_NCLASS:#ifdef SUPPORT_UTF8 if (utf8) { start_bits[24] |= 0xf0; /* Bits for 0xc4 - 0xc8 */ memset(start_bits+25, 0xff, 7); /* Bits for 0xc9 - 0xff */ }#endif /* Fall through */ case OP_CLASS: { tcode++; /* In UTF-8 mode, the bits in a bit map correspond to character values, not to byte values. However, the bit map we are constructing is for byte values. So we have to do a conversion for characters whose value is > 127. In fact, there are only two possible starting bytes for characters in the range 128 - 255. */#ifdef SUPPORT_UTF8 if (utf8) { for (c = 0; c < 16; c++) start_bits[c] |= tcode[c]; for (c = 128; c < 256; c++) { if ((tcode[c/8] && (1 << (c&7))) != 0) { int d = (c >> 6) | 0xc0; /* Set bit for this starter */ start_bits[d/8] |= (1 << (d&7)); /* and then skip on to the */ c = (c & 0xc0) + 0x40 - 1; /* next relevant character. */ } } } /* In non-UTF-8 mode, the two bit maps are completely compatible. */ else#endif { for (c = 0; c < 32; c++) start_bits[c] |= tcode[c]; } /* Advance past the bit map, and act on what follows */ tcode += 32; switch (*tcode) { case OP_CRSTAR: case OP_CRMINSTAR: case OP_CRQUERY: case OP_CRMINQUERY: tcode++; break; case OP_CRRANGE: case OP_CRMINRANGE: if (((tcode[1] << 8) + tcode[2]) == 0) tcode += 5; else try_next = FALSE; break; default: try_next = FALSE; break; } } break; /* End of bitmap class handling */ } /* End of switch */ } /* End of try_next loop */ code += GET(code, 1); /* Advance to next branch */ }while (*code == OP_ALT);return yield;}/************************************************** Study a compiled expression **************************************************//* This function is handed a compiled expression that it must study to produceinformation that will speed up the matching. It returns a pcre_extra blockwhich then gets handed back to pcre_exec().Arguments: re points to the compiled expression options contains option bits errorptr points to where to place error messages; set NULL unless errorReturns: pointer to a pcre_extra block, with study_data filled in and the appropriate flag set; NULL on error or if no optimization possible*/PCRE_EXP_DEFN pcre_extra *pcre_study(const pcre *external_re, int options, const char **errorptr){uschar start_bits[32];pcre_extra *extra;pcre_study_data *study;const uschar *tables;uschar *code;compile_data compile_block;const real_pcre *re = (const real_pcre *)external_re;*errorptr = NULL;if (re == NULL || re->magic_number != MAGIC_NUMBER) { *errorptr = "argument is not a compiled regular expression"; return NULL; }if ((options & ~PUBLIC_STUDY_OPTIONS) != 0) { *errorptr = "unknown or incorrect option bit(s) set"; return NULL; }code = (uschar *)re + re->name_table_offset + (re->name_count * re->name_entry_size);/* For an anchored pattern, or an unanchored pattern that has a first char, ora multiline pattern that matches only at "line starts", no further processingat present. */if ((re->options & PCRE_ANCHORED) != 0 || (re->flags & (PCRE_FIRSTSET|PCRE_STARTLINE)) != 0) return NULL;/* Set the character tables in the block that is passed around */tables = re->tables;if (tables == NULL) (void)pcre_fullinfo(external_re, NULL, PCRE_INFO_DEFAULT_TABLES, (void *)(&tables));compile_block.lcc = tables + lcc_offset;compile_block.fcc = tables + fcc_offset;compile_block.cbits = tables + cbits_offset;compile_block.ctypes = tables + ctypes_offset;/* See if we can find a fixed set of initial characters for the pattern. */memset(start_bits, 0, 32 * sizeof(uschar));if (set_start_bits(code, start_bits, (re->options & PCRE_CASELESS) != 0, (re->options & PCRE_UTF8) != 0, &compile_block) != SSB_DONE) return NULL;/* Get a pcre_extra block and a pcre_study_data block. The study data is put inthe latter, which is pointed to by the former, which may also get additionaldata set later by the calling program. At the moment, the size ofpcre_study_data is fixed. We nevertheless save it in a field for returning viathe pcre_fullinfo() function so that if it becomes variable in the future, wedon't have to change that code. */extra = (pcre_extra *)(pcre_malloc) (sizeof(pcre_extra) + sizeof(pcre_study_data));if (extra == NULL) { *errorptr = "failed to get memory"; return NULL; }study = (pcre_study_data *)((char *)extra + sizeof(pcre_extra));extra->flags = PCRE_EXTRA_STUDY_DATA;extra->study_data = study;study->size = sizeof(pcre_study_data);study->options = PCRE_STUDY_MAPPED;memcpy(study->start_bits, start_bits, sizeof(start_bits));return extra;}/* End of pcre_study.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -