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>