1 /*************************************************
2 * Perl-Compatible Regular Expressions *
3 *************************************************/
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.
10 Written by: Philip Hazel <ph10@cam.ac.uk>
12 Copyright (c) 1997-2000 University of Cambridge
14 -----------------------------------------------------------------------------
15 Permission is granted to anyone to use this software for any purpose on any
16 computer system, and to redistribute it freely, subject to the following
19 1. This software is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 2. The origin of this software must not be misrepresented, either by
24 explicit claim or by omission.
26 3. Altered versions must be plainly marked as such, and must not be
27 misrepresented as being the original software.
29 4. If PCRE is embedded in any software that is released under the GNU
30 General Purpose Licence (GPL), then the terms of that licence shall
31 supersede any condition above with which it is incompatible.
32 -----------------------------------------------------------------------------
36 /* Include the internals header, which itself includes Standard C headers plus
37 the external pcre header. */
43 /*************************************************
44 * Set a bit and maybe its alternate case *
45 *************************************************/
47 /* Given a character, set its bit in the table, and also the bit for the other
48 version of a letter if we are caseless.
51 start_bits points to the bit map
53 caseless the caseless flag
54 cd the block with char table pointers
60 set_bit(uschar *start_bits, int c, BOOL caseless, compile_data *cd)
62 start_bits[c/8] |= (1 << (c&7));
63 if (caseless && (cd->ctypes[c] & ctype_letter) != 0)
64 start_bits[cd->fcc[c]/8] |= (1 << (cd->fcc[c]&7));
69 /*************************************************
70 * Create bitmap of starting chars *
71 *************************************************/
73 /* This function scans a compiled unanchored expression and attempts to build a
74 bitmap of the set of initial characters. If it can't, it returns FALSE. As time
75 goes by, we may be able to get more clever at doing this.
78 code points to an expression
79 start_bits points to a 32-byte table, initialized to 0
80 caseless the current state of the caseless flag
81 cd the block with char table pointers
83 Returns: TRUE if table built, FALSE otherwise
87 set_start_bits(const uschar *code, uschar *start_bits, BOOL caseless,
92 /* This next statement and the later reference to dummy are here in order to
93 trick the optimizer of the IBM C compiler for OS/2 into generating correct
94 code. Apparently IBM isn't going to fix the problem, and we would rather not
95 disable optimization (in this module it actually makes a big difference, and
96 the pcre module can use all the optimization it can get). */
102 const uschar *tcode = code + 3;
103 BOOL try_next = TRUE;
109 /* If a branch starts with a bracket or a positive lookahead assertion,
110 recurse to set bits from within them. That's all for this branch. */
112 if ((int)*tcode >= OP_BRA || *tcode == OP_ASSERT)
114 if (!set_start_bits(tcode, start_bits, caseless, cd))
123 /* Skip over lookbehind and negative lookahead assertions */
127 case OP_ASSERTBACK_NOT:
129 do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT);
133 /* Skip over an option setting, changing the caseless flag */
136 caseless = (tcode[1] & PCRE_CASELESS) != 0;
141 /* BRAZERO does the bracket, but carries on. */
145 if (!set_start_bits(++tcode, start_bits, caseless, cd))
148 do tcode += (tcode[1] << 8) + tcode[2]; while (*tcode == OP_ALT);
153 /* Single-char * or ? sets the bit and tries the next item */
159 set_bit(start_bits, tcode[1], caseless, cd);
164 /* Single-char upto sets the bit and tries the next */
168 set_bit(start_bits, tcode[3], caseless, cd);
173 /* At least one single char sets the bit and stops */
175 case OP_EXACT: /* Fall through */
178 case OP_CHARS: /* Fall through */
183 set_bit(start_bits, tcode[1], caseless, cd);
186 /* Single character type sets the bits and stops */
189 for (c = 0; c < 32; c++)
190 start_bits[c] |= ~cd->cbits[c+cbit_digit];
194 for (c = 0; c < 32; c++)
195 start_bits[c] |= cd->cbits[c+cbit_digit];
198 case OP_NOT_WHITESPACE:
199 for (c = 0; c < 32; c++)
200 start_bits[c] |= ~cd->cbits[c+cbit_space];
204 for (c = 0; c < 32; c++)
205 start_bits[c] |= cd->cbits[c+cbit_space];
208 case OP_NOT_WORDCHAR:
209 for (c = 0; c < 32; c++)
210 start_bits[c] |= ~cd->cbits[c+cbit_word];
214 for (c = 0; c < 32; c++)
215 start_bits[c] |= cd->cbits[c+cbit_word];
218 /* One or more character type fudges the pointer and restarts, knowing
219 it will hit a single character type and stop there. */
232 /* Zero or more repeats of character types set the bits and then
237 tcode += 2; /* Fall through */
242 case OP_TYPEMINQUERY:
246 for (c = 0; c < 32; c++)
247 start_bits[c] |= ~cd->cbits[c+cbit_digit];
251 for (c = 0; c < 32; c++)
252 start_bits[c] |= cd->cbits[c+cbit_digit];
255 case OP_NOT_WHITESPACE:
256 for (c = 0; c < 32; c++)
257 start_bits[c] |= ~cd->cbits[c+cbit_space];
261 for (c = 0; c < 32; c++)
262 start_bits[c] |= cd->cbits[c+cbit_space];
265 case OP_NOT_WORDCHAR:
266 for (c = 0; c < 32; c++)
267 start_bits[c] |= ~cd->cbits[c+cbit_word];
271 for (c = 0; c < 32; c++)
272 start_bits[c] |= cd->cbits[c+cbit_word];
280 /* Character class: set the bits and either carry on or not,
281 according to the repeat count. */
286 for (c = 0; c < 32; c++) start_bits[c] |= tcode[c];
300 if (((tcode[1] << 8) + tcode[2]) == 0)
308 break; /* End of class handling */
310 } /* End of switch */
311 } /* End of try_next loop */
313 code += (code[1] << 8) + code[2]; /* Advance to next branch */
315 while (*code == OP_ALT);
321 /*************************************************
322 * Study a compiled expression *
323 *************************************************/
325 /* This function is handed a compiled expression that it must study to produce
326 information that will speed up the matching. It returns a pcre_extra block
327 which then gets handed back to pcre_exec().
330 re points to the compiled expression
331 options contains option bits
332 errorptr points to where to place error messages;
333 set NULL unless error
335 Returns: pointer to a pcre_extra block,
336 NULL on error or if no optimization possible
340 pcre_study(const pcre *external_re, int options, const char **errorptr)
342 uschar start_bits[32];
343 real_pcre_extra *extra;
344 const real_pcre *re = (const real_pcre *)external_re;
345 compile_data compile_block;
349 if (re == NULL || re->magic_number != MAGIC_NUMBER)
351 *errorptr = "argument is not a compiled regular expression";
355 if ((options & ~PUBLIC_STUDY_OPTIONS) != 0)
357 *errorptr = "unknown or incorrect option bit(s) set";
361 /* For an anchored pattern, or an unchored pattern that has a first char, or a
362 multiline pattern that matches only at "line starts", no further processing at
365 if ((re->options & (PCRE_ANCHORED|PCRE_FIRSTSET|PCRE_STARTLINE)) != 0)
368 /* Set the character tables in the block which is passed around */
370 compile_block.lcc = re->tables + lcc_offset;
371 compile_block.fcc = re->tables + fcc_offset;
372 compile_block.cbits = re->tables + cbits_offset;
373 compile_block.ctypes = re->tables + ctypes_offset;
375 /* See if we can find a fixed set of initial characters for the pattern. */
377 memset(start_bits, 0, 32 * sizeof(uschar));
378 if (!set_start_bits(re->code, start_bits, (re->options & PCRE_CASELESS) != 0,
379 &compile_block)) return NULL;
381 /* Get an "extra" block and put the information therein. */
383 extra = (real_pcre_extra *)(pcre_malloc)(sizeof(real_pcre_extra));
387 *errorptr = "failed to get memory";
391 extra->options = PCRE_STUDY_MAPPED;
392 memcpy(extra->start_bits, start_bits, sizeof(start_bits));
394 return (pcre_extra *)extra;