+ /* Throw away the ] at the end of the character
+ class. */
+ PATFETCH (c);
+
+ if (p == pend) FREE_STACK_RETURN (REG_EBRACK);
+
+ /* Most character classes in a multibyte match
+ just set a flag. Exceptions are is_blank,
+ is_digit, is_cntrl, and is_xdigit, since
+ they can only match ASCII characters. We
+ don't need to handle them for multibyte.
+ They are distinguished by a negative wctype. */
+
+ if (multibyte)
+ SET_RANGE_TABLE_WORK_AREA_BIT (range_table_work,
+ re_wctype_to_bit (cc));
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ++ch)
+ {
+ int translated = TRANSLATE (ch);
+ if (re_iswctype (btowc (ch), cc))
+ SET_LIST_BIT (translated);
+ }
+
+ /* Repeat the loop. */
+ continue;
+ }
+ else
+ {
+ /* Go back to right after the "[:". */
+ p = class_beg;
+ SET_LIST_BIT ('[');
+
+ /* Because the `:' may starts the range, we
+ can't simply set bit and repeat the loop.
+ Instead, just set it to C and handle below. */
+ c = ':';
+ }
+ }
+
+ if (p < pend && p[0] == '-' && p[1] != ']')
+ {
+
+ /* Discard the `-'. */
+ PATFETCH (c1);
+
+ /* Fetch the character which ends the range. */
+ PATFETCH (c1);
+
+ if (SINGLE_BYTE_CHAR_P (c))
+ {
+ if (! SINGLE_BYTE_CHAR_P (c1))
+ {
+ /* Handle a range starting with a
+ character of less than 256, and ending
+ with a character of not less than 256.
+ Split that into two ranges, the low one
+ ending at 0377, and the high one
+ starting at the smallest character in
+ the charset of C1 and ending at C1. */
+ int charset = CHAR_CHARSET (c1);
+ int c2 = MAKE_CHAR (charset, 0, 0);
+
+ SET_RANGE_TABLE_WORK_AREA (range_table_work,
+ c2, c1);
+ c1 = 0377;
+ }
+ }
+ else if (!SAME_CHARSET_P (c, c1))
+ FREE_STACK_RETURN (REG_ERANGE);
+ }
+ else
+ /* Range from C to C. */
+ c1 = c;
+
+ /* Set the range ... */
+ if (SINGLE_BYTE_CHAR_P (c))
+ /* ... into bitmap. */
+ {
+ re_wchar_t this_char;
+ int range_start = c, range_end = c1;
+
+ /* If the start is after the end, the range is empty. */
+ if (range_start > range_end)
+ {
+ if (syntax & RE_NO_EMPTY_RANGES)
+ FREE_STACK_RETURN (REG_ERANGE);
+ /* Else, repeat the loop. */
+ }
+ else
+ {
+ for (this_char = range_start; this_char <= range_end;
+ this_char++)
+ SET_LIST_BIT (TRANSLATE (this_char));
+ }
+ }
+ else
+ /* ... into range table. */
+ SET_RANGE_TABLE_WORK_AREA (range_table_work, c, c1);
+ }
+
+ /* Discard any (non)matching list bytes that are all 0 at the
+ end of the map. Decrease the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+
+ /* Build real range table from work area. */
+ if (RANGE_TABLE_WORK_USED (range_table_work)
+ || RANGE_TABLE_WORK_BITS (range_table_work))
+ {
+ int i;
+ int used = RANGE_TABLE_WORK_USED (range_table_work);
+
+ /* Allocate space for COUNT + RANGE_TABLE. Needs two
+ bytes for flags, two for COUNT, and three bytes for
+ each character. */
+ GET_BUFFER_SPACE (4 + used * 3);
+
+ /* Indicate the existence of range table. */
+ laststart[1] |= 0x80;
+
+ /* Store the character class flag bits into the range table.
+ If not in emacs, these flag bits are always 0. */
+ *b++ = RANGE_TABLE_WORK_BITS (range_table_work) & 0xff;
+ *b++ = RANGE_TABLE_WORK_BITS (range_table_work) >> 8;
+
+ STORE_NUMBER_AND_INCR (b, used / 2);
+ for (i = 0; i < used; i++)
+ STORE_CHARACTER_AND_INCR
+ (b, RANGE_TABLE_WORK_ELT (range_table_work, i));
+ }
+ }
+ break;
+
+
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_open;
+ else
+ goto normal_char;
+
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS)
+ goto handle_close;
+ else
+ goto normal_char;
+
+
+ case '\n':
+ if (syntax & RE_NEWLINE_ALT)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '|':
+ if (syntax & RE_NO_BK_VBAR)
+ goto handle_alt;
+ else
+ goto normal_char;
+
+
+ case '{':
+ if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
+ goto handle_interval;
+ else
+ goto normal_char;
+
+
+ case '\\':
+ if (p == pend) FREE_STACK_RETURN (REG_EESCAPE);
+
+ /* Do not translate the character after the \, so that we can
+ distinguish, e.g., \B from \b, even if we normally would
+ translate, e.g., B to b. */
+ PATFETCH_RAW (c);
+
+ switch (c)
+ {
+ case '(':
+ if (syntax & RE_NO_BK_PARENS)
+ goto normal_backslash;
+
+ handle_open:
+ {
+ int shy = 0;
+ if (p+1 < pend)
+ {
+ /* Look for a special (?...) construct */
+ if ((syntax & RE_SHY_GROUPS) && *p == '?')
+ {
+ PATFETCH (c); /* Gobble up the '?'. */
+ PATFETCH (c);
+ switch (c)
+ {
+ case ':': shy = 1; break;
+ default:
+ /* Only (?:...) is supported right now. */
+ FREE_STACK_RETURN (REG_BADPAT);
+ }
+ }
+ }
+
+ if (!shy)
+ {
+ bufp->re_nsub++;
+ regnum++;
+ }
+
+ if (COMPILE_STACK_FULL)
+ {
+ RETALLOC (compile_stack.stack, compile_stack.size << 1,
+ compile_stack_elt_t);
+ if (compile_stack.stack == NULL) return REG_ESPACE;
+
+ compile_stack.size <<= 1;
+ }
+
+ /* These are the values to restore when we hit end of this
+ group. They are all relative offsets, so that if the
+ whole pattern moves because of realloc, they will still
+ be valid. */
+ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
+ COMPILE_STACK_TOP.fixup_alt_jump
+ = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+ COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
+ COMPILE_STACK_TOP.regnum = shy ? -regnum : regnum;
+
+ /* Do not push a
+ start_memory for groups beyond the last one we can
+ represent in the compiled pattern. */
+ if (regnum <= MAX_REGNUM && !shy)
+ BUF_PUSH_2 (start_memory, regnum);
+
+ compile_stack.avail++;
+
+ fixup_alt_jump = 0;
+ laststart = 0;
+ begalt = b;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+ break;
+ }
+
+ case ')':
+ if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
+
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_backslash;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ handle_close:
+ FIXUP_ALT_JUMP ();
+
+ /* See similar code for backslashed left paren above. */
+ if (COMPILE_STACK_EMPTY)
+ {
+ if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
+ goto normal_char;
+ else
+ FREE_STACK_RETURN (REG_ERPAREN);
+ }
+
+ /* Since we just checked for an empty stack above, this
+ ``can't happen''. */
+ assert (compile_stack.avail != 0);
+ {
+ /* We don't just want to restore into `regnum', because
+ later groups should continue to be numbered higher,
+ as in `(ab)c(de)' -- the second group is #2. */
+ regnum_t this_group_regnum;
+
+ compile_stack.avail--;
+ begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
+ fixup_alt_jump
+ = COMPILE_STACK_TOP.fixup_alt_jump
+ ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1
+ : 0;
+ laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
+ this_group_regnum = COMPILE_STACK_TOP.regnum;
+ /* If we've reached MAX_REGNUM groups, then this open
+ won't actually generate any code, so we'll have to
+ clear pending_exact explicitly. */
+ pending_exact = 0;
+
+ /* We're at the end of the group, so now we know how many
+ groups were inside this one. */
+ if (this_group_regnum <= MAX_REGNUM && this_group_regnum > 0)
+ BUF_PUSH_2 (stop_memory, this_group_regnum);
+ }
+ break;
+
+
+ case '|': /* `\|'. */
+ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
+ goto normal_backslash;
+ handle_alt:
+ if (syntax & RE_LIMITED_OPS)
+ goto normal_char;
+
+ /* Insert before the previous alternative a jump which
+ jumps to this alternative if the former fails. */
+ GET_BUFFER_SPACE (3);
+ INSERT_JUMP (on_failure_jump, begalt, b + 6);
+ pending_exact = 0;
+ b += 3;
+
+ /* The alternative before this one has a jump after it
+ which gets executed if it gets matched. Adjust that
+ jump so it will jump to this alternative's analogous
+ jump (put in below, which in turn will jump to the next
+ (if any) alternative's such jump, etc.). The last such
+ jump jumps to the correct final destination. A picture:
+ _____ _____
+ | | | |
+ | v | v
+ a | b | c
+
+ If we are at `b', then fixup_alt_jump right now points to a
+ three-byte space after `a'. We'll put in the jump, set
+ fixup_alt_jump to right after `b', and leave behind three
+ bytes which we'll fill in when we get to after `c'. */
+
+ FIXUP_ALT_JUMP ();
+
+ /* Mark and leave space for a jump after this alternative,
+ to be filled in later either by next alternative or
+ when know we're at the end of a series of alternatives. */
+ fixup_alt_jump = b;
+ GET_BUFFER_SPACE (3);
+ b += 3;
+
+ laststart = 0;
+ begalt = b;
+ break;
+
+
+ case '{':
+ /* If \{ is a literal. */
+ if (!(syntax & RE_INTERVALS)
+ /* If we're at `\{' and it's not the open-interval
+ operator. */
+ || (syntax & RE_NO_BK_BRACES))
+ goto normal_backslash;
+
+ handle_interval:
+ {
+ /* If got here, then the syntax allows intervals. */
+
+ /* At least (most) this many matches must be made. */
+ int lower_bound = 0, upper_bound = -1;
+
+ beg_interval = p;
+
+ if (p == pend)
+ FREE_STACK_RETURN (REG_EBRACE);
+
+ GET_UNSIGNED_NUMBER (lower_bound);
+
+ if (c == ',')
+ GET_UNSIGNED_NUMBER (upper_bound);
+ else
+ /* Interval such as `{1}' => match exactly once. */
+ upper_bound = lower_bound;
+
+ if (lower_bound < 0 || upper_bound > RE_DUP_MAX
+ || (upper_bound >= 0 && lower_bound > upper_bound))
+ FREE_STACK_RETURN (REG_BADBR);