bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / tomcat-connectors-1.2.32-src / native / iis / pcre / printint.c
1 /*************************************************
2 *      Perl-Compatible Regular Expressions       *
3 *************************************************/
4
5 /*
6 This is a library of functions to support regular expressions whose syntax
7 and semantics are as close as possible to those of the Perl 5 language. See
8 the file Tech.Notes for some information on the internals.
9
10 Written by: Philip Hazel <ph10@cam.ac.uk>
11
12            Copyright (c) 1997-2004 University of Cambridge
13
14 -----------------------------------------------------------------------------
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions are met:
17
18     * Redistributions of source code must retain the above copyright notice,
19       this list of conditions and the following disclaimer.
20
21     * Redistributions in binary form must reproduce the above copyright
22       notice, this list of conditions and the following disclaimer in the
23       documentation and/or other materials provided with the distribution.
24
25     * Neither the name of the University of Cambridge nor the names of its
26       contributors may be used to endorse or promote products derived from
27       this software without specific prior written permission.
28
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
40 -----------------------------------------------------------------------------
41 */
42
43
44 /* This module contains a debugging function for printing out the internal form
45 of a compiled regular expression. It is kept in a separate file so that it can
46 be #included both in the pcretest program, and in the library itself when
47 compiled with the debugging switch. */
48
49
50 static const char *OP_names[] = { OP_NAME_LIST };
51
52
53 /*************************************************
54 *       Print single- or multi-byte character    *
55 *************************************************/
56
57 /* These tables are actually copies of ones in pcre.c. If we compile the
58 library with debugging, they are included twice, but that isn't really a
59 problem - compiling with debugging is pretty rare and these are very small. */
60
61 static const int utf8_t3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
62
63 static const uschar utf8_t4[] = {
64   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
65   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
66   2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
67   3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
68
69 static int
70 print_char(FILE *f, uschar *ptr, BOOL utf8)
71 {
72 int c = *ptr;
73
74 if (!utf8 || (c & 0xc0) != 0xc0)
75   {
76   if (isprint(c)) fprintf(f, "%c", c); else fprintf(f, "\\x%02x", c);
77   return 0;
78   }
79 else
80   {
81   int i;
82   int a = utf8_t4[c & 0x3f];  /* Number of additional bytes */
83   int s = 6*a;
84   c = (c & utf8_t3[a]) << s;
85   for (i = 1; i <= a; i++)
86     {
87     /* This is a check for malformed UTF-8; it should only occur if the sanity
88     check has been turned off. Rather than swallow random bytes, just stop if
89     we hit a bad one. Print it with \X instead of \x as an indication. */
90
91     if ((ptr[i] & 0xc0) != 0x80)
92       {
93       fprintf(f, "\\X{%x}", c);
94       return i - 1;
95       }
96
97     /* The byte is OK */
98
99     s -= 6;
100     c |= (ptr[i] & 0x3f) << s;
101     }
102   if (c < 128) fprintf(f, "\\x%02x", c); else fprintf(f, "\\x{%x}", c);
103   return a;
104   }
105 }
106
107
108
109
110 #ifdef SUPPORT_UCP
111 /*************************************************
112 *          Find Unicode property name            *
113 *************************************************/
114
115 static const char *
116 get_ucpname(int property)
117 {
118 int i;
119 for (i = sizeof(utt)/sizeof(ucp_type_table); i >= 0; i--)
120   {
121   if (property == utt[i].value) break;
122   }
123 return (i >= 0)? utt[i].name : "??";
124 }
125 #endif /* SUPPORT_UCP */
126
127
128
129 /*************************************************
130 *         Print compiled regex                   *
131 *************************************************/
132
133 /* Make this function work for a regex with integers either byte order.
134 However, we assume that what we are passed is a compiled regex. */
135
136 static void
137 print_internals(pcre *external_re, FILE *f)
138 {
139 real_pcre *re = (real_pcre *)external_re;
140 uschar *codestart, *code;
141 BOOL utf8;
142
143 unsigned int options = re->options;
144 int offset = re->name_table_offset;
145 int count = re->name_count;
146 int size = re->name_entry_size;
147
148 if (re->magic_number != MAGIC_NUMBER)
149   {
150   offset = ((offset << 8) & 0xff00) | ((offset >> 8) & 0xff);
151   count = ((count << 8) & 0xff00) | ((count >> 8) & 0xff);
152   size = ((size << 8) & 0xff00) | ((size >> 8) & 0xff);
153   options = ((options << 24) & 0xff000000) |
154             ((options <<  8) & 0x00ff0000) |
155             ((options >>  8) & 0x0000ff00) |
156             ((options >> 24) & 0x000000ff);
157   }
158
159 code = codestart = (uschar *)re + offset + count * size;
160 utf8 = (options & PCRE_UTF8) != 0;
161
162 for(;;)
163   {
164   uschar *ccode;
165   int c;
166   int extra = 0;
167
168   fprintf(f, "%3d ", code - codestart);
169
170   if (*code >= OP_BRA)
171     {
172     if (*code - OP_BRA > EXTRACT_BASIC_MAX)
173       fprintf(f, "%3d Bra extra\n", GET(code, 1));
174     else
175       fprintf(f, "%3d Bra %d\n", GET(code, 1), *code - OP_BRA);
176     code += OP_lengths[OP_BRA];
177     continue;
178     }
179
180   switch(*code)
181     {
182     case OP_END:
183     fprintf(f, "    %s\n", OP_names[*code]);
184     fprintf(f, "------------------------------------------------------------------\n");
185     return;
186
187     case OP_OPT:
188     fprintf(f, " %.2x %s", code[1], OP_names[*code]);
189     break;
190
191     case OP_CHAR:
192       {
193       fprintf(f, "    ");
194       do
195         {
196         code++;
197         code += 1 + print_char(f, code, utf8);
198         }
199       while (*code == OP_CHAR);
200       fprintf(f, "\n");
201       continue;
202       }
203     break;
204
205     case OP_CHARNC:
206       {
207       fprintf(f, " NC ");
208       do
209         {
210         code++;
211         code += 1 + print_char(f, code, utf8);
212         }
213       while (*code == OP_CHARNC);
214       fprintf(f, "\n");
215       continue;
216       }
217     break;
218
219     case OP_KETRMAX:
220     case OP_KETRMIN:
221     case OP_ALT:
222     case OP_KET:
223     case OP_ASSERT:
224     case OP_ASSERT_NOT:
225     case OP_ASSERTBACK:
226     case OP_ASSERTBACK_NOT:
227     case OP_ONCE:
228     case OP_COND:
229     case OP_REVERSE:
230     fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]);
231     break;
232
233     case OP_BRANUMBER:
234     printf("%3d %s", GET2(code, 1), OP_names[*code]);
235     break;
236
237     case OP_CREF:
238     if (GET2(code, 1) == CREF_RECURSE)
239       fprintf(f, "    Cond recurse");
240     else
241       fprintf(f, "%3d %s", GET2(code,1), OP_names[*code]);
242     break;
243
244     case OP_STAR:
245     case OP_MINSTAR:
246     case OP_PLUS:
247     case OP_MINPLUS:
248     case OP_QUERY:
249     case OP_MINQUERY:
250     case OP_TYPESTAR:
251     case OP_TYPEMINSTAR:
252     case OP_TYPEPLUS:
253     case OP_TYPEMINPLUS:
254     case OP_TYPEQUERY:
255     case OP_TYPEMINQUERY:
256     fprintf(f, "    ");
257     if (*code >= OP_TYPESTAR)
258       {
259       fprintf(f, "%s", OP_names[code[1]]);
260 #ifdef SUPPORT_UCP
261       if (code[1] == OP_PROP || code[1] == OP_NOTPROP)
262         {
263         fprintf(f, " %s ", get_ucpname(code[2]));
264         extra = 1;
265         }
266 #endif
267       }
268     else extra = print_char(f, code+1, utf8);
269     fprintf(f, "%s", OP_names[*code]);
270     break;
271
272     case OP_EXACT:
273     case OP_UPTO:
274     case OP_MINUPTO:
275     fprintf(f, "    ");
276     extra = print_char(f, code+3, utf8);
277     fprintf(f, "{");
278     if (*code != OP_EXACT) fprintf(f, ",");
279     fprintf(f, "%d}", GET2(code,1));
280     if (*code == OP_MINUPTO) fprintf(f, "?");
281     break;
282
283     case OP_TYPEEXACT:
284     case OP_TYPEUPTO:
285     case OP_TYPEMINUPTO:
286     fprintf(f, "    %s", OP_names[code[3]]);
287 #ifdef SUPPORT_UCP
288     if (code[3] == OP_PROP || code[3] == OP_NOTPROP)
289       {
290       fprintf(f, " %s ", get_ucpname(code[4]));
291       extra = 1;
292       }
293 #endif
294     fprintf(f, "{");
295     if (*code != OP_TYPEEXACT) fprintf(f, "0,");
296     fprintf(f, "%d}", GET2(code,1));
297     if (*code == OP_TYPEMINUPTO) fprintf(f, "?");
298     break;
299
300     case OP_NOT:
301     if (isprint(c = code[1])) fprintf(f, "    [^%c]", c);
302       else fprintf(f, "    [^\\x%02x]", c);
303     break;
304
305     case OP_NOTSTAR:
306     case OP_NOTMINSTAR:
307     case OP_NOTPLUS:
308     case OP_NOTMINPLUS:
309     case OP_NOTQUERY:
310     case OP_NOTMINQUERY:
311     if (isprint(c = code[1])) fprintf(f, "    [^%c]", c);
312       else fprintf(f, "    [^\\x%02x]", c);
313     fprintf(f, "%s", OP_names[*code]);
314     break;
315
316     case OP_NOTEXACT:
317     case OP_NOTUPTO:
318     case OP_NOTMINUPTO:
319     if (isprint(c = code[3])) fprintf(f, "    [^%c]{", c);
320       else fprintf(f, "    [^\\x%02x]{", c);
321     if (*code != OP_NOTEXACT) fprintf(f, ",");
322     fprintf(f, "%d}", GET2(code,1));
323     if (*code == OP_NOTMINUPTO) fprintf(f, "?");
324     break;
325
326     case OP_RECURSE:
327     fprintf(f, "%3d %s", GET(code, 1), OP_names[*code]);
328     break;
329
330     case OP_REF:
331     fprintf(f, "    \\%d", GET2(code,1));
332     ccode = code + OP_lengths[*code];
333     goto CLASS_REF_REPEAT;
334
335     case OP_CALLOUT:
336     fprintf(f, "    %s %d %d %d", OP_names[*code], code[1], GET(code,2),
337       GET(code, 2 + LINK_SIZE));
338     break;
339
340 #ifdef SUPPORT_UCP
341     case OP_PROP:
342     case OP_NOTPROP:
343     fprintf(f, "    %s %s", OP_names[*code], get_ucpname(code[1]));
344     break;
345 #endif
346
347     /* OP_XCLASS can only occur in UTF-8 mode. However, there's no harm in
348     having this code always here, and it makes it less messy without all those
349     #ifdefs. */
350
351     case OP_CLASS:
352     case OP_NCLASS:
353     case OP_XCLASS:
354       {
355       int i, min, max;
356       BOOL printmap;
357
358       fprintf(f, "    [");
359
360       if (*code == OP_XCLASS)
361         {
362         extra = GET(code, 1);
363         ccode = code + LINK_SIZE + 1;
364         printmap = (*ccode & XCL_MAP) != 0;
365         if ((*ccode++ & XCL_NOT) != 0) fprintf(f, "^");
366         }
367       else
368         {
369         printmap = TRUE;
370         ccode = code + 1;
371         }
372
373       /* Print a bit map */
374
375       if (printmap)
376         {
377         for (i = 0; i < 256; i++)
378           {
379           if ((ccode[i/8] & (1 << (i&7))) != 0)
380             {
381             int j;
382             for (j = i+1; j < 256; j++)
383               if ((ccode[j/8] & (1 << (j&7))) == 0) break;
384             if (i == '-' || i == ']') fprintf(f, "\\");
385             if (isprint(i)) fprintf(f, "%c", i); else fprintf(f, "\\x%02x", i);
386             if (--j > i)
387               {
388               if (j != i + 1) fprintf(f, "-");
389               if (j == '-' || j == ']') fprintf(f, "\\");
390               if (isprint(j)) fprintf(f, "%c", j); else fprintf(f, "\\x%02x", j);
391               }
392             i = j;
393             }
394           }
395         ccode += 32;
396         }
397
398       /* For an XCLASS there is always some additional data */
399
400       if (*code == OP_XCLASS)
401         {
402         int ch;
403         while ((ch = *ccode++) != XCL_END)
404           {
405 #ifdef SUPPORT_UCP
406           if (ch == XCL_PROP)
407             {
408             fprintf(f, "\\p{%s}", get_ucpname(*ccode++));
409             }
410           else if (ch == XCL_NOTPROP)
411             {
412             fprintf(f, "\\P{%s}", get_ucpname(*ccode++));
413             }
414           else
415 #endif
416             {
417             ccode += 1 + print_char(f, ccode, TRUE);
418             if (ch == XCL_RANGE)
419               {
420               fprintf(f, "-");
421               ccode += 1 + print_char(f, ccode, TRUE);
422               }
423             }
424           }
425         }
426
427       /* Indicate a non-UTF8 class which was created by negation */
428
429       fprintf(f, "]%s", (*code == OP_NCLASS)? " (neg)" : "");
430
431       /* Handle repeats after a class or a back reference */
432
433       CLASS_REF_REPEAT:
434       switch(*ccode)
435         {
436         case OP_CRSTAR:
437         case OP_CRMINSTAR:
438         case OP_CRPLUS:
439         case OP_CRMINPLUS:
440         case OP_CRQUERY:
441         case OP_CRMINQUERY:
442         fprintf(f, "%s", OP_names[*ccode]);
443         extra += OP_lengths[*ccode];
444         break;
445
446         case OP_CRRANGE:
447         case OP_CRMINRANGE:
448         min = GET2(ccode,1);
449         max = GET2(ccode,3);
450         if (max == 0) fprintf(f, "{%d,}", min);
451         else fprintf(f, "{%d,%d}", min, max);
452         if (*ccode == OP_CRMINRANGE) fprintf(f, "?");
453         extra += OP_lengths[*ccode];
454         break;
455         }
456       }
457     break;
458
459     /* Anything else is just an item with no data*/
460
461     default:
462     fprintf(f, "    %s", OP_names[*code]);
463     break;
464     }
465
466   code += OP_lengths[*code] + extra;
467   fprintf(f, "\n");
468   }
469 }
470
471 /* End of printint.c */