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