Annotation of embedaddon/pcre/pcre_printint.c, revision 1.1
1.1 ! misho 1: /*************************************************
! 2: * Perl-Compatible Regular Expressions *
! 3: *************************************************/
! 4:
! 5: /* PCRE is a library of functions to support regular expressions whose syntax
! 6: and semantics are as close as possible to those of the Perl 5 language.
! 7:
! 8: Written by Philip Hazel
! 9: Copyright (c) 1997-2012 University of Cambridge
! 10:
! 11: -----------------------------------------------------------------------------
! 12: Redistribution and use in source and binary forms, with or without
! 13: modification, are permitted provided that the following conditions are met:
! 14:
! 15: * Redistributions of source code must retain the above copyright notice,
! 16: this list of conditions and the following disclaimer.
! 17:
! 18: * Redistributions in binary form must reproduce the above copyright
! 19: notice, this list of conditions and the following disclaimer in the
! 20: documentation and/or other materials provided with the distribution.
! 21:
! 22: * Neither the name of the University of Cambridge nor the names of its
! 23: contributors may be used to endorse or promote products derived from
! 24: this software without specific prior written permission.
! 25:
! 26: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
! 27: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 28: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 29: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
! 30: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 31: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 32: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 33: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 34: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 35: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 36: POSSIBILITY OF SUCH DAMAGE.
! 37: -----------------------------------------------------------------------------
! 38: */
! 39:
! 40:
! 41: /* This module contains a PCRE private debugging function for printing out the
! 42: internal form of a compiled regular expression, along with some supporting
! 43: local functions. This source file is used in two places:
! 44:
! 45: (1) It is #included by pcre_compile.c when it is compiled in debugging mode
! 46: (PCRE_DEBUG defined in pcre_internal.h). It is not included in production
! 47: compiles. In this case PCRE_INCLUDED is defined.
! 48:
! 49: (2) It is also compiled separately and linked with pcretest.c, which can be
! 50: asked to print out a compiled regex for debugging purposes. */
! 51:
! 52: #ifndef PCRE_INCLUDED
! 53:
! 54: #ifdef HAVE_CONFIG_H
! 55: #include "config.h"
! 56: #endif
! 57:
! 58: /* For pcretest program. */
! 59: #define PRIV(name) name
! 60:
! 61: /* We have to include pcre_internal.h because we need the internal info for
! 62: displaying the results of pcre_study() and we also need to know about the
! 63: internal macros, structures, and other internal data values; pcretest has
! 64: "inside information" compared to a program that strictly follows the PCRE API.
! 65:
! 66: Although pcre_internal.h does itself include pcre.h, we explicitly include it
! 67: here before pcre_internal.h so that the PCRE_EXP_xxx macros get set
! 68: appropriately for an application, not for building PCRE. */
! 69:
! 70: #include "pcre.h"
! 71: #include "pcre_internal.h"
! 72:
! 73: /* These are the funtions that are contained within. It doesn't seem worth
! 74: having a separate .h file just for this. */
! 75:
! 76: #endif /* PCRE_INCLUDED */
! 77:
! 78: #ifdef PCRE_INCLUDED
! 79: static /* Keep the following function as private. */
! 80: #endif
! 81: #ifdef COMPILE_PCRE8
! 82: void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths);
! 83: #else
! 84: void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths);
! 85: #endif
! 86:
! 87: /* Macro that decides whether a character should be output as a literal or in
! 88: hexadecimal. We don't use isprint() because that can vary from system to system
! 89: (even without the use of locales) and we want the output always to be the same,
! 90: for testing purposes. */
! 91:
! 92: #ifdef EBCDIC
! 93: #define PRINTABLE(c) ((c) >= 64 && (c) < 255)
! 94: #else
! 95: #define PRINTABLE(c) ((c) >= 32 && (c) < 127)
! 96: #endif
! 97:
! 98: /* The table of operator names. */
! 99:
! 100: static const char *priv_OP_names[] = { OP_NAME_LIST };
! 101:
! 102: /* This table of operator lengths is not actually used by the working code,
! 103: but its size is needed for a check that ensures it is the correct size for the
! 104: number of opcodes (thus catching update omissions). */
! 105:
! 106: static const pcre_uint8 priv_OP_lengths[] = { OP_LENGTHS };
! 107:
! 108:
! 109:
! 110: /*************************************************
! 111: * Print single- or multi-byte character *
! 112: *************************************************/
! 113:
! 114: static int
! 115: print_char(FILE *f, pcre_uchar *ptr, BOOL utf)
! 116: {
! 117: int c = *ptr;
! 118:
! 119: #ifndef SUPPORT_UTF
! 120:
! 121: (void)utf; /* Avoid compiler warning */
! 122: if (PRINTABLE(c)) fprintf(f, "%c", c);
! 123: else if (c <= 0xff) fprintf(f, "\\x%02x", c);
! 124: else fprintf(f, "\\x{%x}", c);
! 125: return 0;
! 126:
! 127: #else
! 128:
! 129: #ifdef COMPILE_PCRE8
! 130:
! 131: if (!utf || (c & 0xc0) != 0xc0)
! 132: {
! 133: if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c);
! 134: return 0;
! 135: }
! 136: else
! 137: {
! 138: int i;
! 139: int a = PRIV(utf8_table4)[c & 0x3f]; /* Number of additional bytes */
! 140: int s = 6*a;
! 141: c = (c & PRIV(utf8_table3)[a]) << s;
! 142: for (i = 1; i <= a; i++)
! 143: {
! 144: /* This is a check for malformed UTF-8; it should only occur if the sanity
! 145: check has been turned off. Rather than swallow random bytes, just stop if
! 146: we hit a bad one. Print it with \X instead of \x as an indication. */
! 147:
! 148: if ((ptr[i] & 0xc0) != 0x80)
! 149: {
! 150: fprintf(f, "\\X{%x}", c);
! 151: return i - 1;
! 152: }
! 153:
! 154: /* The byte is OK */
! 155:
! 156: s -= 6;
! 157: c |= (ptr[i] & 0x3f) << s;
! 158: }
! 159: fprintf(f, "\\x{%x}", c);
! 160: return a;
! 161: }
! 162:
! 163: #else
! 164:
! 165: #ifdef COMPILE_PCRE16
! 166:
! 167: if (!utf || (c & 0xfc00) != 0xd800)
! 168: {
! 169: if (PRINTABLE(c)) fprintf(f, "%c", c);
! 170: else if (c <= 0xff) fprintf(f, "\\x%02x", c);
! 171: else fprintf(f, "\\x{%x}", c);
! 172: return 0;
! 173: }
! 174: else
! 175: {
! 176: /* This is a check for malformed UTF-16; it should only occur if the sanity
! 177: check has been turned off. Rather than swallow a low surrogate, just stop if
! 178: we hit a bad one. Print it with \X instead of \x as an indication. */
! 179:
! 180: if ((ptr[1] & 0xfc00) != 0xdc00)
! 181: {
! 182: fprintf(f, "\\X{%x}", c);
! 183: return 0;
! 184: }
! 185:
! 186: c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;
! 187: fprintf(f, "\\x{%x}", c);
! 188: return 1;
! 189: }
! 190:
! 191: #endif /* COMPILE_PCRE16 */
! 192:
! 193: #endif /* COMPILE_PCRE8 */
! 194:
! 195: #endif /* SUPPORT_UTF */
! 196: }
! 197:
! 198: /*************************************************
! 199: * Print uchar string (regardless of utf) *
! 200: *************************************************/
! 201:
! 202: static void
! 203: print_puchar(FILE *f, PCRE_PUCHAR ptr)
! 204: {
! 205: while (*ptr != '\0')
! 206: {
! 207: register int c = *ptr++;
! 208: if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
! 209: }
! 210: }
! 211:
! 212: /*************************************************
! 213: * Find Unicode property name *
! 214: *************************************************/
! 215:
! 216: static const char *
! 217: get_ucpname(int ptype, int pvalue)
! 218: {
! 219: #ifdef SUPPORT_UCP
! 220: int i;
! 221: for (i = PRIV(utt_size) - 1; i >= 0; i--)
! 222: {
! 223: if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;
! 224: }
! 225: return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";
! 226: #else
! 227: /* It gets harder and harder to shut off unwanted compiler warnings. */
! 228: ptype = ptype * pvalue;
! 229: return (ptype == pvalue)? "??" : "??";
! 230: #endif
! 231: }
! 232:
! 233:
! 234:
! 235: /*************************************************
! 236: * Print compiled regex *
! 237: *************************************************/
! 238:
! 239: /* Make this function work for a regex with integers either byte order.
! 240: However, we assume that what we are passed is a compiled regex. The
! 241: print_lengths flag controls whether offsets and lengths of items are printed.
! 242: They can be turned off from pcretest so that automatic tests on bytecode can be
! 243: written that do not depend on the value of LINK_SIZE. */
! 244:
! 245: #ifdef PCRE_INCLUDED
! 246: static /* Keep the following function as private. */
! 247: #endif
! 248: #ifdef COMPILE_PCRE8
! 249: void
! 250: pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths)
! 251: #else
! 252: void
! 253: pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths)
! 254: #endif
! 255: {
! 256: REAL_PCRE *re = (REAL_PCRE *)external_re;
! 257: pcre_uchar *codestart, *code;
! 258: BOOL utf;
! 259:
! 260: unsigned int options = re->options;
! 261: int offset = re->name_table_offset;
! 262: int count = re->name_count;
! 263: int size = re->name_entry_size;
! 264:
! 265: if (re->magic_number != MAGIC_NUMBER)
! 266: {
! 267: offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff);
! 268: count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff);
! 269: size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff);
! 270: options = ((options << 24) & 0xff000000) |
! 271: ((options << 8) & 0x00ff0000) |
! 272: ((options >> 8) & 0x0000ff00) |
! 273: ((options >> 24) & 0x000000ff);
! 274: }
! 275:
! 276: code = codestart = (pcre_uchar *)re + offset + count * size;
! 277: /* PCRE_UTF16 has the same value as PCRE_UTF8. */
! 278: utf = (options & PCRE_UTF8) != 0;
! 279:
! 280: for(;;)
! 281: {
! 282: pcre_uchar *ccode;
! 283: const char *flag = " ";
! 284: int c;
! 285: int extra = 0;
! 286:
! 287: if (print_lengths)
! 288: fprintf(f, "%3d ", (int)(code - codestart));
! 289: else
! 290: fprintf(f, " ");
! 291:
! 292: switch(*code)
! 293: {
! 294: /* ========================================================================== */
! 295: /* These cases are never obeyed. This is a fudge that causes a compile-
! 296: time error if the vectors OP_names or OP_lengths, which are indexed
! 297: by opcode, are not the correct length. It seems to be the only way to do
! 298: such a check at compile time, as the sizeof() operator does not work in
! 299: the C preprocessor. */
! 300:
! 301: case OP_TABLE_LENGTH:
! 302: case OP_TABLE_LENGTH +
! 303: ((sizeof(priv_OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
! 304: (sizeof(priv_OP_lengths) == OP_TABLE_LENGTH)):
! 305: break;
! 306: /* ========================================================================== */
! 307:
! 308: case OP_END:
! 309: fprintf(f, " %s\n", priv_OP_names[*code]);
! 310: fprintf(f, "------------------------------------------------------------------\n");
! 311: return;
! 312:
! 313: case OP_CHAR:
! 314: fprintf(f, " ");
! 315: do
! 316: {
! 317: code++;
! 318: code += 1 + print_char(f, code, utf);
! 319: }
! 320: while (*code == OP_CHAR);
! 321: fprintf(f, "\n");
! 322: continue;
! 323:
! 324: case OP_CHARI:
! 325: fprintf(f, " /i ");
! 326: do
! 327: {
! 328: code++;
! 329: code += 1 + print_char(f, code, utf);
! 330: }
! 331: while (*code == OP_CHARI);
! 332: fprintf(f, "\n");
! 333: continue;
! 334:
! 335: case OP_CBRA:
! 336: case OP_CBRAPOS:
! 337: case OP_SCBRA:
! 338: case OP_SCBRAPOS:
! 339: if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
! 340: else fprintf(f, " ");
! 341: fprintf(f, "%s %d", priv_OP_names[*code], GET2(code, 1+LINK_SIZE));
! 342: break;
! 343:
! 344: case OP_BRA:
! 345: case OP_BRAPOS:
! 346: case OP_SBRA:
! 347: case OP_SBRAPOS:
! 348: case OP_KETRMAX:
! 349: case OP_KETRMIN:
! 350: case OP_KETRPOS:
! 351: case OP_ALT:
! 352: case OP_KET:
! 353: case OP_ASSERT:
! 354: case OP_ASSERT_NOT:
! 355: case OP_ASSERTBACK:
! 356: case OP_ASSERTBACK_NOT:
! 357: case OP_ONCE:
! 358: case OP_ONCE_NC:
! 359: case OP_COND:
! 360: case OP_SCOND:
! 361: case OP_REVERSE:
! 362: if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
! 363: else fprintf(f, " ");
! 364: fprintf(f, "%s", priv_OP_names[*code]);
! 365: break;
! 366:
! 367: case OP_CLOSE:
! 368: fprintf(f, " %s %d", priv_OP_names[*code], GET2(code, 1));
! 369: break;
! 370:
! 371: case OP_CREF:
! 372: case OP_NCREF:
! 373: fprintf(f, "%3d %s", GET2(code,1), priv_OP_names[*code]);
! 374: break;
! 375:
! 376: case OP_RREF:
! 377: c = GET2(code, 1);
! 378: if (c == RREF_ANY)
! 379: fprintf(f, " Cond recurse any");
! 380: else
! 381: fprintf(f, " Cond recurse %d", c);
! 382: break;
! 383:
! 384: case OP_NRREF:
! 385: c = GET2(code, 1);
! 386: if (c == RREF_ANY)
! 387: fprintf(f, " Cond nrecurse any");
! 388: else
! 389: fprintf(f, " Cond nrecurse %d", c);
! 390: break;
! 391:
! 392: case OP_DEF:
! 393: fprintf(f, " Cond def");
! 394: break;
! 395:
! 396: case OP_STARI:
! 397: case OP_MINSTARI:
! 398: case OP_POSSTARI:
! 399: case OP_PLUSI:
! 400: case OP_MINPLUSI:
! 401: case OP_POSPLUSI:
! 402: case OP_QUERYI:
! 403: case OP_MINQUERYI:
! 404: case OP_POSQUERYI:
! 405: flag = "/i";
! 406: /* Fall through */
! 407: case OP_STAR:
! 408: case OP_MINSTAR:
! 409: case OP_POSSTAR:
! 410: case OP_PLUS:
! 411: case OP_MINPLUS:
! 412: case OP_POSPLUS:
! 413: case OP_QUERY:
! 414: case OP_MINQUERY:
! 415: case OP_POSQUERY:
! 416: case OP_TYPESTAR:
! 417: case OP_TYPEMINSTAR:
! 418: case OP_TYPEPOSSTAR:
! 419: case OP_TYPEPLUS:
! 420: case OP_TYPEMINPLUS:
! 421: case OP_TYPEPOSPLUS:
! 422: case OP_TYPEQUERY:
! 423: case OP_TYPEMINQUERY:
! 424: case OP_TYPEPOSQUERY:
! 425: fprintf(f, " %s ", flag);
! 426: if (*code >= OP_TYPESTAR)
! 427: {
! 428: fprintf(f, "%s", priv_OP_names[code[1]]);
! 429: if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
! 430: {
! 431: fprintf(f, " %s ", get_ucpname(code[2], code[3]));
! 432: extra = 2;
! 433: }
! 434: }
! 435: else extra = print_char(f, code+1, utf);
! 436: fprintf(f, "%s", priv_OP_names[*code]);
! 437: break;
! 438:
! 439: case OP_EXACTI:
! 440: case OP_UPTOI:
! 441: case OP_MINUPTOI:
! 442: case OP_POSUPTOI:
! 443: flag = "/i";
! 444: /* Fall through */
! 445: case OP_EXACT:
! 446: case OP_UPTO:
! 447: case OP_MINUPTO:
! 448: case OP_POSUPTO:
! 449: fprintf(f, " %s ", flag);
! 450: extra = print_char(f, code + 1 + IMM2_SIZE, utf);
! 451: fprintf(f, "{");
! 452: if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
! 453: fprintf(f, "%d}", GET2(code,1));
! 454: if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
! 455: else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
! 456: break;
! 457:
! 458: case OP_TYPEEXACT:
! 459: case OP_TYPEUPTO:
! 460: case OP_TYPEMINUPTO:
! 461: case OP_TYPEPOSUPTO:
! 462: fprintf(f, " %s", priv_OP_names[code[1 + IMM2_SIZE]]);
! 463: if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
! 464: {
! 465: fprintf(f, " %s ", get_ucpname(code[1 + IMM2_SIZE + 1],
! 466: code[1 + IMM2_SIZE + 2]));
! 467: extra = 2;
! 468: }
! 469: fprintf(f, "{");
! 470: if (*code != OP_TYPEEXACT) fprintf(f, "0,");
! 471: fprintf(f, "%d}", GET2(code,1));
! 472: if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
! 473: else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
! 474: break;
! 475:
! 476: case OP_NOTI:
! 477: flag = "/i";
! 478: /* Fall through */
! 479: case OP_NOT:
! 480: c = code[1];
! 481: if (PRINTABLE(c)) fprintf(f, " %s [^%c]", flag, c);
! 482: else if (utf || c > 0xff)
! 483: fprintf(f, " %s [^\\x{%02x}]", flag, c);
! 484: else
! 485: fprintf(f, " %s [^\\x%02x]", flag, c);
! 486: break;
! 487:
! 488: case OP_NOTSTARI:
! 489: case OP_NOTMINSTARI:
! 490: case OP_NOTPOSSTARI:
! 491: case OP_NOTPLUSI:
! 492: case OP_NOTMINPLUSI:
! 493: case OP_NOTPOSPLUSI:
! 494: case OP_NOTQUERYI:
! 495: case OP_NOTMINQUERYI:
! 496: case OP_NOTPOSQUERYI:
! 497: flag = "/i";
! 498: /* Fall through */
! 499:
! 500: case OP_NOTSTAR:
! 501: case OP_NOTMINSTAR:
! 502: case OP_NOTPOSSTAR:
! 503: case OP_NOTPLUS:
! 504: case OP_NOTMINPLUS:
! 505: case OP_NOTPOSPLUS:
! 506: case OP_NOTQUERY:
! 507: case OP_NOTMINQUERY:
! 508: case OP_NOTPOSQUERY:
! 509: c = code[1];
! 510: if (PRINTABLE(c)) fprintf(f, " %s [^%c]", flag, c);
! 511: else fprintf(f, " %s [^\\x%02x]", flag, c);
! 512: fprintf(f, "%s", priv_OP_names[*code]);
! 513: break;
! 514:
! 515: case OP_NOTEXACTI:
! 516: case OP_NOTUPTOI:
! 517: case OP_NOTMINUPTOI:
! 518: case OP_NOTPOSUPTOI:
! 519: flag = "/i";
! 520: /* Fall through */
! 521:
! 522: case OP_NOTEXACT:
! 523: case OP_NOTUPTO:
! 524: case OP_NOTMINUPTO:
! 525: case OP_NOTPOSUPTO:
! 526: c = code[1 + IMM2_SIZE];
! 527: if (PRINTABLE(c)) fprintf(f, " %s [^%c]{", flag, c);
! 528: else fprintf(f, " %s [^\\x%02x]{", flag, c);
! 529: if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
! 530: fprintf(f, "%d}", GET2(code,1));
! 531: if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
! 532: else
! 533: if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
! 534: break;
! 535:
! 536: case OP_RECURSE:
! 537: if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
! 538: else fprintf(f, " ");
! 539: fprintf(f, "%s", priv_OP_names[*code]);
! 540: break;
! 541:
! 542: case OP_REFI:
! 543: flag = "/i";
! 544: /* Fall through */
! 545: case OP_REF:
! 546: fprintf(f, " %s \\%d", flag, GET2(code,1));
! 547: ccode = code + priv_OP_lengths[*code];
! 548: goto CLASS_REF_REPEAT;
! 549:
! 550: case OP_CALLOUT:
! 551: fprintf(f, " %s %d %d %d", priv_OP_names[*code], code[1], GET(code,2),
! 552: GET(code, 2 + LINK_SIZE));
! 553: break;
! 554:
! 555: case OP_PROP:
! 556: case OP_NOTPROP:
! 557: fprintf(f, " %s %s", priv_OP_names[*code], get_ucpname(code[1], code[2]));
! 558: break;
! 559:
! 560: /* OP_XCLASS can only occur in UTF or PCRE16 modes. However, there's no
! 561: harm in having this code always here, and it makes it less messy without
! 562: all those #ifdefs. */
! 563:
! 564: case OP_CLASS:
! 565: case OP_NCLASS:
! 566: case OP_XCLASS:
! 567: {
! 568: int i, min, max;
! 569: BOOL printmap;
! 570: pcre_uint8 *map;
! 571:
! 572: fprintf(f, " [");
! 573:
! 574: if (*code == OP_XCLASS)
! 575: {
! 576: extra = GET(code, 1);
! 577: ccode = code + LINK_SIZE + 1;
! 578: printmap = (*ccode & XCL_MAP) != 0;
! 579: if ((*ccode++ & XCL_NOT) != 0) fprintf(f, "^");
! 580: }
! 581: else
! 582: {
! 583: printmap = TRUE;
! 584: ccode = code + 1;
! 585: }
! 586:
! 587: /* Print a bit map */
! 588:
! 589: if (printmap)
! 590: {
! 591: map = (pcre_uint8 *)ccode;
! 592: for (i = 0; i < 256; i++)
! 593: {
! 594: if ((map[i/8] & (1 << (i&7))) != 0)
! 595: {
! 596: int j;
! 597: for (j = i+1; j < 256; j++)
! 598: if ((map[j/8] & (1 << (j&7))) == 0) break;
! 599: if (i == '-' || i == ']') fprintf(f, "\\");
! 600: if (PRINTABLE(i)) fprintf(f, "%c", i);
! 601: else fprintf(f, "\\x%02x", i);
! 602: if (--j > i)
! 603: {
! 604: if (j != i + 1) fprintf(f, "-");
! 605: if (j == '-' || j == ']') fprintf(f, "\\");
! 606: if (PRINTABLE(j)) fprintf(f, "%c", j);
! 607: else fprintf(f, "\\x%02x", j);
! 608: }
! 609: i = j;
! 610: }
! 611: }
! 612: ccode += 32 / sizeof(pcre_uchar);
! 613: }
! 614:
! 615: /* For an XCLASS there is always some additional data */
! 616:
! 617: if (*code == OP_XCLASS)
! 618: {
! 619: int ch;
! 620: while ((ch = *ccode++) != XCL_END)
! 621: {
! 622: if (ch == XCL_PROP)
! 623: {
! 624: int ptype = *ccode++;
! 625: int pvalue = *ccode++;
! 626: fprintf(f, "\\p{%s}", get_ucpname(ptype, pvalue));
! 627: }
! 628: else if (ch == XCL_NOTPROP)
! 629: {
! 630: int ptype = *ccode++;
! 631: int pvalue = *ccode++;
! 632: fprintf(f, "\\P{%s}", get_ucpname(ptype, pvalue));
! 633: }
! 634: else
! 635: {
! 636: ccode += 1 + print_char(f, ccode, utf);
! 637: if (ch == XCL_RANGE)
! 638: {
! 639: fprintf(f, "-");
! 640: ccode += 1 + print_char(f, ccode, utf);
! 641: }
! 642: }
! 643: }
! 644: }
! 645:
! 646: /* Indicate a non-UTF class which was created by negation */
! 647:
! 648: fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");
! 649:
! 650: /* Handle repeats after a class or a back reference */
! 651:
! 652: CLASS_REF_REPEAT:
! 653: switch(*ccode)
! 654: {
! 655: case OP_CRSTAR:
! 656: case OP_CRMINSTAR:
! 657: case OP_CRPLUS:
! 658: case OP_CRMINPLUS:
! 659: case OP_CRQUERY:
! 660: case OP_CRMINQUERY:
! 661: fprintf(f, "%s", priv_OP_names[*ccode]);
! 662: extra += priv_OP_lengths[*ccode];
! 663: break;
! 664:
! 665: case OP_CRRANGE:
! 666: case OP_CRMINRANGE:
! 667: min = GET2(ccode,1);
! 668: max = GET2(ccode,1 + IMM2_SIZE);
! 669: if (max == 0) fprintf(f, "{%d,}", min);
! 670: else fprintf(f, "{%d,%d}", min, max);
! 671: if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
! 672: extra += priv_OP_lengths[*ccode];
! 673: break;
! 674:
! 675: /* Do nothing if it's not a repeat; this code stops picky compilers
! 676: warning about the lack of a default code path. */
! 677:
! 678: default:
! 679: break;
! 680: }
! 681: }
! 682: break;
! 683:
! 684: case OP_MARK:
! 685: case OP_PRUNE_ARG:
! 686: case OP_SKIP_ARG:
! 687: case OP_THEN_ARG:
! 688: fprintf(f, " %s ", priv_OP_names[*code]);
! 689: print_puchar(f, code + 2);
! 690: extra += code[1];
! 691: break;
! 692:
! 693: case OP_THEN:
! 694: fprintf(f, " %s", priv_OP_names[*code]);
! 695: break;
! 696:
! 697: case OP_CIRCM:
! 698: case OP_DOLLM:
! 699: flag = "/m";
! 700: /* Fall through */
! 701:
! 702: /* Anything else is just an item with no data, but possibly a flag. */
! 703:
! 704: default:
! 705: fprintf(f, " %s %s", flag, priv_OP_names[*code]);
! 706: break;
! 707: }
! 708:
! 709: code += priv_OP_lengths[*code] + extra;
! 710: fprintf(f, "\n");
! 711: }
! 712: }
! 713:
! 714: /* End of pcre_printint.src */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>