📄 pcretest.c
字号:
clock_t start_time = clock(); for (i = 0; i < LOOPREPEAT; i++) { re = pcre_compile((char *)p, options, &error, &erroroffset, tables); if (re != NULL) free(re); } time_taken = clock() - start_time; fprintf(outfile, "Compile time %.3f milliseconds\n", (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / (double)CLOCKS_PER_SEC); } re = pcre_compile((char *)p, options, &error, &erroroffset, tables); /* Compilation failed; go back for another re, skipping to blank line if non-interactive. */ if (re == NULL) { fprintf(outfile, "Failed: %s at offset %d\n", error, erroroffset); SKIP_DATA: if (infile != stdin) { for (;;) { if (fgets((char *)buffer, BUFFER_SIZE, infile) == NULL) { done = 1; goto CONTINUE; } len = (int)strlen((char *)buffer); while (len > 0 && isspace(buffer[len-1])) len--; if (len == 0) break; } fprintf(outfile, "\n"); } goto CONTINUE; } /* Compilation succeeded; print data if required. There are now two info-returning functions. The old one has a limited interface and returns only limited data. Check that it agrees with the newer one. */ if (log_store) fprintf(outfile, "Memory allocation (code space): %d\n", (int)(gotten_store - sizeof(real_pcre) - ((real_pcre *)re)->name_count * ((real_pcre *)re)->name_entry_size)); /* Extract the size for possible writing before possibly flipping it, and remember the store that was got. */ true_size = ((real_pcre *)re)->size; regex_gotten_store = gotten_store; /* If /S was present, study the regexp to generate additional info to help with the matching. */ if (do_study) { if (timeit) { register int i; clock_t time_taken; clock_t start_time = clock(); for (i = 0; i < LOOPREPEAT; i++) extra = pcre_study(re, study_options, &error); time_taken = clock() - start_time; if (extra != NULL) free(extra); fprintf(outfile, " Study time %.3f milliseconds\n", (((double)time_taken * 1000.0) / (double)LOOPREPEAT) / (double)CLOCKS_PER_SEC); } extra = pcre_study(re, study_options, &error); if (error != NULL) fprintf(outfile, "Failed to study: %s\n", error); else if (extra != NULL) true_study_size = ((pcre_study_data *)(extra->study_data))->size; } /* If the 'F' option was present, we flip the bytes of all the integer fields in the regex data block and the study block. This is to make it possible to test PCRE's handling of byte-flipped patterns, e.g. those compiled on a different architecture. */ if (do_flip) { real_pcre *rre = (real_pcre *)re; rre->magic_number = byteflip(rre->magic_number, sizeof(rre->magic_number)); rre->size = byteflip(rre->size, sizeof(rre->size)); rre->options = byteflip(rre->options, sizeof(rre->options)); rre->top_bracket = byteflip(rre->top_bracket, sizeof(rre->top_bracket)); rre->top_backref = byteflip(rre->top_backref, sizeof(rre->top_backref)); rre->first_byte = byteflip(rre->first_byte, sizeof(rre->first_byte)); rre->req_byte = byteflip(rre->req_byte, sizeof(rre->req_byte)); rre->name_table_offset = byteflip(rre->name_table_offset, sizeof(rre->name_table_offset)); rre->name_entry_size = byteflip(rre->name_entry_size, sizeof(rre->name_entry_size)); rre->name_count = byteflip(rre->name_count, sizeof(rre->name_count)); if (extra != NULL) { pcre_study_data *rsd = (pcre_study_data *)(extra->study_data); rsd->size = byteflip(rsd->size, sizeof(rsd->size)); rsd->options = byteflip(rsd->options, sizeof(rsd->options)); } } /* Extract information from the compiled data if required */ SHOW_INFO: if (do_showinfo) { unsigned long int get_options, all_options; int old_first_char, old_options, old_count; int count, backrefmax, first_char, need_char; int nameentrysize, namecount; const uschar *nametable; if (do_debug) { fprintf(outfile, "------------------------------------------------------------------\n"); print_internals(re, outfile); } new_info(re, NULL, PCRE_INFO_OPTIONS, &get_options); new_info(re, NULL, PCRE_INFO_SIZE, &size); new_info(re, NULL, PCRE_INFO_CAPTURECOUNT, &count); new_info(re, NULL, PCRE_INFO_BACKREFMAX, &backrefmax); new_info(re, NULL, PCRE_INFO_FIRSTBYTE, &first_char); new_info(re, NULL, PCRE_INFO_LASTLITERAL, &need_char); new_info(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &nameentrysize); new_info(re, NULL, PCRE_INFO_NAMECOUNT, &namecount); new_info(re, NULL, PCRE_INFO_NAMETABLE, (void *)&nametable); old_count = pcre_info(re, &old_options, &old_first_char); if (count < 0) fprintf(outfile, "Error %d from pcre_info()\n", count); else { if (old_count != count) fprintf(outfile, "Count disagreement: pcre_fullinfo=%d pcre_info=%d\n", count, old_count); if (old_first_char != first_char) fprintf(outfile, "First char disagreement: pcre_fullinfo=%d pcre_info=%d\n", first_char, old_first_char); if (old_options != (int)get_options) fprintf(outfile, "Options disagreement: pcre_fullinfo=%ld pcre_info=%d\n", get_options, old_options); } if (size != regex_gotten_store) fprintf(outfile, "Size disagreement: pcre_fullinfo=%d call to malloc for %d\n", size, regex_gotten_store); fprintf(outfile, "Capturing subpattern count = %d\n", count); if (backrefmax > 0) fprintf(outfile, "Max back reference = %d\n", backrefmax); if (namecount > 0) { fprintf(outfile, "Named capturing subpatterns:\n"); while (namecount-- > 0) { fprintf(outfile, " %s %*s%3d\n", nametable + 2, nameentrysize - 3 - (int)strlen((char *)nametable + 2), "", GET2(nametable, 0)); nametable += nameentrysize; } } /* The NOPARTIAL bit is a private bit in the options, so we have to fish it out via out back door */ all_options = ((real_pcre *)re)->options; if (do_flip) { all_options = byteflip(all_options, sizeof(all_options)); } if ((all_options & PCRE_NOPARTIAL) != 0) fprintf(outfile, "Partial matching not supported\n"); if (get_options == 0) fprintf(outfile, "No options\n"); else fprintf(outfile, "Options:%s%s%s%s%s%s%s%s%s%s\n", ((get_options & PCRE_ANCHORED) != 0)? " anchored" : "", ((get_options & PCRE_CASELESS) != 0)? " caseless" : "", ((get_options & PCRE_EXTENDED) != 0)? " extended" : "", ((get_options & PCRE_MULTILINE) != 0)? " multiline" : "", ((get_options & PCRE_DOTALL) != 0)? " dotall" : "", ((get_options & PCRE_DOLLAR_ENDONLY) != 0)? " dollar_endonly" : "", ((get_options & PCRE_EXTRA) != 0)? " extra" : "", ((get_options & PCRE_UNGREEDY) != 0)? " ungreedy" : "", ((get_options & PCRE_UTF8) != 0)? " utf8" : "", ((get_options & PCRE_NO_UTF8_CHECK) != 0)? " no_utf8_check" : ""); if (((((real_pcre *)re)->options) & PCRE_ICHANGED) != 0) fprintf(outfile, "Case state changes\n"); if (first_char == -1) { fprintf(outfile, "First char at start or follows \\n\n"); } else if (first_char < 0) { fprintf(outfile, "No first char\n"); } else { int ch = first_char & 255; const char *caseless = ((first_char & REQ_CASELESS) == 0)? "" : " (caseless)"; if (isprint(ch)) fprintf(outfile, "First char = \'%c\'%s\n", ch, caseless); else fprintf(outfile, "First char = %d%s\n", ch, caseless); } if (need_char < 0) { fprintf(outfile, "No need char\n"); } else { int ch = need_char & 255; const char *caseless = ((need_char & REQ_CASELESS) == 0)? "" : " (caseless)"; if (isprint(ch)) fprintf(outfile, "Need char = \'%c\'%s\n", ch, caseless); else fprintf(outfile, "Need char = %d%s\n", ch, caseless); } /* Don't output study size; at present it is in any case a fixed value, but it varies, depending on the computer architecture, and so messes up the test suite. (And with the /F option, it might be flipped.) */ if (do_study) { if (extra == NULL) fprintf(outfile, "Study returned NULL\n"); else { uschar *start_bits = NULL; new_info(re, extra, PCRE_INFO_FIRSTTABLE, &start_bits); if (start_bits == NULL) fprintf(outfile, "No starting byte set\n"); else { int i; int c = 24; fprintf(outfile, "Starting byte set: "); for (i = 0; i < 256; i++) { if ((start_bits[i/8] & (1<<(i&7))) != 0) { if (c > 75) { fprintf(outfile, "\n "); c = 2; } if (isprint(i) && i != ' ') { fprintf(outfile, "%c ", i); c += 2; } else { fprintf(outfile, "\\x%02x ", i); c += 5; } } } fprintf(outfile, "\n"); } } } } /* If the '>' option was present, we write out the regex to a file, and that is all. The first 8 bytes of the file are the regex length and then the study length, in big-endian order. */ if (to_file != NULL) { FILE *f = fopen((char *)to_file, "wb"); if (f == NULL) { fprintf(outfile, "Unable to open %s: %s\n", to_file, strerror(errno)); } else { uschar sbuf[8]; sbuf[0] = (true_size >> 24) & 255; sbuf[1] = (true_size >> 16) & 255; sbuf[2] = (true_size >> 8) & 255; sbuf[3] = (true_size) & 255; sbuf[4] = (true_study_size >> 24) & 255; sbuf[5] = (true_study_size >> 16) & 255; sbuf[6] = (true_study_size >> 8) & 255; sbuf[7] = (true_study_size) & 255; if (fwrite(sbuf, 1, 8, f) < 8 || fwrite(re, 1, true_size, f) < true_size) { fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno)); } else { fprintf(outfile, "Compiled regex written to %s\n", to_file); if (extra != NULL) { if (fwrite(extra->study_data, 1, true_study_size, f) < true_study_size) { fprintf(outfile, "Write error on %s: %s\n", to_file, strerror(errno)); } else fprintf(outfile, "Study data written to %s\n", to_file); } } fclose(f); } continue; /* With next regex */ } } /* End of non-POSIX compile */ /* Read data lines and test them */ for (;;) { unsigned char *q; unsigned char *bptr = dbuffer; int *use_offsets = offsets; int use_size_offsets = size_offsets; int callout_data = 0; int callout_data_set = 0; int count, c; int copystrings = 0; int find_match_limit = 0; int getstrings = 0; int getlist = 0; int gmatched = 0; int start_offset = 0; int g_notempty = 0; options = 0; pcre_callout = callout; first_callout = 1; callout_extra = 0; callout_count = 0; callout_fail_count = 999999; callout_fail_id = -1; show_malloc = 0; if (infile == stdin) printf("data> "); if (fgets((char *)buffer, BUFFER_SIZE, infile) == NULL) { done = 1; goto CONTINUE; } if (infile != stdin) fprintf(outfile, "%s", (char *)buffer); len = (int)strlen((char *)buffer); while (len > 0 && isspace(buffer[len-1])) len--; buffer[len] = 0; if (len == 0) break; p = buffer; while (isspace(*p)) p++; q = dbuffer; while ((c = *p++) != 0) { int i = 0; int n = 0; if (c == '\\') switch ((c = *p++)) { case 'a': c = 7; break; case 'b': c = '\b'; break; case 'e': c = 27; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c -= '0'; while (i++ < 2 && isdigit(*p) && *p != '8' && *p != '9') c = c * 8 + *p++ - '0'; break; case 'x': /* Handle \x{..} specially - new Perl thing for utf8 */ if (*p == '{') { unsigned char *pt = p; c = 0; while (isxdigit(*(++pt))) c = c * 16 + tolower(*pt) - ((isdigit(*pt))? '0' : 'W'); if (*pt == '}') { unsigned char buff8[8]; int ii, utn; utn = ord2utf8(c, buff8); for (ii = 0; ii < utn - 1; ii++) *q++ = buff8[ii]; c = buff8[ii]; /* Last byte */ p = pt + 1; break; } /* Not correct form; fall through */ } /* Ordinary \x */ c = 0; while (i++ < 2 && isxdigit(*p)) { c = c * 16 + tolower(*p) - ((isdigit(*p))? '0' : 'W'); p++; } break; case 0: /* \ followed by EOF allows for an empty line */ p--; continue; case '>': while(isdigit(*p)) start_offset = start_offset * 10 + *p++ - '0'; continue; case 'A': /* Option setting */ options |= PCRE_ANCHORED; continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -