📄 pcretest.c
字号:
/************************************************** Byte flipping function **************************************************/static long intbyteflip(long int value, int n){if (n == 2) return ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);return ((value & 0x000000ff) << 24) | ((value & 0x0000ff00) << 8) | ((value & 0x00ff0000) >> 8) | ((value & 0xff000000) >> 24);}/************************************************** Main Program **************************************************//* Read lines from named file or stdin and write to named file or stdout; linesconsist of a regular expression, in delimiters and optionally followed byoptions, followed by a set of test data, terminated by an empty line. */int main(int argc, char **argv){FILE *infile = stdin;int options = 0;int study_options = 0;int op = 1;int timeit = 0;int showinfo = 0;int showstore = 0;int size_offsets = 45;int size_offsets_max;int *offsets;#if !defined NOPOSIXint posix = 0;#endifint debug = 0;int done = 0;unsigned char *buffer;unsigned char *dbuffer;/* Get buffers from malloc() so that Electric Fence will check their misusewhen I am debugging. */buffer = (unsigned char *)malloc(BUFFER_SIZE);dbuffer = (unsigned char *)malloc(DBUFFER_SIZE);pbuffer = (unsigned char *)malloc(PBUFFER_SIZE);/* The outfile variable is static so that new_malloc can use it. The _setmode()stuff is some magic that I don't understand, but which apparently does goodthings in Windows. It's related to line terminations. */#if defined(_WIN32) || defined(WIN32)_setmode( _fileno( stdout ), 0x8000 );#endif /* defined(_WIN32) || defined(WIN32) */outfile = stdout;/* Scan options */while (argc > 1 && argv[op][0] == '-') { unsigned char *endptr; if (strcmp(argv[op], "-s") == 0 || strcmp(argv[op], "-m") == 0) showstore = 1; else if (strcmp(argv[op], "-t") == 0) timeit = 1; else if (strcmp(argv[op], "-i") == 0) showinfo = 1; else if (strcmp(argv[op], "-d") == 0) showinfo = debug = 1; else if (strcmp(argv[op], "-o") == 0 && argc > 2 && ((size_offsets = get_value((unsigned char *)argv[op+1], &endptr)), *endptr == 0)) { op++; argc--; }#if !defined NOPOSIX else if (strcmp(argv[op], "-p") == 0) posix = 1;#endif else if (strcmp(argv[op], "-C") == 0) { int rc; printf("PCRE version %s\n", pcre_version()); printf("Compiled with\n"); (void)pcre_config(PCRE_CONFIG_UTF8, &rc); printf(" %sUTF-8 support\n", rc? "" : "No "); (void)pcre_config(PCRE_CONFIG_UNICODE_PROPERTIES, &rc); printf(" %sUnicode properties support\n", rc? "" : "No "); (void)pcre_config(PCRE_CONFIG_NEWLINE, &rc); printf(" Newline character is %s\n", (rc == '\r')? "CR" : "LF"); (void)pcre_config(PCRE_CONFIG_LINK_SIZE, &rc); printf(" Internal link size = %d\n", rc); (void)pcre_config(PCRE_CONFIG_POSIX_MALLOC_THRESHOLD, &rc); printf(" POSIX malloc threshold = %d\n", rc); (void)pcre_config(PCRE_CONFIG_MATCH_LIMIT, &rc); printf(" Default match limit = %d\n", rc); (void)pcre_config(PCRE_CONFIG_STACKRECURSE, &rc); printf(" Match recursion uses %s\n", rc? "stack" : "heap"); exit(0); } else { printf("** Unknown or malformed option %s\n", argv[op]); printf("Usage: pcretest [-d] [-i] [-o <n>] [-p] [-s] [-t] [<input> [<output>]]\n"); printf(" -C show PCRE compile-time options and exit\n"); printf(" -d debug: show compiled code; implies -i\n" " -i show information about compiled pattern\n" " -m output memory used information\n" " -o <n> set size of offsets vector to <n>\n");#if !defined NOPOSIX printf(" -p use POSIX interface\n");#endif printf(" -s output store (memory) used information\n" " -t time compilation and execution\n"); return 1; } op++; argc--; }/* Get the store for the offsets vector, and remember what it was */size_offsets_max = size_offsets;offsets = (int *)malloc(size_offsets_max * sizeof(int));if (offsets == NULL) { printf("** Failed to get %d bytes of memory for offsets vector\n", size_offsets_max * sizeof(int)); return 1; }/* Sort out the input and output files */if (argc > 1) { infile = fopen(argv[op], "rb"); if (infile == NULL) { printf("** Failed to open %s\n", argv[op]); return 1; } }if (argc > 2) { outfile = fopen(argv[op+1], "wb"); if (outfile == NULL) { printf("** Failed to open %s\n", argv[op+1]); return 1; } }/* Set alternative malloc function */pcre_malloc = new_malloc;pcre_free = new_free;pcre_stack_malloc = stack_malloc;pcre_stack_free = stack_free;/* Heading line, then prompt for first regex if stdin */fprintf(outfile, "PCRE version %s\n\n", pcre_version());/* Main loop */while (!done) { pcre *re = NULL; pcre_extra *extra = NULL;#if !defined NOPOSIX /* There are still compilers that require no indent */ regex_t preg; int do_posix = 0;#endif const char *error; unsigned char *p, *pp, *ppp; unsigned char *to_file = NULL; const unsigned char *tables = NULL; unsigned long int true_size, true_study_size = 0; size_t size, regex_gotten_store; int do_study = 0; int do_debug = debug; int do_G = 0; int do_g = 0; int do_showinfo = showinfo; int do_showrest = 0; int do_flip = 0; int erroroffset, len, delimiter; use_utf8 = 0; if (infile == stdin) printf(" re> "); if (fgets((char *)buffer, BUFFER_SIZE, infile) == NULL) break; if (infile != stdin) fprintf(outfile, "%s", (char *)buffer); fflush(outfile); p = buffer; while (isspace(*p)) p++; if (*p == 0) continue; /* See if the pattern is to be loaded pre-compiled from a file. */ if (*p == '<' && strchr((char *)(p+1), '<') == NULL) { unsigned long int magic; uschar sbuf[8]; FILE *f; p++; pp = p + (int)strlen((char *)p); while (isspace(pp[-1])) pp--; *pp = 0; f = fopen((char *)p, "rb"); if (f == NULL) { fprintf(outfile, "Failed to open %s: %s\n", p, strerror(errno)); continue; } if (fread(sbuf, 1, 8, f) != 8) goto FAIL_READ; true_size = (sbuf[0] << 24) | (sbuf[1] << 16) | (sbuf[2] << 8) | sbuf[3]; true_study_size = (sbuf[4] << 24) | (sbuf[5] << 16) | (sbuf[6] << 8) | sbuf[7]; re = (real_pcre *)new_malloc(true_size); regex_gotten_store = gotten_store; if (fread(re, 1, true_size, f) != true_size) goto FAIL_READ; magic = ((real_pcre *)re)->magic_number; if (magic != MAGIC_NUMBER) { if (byteflip(magic, sizeof(magic)) == MAGIC_NUMBER) { do_flip = 1; } else { fprintf(outfile, "Data in %s is not a compiled PCRE regex\n", p); fclose(f); continue; } } fprintf(outfile, "Compiled regex%s loaded from %s\n", do_flip? " (byte-inverted)" : "", p); /* Need to know if UTF-8 for printing data strings */ new_info(re, NULL, PCRE_INFO_OPTIONS, &options); use_utf8 = (options & PCRE_UTF8) != 0; /* Now see if there is any following study data */ if (true_study_size != 0) { pcre_study_data *psd; extra = (pcre_extra *)new_malloc(sizeof(pcre_extra) + true_study_size); extra->flags = PCRE_EXTRA_STUDY_DATA; psd = (pcre_study_data *)(((char *)extra) + sizeof(pcre_extra)); extra->study_data = psd; if (fread(psd, 1, true_study_size, f) != true_study_size) { FAIL_READ: fprintf(outfile, "Failed to read data from %s\n", p); if (extra != NULL) new_free(extra); if (re != NULL) new_free(re); fclose(f); continue; } fprintf(outfile, "Study data loaded from %s\n", p); do_study = 1; /* To get the data output if requested */ } else fprintf(outfile, "No study data\n"); fclose(f); goto SHOW_INFO; } /* In-line pattern (the usual case). Get the delimiter and seek the end of the pattern; if is isn't complete, read more. */ delimiter = *p++; if (isalnum(delimiter) || delimiter == '\\') { fprintf(outfile, "** Delimiter must not be alphameric or \\\n"); goto SKIP_DATA; } pp = p; for(;;) { while (*pp != 0) { if (*pp == '\\' && pp[1] != 0) pp++; else if (*pp == delimiter) break; pp++; } if (*pp != 0) break; len = BUFFER_SIZE - (pp - buffer); if (len < 256) { fprintf(outfile, "** Expression too long - missing delimiter?\n"); goto SKIP_DATA; } if (infile == stdin) printf(" > "); if (fgets((char *)pp, len, infile) == NULL) { fprintf(outfile, "** Unexpected EOF\n"); done = 1; goto CONTINUE; } if (infile != stdin) fprintf(outfile, "%s", (char *)pp); } /* If the first character after the delimiter is backslash, make the pattern end with backslash. This is purely to provide a way of testing for the error message when a pattern ends with backslash. */ if (pp[1] == '\\') *pp++ = '\\'; /* Terminate the pattern at the delimiter, and save a copy of the pattern for callouts. */ *pp++ = 0; strcpy((char *)pbuffer, (char *)p); /* Look for options after final delimiter */ options = 0; study_options = 0; log_store = showstore; /* default from command line */ while (*pp != 0) { switch (*pp++) { case 'g': do_g = 1; break; case 'i': options |= PCRE_CASELESS; break; case 'm': options |= PCRE_MULTILINE; break; case 's': options |= PCRE_DOTALL; break; case 'x': options |= PCRE_EXTENDED; break; case '+': do_showrest = 1; break; case 'A': options |= PCRE_ANCHORED; break; case 'C': options |= PCRE_AUTO_CALLOUT; break; case 'D': do_debug = do_showinfo = 1; break; case 'E': options |= PCRE_DOLLAR_ENDONLY; break; case 'F': do_flip = 1; break; case 'G': do_G = 1; break; case 'I': do_showinfo = 1; break; case 'M': log_store = 1; break; case 'N': options |= PCRE_NO_AUTO_CAPTURE; break;#if !defined NOPOSIX case 'P': do_posix = 1; break;#endif case 'S': do_study = 1; break; case 'U': options |= PCRE_UNGREEDY; break; case 'X': options |= PCRE_EXTRA; break; case '8': options |= PCRE_UTF8; use_utf8 = 1; break; case '?': options |= PCRE_NO_UTF8_CHECK; break; case 'L': ppp = pp; while (*ppp != '\n' && *ppp != ' ') ppp++; *ppp = 0; if (setlocale(LC_CTYPE, (const char *)pp) == NULL) { fprintf(outfile, "** Failed to set locale \"%s\"\n", pp); goto SKIP_DATA; } tables = pcre_maketables(); pp = ppp; break; case '>': to_file = pp; while (*pp != 0) pp++; while (isspace(pp[-1])) pp--; *pp = 0; break; case '\n': case ' ': break; default: fprintf(outfile, "** Unknown option '%c'\n", pp[-1]); goto SKIP_DATA; } } /* Handle compiling via the POSIX interface, which doesn't support the timing, showing, or debugging options, nor the ability to pass over local character tables. */#if !defined NOPOSIX if (posix || do_posix) { int rc; int cflags = 0; if ((options & PCRE_CASELESS) != 0) cflags |= REG_ICASE; if ((options & PCRE_MULTILINE) != 0) cflags |= REG_NEWLINE; rc = regcomp(&preg, (char *)p, cflags); /* Compilation failed; go back for another re, skipping to blank line if non-interactive. */ if (rc != 0) { (void)regerror(rc, &preg, (char *)buffer, BUFFER_SIZE); fprintf(outfile, "Failed: POSIX code %d: %s\n", rc, buffer); goto SKIP_DATA; } } /* Handle compiling via the native interface */ else#endif /* !defined NOPOSIX */ { if (timeit) { register int i; clock_t time_taken;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -