Blame pcre_printint.c

Packit 78a954
/*************************************************
Packit 78a954
*      Perl-Compatible Regular Expressions       *
Packit 78a954
*************************************************/
Packit 78a954
Packit 78a954
/* PCRE is a library of functions to support regular expressions whose syntax
Packit 78a954
and semantics are as close as possible to those of the Perl 5 language.
Packit 78a954
Packit 78a954
                       Written by Philip Hazel
Packit 78a954
           Copyright (c) 1997-2012 University of Cambridge
Packit 78a954
Packit 78a954
-----------------------------------------------------------------------------
Packit 78a954
Redistribution and use in source and binary forms, with or without
Packit 78a954
modification, are permitted provided that the following conditions are met:
Packit 78a954
Packit 78a954
    * Redistributions of source code must retain the above copyright notice,
Packit 78a954
      this list of conditions and the following disclaimer.
Packit 78a954
Packit 78a954
    * Redistributions in binary form must reproduce the above copyright
Packit 78a954
      notice, this list of conditions and the following disclaimer in the
Packit 78a954
      documentation and/or other materials provided with the distribution.
Packit 78a954
Packit 78a954
    * Neither the name of the University of Cambridge nor the names of its
Packit 78a954
      contributors may be used to endorse or promote products derived from
Packit 78a954
      this software without specific prior written permission.
Packit 78a954
Packit 78a954
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 78a954
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 78a954
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 78a954
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit 78a954
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit 78a954
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit 78a954
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit 78a954
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit 78a954
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit 78a954
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit 78a954
POSSIBILITY OF SUCH DAMAGE.
Packit 78a954
-----------------------------------------------------------------------------
Packit 78a954
*/
Packit 78a954
Packit 78a954
Packit 78a954
/* This module contains a PCRE private debugging function for printing out the
Packit 78a954
internal form of a compiled regular expression, along with some supporting
Packit 78a954
local functions. This source file is used in two places:
Packit 78a954
Packit 78a954
(1) It is #included by pcre_compile.c when it is compiled in debugging mode
Packit 78a954
(PCRE_DEBUG defined in pcre_internal.h). It is not included in production
Packit 78a954
compiles. In this case PCRE_INCLUDED is defined.
Packit 78a954
Packit 78a954
(2) It is also compiled separately and linked with pcretest.c, which can be
Packit 78a954
asked to print out a compiled regex for debugging purposes. */
Packit 78a954
Packit 78a954
#ifndef PCRE_INCLUDED
Packit 78a954
Packit 78a954
#ifdef HAVE_CONFIG_H
Packit 78a954
#include "config.h"
Packit 78a954
#endif
Packit 78a954
Packit 78a954
/* For pcretest program. */
Packit 78a954
#define PRIV(name) name
Packit 78a954
Packit 78a954
/* We have to include pcre_internal.h because we need the internal info for
Packit 78a954
displaying the results of pcre_study() and we also need to know about the
Packit 78a954
internal macros, structures, and other internal data values; pcretest has
Packit 78a954
"inside information" compared to a program that strictly follows the PCRE API.
Packit 78a954
Packit 78a954
Although pcre_internal.h does itself include pcre.h, we explicitly include it
Packit 78a954
here before pcre_internal.h so that the PCRE_EXP_xxx macros get set
Packit 78a954
appropriately for an application, not for building PCRE. */
Packit 78a954
Packit 78a954
#include "pcre.h"
Packit 78a954
#include "pcre_internal.h"
Packit 78a954
Packit 78a954
/* These are the funtions that are contained within. It doesn't seem worth
Packit 78a954
having a separate .h file just for this. */
Packit 78a954
Packit 78a954
#endif /* PCRE_INCLUDED */
Packit 78a954
Packit 78a954
#ifdef PCRE_INCLUDED
Packit 78a954
static /* Keep the following function as private. */
Packit 78a954
#endif
Packit 78a954
Packit 78a954
#if defined COMPILE_PCRE8
Packit 78a954
void pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths);
Packit 78a954
#elif defined COMPILE_PCRE16
Packit 78a954
void pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths);
Packit 78a954
#elif defined COMPILE_PCRE32
Packit 78a954
void pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths);
Packit 78a954
#endif
Packit 78a954
Packit 78a954
/* Macro that decides whether a character should be output as a literal or in
Packit 78a954
hexadecimal. We don't use isprint() because that can vary from system to system
Packit 78a954
(even without the use of locales) and we want the output always to be the same,
Packit 78a954
for testing purposes. */
Packit 78a954
Packit 78a954
#ifdef EBCDIC
Packit 78a954
#define PRINTABLE(c) ((c) >= 64 && (c) < 255)
Packit 78a954
#else
Packit 78a954
#define PRINTABLE(c) ((c) >= 32 && (c) < 127)
Packit 78a954
#endif
Packit 78a954
Packit 78a954
/* The table of operator names. */
Packit 78a954
Packit 78a954
static const char *priv_OP_names[] = { OP_NAME_LIST };
Packit 78a954
Packit 78a954
/* This table of operator lengths is not actually used by the working code,
Packit 78a954
but its size is needed for a check that ensures it is the correct size for the
Packit 78a954
number of opcodes (thus catching update omissions). */
Packit 78a954
Packit 78a954
static const pcre_uint8 priv_OP_lengths[] = { OP_LENGTHS };
Packit 78a954
Packit 78a954
Packit 78a954
Packit 78a954
/*************************************************
Packit 78a954
*       Print single- or multi-byte character    *
Packit 78a954
*************************************************/
Packit 78a954
Packit 78a954
static unsigned int
Packit 78a954
print_char(FILE *f, pcre_uchar *ptr, BOOL utf)
Packit 78a954
{
Packit 78a954
pcre_uint32 c = *ptr;
Packit 78a954
Packit 78a954
#ifndef SUPPORT_UTF
Packit 78a954
Packit 78a954
(void)utf;  /* Avoid compiler warning */
Packit 78a954
if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
Packit 78a954
else if (c <= 0x80) fprintf(f, "\\x%02x", c);
Packit 78a954
else fprintf(f, "\\x{%x}", c);
Packit 78a954
return 0;
Packit 78a954
Packit 78a954
#else
Packit 78a954
Packit 78a954
#if defined COMPILE_PCRE8
Packit 78a954
Packit 78a954
if (!utf || (c & 0xc0) != 0xc0)
Packit 78a954
  {
Packit 78a954
  if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
Packit 78a954
  else if (c < 0x80) fprintf(f, "\\x%02x", c);
Packit 78a954
  else fprintf(f, "\\x{%02x}", c);
Packit 78a954
  return 0;
Packit 78a954
  }
Packit 78a954
else
Packit 78a954
  {
Packit 78a954
  int i;
Packit 78a954
  int a = PRIV(utf8_table4)[c & 0x3f];  /* Number of additional bytes */
Packit 78a954
  int s = 6*a;
Packit 78a954
  c = (c & PRIV(utf8_table3)[a]) << s;
Packit 78a954
  for (i = 1; i <= a; i++)
Packit 78a954
    {
Packit 78a954
    /* This is a check for malformed UTF-8; it should only occur if the sanity
Packit 78a954
    check has been turned off. Rather than swallow random bytes, just stop if
Packit 78a954
    we hit a bad one. Print it with \X instead of \x as an indication. */
Packit 78a954
Packit 78a954
    if ((ptr[i] & 0xc0) != 0x80)
Packit 78a954
      {
Packit 78a954
      fprintf(f, "\\X{%x}", c);
Packit 78a954
      return i - 1;
Packit 78a954
      }
Packit 78a954
Packit 78a954
    /* The byte is OK */
Packit 78a954
Packit 78a954
    s -= 6;
Packit 78a954
    c |= (ptr[i] & 0x3f) << s;
Packit 78a954
    }
Packit 78a954
  fprintf(f, "\\x{%x}", c);
Packit 78a954
  return a;
Packit 78a954
  }
Packit 78a954
Packit 78a954
#elif defined COMPILE_PCRE16
Packit 78a954
Packit 78a954
if (!utf || (c & 0xfc00) != 0xd800)
Packit 78a954
  {
Packit 78a954
  if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
Packit 78a954
  else if (c <= 0x80) fprintf(f, "\\x%02x", c);
Packit 78a954
  else fprintf(f, "\\x{%02x}", c);
Packit 78a954
  return 0;
Packit 78a954
  }
Packit 78a954
else
Packit 78a954
  {
Packit 78a954
  /* This is a check for malformed UTF-16; it should only occur if the sanity
Packit 78a954
  check has been turned off. Rather than swallow a low surrogate, just stop if
Packit 78a954
  we hit a bad one. Print it with \X instead of \x as an indication. */
Packit 78a954
Packit 78a954
  if ((ptr[1] & 0xfc00) != 0xdc00)
Packit 78a954
    {
Packit 78a954
    fprintf(f, "\\X{%x}", c);
Packit 78a954
    return 0;
Packit 78a954
    }
Packit 78a954
Packit 78a954
  c = (((c & 0x3ff) << 10) | (ptr[1] & 0x3ff)) + 0x10000;
Packit 78a954
  fprintf(f, "\\x{%x}", c);
Packit 78a954
  return 1;
Packit 78a954
  }
Packit 78a954
Packit 78a954
#elif defined COMPILE_PCRE32
Packit 78a954
Packit 78a954
if (!utf || (c & 0xfffff800u) != 0xd800u)
Packit 78a954
  {
Packit 78a954
  if (PRINTABLE(c)) fprintf(f, "%c", (char)c);
Packit 78a954
  else if (c <= 0x80) fprintf(f, "\\x%02x", c);
Packit 78a954
  else fprintf(f, "\\x{%x}", c);
Packit 78a954
  return 0;
Packit 78a954
  }
Packit 78a954
else
Packit 78a954
  {
Packit 78a954
  /* This is a check for malformed UTF-32; it should only occur if the sanity
Packit 78a954
  check has been turned off. Rather than swallow a surrogate, just stop if
Packit 78a954
  we hit one. Print it with \X instead of \x as an indication. */
Packit 78a954
  fprintf(f, "\\X{%x}", c);
Packit 78a954
  return 0;
Packit 78a954
  }
Packit 78a954
Packit 78a954
#endif /* COMPILE_PCRE[8|16|32] */
Packit 78a954
Packit 78a954
#endif /* SUPPORT_UTF */
Packit 78a954
}
Packit 78a954
Packit 78a954
/*************************************************
Packit 78a954
*  Print uchar string (regardless of utf)        *
Packit 78a954
*************************************************/
Packit 78a954
Packit 78a954
static void
Packit 78a954
print_puchar(FILE *f, PCRE_PUCHAR ptr)
Packit 78a954
{
Packit 78a954
while (*ptr != '\0')
Packit 78a954
  {
Packit 78a954
  register pcre_uint32 c = *ptr++;
Packit 78a954
  if (PRINTABLE(c)) fprintf(f, "%c", c); else fprintf(f, "\\x{%x}", c);
Packit 78a954
  }
Packit 78a954
}
Packit 78a954
Packit 78a954
/*************************************************
Packit 78a954
*          Find Unicode property name            *
Packit 78a954
*************************************************/
Packit 78a954
Packit 78a954
static const char *
Packit 78a954
get_ucpname(unsigned int ptype, unsigned int pvalue)
Packit 78a954
{
Packit 78a954
#ifdef SUPPORT_UCP
Packit 78a954
int i;
Packit 78a954
for (i = PRIV(utt_size) - 1; i >= 0; i--)
Packit 78a954
  {
Packit 78a954
  if (ptype == PRIV(utt)[i].type && pvalue == PRIV(utt)[i].value) break;
Packit 78a954
  }
Packit 78a954
return (i >= 0)? PRIV(utt_names) + PRIV(utt)[i].name_offset : "??";
Packit 78a954
#else
Packit 78a954
/* It gets harder and harder to shut off unwanted compiler warnings. */
Packit 78a954
ptype = ptype * pvalue;
Packit 78a954
return (ptype == pvalue)? "??" : "??";
Packit 78a954
#endif
Packit 78a954
}
Packit 78a954
Packit 78a954
Packit 78a954
/*************************************************
Packit 78a954
*       Print Unicode property value             *
Packit 78a954
*************************************************/
Packit 78a954
Packit 78a954
/* "Normal" properties can be printed from tables. The PT_CLIST property is a
Packit 78a954
pseudo-property that contains a pointer to a list of case-equivalent
Packit 78a954
characters. This is used only when UCP support is available and UTF mode is
Packit 78a954
selected. It should never occur otherwise, but just in case it does, have
Packit 78a954
something ready to print. */
Packit 78a954
Packit 78a954
static void
Packit 78a954
print_prop(FILE *f, pcre_uchar *code, const char *before, const char *after)
Packit 78a954
{
Packit 78a954
if (code[1] != PT_CLIST)
Packit 78a954
  {
Packit 78a954
  fprintf(f, "%s%s %s%s", before, priv_OP_names[*code], get_ucpname(code[1],
Packit 78a954
    code[2]), after);
Packit 78a954
  }
Packit 78a954
else
Packit 78a954
  {
Packit 78a954
  const char *not = (*code == OP_PROP)? "" : "not ";
Packit 78a954
#ifndef SUPPORT_UCP
Packit 78a954
  fprintf(f, "%s%sclist %d%s", before, not, code[2], after);
Packit 78a954
#else
Packit 78a954
  const pcre_uint32 *p = PRIV(ucd_caseless_sets) + code[2];
Packit 78a954
  fprintf (f, "%s%sclist", before, not);
Packit 78a954
  while (*p < NOTACHAR) fprintf(f, " %04x", *p++);
Packit 78a954
  fprintf(f, "%s", after);
Packit 78a954
#endif
Packit 78a954
  }
Packit 78a954
}
Packit 78a954
Packit 78a954
Packit 78a954
Packit 78a954
Packit 78a954
/*************************************************
Packit 78a954
*         Print compiled regex                   *
Packit 78a954
*************************************************/
Packit 78a954
Packit 78a954
/* Make this function work for a regex with integers either byte order.
Packit 78a954
However, we assume that what we are passed is a compiled regex. The
Packit 78a954
print_lengths flag controls whether offsets and lengths of items are printed.
Packit 78a954
They can be turned off from pcretest so that automatic tests on bytecode can be
Packit 78a954
written that do not depend on the value of LINK_SIZE. */
Packit 78a954
Packit 78a954
#ifdef PCRE_INCLUDED
Packit 78a954
static /* Keep the following function as private. */
Packit 78a954
#endif
Packit 78a954
#if defined COMPILE_PCRE8
Packit 78a954
void
Packit 78a954
pcre_printint(pcre *external_re, FILE *f, BOOL print_lengths)
Packit 78a954
#elif defined COMPILE_PCRE16
Packit 78a954
void
Packit 78a954
pcre16_printint(pcre *external_re, FILE *f, BOOL print_lengths)
Packit 78a954
#elif defined COMPILE_PCRE32
Packit 78a954
void
Packit 78a954
pcre32_printint(pcre *external_re, FILE *f, BOOL print_lengths)
Packit 78a954
#endif
Packit 78a954
{
Packit 78a954
REAL_PCRE *re = (REAL_PCRE *)external_re;
Packit 78a954
pcre_uchar *codestart, *code;
Packit 78a954
BOOL utf;
Packit 78a954
Packit 78a954
unsigned int options = re->options;
Packit 78a954
int offset = re->name_table_offset;
Packit 78a954
int count = re->name_count;
Packit 78a954
int size = re->name_entry_size;
Packit 78a954
Packit 78a954
if (re->magic_number != MAGIC_NUMBER)
Packit 78a954
  {
Packit 78a954
  offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff);
Packit 78a954
  count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff);
Packit 78a954
  size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff);
Packit 78a954
  options = ((options << 24) & 0xff000000) |
Packit 78a954
            ((options <<  8) & 0x00ff0000) |
Packit 78a954
            ((options >>  8) & 0x0000ff00) |
Packit 78a954
            ((options >> 24) & 0x000000ff);
Packit 78a954
  }
Packit 78a954
Packit 78a954
code = codestart = (pcre_uchar *)re + offset + count * size;
Packit 78a954
/* PCRE_UTF(16|32) have the same value as PCRE_UTF8. */
Packit 78a954
utf = (options & PCRE_UTF8) != 0;
Packit 78a954
Packit 78a954
for(;;)
Packit 78a954
  {
Packit 78a954
  pcre_uchar *ccode;
Packit 78a954
  const char *flag = "  ";
Packit 78a954
  pcre_uint32 c;
Packit 78a954
  unsigned int extra = 0;
Packit 78a954
Packit 78a954
  if (print_lengths)
Packit 78a954
    fprintf(f, "%3d ", (int)(code - codestart));
Packit 78a954
  else
Packit 78a954
    fprintf(f, "    ");
Packit 78a954
Packit 78a954
  switch(*code)
Packit 78a954
    {
Packit 78a954
/* ========================================================================== */
Packit 78a954
      /* These cases are never obeyed. This is a fudge that causes a compile-
Packit 78a954
      time error if the vectors OP_names or OP_lengths, which are indexed
Packit 78a954
      by opcode, are not the correct length. It seems to be the only way to do
Packit 78a954
      such a check at compile time, as the sizeof() operator does not work in
Packit 78a954
      the C preprocessor. */
Packit 78a954
Packit 78a954
      case OP_TABLE_LENGTH:
Packit 78a954
      case OP_TABLE_LENGTH +
Packit 78a954
        ((sizeof(priv_OP_names)/sizeof(const char *) == OP_TABLE_LENGTH) &&
Packit 78a954
        (sizeof(priv_OP_lengths) == OP_TABLE_LENGTH)):
Packit 78a954
      break;
Packit 78a954
/* ========================================================================== */
Packit 78a954
Packit 78a954
    case OP_END:
Packit 78a954
    fprintf(f, "    %s\n", priv_OP_names[*code]);
Packit 78a954
    fprintf(f, "------------------------------------------------------------------\n");
Packit 78a954
    return;
Packit 78a954
Packit 78a954
    case OP_CHAR:
Packit 78a954
    fprintf(f, "    ");
Packit 78a954
    do
Packit 78a954
      {
Packit 78a954
      code++;
Packit 78a954
      code += 1 + print_char(f, code, utf);
Packit 78a954
      }
Packit 78a954
    while (*code == OP_CHAR);
Packit 78a954
    fprintf(f, "\n");
Packit 78a954
    continue;
Packit 78a954
Packit 78a954
    case OP_CHARI:
Packit 78a954
    fprintf(f, " /i ");
Packit 78a954
    do
Packit 78a954
      {
Packit 78a954
      code++;
Packit 78a954
      code += 1 + print_char(f, code, utf);
Packit 78a954
      }
Packit 78a954
    while (*code == OP_CHARI);
Packit 78a954
    fprintf(f, "\n");
Packit 78a954
    continue;
Packit 78a954
Packit 78a954
    case OP_CBRA:
Packit 78a954
    case OP_CBRAPOS:
Packit 78a954
    case OP_SCBRA:
Packit 78a954
    case OP_SCBRAPOS:
Packit 78a954
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
Packit 78a954
      else fprintf(f, "    ");
Packit 78a954
    fprintf(f, "%s %d", priv_OP_names[*code], GET2(code, 1+LINK_SIZE));
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_BRA:
Packit 78a954
    case OP_BRAPOS:
Packit 78a954
    case OP_SBRA:
Packit 78a954
    case OP_SBRAPOS:
Packit 78a954
    case OP_KETRMAX:
Packit 78a954
    case OP_KETRMIN:
Packit 78a954
    case OP_KETRPOS:
Packit 78a954
    case OP_ALT:
Packit 78a954
    case OP_KET:
Packit 78a954
    case OP_ASSERT:
Packit 78a954
    case OP_ASSERT_NOT:
Packit 78a954
    case OP_ASSERTBACK:
Packit 78a954
    case OP_ASSERTBACK_NOT:
Packit 78a954
    case OP_ONCE:
Packit 78a954
    case OP_ONCE_NC:
Packit 78a954
    case OP_COND:
Packit 78a954
    case OP_SCOND:
Packit 78a954
    case OP_REVERSE:
Packit 78a954
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
Packit 78a954
      else fprintf(f, "    ");
Packit 78a954
    fprintf(f, "%s", priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_CLOSE:
Packit 78a954
    fprintf(f, "    %s %d", priv_OP_names[*code], GET2(code, 1));
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_CREF:
Packit 78a954
    fprintf(f, "%3d %s", GET2(code,1), priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_DNCREF:
Packit 78a954
      {
Packit 78a954
      pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) +
Packit 78a954
        IMM2_SIZE;
Packit 78a954
      fprintf(f, " %s Cond ref <", flag);
Packit 78a954
      print_puchar(f, entry);
Packit 78a954
      fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
Packit 78a954
      }
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_RREF:
Packit 78a954
    c = GET2(code, 1);
Packit 78a954
    if (c == RREF_ANY)
Packit 78a954
      fprintf(f, "    Cond recurse any");
Packit 78a954
    else
Packit 78a954
      fprintf(f, "    Cond recurse %d", c);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_DNRREF:
Packit 78a954
      {
Packit 78a954
      pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) +
Packit 78a954
        IMM2_SIZE;
Packit 78a954
      fprintf(f, " %s Cond recurse <", flag);
Packit 78a954
      print_puchar(f, entry);
Packit 78a954
      fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
Packit 78a954
      }
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_DEF:
Packit 78a954
    fprintf(f, "    Cond def");
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_STARI:
Packit 78a954
    case OP_MINSTARI:
Packit 78a954
    case OP_POSSTARI:
Packit 78a954
    case OP_PLUSI:
Packit 78a954
    case OP_MINPLUSI:
Packit 78a954
    case OP_POSPLUSI:
Packit 78a954
    case OP_QUERYI:
Packit 78a954
    case OP_MINQUERYI:
Packit 78a954
    case OP_POSQUERYI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
    case OP_STAR:
Packit 78a954
    case OP_MINSTAR:
Packit 78a954
    case OP_POSSTAR:
Packit 78a954
    case OP_PLUS:
Packit 78a954
    case OP_MINPLUS:
Packit 78a954
    case OP_POSPLUS:
Packit 78a954
    case OP_QUERY:
Packit 78a954
    case OP_MINQUERY:
Packit 78a954
    case OP_POSQUERY:
Packit 78a954
    case OP_TYPESTAR:
Packit 78a954
    case OP_TYPEMINSTAR:
Packit 78a954
    case OP_TYPEPOSSTAR:
Packit 78a954
    case OP_TYPEPLUS:
Packit 78a954
    case OP_TYPEMINPLUS:
Packit 78a954
    case OP_TYPEPOSPLUS:
Packit 78a954
    case OP_TYPEQUERY:
Packit 78a954
    case OP_TYPEMINQUERY:
Packit 78a954
    case OP_TYPEPOSQUERY:
Packit 78a954
    fprintf(f, " %s ", flag);
Packit 78a954
    if (*code >= OP_TYPESTAR)
Packit 78a954
      {
Packit 78a954
      if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
Packit 78a954
        {
Packit 78a954
        print_prop(f, code + 1, "", " ");
Packit 78a954
        extra = 2;
Packit 78a954
        }
Packit 78a954
      else fprintf(f, "%s", priv_OP_names[code[1]]);
Packit 78a954
      }
Packit 78a954
    else extra = print_char(f, code+1, utf);
Packit 78a954
    fprintf(f, "%s", priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_EXACTI:
Packit 78a954
    case OP_UPTOI:
Packit 78a954
    case OP_MINUPTOI:
Packit 78a954
    case OP_POSUPTOI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
    case OP_EXACT:
Packit 78a954
    case OP_UPTO:
Packit 78a954
    case OP_MINUPTO:
Packit 78a954
    case OP_POSUPTO:
Packit 78a954
    fprintf(f, " %s ", flag);
Packit 78a954
    extra = print_char(f, code + 1 + IMM2_SIZE, utf);
Packit 78a954
    fprintf(f, "{");
Packit 78a954
    if (*code != OP_EXACT && *code != OP_EXACTI) fprintf(f, "0,");
Packit 78a954
    fprintf(f, "%d}", GET2(code,1));
Packit 78a954
    if (*code == OP_MINUPTO || *code == OP_MINUPTOI) fprintf(f, "?");
Packit 78a954
      else if (*code == OP_POSUPTO || *code == OP_POSUPTOI) fprintf(f, "+");
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_TYPEEXACT:
Packit 78a954
    case OP_TYPEUPTO:
Packit 78a954
    case OP_TYPEMINUPTO:
Packit 78a954
    case OP_TYPEPOSUPTO:
Packit 78a954
    if (code[1 + IMM2_SIZE] == OP_PROP || code[1 + IMM2_SIZE] == OP_NOTPROP)
Packit 78a954
      {
Packit 78a954
      print_prop(f, code + IMM2_SIZE + 1, "    ", " ");
Packit 78a954
      extra = 2;
Packit 78a954
      }
Packit 78a954
    else fprintf(f, "    %s", priv_OP_names[code[1 + IMM2_SIZE]]);
Packit 78a954
    fprintf(f, "{");
Packit 78a954
    if (*code != OP_TYPEEXACT) fprintf(f, "0,");
Packit 78a954
    fprintf(f, "%d}", GET2(code,1));
Packit 78a954
    if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
Packit 78a954
      else if (*code == OP_TYPEPOSUPTO) fprintf(f, "+");
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_NOTI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
    case OP_NOT:
Packit 78a954
    fprintf(f, " %s [^", flag);
Packit 78a954
    extra = print_char(f, code + 1, utf);
Packit 78a954
    fprintf(f, "]");
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_NOTSTARI:
Packit 78a954
    case OP_NOTMINSTARI:
Packit 78a954
    case OP_NOTPOSSTARI:
Packit 78a954
    case OP_NOTPLUSI:
Packit 78a954
    case OP_NOTMINPLUSI:
Packit 78a954
    case OP_NOTPOSPLUSI:
Packit 78a954
    case OP_NOTQUERYI:
Packit 78a954
    case OP_NOTMINQUERYI:
Packit 78a954
    case OP_NOTPOSQUERYI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
Packit 78a954
    case OP_NOTSTAR:
Packit 78a954
    case OP_NOTMINSTAR:
Packit 78a954
    case OP_NOTPOSSTAR:
Packit 78a954
    case OP_NOTPLUS:
Packit 78a954
    case OP_NOTMINPLUS:
Packit 78a954
    case OP_NOTPOSPLUS:
Packit 78a954
    case OP_NOTQUERY:
Packit 78a954
    case OP_NOTMINQUERY:
Packit 78a954
    case OP_NOTPOSQUERY:
Packit 78a954
    fprintf(f, " %s [^", flag);
Packit 78a954
    extra = print_char(f, code + 1, utf);
Packit 78a954
    fprintf(f, "]%s", priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_NOTEXACTI:
Packit 78a954
    case OP_NOTUPTOI:
Packit 78a954
    case OP_NOTMINUPTOI:
Packit 78a954
    case OP_NOTPOSUPTOI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
Packit 78a954
    case OP_NOTEXACT:
Packit 78a954
    case OP_NOTUPTO:
Packit 78a954
    case OP_NOTMINUPTO:
Packit 78a954
    case OP_NOTPOSUPTO:
Packit 78a954
    fprintf(f, " %s [^", flag);
Packit 78a954
    extra = print_char(f, code + 1 + IMM2_SIZE, utf);
Packit 78a954
    fprintf(f, "]{");
Packit 78a954
    if (*code != OP_NOTEXACT && *code != OP_NOTEXACTI) fprintf(f, "0,");
Packit 78a954
    fprintf(f, "%d}", GET2(code,1));
Packit 78a954
    if (*code == OP_NOTMINUPTO || *code == OP_NOTMINUPTOI) fprintf(f, "?");
Packit 78a954
      else
Packit 78a954
    if (*code == OP_NOTPOSUPTO || *code == OP_NOTPOSUPTOI) fprintf(f, "+");
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_RECURSE:
Packit 78a954
    if (print_lengths) fprintf(f, "%3d ", GET(code, 1));
Packit 78a954
      else fprintf(f, "    ");
Packit 78a954
    fprintf(f, "%s", priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_REFI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
    case OP_REF:
Packit 78a954
    fprintf(f, " %s \\%d", flag, GET2(code,1));
Packit 78a954
    ccode = code + priv_OP_lengths[*code];
Packit 78a954
    goto CLASS_REF_REPEAT;
Packit 78a954
Packit 78a954
    case OP_DNREFI:
Packit 78a954
    flag = "/i";
Packit 78a954
    /* Fall through */
Packit 78a954
    case OP_DNREF:
Packit 78a954
      {
Packit 78a954
      pcre_uchar *entry = (pcre_uchar *)re + offset + (GET2(code, 1) * size) +
Packit 78a954
        IMM2_SIZE;
Packit 78a954
      fprintf(f, " %s \\k<", flag);
Packit 78a954
      print_puchar(f, entry);
Packit 78a954
      fprintf(f, ">%d", GET2(code, 1 + IMM2_SIZE));
Packit 78a954
      }
Packit 78a954
    ccode = code + priv_OP_lengths[*code];
Packit 78a954
    goto CLASS_REF_REPEAT;
Packit 78a954
Packit 78a954
    case OP_CALLOUT:
Packit 78a954
    fprintf(f, "    %s %d %d %d", priv_OP_names[*code], code[1], GET(code,2),
Packit 78a954
      GET(code, 2 + LINK_SIZE));
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_PROP:
Packit 78a954
    case OP_NOTPROP:
Packit 78a954
    print_prop(f, code, "    ", "");
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    /* OP_XCLASS cannot occur in 8-bit, non-UTF mode. However, there's no harm
Packit 78a954
    in having this code always here, and it makes it less messy without all
Packit 78a954
    those #ifdefs. */
Packit 78a954
Packit 78a954
    case OP_CLASS:
Packit 78a954
    case OP_NCLASS:
Packit 78a954
    case OP_XCLASS:
Packit 78a954
      {
Packit 78a954
      int i;
Packit 78a954
      unsigned int min, max;
Packit 78a954
      BOOL printmap;
Packit 78a954
      BOOL invertmap = FALSE;
Packit 78a954
      pcre_uint8 *map;
Packit 78a954
      pcre_uint8 inverted_map[32];
Packit 78a954
Packit 78a954
      fprintf(f, "    [");
Packit 78a954
Packit 78a954
      if (*code == OP_XCLASS)
Packit 78a954
        {
Packit 78a954
        extra = GET(code, 1);
Packit 78a954
        ccode = code + LINK_SIZE + 1;
Packit 78a954
        printmap = (*ccode & XCL_MAP) != 0;
Packit 78a954
        if ((*ccode & XCL_NOT) != 0)
Packit 78a954
          {
Packit 78a954
          invertmap = (*ccode & XCL_HASPROP) == 0;
Packit 78a954
          fprintf(f, "^");
Packit 78a954
          }
Packit 78a954
        ccode++;
Packit 78a954
        }
Packit 78a954
      else
Packit 78a954
        {
Packit 78a954
        printmap = TRUE;
Packit 78a954
        ccode = code + 1;
Packit 78a954
        }
Packit 78a954
Packit 78a954
      /* Print a bit map */
Packit 78a954
Packit 78a954
      if (printmap)
Packit 78a954
        {
Packit 78a954
        map = (pcre_uint8 *)ccode;
Packit 78a954
        if (invertmap)
Packit 78a954
          {
Packit 78a954
          for (i = 0; i < 32; i++) inverted_map[i] = ~map[i];
Packit 78a954
          map = inverted_map;
Packit 78a954
          }
Packit 78a954
Packit 78a954
        for (i = 0; i < 256; i++)
Packit 78a954
          {
Packit 78a954
          if ((map[i/8] & (1 << (i&7))) != 0)
Packit 78a954
            {
Packit 78a954
            int j;
Packit 78a954
            for (j = i+1; j < 256; j++)
Packit 78a954
              if ((map[j/8] & (1 << (j&7))) == 0) break;
Packit 78a954
            if (i == '-' || i == ']') fprintf(f, "\\");
Packit 78a954
            if (PRINTABLE(i)) fprintf(f, "%c", i);
Packit 78a954
              else fprintf(f, "\\x%02x", i);
Packit 78a954
            if (--j > i)
Packit 78a954
              {
Packit 78a954
              if (j != i + 1) fprintf(f, "-");
Packit 78a954
              if (j == '-' || j == ']') fprintf(f, "\\");
Packit 78a954
              if (PRINTABLE(j)) fprintf(f, "%c", j);
Packit 78a954
                else fprintf(f, "\\x%02x", j);
Packit 78a954
              }
Packit 78a954
            i = j;
Packit 78a954
            }
Packit 78a954
          }
Packit 78a954
        ccode += 32 / sizeof(pcre_uchar);
Packit 78a954
        }
Packit 78a954
Packit 78a954
      /* For an XCLASS there is always some additional data */
Packit 78a954
Packit 78a954
      if (*code == OP_XCLASS)
Packit 78a954
        {
Packit 78a954
        pcre_uchar ch;
Packit 78a954
        while ((ch = *ccode++) != XCL_END)
Packit 78a954
          {
Packit 78a954
          BOOL not = FALSE;
Packit 78a954
          const char *notch = "";
Packit 78a954
Packit 78a954
          switch(ch)
Packit 78a954
            {
Packit 78a954
            case XCL_NOTPROP:
Packit 78a954
            not = TRUE;
Packit 78a954
            notch = "^";
Packit 78a954
            /* Fall through */
Packit 78a954
Packit 78a954
            case XCL_PROP:
Packit 78a954
              {
Packit 78a954
              unsigned int ptype = *ccode++;
Packit 78a954
              unsigned int pvalue = *ccode++;
Packit 78a954
Packit 78a954
              switch(ptype)
Packit 78a954
                {
Packit 78a954
                case PT_PXGRAPH:
Packit 78a954
                fprintf(f, "[:%sgraph:]", notch);
Packit 78a954
                break;
Packit 78a954
Packit 78a954
                case PT_PXPRINT:
Packit 78a954
                fprintf(f, "[:%sprint:]", notch);
Packit 78a954
                break;
Packit 78a954
Packit 78a954
                case PT_PXPUNCT:
Packit 78a954
                fprintf(f, "[:%spunct:]", notch);
Packit 78a954
                break;
Packit 78a954
Packit 78a954
                default:
Packit 78a954
                fprintf(f, "\\%c{%s}", (not? 'P':'p'),
Packit 78a954
                  get_ucpname(ptype, pvalue));
Packit 78a954
                break;
Packit 78a954
                }
Packit 78a954
              }
Packit 78a954
            break;
Packit 78a954
Packit 78a954
            default:
Packit 78a954
            ccode += 1 + print_char(f, ccode, utf);
Packit 78a954
            if (ch == XCL_RANGE)
Packit 78a954
              {
Packit 78a954
              fprintf(f, "-");
Packit 78a954
              ccode += 1 + print_char(f, ccode, utf);
Packit 78a954
              }
Packit 78a954
            break;
Packit 78a954
            }
Packit 78a954
          }
Packit 78a954
        }
Packit 78a954
Packit 78a954
      /* Indicate a non-UTF class which was created by negation */
Packit 78a954
Packit 78a954
      fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");
Packit 78a954
Packit 78a954
      /* Handle repeats after a class or a back reference */
Packit 78a954
Packit 78a954
      CLASS_REF_REPEAT:
Packit 78a954
      switch(*ccode)
Packit 78a954
        {
Packit 78a954
        case OP_CRSTAR:
Packit 78a954
        case OP_CRMINSTAR:
Packit 78a954
        case OP_CRPLUS:
Packit 78a954
        case OP_CRMINPLUS:
Packit 78a954
        case OP_CRQUERY:
Packit 78a954
        case OP_CRMINQUERY:
Packit 78a954
        case OP_CRPOSSTAR:
Packit 78a954
        case OP_CRPOSPLUS:
Packit 78a954
        case OP_CRPOSQUERY:
Packit 78a954
        fprintf(f, "%s", priv_OP_names[*ccode]);
Packit 78a954
        extra += priv_OP_lengths[*ccode];
Packit 78a954
        break;
Packit 78a954
Packit 78a954
        case OP_CRRANGE:
Packit 78a954
        case OP_CRMINRANGE:
Packit 78a954
        case OP_CRPOSRANGE:
Packit 78a954
        min = GET2(ccode,1);
Packit 78a954
        max = GET2(ccode,1 + IMM2_SIZE);
Packit 78a954
        if (max == 0) fprintf(f, "{%u,}", min);
Packit 78a954
        else fprintf(f, "{%u,%u}", min, max);
Packit 78a954
        if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
Packit 78a954
        else if (*ccode == OP_CRPOSRANGE) fprintf(f, "+");
Packit 78a954
        extra += priv_OP_lengths[*ccode];
Packit 78a954
        break;
Packit 78a954
Packit 78a954
        /* Do nothing if it's not a repeat; this code stops picky compilers
Packit 78a954
        warning about the lack of a default code path. */
Packit 78a954
Packit 78a954
        default:
Packit 78a954
        break;
Packit 78a954
        }
Packit 78a954
      }
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_MARK:
Packit 78a954
    case OP_PRUNE_ARG:
Packit 78a954
    case OP_SKIP_ARG:
Packit 78a954
    case OP_THEN_ARG:
Packit 78a954
    fprintf(f, "    %s ", priv_OP_names[*code]);
Packit 78a954
    print_puchar(f, code + 2);
Packit 78a954
    extra += code[1];
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_THEN:
Packit 78a954
    fprintf(f, "    %s", priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
Packit 78a954
    case OP_CIRCM:
Packit 78a954
    case OP_DOLLM:
Packit 78a954
    flag = "/m";
Packit 78a954
    /* Fall through */
Packit 78a954
Packit 78a954
    /* Anything else is just an item with no data, but possibly a flag. */
Packit 78a954
Packit 78a954
    default:
Packit 78a954
    fprintf(f, " %s %s", flag, priv_OP_names[*code]);
Packit 78a954
    break;
Packit 78a954
    }
Packit 78a954
Packit 78a954
  code += priv_OP_lengths[*code] + extra;
Packit 78a954
  fprintf(f, "\n");
Packit 78a954
  }
Packit 78a954
}
Packit 78a954
Packit 78a954
/* End of pcre_printint.src */