From: Brendan Kehoe Date: Thu, 26 Oct 1995 23:54:44 +0000 (+0000) Subject: * regex.h: Renamed to gnu-regex.h. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=811f1bdce68c1ac53f95f0cf3ffe23b0ff703eaa;p=binutils-gdb.git * regex.h: Renamed to gnu-regex.h. * regex.c: Renamed to gnu-regex.c. * Makefile.in (POSSLIBS): Refer to gnu-regex.h and gnu-regex.c. (REGEX, REGEX1): Change to gnu-regex.o instead of regex.o. (regex.o): Renamed to gnu-regex.o; refer to gnu-regex.c. (irix5-nat.o, osfsolib.o, gnu-regex.o, solib.o, source.o, symtab.o): Likewise. * irix5-nat.c, osfsolib.c, gnu-regex.c, solib.c, source.c, symtab.c): Include "gnu-regex.h" instead of "regex.h". * alpha-tdep.c (in_prologue): Rename to alpha_in_prologue, to avoid conflicts with symtab.h. fixes building gdb under OSF/1 4.0 --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5a0e7a6947f..634e9ac1b6b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +Thu Oct 26 15:21:32 1995 Brendan Kehoe + + * regex.h: Renamed to gnu-regex.h. + * regex.c: Renamed to gnu-regex.c. + * Makefile.in (POSSLIBS): Refer to gnu-regex.h and gnu-regex.c. + (REGEX, REGEX1): Change to gnu-regex.o instead of regex.o. + (regex.o): Renamed to gnu-regex.o; refer to gnu-regex.c. + (irix5-nat.o, osfsolib.o, gnu-regex.o, solib.o, source.o, symtab.o): + Likewise. + * irix5-nat.c, osfsolib.c, gnu-regex.c, solib.c, source.c, symtab.c): + Include "gnu-regex.h" instead of "regex.h". + * alpha-tdep.c (in_prologue): Rename to alpha_in_prologue, to + avoid conflicts with symtab.h. + Tue Oct 24 18:30:18 1995 Jason Molenda (crash@phydeaux.cygnus.com) * config/pa/hppahpux.mh: Remove hardcoding of X locations. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 693fb860090..ff0ec6498af 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -148,7 +148,7 @@ ENABLE_OBS= @ENABLE_OBS@ # All the includes used for CFLAGS and for lint. # -I. for config files. -# -I$(srcdir) for gdb internal headers and possibly for regex.h also. +# -I$(srcdir) for gdb internal headers and possibly for gnu-regex.h also. # -I$(srcdir)/config for more generic config files. # It is also possible that you will need to add -I/usr/include/sys if @@ -186,8 +186,8 @@ INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) $(LDFLAGS) # We are using our own version of REGEX now to be consistent across # machines. -REGEX = regex.o -REGEX1 = regex.o +REGEX = gnu-regex.o +REGEX1 = gnu-regex.o # If your system is missing alloca(), or, more likely, it's there but # it doesn't work, then refer to libiberty. @@ -437,7 +437,7 @@ INFOFILES = gdb.info* REMOTE_EXAMPLES = m68k-stub.c i386-stub.c sparc-stub.c rem-multi.shar -POSSLIBS = regex.c regex.h +POSSLIBS = gnu-regex.c gnu-regex.h # {X,T,NAT}DEPFILES are something of a pain in that it's hard to # default their values the way we do for SER_HARDWIRE; in the future @@ -1213,7 +1213,7 @@ inftarg.o: inftarg.c $(wait_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ irix4-nat.o: irix4-nat.c $(defs_h) $(inferior_h) irix5-nat.o: irix5-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) target.h \ - $(symtab_h) symfile.h objfiles.h $(command_h) $(frame_h) regex.h \ + $(symtab_h) symfile.h objfiles.h $(command_h) $(frame_h) gnu-regex.h \ language.h isi-xdep.o: isi-xdep.c @@ -1308,7 +1308,7 @@ objfiles.o: objfiles.c $(bfd_h) $(defs_h) objfiles.h symfile.h \ $(symtab_h) osfsolib.o: osfsolib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ - objfiles.h regex.h symfile.h target.h language.h + objfiles.h gnu-regex.h symfile.h target.h language.h somread.o: somread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \ gdb-stabs.h objfiles.h symfile.h $(symtab_h) @@ -1332,7 +1332,7 @@ pyr-tdep.o: pyr-tdep.c $(defs_h) pyr-xdep.o: pyr-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h) -regex.o: regex.c regex.h $(defs_h) +gnu-regex.o: gnu-regex.c gnu-regex.h $(defs_h) remote-adapt.o: remote-adapt.c $(wait_h) $(defs_h) $(gdbcore_h) \ $(inferior_h) target.h terminal.h @@ -1424,10 +1424,10 @@ sh3-rom.o: sh3-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \ $(inferior_h) target.h serial.h terminal.h solib.o: solib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \ - objfiles.h regex.h symfile.h target.h + objfiles.h gnu-regex.h symfile.h target.h source.o: source.c $(defs_h) $(expression_h) $(frame_h) $(gdbcmd_h) \ - $(gdbcore_h) language.h objfiles.h regex.h symfile.h $(symtab_h) + $(gdbcore_h) language.h objfiles.h gnu-regex.h symfile.h $(symtab_h) sparc-nat.o: sparc-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h @@ -1459,7 +1459,7 @@ symmisc.o: symmisc.c $(bfd_h) $(breakpoint_h) $(command_h) $(defs_h) \ symtab.o: symtab.c call-cmds.h $(defs_h) $(expression_h) $(frame_h) \ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \ - regex.h symfile.h $(symtab_h) target.h $(value_h) + gnu-regex.h symfile.h $(symtab_h) target.h $(value_h) tahoe-tdep.o: tahoe-tdep.c $(OP_INCLUDE)/tahoe.h $(defs_h) \ $(symtab_h) diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 6ec6f6da553..ce1c8ed26d0 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -58,7 +58,7 @@ static void reinit_frame_cache_sfunc PARAMS ((char *, int, static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc, alpha_extra_func_info_t proc_desc)); -static int in_prologue PARAMS ((CORE_ADDR pc, +static int alpha_in_prologue PARAMS ((CORE_ADDR pc, alpha_extra_func_info_t proc_desc)); /* Heuristic_proc_start may hunt through the text section for a long @@ -444,7 +444,7 @@ after_prologue (pc, proc_desc) are definatly *not* in a function prologue. */ static int -in_prologue (pc, proc_desc) +alpha_in_prologue (pc, proc_desc) CORE_ADDR pc; alpha_extra_func_info_t proc_desc; { @@ -530,7 +530,7 @@ find_proc_desc (pc, next_frame) proc_desc = (alpha_extra_func_info_t)SYMBOL_VALUE(sym); if (next_frame == NULL) { - if (PROC_DESC_IS_DUMMY (proc_desc) || in_prologue (pc, proc_desc)) + if (PROC_DESC_IS_DUMMY (proc_desc) || alpha_in_prologue (pc, proc_desc)) { alpha_extra_func_info_t found_heuristic = heuristic_proc_desc (PROC_LOW_ADDR (proc_desc), diff --git a/gdb/gnu-regex.c b/gdb/gnu-regex.c new file mode 100644 index 00000000000..062fbc683d1 --- /dev/null +++ b/gdb/gnu-regex.c @@ -0,0 +1,1757 @@ +/* Extended regular expression matching and search library. + Copyright (C) 1985, 1989 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* To test, compile with -Dtest. + This Dtestable feature turns this into a self-contained program + which reads a pattern, describes how it compiles, + then reads a string and searches for it. */ + +#ifdef emacs + +/* The `emacs' switch turns on certain special matching commands + that make sense only in emacs. */ + +#include "config.h" +#include "lisp.h" +#include "buffer.h" +#include "syntax.h" + +#else /* not emacs */ + +#include "defs.h" +#include "gdb_string.h" + +/* + * Define the syntax stuff, so we can do the \<...\> things. + */ + +#ifndef Sword /* must be non-zero in some of the tests below... */ +#define Sword 1 +#endif + +#define SYNTAX(c) re_syntax_table[c] + +#ifdef SYNTAX_TABLE + +char *re_syntax_table; + +#else + +static char re_syntax_table[256]; + +static void +init_syntax_once () +{ + register int c; + static int done = 0; + + if (done) + return; + + memset (re_syntax_table, '\0', sizeof re_syntax_table); + + for (c = 'a'; c <= 'z'; c++) + re_syntax_table[c] = Sword; + + for (c = 'A'; c <= 'Z'; c++) + re_syntax_table[c] = Sword; + + for (c = '0'; c <= '9'; c++) + re_syntax_table[c] = Sword; + + done = 1; +} + +#endif /* SYNTAX_TABLE */ +#endif /* not emacs */ + +#include "gnu-regex.h" + +/* Number of failure points to allocate space for initially, + when matching. If this number is exceeded, more space is allocated, + so it is not a hard limit. */ + +#ifndef NFAILURES +#define NFAILURES 80 +#endif /* NFAILURES */ + +/* width of a byte in bits */ + +#define BYTEWIDTH 8 + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +#undef SIGN_EXTEND_CHAR +#if __STDC__ +#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +#else /* not __STDC__ */ +/* As in Harbison and Steele. */ +#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +#endif + +static int obscure_syntax = 0; + +/* Specify the precise syntax of regexp for compilation. + This provides for compatibility for various utilities + which historically have different, incompatible syntaxes. + + The argument SYNTAX is a bit-mask containing the two bits + RE_NO_BK_PARENS and RE_NO_BK_VBAR. */ + +int +re_set_syntax (syntax) + int syntax; +{ + int ret; + + ret = obscure_syntax; + obscure_syntax = syntax; + return ret; +} + +/* re_compile_pattern takes a regular-expression string + and converts it into a buffer full of byte commands for matching. + + PATTERN is the address of the pattern string + SIZE is the length of it. + BUFP is a struct re_pattern_buffer * which points to the info + on where to store the byte commands. + This structure contains a char * which points to the + actual space, which should have been obtained with malloc. + re_compile_pattern may use realloc to grow the buffer space. + + The number of bytes of commands can be found out by looking in + the struct re_pattern_buffer that bufp pointed to, + after re_compile_pattern returns. +*/ + +#define PATPUSH(ch) (*b++ = (char) (ch)) + +#define PATFETCH(c) \ + {if (p == pend) goto end_of_pattern; \ + c = * (unsigned char *) p++; \ + if (translate) c = translate[c]; } + +#define PATFETCH_RAW(c) \ + {if (p == pend) goto end_of_pattern; \ + c = * (unsigned char *) p++; } + +#define PATUNFETCH p-- + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +#define MAX_BUF_SIZE (1 << 16) + + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +#define EXTEND_BUFFER \ + do { \ + char *old_buffer = bufp->buffer; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + goto too_big; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated);\ + if (bufp->buffer == NULL) \ + goto memory_exhausted; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != bufp->buffer) \ + { \ + b = (b - old_buffer) + bufp->buffer; \ + begalt = (begalt - old_buffer) + bufp->buffer; \ + if (fixup_jump) \ + fixup_jump = (fixup_jump - old_buffer) + bufp->buffer;\ + if (laststart) \ + laststart = (laststart - old_buffer) + bufp->buffer; \ + if (pending_exact) \ + pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ + } \ + } while (0) + +static void store_jump (), insert_jump (); + +char * +re_compile_pattern (pattern, size, bufp) + char *pattern; + int size; + struct re_pattern_buffer *bufp; +{ + register char *b = bufp->buffer; + register char *p = pattern; + char *pend = pattern + size; + register unsigned c, c1; + char *p1; + unsigned char *translate = (unsigned char *) bufp->translate; + + /* address of the count-byte of the most recently inserted "exactn" command. + This makes it possible to tell whether a new exact-match character + can be added to that command or requires a new "exactn" command. */ + + char *pending_exact = 0; + + /* address of the place where a forward-jump should go + to the end of the containing expression. + Each alternative of an "or", except the last, ends with a forward-jump + of this sort. */ + + char *fixup_jump = 0; + + /* address of start of the most recently finished expression. + This tells postfix * where to find the start of its operand. */ + + char *laststart = 0; + + /* In processing a repeat, 1 means zero matches is allowed */ + + char zero_times_ok; + + /* In processing a repeat, 1 means many matches is allowed */ + + char many_times_ok; + + /* address of beginning of regexp, or inside of last \( */ + + char *begalt = b; + + /* Stack of information saved by \( and restored by \). + Four stack elements are pushed by each \(: + First, the value of b. + Second, the value of fixup_jump. + Third, the value of regnum. + Fourth, the value of begalt. */ + + int stackb[40]; + int *stackp = stackb; + int *stacke = stackb + 40; + int *stackt; + + /* Counts \('s as they are encountered. Remembered for the matching \), + where it becomes the "register number" to put in the stop_memory command */ + + int regnum = 1; + + bufp->fastmap_accurate = 0; + +#ifndef emacs +#ifndef SYNTAX_TABLE + /* + * Initialize the syntax table. + */ + init_syntax_once(); +#endif +#endif + + if (bufp->allocated == 0) + { + bufp->allocated = 28; + if (bufp->buffer) + /* EXTEND_BUFFER loses when bufp->allocated is 0 */ + bufp->buffer = (char *) realloc (bufp->buffer, 28); + else + /* Caller did not allocate a buffer. Do it for him */ + bufp->buffer = (char *) malloc (28); + if (!bufp->buffer) goto memory_exhausted; + begalt = b = bufp->buffer; + } + + while (p != pend) + { + if (b - bufp->buffer > bufp->allocated - 10) + /* Note that EXTEND_BUFFER clobbers c */ + EXTEND_BUFFER; + + PATFETCH (c); + + switch (c) + { + case '$': + if (obscure_syntax & RE_TIGHT_VBAR) + { + if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend) + goto normal_char; + /* Make operand of last vbar end before this `$'. */ + if (fixup_jump) + store_jump (fixup_jump, jump, b); + fixup_jump = 0; + PATPUSH (endline); + break; + } + + /* $ means succeed if at end of line, but only in special contexts. + If randomly in the middle of a pattern, it is a normal character. */ + if (p == pend || *p == '\n' + || (obscure_syntax & RE_CONTEXT_INDEP_OPS) + || (obscure_syntax & RE_NO_BK_PARENS + ? *p == ')' + : *p == '\\' && p[1] == ')') + || (obscure_syntax & RE_NO_BK_VBAR + ? *p == '|' + : *p == '\\' && p[1] == '|')) + { + PATPUSH (endline); + break; + } + goto normal_char; + + case '^': + /* ^ means succeed if at beg of line, but only if no preceding pattern. */ + + if (laststart && p[-2] != '\n' + && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + if (obscure_syntax & RE_TIGHT_VBAR) + { + if (p != pattern + 1 + && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + PATPUSH (begline); + begalt = b; + } + else + PATPUSH (begline); + break; + + case '+': + case '?': + if (obscure_syntax & RE_BK_PLUS_QM) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern, char not special. */ + if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + /* If there is a sequence of repetition chars, + collapse it down to equivalent to just one. */ + zero_times_ok = 0; + many_times_ok = 0; + while (1) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + if (p == pend) + break; + PATFETCH (c); + if (c == '*') + ; + else if (!(obscure_syntax & RE_BK_PLUS_QM) + && (c == '+' || c == '?')) + ; + else if ((obscure_syntax & RE_BK_PLUS_QM) + && c == '\\') + { + int c1; + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + c = c1; + } + else + { + PATUNFETCH; + break; + } + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether 0 matches is allowed, + and whether 2 or more matches is allowed. */ + if (many_times_ok) + { + /* If more than one repetition is allowed, + put in a backward jump at the end. */ + store_jump (b, maybe_finalize_jump, laststart - 3); + b += 3; + } + insert_jump (on_failure_jump, laststart, b + 3, b); + pending_exact = 0; + b += 3; + if (!zero_times_ok) + { + /* At least one repetition required: insert before the loop + a skip over the initial on-failure-jump instruction */ + insert_jump (dummy_failure_jump, laststart, laststart + 6, b); + b += 3; + } + break; + + case '.': + laststart = b; + PATPUSH (anychar); + break; + + case '[': + while (b - bufp->buffer + > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH) + /* Note that EXTEND_BUFFER clobbers c */ + EXTEND_BUFFER; + + laststart = b; + if (*p == '^') + PATPUSH (charset_not), p++; + else + PATPUSH (charset); + p1 = p; + + PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + /* Clear the whole map */ + memset (b, '\0', (1 << BYTEWIDTH) / BYTEWIDTH); + /* Read in characters and ranges, setting map bits */ + while (1) + { + PATFETCH (c); + if (c == ']' && p != p1 + 1) break; + if (*p == '-' && p[1] != ']') + { + PATFETCH (c1); + PATFETCH (c1); + while (c <= c1) + b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++; + } + else + { + b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH); + } + } + /* Discard any bitmap bytes that are all 0 at the end of the map. + Decrement the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; + break; + + case '(': + if (! (obscure_syntax & RE_NO_BK_PARENS)) + goto normal_char; + else + goto handle_open; + + case ')': + if (! (obscure_syntax & RE_NO_BK_PARENS)) + goto normal_char; + else + goto handle_close; + + case '\n': + if (! (obscure_syntax & RE_NEWLINE_OR)) + goto normal_char; + else + goto handle_bar; + + case '|': + if (! (obscure_syntax & RE_NO_BK_VBAR)) + goto normal_char; + else + goto handle_bar; + + case '\\': + if (p == pend) goto invalid_pattern; + PATFETCH_RAW (c); + switch (c) + { + case '(': + if (obscure_syntax & RE_NO_BK_PARENS) + goto normal_backsl; + handle_open: + if (stackp == stacke) goto nesting_too_deep; + if (regnum < RE_NREGS) + { + PATPUSH (start_memory); + PATPUSH (regnum); + } + *stackp++ = b - bufp->buffer; + *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0; + *stackp++ = regnum++; + *stackp++ = begalt - bufp->buffer; + fixup_jump = 0; + laststart = 0; + begalt = b; + break; + + case ')': + if (obscure_syntax & RE_NO_BK_PARENS) + goto normal_backsl; + handle_close: + if (stackp == stackb) goto unmatched_close; + begalt = *--stackp + bufp->buffer; + if (fixup_jump) + store_jump (fixup_jump, jump, b); + if (stackp[-1] < RE_NREGS) + { + PATPUSH (stop_memory); + PATPUSH (stackp[-1]); + } + stackp -= 2; + fixup_jump = 0; + if (*stackp) + fixup_jump = *stackp + bufp->buffer - 1; + laststart = *--stackp + bufp->buffer; + break; + + case '|': + if (obscure_syntax & RE_NO_BK_VBAR) + goto normal_backsl; + handle_bar: + insert_jump (on_failure_jump, begalt, b + 6, b); + pending_exact = 0; + b += 3; + if (fixup_jump) + store_jump (fixup_jump, jump, b); + fixup_jump = b; + b += 3; + laststart = 0; + begalt = b; + break; + +#ifdef emacs + case '=': + PATPUSH (at_dot); + break; + + case 's': + laststart = b; + PATPUSH (syntaxspec); + PATFETCH (c); + PATPUSH (syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATPUSH (notsyntaxspec); + PATFETCH (c); + PATPUSH (syntax_spec_code[c]); + break; +#endif /* emacs */ + + case 'w': + laststart = b; + PATPUSH (wordchar); + break; + + case 'W': + laststart = b; + PATPUSH (notwordchar); + break; + + case '<': + PATPUSH (wordbeg); + break; + + case '>': + PATPUSH (wordend); + break; + + case 'b': + PATPUSH (wordbound); + break; + + case 'B': + PATPUSH (notwordbound); + break; + + case '`': + PATPUSH (begbuf); + break; + + case '\'': + PATPUSH (endbuf); + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + c1 = c - '0'; + if (c1 >= regnum) + goto normal_char; + for (stackt = stackp - 2; stackt > stackb; stackt -= 4) + if (*stackt == c1) + goto normal_char; + laststart = b; + PATPUSH (duplicate); + PATPUSH (c1); + break; + + case '+': + case '?': + if (obscure_syntax & RE_BK_PLUS_QM) + goto handle_plus; + + default: + normal_backsl: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + if (translate) c = translate[c]; + goto normal_char; + } + break; + + default: + normal_char: + if (!pending_exact || pending_exact + *pending_exact + 1 != b + || *pending_exact == 0177 || *p == '*' || *p == '^' + || ((obscure_syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?'))) + { + laststart = b; + PATPUSH (exactn); + pending_exact = b; + PATPUSH (0); + } + PATPUSH (c); + (*pending_exact)++; + } + } + + if (fixup_jump) + store_jump (fixup_jump, jump, b); + + if (stackp != stackb) goto unmatched_open; + + bufp->used = b - bufp->buffer; + return 0; + + invalid_pattern: + return "Invalid regular expression"; + + unmatched_open: + return "Unmatched \\("; + + unmatched_close: + return "Unmatched \\)"; + + end_of_pattern: + return "Premature end of regular expression"; + + nesting_too_deep: + return "Nesting too deep"; + + too_big: + return "Regular expression too big"; + + memory_exhausted: + return "Memory exhausted"; +} + +/* Store where `from' points a jump operation to jump to where `to' points. + `opcode' is the opcode to store. */ + +static void +store_jump (from, opcode, to) + char *from, *to; + char opcode; +{ + from[0] = opcode; + from[1] = (to - (from + 3)) & 0377; + from[2] = (to - (from + 3)) >> 8; +} + +/* Open up space at char FROM, and insert there a jump to TO. + CURRENT_END gives te end of the storage no in use, + so we know how much data to copy up. + OP is the opcode of the jump to insert. + + If you call this function, you must zero out pending_exact. */ + +static void +insert_jump (op, from, to, current_end) + char op; + char *from, *to, *current_end; +{ + register char *pto = current_end + 3; + register char *pfrom = current_end; + while (pfrom != from) + *--pto = *--pfrom; + store_jump (from, op, to); +} + +/* Given a pattern, compute a fastmap from it. + The fastmap records which of the (1 << BYTEWIDTH) possible characters + can start a string that matches the pattern. + This fastmap is used by re_search to skip quickly over totally implausible text. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data area + as bufp->fastmap. + The other components of bufp describe the pattern to be used. */ + +void +re_compile_fastmap (bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *pattern = (unsigned char *) bufp->buffer; + int size = bufp->used; + register char *fastmap = bufp->fastmap; + register unsigned char *p = pattern; + register unsigned char *pend = pattern + size; + register int j; + unsigned char *translate = (unsigned char *) bufp->translate; + + unsigned char *stackb[NFAILURES]; + unsigned char **stackp = stackb; + + memset (fastmap, '\0', (1 << BYTEWIDTH)); + bufp->fastmap_accurate = 1; + bufp->can_be_null = 0; + + while (p) + { + if (p == pend) + { + bufp->can_be_null = 1; + break; + } +#ifdef SWITCH_ENUM_BUG + switch ((int) ((enum regexpcode) *p++)) +#else + switch ((enum regexpcode) *p++) +#endif + { + case exactn: + if (translate) + fastmap[translate[p[1]]] = 1; + else + fastmap[p[1]] = 1; + break; + + case begline: + case before_dot: + case at_dot: + case after_dot: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + continue; + + case endline: + if (translate) + fastmap[translate['\n']] = 1; + else + fastmap['\n'] = 1; + if (bufp->can_be_null != 1) + bufp->can_be_null = 2; + break; + + case finalize_jump: + case maybe_finalize_jump: + case jump: + case dummy_failure_jump: + bufp->can_be_null = 1; + j = *p++ & 0377; + j += SIGN_EXTEND_CHAR (*(char *)p) << 8; + p += j + 1; /* The 1 compensates for missing ++ above */ + if (j > 0) + continue; + /* Jump backward reached implies we just went through + the body of a loop and matched nothing. + Opcode jumped to should be an on_failure_jump. + Just treat it like an ordinary jump. + For a * loop, it has pushed its failure point already; + if so, discard that as redundant. */ + if ((enum regexpcode) *p != on_failure_jump) + continue; + p++; + j = *p++ & 0377; + j += SIGN_EXTEND_CHAR (*(char *)p) << 8; + p += j + 1; /* The 1 compensates for missing ++ above */ + if (stackp != stackb && *stackp == p) + stackp--; + continue; + + case on_failure_jump: + j = *p++ & 0377; + j += SIGN_EXTEND_CHAR (*(char *)p) << 8; + p++; + *++stackp = p + j; + continue; + + case start_memory: + case stop_memory: + p++; + continue; + + case duplicate: + bufp->can_be_null = 1; + fastmap['\n'] = 1; + case anychar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (j != '\n') + fastmap[j] = 1; + if (bufp->can_be_null) + return; + /* Don't return; check the alternative paths + so we can set can_be_null if appropriate. */ + break; + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; +#endif /* emacs */ + + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + { + if (translate) + fastmap[translate[j]] = 1; + else + fastmap[j] = 1; + } + break; + + case charset_not: + /* Chars beyond end of map must be allowed */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + if (translate) + fastmap[translate[j]] = 1; + else + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + { + if (translate) + fastmap[translate[j]] = 1; + else + fastmap[j] = 1; + } + break; + case unused: + case syntaxspec: + case notsyntaxspec: + default: + break; + } + + /* Get here means we have successfully found the possible starting characters + of one path of the pattern. We need not follow this path any farther. + Instead, look at the next alternative remembered in the stack. */ + if (stackp != stackb) + p = *stackp--; + else + break; + } +} + +/* Like re_search_2, below, but only one string is specified. */ + +int +re_search (pbufp, string, size, startpos, range, regs) + struct re_pattern_buffer *pbufp; + char *string; + int size, startpos, range; + struct re_registers *regs; +{ + return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size); +} + +/* Like re_match_2 but tries first a match starting at index STARTPOS, + then at STARTPOS + 1, and so on. + RANGE is the number of places to try before giving up. + If RANGE is negative, the starting positions tried are + STARTPOS, STARTPOS - 1, etc. + It is up to the caller to make sure that range is not so large + as to take the starting position outside of the input strings. + +The value returned is the position at which the match was found, + or -1 if no match was found, + or -2 if error (such as failure stack overflow). */ + +int +re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop) + struct re_pattern_buffer *pbufp; + char *string1, *string2; + int size1, size2; + int startpos; + register int range; + struct re_registers *regs; + int mstop; +{ + register char *fastmap = pbufp->fastmap; + register unsigned char *translate = (unsigned char *) pbufp->translate; + int total = size1 + size2; + int val; + + /* Update the fastmap now if not correct already */ + if (fastmap && !pbufp->fastmap_accurate) + re_compile_fastmap (pbufp); + + /* Don't waste time in a long search for a pattern + that says it is anchored. */ + if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf + && range > 0) + { + if (startpos > 0) + return -1; + else + range = 1; + } + + while (1) + { + /* If a fastmap is supplied, skip quickly over characters + that cannot possibly be the start of a match. + Note, however, that if the pattern can possibly match + the null string, we must test it at each starting point + so that we take the first null string we get. */ + + if (fastmap && startpos < total && pbufp->can_be_null != 1) + { + if (range > 0) + { + register int lim = 0; + register unsigned char *p; + int irange = range; + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + p = ((unsigned char *) + &(startpos >= size1 ? string2 - size1 : string1)[startpos]); + + if (translate) + { + while (range > lim && !fastmap[translate[*p++]]) + range--; + } + else + { + while (range > lim && !fastmap[*p++]) + range--; + } + startpos += irange - range; + } + else + { + register unsigned char c; + if (startpos >= size1) + c = string2[startpos - size1]; + else + c = string1[startpos]; + c &= 0xff; + if (translate ? !fastmap[translate[c]] : !fastmap[c]) + goto advance; + } + } + + if (range >= 0 && startpos == total + && fastmap && pbufp->can_be_null == 0) + return -1; + + val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs, mstop); + if (0 <= val) + { + if (val == -2) + return -2; + return startpos; + } + +#ifdef C_ALLOCA + alloca (0); +#endif /* C_ALLOCA */ + + advance: + if (!range) break; + if (range > 0) range--, startpos++; else range++, startpos--; + } + return -1; +} + +#ifndef emacs /* emacs never uses this */ +int +re_match (pbufp, string, size, pos, regs) + struct re_pattern_buffer *pbufp; + char *string; + int size, pos; + struct re_registers *regs; +{ + return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size); +} +#endif /* emacs */ + +/* Maximum size of failure stack. Beyond this, overflow is an error. */ + +int re_max_failures = 2000; + +static int memcmp_translate(); +/* Match the pattern described by PBUFP + against data which is the virtual concatenation of STRING1 and STRING2. + SIZE1 and SIZE2 are the sizes of the two data strings. + Start the match at position POS. + Do not consider matching past the position MSTOP. + + If pbufp->fastmap is nonzero, then it had better be up to date. + + The reason that the data to match are specified as two components + which are to be regarded as concatenated + is so this function can be used directly on the contents of an Emacs buffer. + + -1 is returned if there is no match. -2 is returned if there is + an error (such as match stack overflow). Otherwise the value is the length + of the substring which was matched. */ + +int +re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop) + struct re_pattern_buffer *pbufp; + unsigned char *string1, *string2; + int size1, size2; + int pos; + struct re_registers *regs; + int mstop; +{ + register unsigned char *p = (unsigned char *) pbufp->buffer; + register unsigned char *pend = p + pbufp->used; + /* End of first string */ + unsigned char *end1; + /* End of second string */ + unsigned char *end2; + /* Pointer just past last char to consider matching */ + unsigned char *end_match_1, *end_match_2; + register unsigned char *d, *dend; + register int mcnt; + unsigned char *translate = (unsigned char *) pbufp->translate; + + /* Failure point stack. Each place that can handle a failure further down the line + pushes a failure point on this stack. It consists of two char *'s. + The first one pushed is where to resume scanning the pattern; + the second pushed is where to resume scanning the strings. + If the latter is zero, the failure point is a "dummy". + If a failure happens and the innermost failure point is dormant, + it discards that failure point and tries the next one. */ + + unsigned char *initial_stack[2 * NFAILURES]; + unsigned char **stackb = initial_stack; + unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES]; + + /* Information on the "contents" of registers. + These are pointers into the input strings; they record + just what was matched (on this attempt) by some part of the pattern. + The start_memory command stores the start of a register's contents + and the stop_memory command stores the end. + + At that point, regstart[regnum] points to the first character in the register, + regend[regnum] points to the first character beyond the end of the register, + regstart_seg1[regnum] is true iff regstart[regnum] points into string1, + and regend_seg1[regnum] is true iff regend[regnum] points into string1. */ + + unsigned char *regstart[RE_NREGS]; + unsigned char *regend[RE_NREGS]; + unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS]; + + /* Set up pointers to ends of strings. + Don't allow the second string to be empty unless both are empty. */ + if (!size2) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings */ + if (mstop <= size1) + { + end_match_1 = string1 + mstop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + mstop - size1; + } + + /* Initialize \) text positions to -1 + to mark ones that no \( or \) has been seen for. */ + + for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++) + regend[mcnt] = (unsigned char *) -1; + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. + `d' is advanced into the following input string whenever necessary, + but this happens before fetching; + therefore, at the beginning of the loop, + `d' can be pointing at the end of a string, + but it cannot equal string2. */ + + if (pos <= size1) + d = string1 + pos, dend = end_match_1; + else + d = string2 + pos - size1, dend = end_match_2; + +/* Write PREFETCH; just before fetching a character with *d. */ +#define PREFETCH \ + while (d == dend) \ + { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \ + d = string2; /* end of string1 => advance to string2. */ \ + dend = end_match_2; } + + /* This loop loops over pattern commands. + It exits by returning from the function if match is complete, + or it drops through if match fails at this starting point in the input data. */ + + while (1) + { + if (p == pend) + /* End of pattern means we have succeeded! */ + { + /* If caller wants register contents data back, convert it to indices */ + if (regs) + { + regs->start[0] = pos; + if (dend == end_match_1) + regs->end[0] = d - string1; + else + regs->end[0] = d - string2 + size1; + for (mcnt = 1; mcnt < RE_NREGS; mcnt++) + { + if (regend[mcnt] == (unsigned char *) -1) + { + regs->start[mcnt] = -1; + regs->end[mcnt] = -1; + continue; + } + if (regstart_seg1[mcnt]) + regs->start[mcnt] = regstart[mcnt] - string1; + else + regs->start[mcnt] = regstart[mcnt] - string2 + size1; + if (regend_seg1[mcnt]) + regs->end[mcnt] = regend[mcnt] - string1; + else + regs->end[mcnt] = regend[mcnt] - string2 + size1; + } + } + if (dend == end_match_1) + return (d - string1 - pos); + else + return d - string2 + size1 - pos; + } + + /* Otherwise match next pattern command */ +#ifdef SWITCH_ENUM_BUG + switch ((int) ((enum regexpcode) *p++)) +#else + switch ((enum regexpcode) *p++) +#endif + { + + /* \( is represented by a start_memory, \) by a stop_memory. + Both of those commands contain a "register number" argument. + The text matched within the \( and \) is recorded under that number. + Then, \ turns into a `duplicate' command which + is followed by the numeric value of as the register number. */ + + case start_memory: + regstart[*p] = d; + regstart_seg1[*p++] = (dend == end_match_1); + break; + + case stop_memory: + regend[*p] = d; + regend_seg1[*p++] = (dend == end_match_1); + break; + + case duplicate: + { + int regno = *p++; /* Get which register to match against */ + register unsigned char *d2, *dend2; + + d2 = regstart[regno]; + dend2 = ((regstart_seg1[regno] == regend_seg1[regno]) + ? regend[regno] : end_match_1); + while (1) + { + /* Advance to next segment in register contents, if necessary */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */ + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* Advance to next segment in data being matched, if necessary */ + PREFETCH; + + /* mcnt gets # consecutive chars to compare */ + mcnt = dend - d; + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + /* Compare that many; failure if mismatch, else skip them. */ + if (translate ? memcmp_translate (d, d2, mcnt, translate) : memcmp (d, d2, mcnt)) + goto fail; + d += mcnt, d2 += mcnt; + } + } + break; + + case anychar: + /* fetch a data character */ + PREFETCH; + /* Match anything but a newline. */ + if ((translate ? translate[*d++] : *d++) == '\n') + goto fail; + break; + + case charset: + case charset_not: + { + /* Nonzero for charset_not */ + int not = 0; + register int c; + if (*(p - 1) == (unsigned char) charset_not) + not = 1; + + /* fetch a data character */ + PREFETCH; + + if (translate) + c = translate [*d]; + else + c = *d; + + if (c < *p * BYTEWIDTH + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; + d++; + break; + } + + case begline: + if (d == string1 || d[-1] == '\n') + break; + goto fail; + + case endline: + if (d == end2 + || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n')) + break; + goto fail; + + /* "or" constructs ("|") are handled by starting each alternative + with an on_failure_jump that points to the start of the next alternative. + Each alternative except the last ends with a jump to the joining point. + (Actually, each jump except for the last one really jumps + to the following jump, because tensioning the jumps is a hassle.) */ + + /* The start of a stupid repeat has an on_failure_jump that points + past the end of the repeat text. + This makes a failure point so that, on failure to match a repetition, + matching restarts past as many repetitions have been found + with no way to fail and look for another one. */ + + /* A smart repeat is similar but loops back to the on_failure_jump + so that each repetition makes another failure point. */ + + case on_failure_jump: + if (stackp == stacke) + { + unsigned char **stackx; + if (stacke - stackb > re_max_failures * 2) + return -2; + stackx = (unsigned char **) alloca (2 * (stacke - stackb) + * sizeof (char *)); + memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *)); + stackp = stackx + (stackp - stackb); + stacke = stackx + 2 * (stacke - stackb); + stackb = stackx; + } + mcnt = *p++ & 0377; + mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; + p++; + *stackp++ = mcnt + p; + *stackp++ = d; + break; + + /* The end of a smart repeat has an maybe_finalize_jump back. + Change it either to a finalize_jump or an ordinary jump. */ + + case maybe_finalize_jump: + mcnt = *p++ & 0377; + mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; + p++; + { + register unsigned char *p2 = p; + /* Compare what follows with the begining of the repeat. + If we can establish that there is nothing that they would + both match, we can change to finalize_jump */ + while (p2 != pend + && (*p2 == (unsigned char) stop_memory + || *p2 == (unsigned char) start_memory)) + p2++; + if (p2 == pend) + p[-3] = (unsigned char) finalize_jump; + else if (*p2 == (unsigned char) exactn + || *p2 == (unsigned char) endline) + { + register int c = *p2 == (unsigned char) endline ? '\n' : p2[2]; + register unsigned char *p1 = p + mcnt; + /* p1[0] ... p1[2] are an on_failure_jump. + Examine what follows that */ + if (p1[3] == (unsigned char) exactn && p1[5] != c) + p[-3] = (unsigned char) finalize_jump; + else if (p1[3] == (unsigned char) charset + || p1[3] == (unsigned char) charset_not) + { + int not = p1[3] == (unsigned char) charset_not; + if (c < p1[4] * BYTEWIDTH + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + /* not is 1 if c would match */ + /* That means it is not safe to finalize */ + if (!not) + p[-3] = (unsigned char) finalize_jump; + } + } + } + p -= 2; + if (p[-1] != (unsigned char) finalize_jump) + { + p[-1] = (unsigned char) jump; + goto nofinalize; + } + + /* The end of a stupid repeat has a finalize-jump + back to the start, where another failure point will be made + which will point after all the repetitions found so far. */ + + case finalize_jump: + stackp -= 2; + + case jump: + nofinalize: + mcnt = *p++ & 0377; + mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; + p += mcnt + 1; /* The 1 compensates for missing ++ above */ + break; + + case dummy_failure_jump: + if (stackp == stacke) + { + unsigned char **stackx + = (unsigned char **) alloca (2 * (stacke - stackb) + * sizeof (char *)); + memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *)); + stackp = stackx + (stackp - stackb); + stacke = stackx + 2 * (stacke - stackb); + stackb = stackx; + } + *stackp++ = 0; + *stackp++ = 0; + goto nofinalize; + + case wordbound: + if (d == string1 /* Points to first char */ + || d == end2 /* Points to end */ + || (d == end1 && size2 == 0)) /* Points to end */ + break; + if ((SYNTAX (d[-1]) == Sword) + != (SYNTAX (d == end1 ? *string2 : *d) == Sword)) + break; + goto fail; + + case notwordbound: + if (d == string1 /* Points to first char */ + || d == end2 /* Points to end */ + || (d == end1 && size2 == 0)) /* Points to end */ + goto fail; + if ((SYNTAX (d[-1]) == Sword) + != (SYNTAX (d == end1 ? *string2 : *d) == Sword)) + goto fail; + break; + + case wordbeg: + if (d == end2 /* Points to end */ + || (d == end1 && size2 == 0) /* Points to end */ + || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */ + goto fail; + if (d == string1 /* Points to first char */ + || SYNTAX (d[-1]) != Sword) /* prev char not letter */ + break; + goto fail; + + case wordend: + if (d == string1 /* Points to first char */ + || SYNTAX (d[-1]) != Sword) /* prev char not letter */ + goto fail; + if (d == end2 /* Points to end */ + || (d == end1 && size2 == 0) /* Points to end */ + || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */ + break; + goto fail; + +#ifdef emacs + case before_dot: + if (((d - string2 <= (unsigned) size2) + ? d - bf_p2 : d - bf_p1) + <= point) + goto fail; + break; + + case at_dot: + if (((d - string2 <= (unsigned) size2) + ? d - bf_p2 : d - bf_p1) + == point) + goto fail; + break; + + case after_dot: + if (((d - string2 <= (unsigned) size2) + ? d - bf_p2 : d - bf_p1) + >= point) + goto fail; + break; + + case wordchar: + mcnt = (int) Sword; + goto matchsyntax; + + case syntaxspec: + mcnt = *p++; + matchsyntax: + PREFETCH; + if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail; + break; + + case notwordchar: + mcnt = (int) Sword; + goto matchnotsyntax; + + case notsyntaxspec: + mcnt = *p++; + matchnotsyntax: + PREFETCH; + if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; + break; +#else + case wordchar: + PREFETCH; + if (SYNTAX (*d++) == 0) goto fail; + break; + + case notwordchar: + PREFETCH; + if (SYNTAX (*d++) != 0) goto fail; + break; +#endif /* not emacs */ + + case begbuf: + if (d == string1) /* Note, d cannot equal string2 */ + break; /* unless string1 == string2. */ + goto fail; + + case endbuf: + if (d == end2 || (d == end1 && size2 == 0)) + break; + goto fail; + + case exactn: + /* Match the next few pattern characters exactly. + mcnt is how many characters to match. */ + mcnt = *p++; + if (translate) + { + do + { + PREFETCH; + if (translate[*d++] != *p++) goto fail; + } + while (--mcnt); + } + else + { + do + { + PREFETCH; + if (*d++ != *p++) goto fail; + } + while (--mcnt); + } + break; + case unused: + case before_dot: + case at_dot: + case after_dot: + case syntaxspec: + case notsyntaxspec: + default: + break; + } + continue; /* Successfully matched one pattern command; keep matching */ + + /* Jump here if any matching operation fails. */ + fail: + if (stackp != stackb) + /* A restart point is known. Restart there and pop it. */ + { + if (!stackp[-2]) + { /* If innermost failure point is dormant, flush it and keep looking */ + stackp -= 2; + goto fail; + } + d = *--stackp; + p = *--stackp; + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else break; /* Matching at this starting point really fails! */ + } + return -1; /* Failure to match */ +} + +static int +memcmp_translate (s1, s2, len, translate) + unsigned char *s1, *s2; + register int len; + unsigned char *translate; +{ + register unsigned char *p1 = s1, *p2 = s2; + while (len) + { + if (translate [*p1++] != translate [*p2++]) return 1; + len--; + } + return 0; +} + +/* Entry points compatible with bsd4.2 regex library */ + +#ifndef emacs + +static struct re_pattern_buffer re_comp_buf; + +char * +re_comp (s) + const char *s; +{ + if (!s) + { + if (!re_comp_buf.buffer) + return "No previous regular expression"; + return 0; + } + + if (!re_comp_buf.buffer) + { + if (!(re_comp_buf.buffer = (char *) malloc (200))) + return "Memory exhausted"; + re_comp_buf.allocated = 200; + if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH))) + return "Memory exhausted"; + } + return re_compile_pattern (s, strlen (s), &re_comp_buf); +} + +int +re_exec (s) + char *s; +{ + int len = strlen (s); + return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0); +} + +#endif /* emacs */ + +#ifdef test + +#include + +/* Indexed by a character, gives the upper case equivalent of the character */ + +static char upcase[0400] = + { 000, 001, 002, 003, 004, 005, 006, 007, + 010, 011, 012, 013, 014, 015, 016, 017, + 020, 021, 022, 023, 024, 025, 026, 027, + 030, 031, 032, 033, 034, 035, 036, 037, + 040, 041, 042, 043, 044, 045, 046, 047, + 050, 051, 052, 053, 054, 055, 056, 057, + 060, 061, 062, 063, 064, 065, 066, 067, + 070, 071, 072, 073, 074, 075, 076, 077, + 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, + 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, + 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, + 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, + 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, + 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 + }; + +main (argc, argv) + int argc; + char **argv; +{ + char pat[80]; + struct re_pattern_buffer buf; + int i; + char c; + char fastmap[(1 << BYTEWIDTH)]; + + /* Allow a command argument to specify the style of syntax. */ + if (argc > 1) + obscure_syntax = atoi (argv[1]); + + buf.allocated = 40; + buf.buffer = (char *) malloc (buf.allocated); + buf.fastmap = fastmap; + buf.translate = upcase; + + while (1) + { + gets (pat); + + if (*pat) + { + re_compile_pattern (pat, strlen(pat), &buf); + + for (i = 0; i < buf.used; i++) + printchar (buf.buffer[i]); + + putchar_unfiltered ('\n'); + + printf_unfiltered ("%d allocated, %d used.\n", buf.allocated, buf.used); + + re_compile_fastmap (&buf); + printf_unfiltered ("Allowed by fastmap: "); + for (i = 0; i < (1 << BYTEWIDTH); i++) + if (fastmap[i]) printchar (i); + putchar_unfiltered ('\n'); + } + + gets (pat); /* Now read the string to match against */ + + i = re_match (&buf, pat, strlen (pat), 0, 0); + printf_unfiltered ("Match value %d.\n", i); + } +} + +#ifdef NOTDEF +print_buf (bufp) + struct re_pattern_buffer *bufp; +{ + int i; + + printf_unfiltered ("buf is :\n----------------\n"); + for (i = 0; i < bufp->used; i++) + printchar (bufp->buffer[i]); + + printf_unfiltered ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used); + + printf_unfiltered ("Allowed by fastmap: "); + for (i = 0; i < (1 << BYTEWIDTH); i++) + if (bufp->fastmap[i]) + printchar (i); + printf_unfiltered ("\nAllowed by translate: "); + if (bufp->translate) + for (i = 0; i < (1 << BYTEWIDTH); i++) + if (bufp->translate[i]) + printchar (i); + printf_unfiltered ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't"); + printf_unfiltered ("can %s be null\n----------", bufp->can_be_null ? "" : "not"); +} +#endif + +printchar (c) + char c; +{ + if (c < 041 || c >= 0177) + { + putchar_unfiltered ('\\'); + putchar_unfiltered (((c >> 6) & 3) + '0'); + putchar_unfiltered (((c >> 3) & 7) + '0'); + putchar_unfiltered ((c & 7) + '0'); + } + else + putchar_unfiltered (c); +} + +error (string) + char *string; +{ + puts_unfiltered (string); + exit (1); +} + +#endif /* test */ diff --git a/gdb/gnu-regex.h b/gdb/gnu-regex.h new file mode 100644 index 00000000000..7b1a4af20cd --- /dev/null +++ b/gdb/gnu-regex.h @@ -0,0 +1,181 @@ +/* Definitions for data structures callers pass the regex library. + Copyright (C) 1985, 1989 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Define number of parens for which we record the beginnings and ends. + This affects how much space the `struct re_registers' type takes up. */ +#ifndef RE_NREGS +#define RE_NREGS 10 +#endif + +/* These bits are used in the obscure_syntax variable to choose among + alternative regexp syntaxes. */ + +/* 1 means plain parentheses serve as grouping, and backslash + parentheses are needed for literal searching. + 0 means backslash-parentheses are grouping, and plain parentheses + are for literal searching. */ +#define RE_NO_BK_PARENS 1 + +/* 1 means plain | serves as the "or"-operator, and \| is a literal. + 0 means \| serves as the "or"-operator, and | is a literal. */ +#define RE_NO_BK_VBAR 2 + +/* 0 means plain + or ? serves as an operator, and \+, \? are literals. + 1 means \+, \? are operators and plain +, ? are literals. */ +#define RE_BK_PLUS_QM 4 + +/* 1 means | binds tighter than ^ or $. + 0 means the contrary. */ +#define RE_TIGHT_VBAR 8 + +/* 1 means treat \n as an _OR operator + 0 means treat it as a normal character */ +#define RE_NEWLINE_OR 16 + +/* 0 means that a special characters (such as *, ^, and $) always have + their special meaning regardless of the surrounding context. + 1 means that special characters may act as normal characters in some + contexts. Specifically, this applies to: + ^ - only special at the beginning, or after ( or | + $ - only special at the end, or before ) or | + *, +, ? - only special when not after the beginning, (, or | */ +#define RE_CONTEXT_INDEP_OPS 32 + +/* Now define combinations of bits for the standard possibilities. */ +#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS) +#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR) +#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR) +#define RE_SYNTAX_EMACS 0 + +/* This data structure is used to represent a compiled pattern. */ + +struct re_pattern_buffer + { + char *buffer; /* Space holding the compiled pattern commands. */ + int allocated; /* Size of space that buffer points to */ + int used; /* Length of portion of buffer actually occupied */ + char *fastmap; /* Pointer to fastmap, if any, or zero if none. */ + /* re_search uses the fastmap, if there is one, + to skip quickly over totally implausible characters */ + char *translate; /* Translate table to apply to all characters before comparing. + Or zero for no translation. + The translation is applied to a pattern when it is compiled + and to data when it is matched. */ + char fastmap_accurate; + /* Set to zero when a new pattern is stored, + set to one when the fastmap is updated from it. */ + char can_be_null; /* Set to one by compiling fastmap + if this pattern might match the null string. + It does not necessarily match the null string + in that case, but if this is zero, it cannot. + 2 as value means can match null string + but at end of range or before a character + listed in the fastmap. */ + }; + +/* Structure to store "register" contents data in. + + Pass the address of such a structure as an argument to re_match, etc., + if you want this information back. + + start[i] and end[i] record the string matched by \( ... \) grouping i, + for i from 1 to RE_NREGS - 1. + start[0] and end[0] record the entire string matched. */ + +struct re_registers + { + int start[RE_NREGS]; + int end[RE_NREGS]; + }; + +/* These are the command codes that appear in compiled regular expressions, one per byte. + Some command codes are followed by argument bytes. + A command code can specify any interpretation whatever for its arguments. + Zero-bytes may appear in the compiled regular expression. */ + +enum regexpcode + { + unused, + exactn, /* followed by one byte giving n, and then by n literal bytes */ + begline, /* fails unless at beginning of line */ + endline, /* fails unless at end of line */ + jump, /* followed by two bytes giving relative address to jump to */ + on_failure_jump, /* followed by two bytes giving relative address of place + to resume at in case of failure. */ + finalize_jump, /* Throw away latest failure point and then jump to address. */ + maybe_finalize_jump, /* Like jump but finalize if safe to do so. + This is used to jump back to the beginning + of a repeat. If the command that follows + this jump is clearly incompatible with the + one at the beginning of the repeat, such that + we can be sure that there is no use backtracking + out of repetitions already completed, + then we finalize. */ + dummy_failure_jump, /* jump, and push a dummy failure point. + This failure point will be thrown away + if an attempt is made to use it for a failure. + A + construct makes this before the first repeat. */ + anychar, /* matches any one character */ + charset, /* matches any one char belonging to specified set. + First following byte is # bitmap bytes. + Then come bytes for a bit-map saying which chars are in. + Bits in each byte are ordered low-bit-first. + A character is in the set if its bit is 1. + A character too large to have a bit in the map + is automatically not in the set */ + charset_not, /* similar but match any character that is NOT one of those specified */ + start_memory, /* starts remembering the text that is matched + and stores it in a memory register. + followed by one byte containing the register number. + Register numbers must be in the range 0 through NREGS. */ + stop_memory, /* stops remembering the text that is matched + and stores it in a memory register. + followed by one byte containing the register number. + Register numbers must be in the range 0 through NREGS. */ + duplicate, /* match a duplicate of something remembered. + Followed by one byte containing the index of the memory register. */ + before_dot, /* Succeeds if before dot */ + at_dot, /* Succeeds if at dot */ + after_dot, /* Succeeds if after dot */ + begbuf, /* Succeeds if at beginning of buffer */ + endbuf, /* Succeeds if at end of buffer */ + wordchar, /* Matches any word-constituent character */ + notwordchar, /* Matches any char that is not a word-constituent */ + wordbeg, /* Succeeds if at word beginning */ + wordend, /* Succeeds if at word end */ + wordbound, /* Succeeds if at a word boundary */ + notwordbound, /* Succeeds if not at a word boundary */ + syntaxspec, /* Matches any character whose syntax is specified. + followed by a byte which contains a syntax code, Sword or such like */ + notsyntaxspec /* Matches any character whose syntax differs from the specified. */ + }; + +extern char *re_compile_pattern (); +/* Is this really advertised? */ +extern void re_compile_fastmap (); +extern int re_search (), re_search_2 (); +extern int re_match (), re_match_2 (); + +/* 4.2 bsd compatibility (yuck) */ +extern char *re_comp (); +extern int re_exec (); + +#ifdef SYNTAX_TABLE +extern char *re_syntax_table; +#endif + +extern int re_set_syntax (); diff --git a/gdb/irix5-nat.c b/gdb/irix5-nat.c index 3ba00b1017e..16e2906055b 100644 --- a/gdb/irix5-nat.c +++ b/gdb/irix5-nat.c @@ -196,7 +196,7 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) #include "objfiles.h" #include "command.h" #include "frame.h" -#include "regex.h" +#include "gnu-regex.h" #include "inferior.h" #include "language.h" diff --git a/gdb/osfsolib.c b/gdb/osfsolib.c index d2b55302e96..79301e4fc5a 100644 --- a/gdb/osfsolib.c +++ b/gdb/osfsolib.c @@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "command.h" #include "target.h" #include "frame.h" -#include "regex.h" +#include "gnu-regex.h" #include "inferior.h" #include "language.h" diff --git a/gdb/regex.c b/gdb/regex.c deleted file mode 100644 index 62e460676b5..00000000000 --- a/gdb/regex.c +++ /dev/null @@ -1,1757 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 1985, 1989 Free Software Foundation, Inc. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* To test, compile with -Dtest. - This Dtestable feature turns this into a self-contained program - which reads a pattern, describes how it compiles, - then reads a string and searches for it. */ - -#ifdef emacs - -/* The `emacs' switch turns on certain special matching commands - that make sense only in emacs. */ - -#include "config.h" -#include "lisp.h" -#include "buffer.h" -#include "syntax.h" - -#else /* not emacs */ - -#include "defs.h" -#include "gdb_string.h" - -/* - * Define the syntax stuff, so we can do the \<...\> things. - */ - -#ifndef Sword /* must be non-zero in some of the tests below... */ -#define Sword 1 -#endif - -#define SYNTAX(c) re_syntax_table[c] - -#ifdef SYNTAX_TABLE - -char *re_syntax_table; - -#else - -static char re_syntax_table[256]; - -static void -init_syntax_once () -{ - register int c; - static int done = 0; - - if (done) - return; - - memset (re_syntax_table, '\0', sizeof re_syntax_table); - - for (c = 'a'; c <= 'z'; c++) - re_syntax_table[c] = Sword; - - for (c = 'A'; c <= 'Z'; c++) - re_syntax_table[c] = Sword; - - for (c = '0'; c <= '9'; c++) - re_syntax_table[c] = Sword; - - done = 1; -} - -#endif /* SYNTAX_TABLE */ -#endif /* not emacs */ - -#include "regex.h" - -/* Number of failure points to allocate space for initially, - when matching. If this number is exceeded, more space is allocated, - so it is not a hard limit. */ - -#ifndef NFAILURES -#define NFAILURES 80 -#endif /* NFAILURES */ - -/* width of a byte in bits */ - -#define BYTEWIDTH 8 - -/* We remove any previous definition of `SIGN_EXTEND_CHAR', - since ours (we hope) works properly with all combinations of - machines, compilers, `char' and `unsigned char' argument types. - (Per Bothner suggested the basic approach.) */ -#undef SIGN_EXTEND_CHAR -#if __STDC__ -#define SIGN_EXTEND_CHAR(c) ((signed char) (c)) -#else /* not __STDC__ */ -/* As in Harbison and Steele. */ -#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) -#endif - -static int obscure_syntax = 0; - -/* Specify the precise syntax of regexp for compilation. - This provides for compatibility for various utilities - which historically have different, incompatible syntaxes. - - The argument SYNTAX is a bit-mask containing the two bits - RE_NO_BK_PARENS and RE_NO_BK_VBAR. */ - -int -re_set_syntax (syntax) - int syntax; -{ - int ret; - - ret = obscure_syntax; - obscure_syntax = syntax; - return ret; -} - -/* re_compile_pattern takes a regular-expression string - and converts it into a buffer full of byte commands for matching. - - PATTERN is the address of the pattern string - SIZE is the length of it. - BUFP is a struct re_pattern_buffer * which points to the info - on where to store the byte commands. - This structure contains a char * which points to the - actual space, which should have been obtained with malloc. - re_compile_pattern may use realloc to grow the buffer space. - - The number of bytes of commands can be found out by looking in - the struct re_pattern_buffer that bufp pointed to, - after re_compile_pattern returns. -*/ - -#define PATPUSH(ch) (*b++ = (char) (ch)) - -#define PATFETCH(c) \ - {if (p == pend) goto end_of_pattern; \ - c = * (unsigned char *) p++; \ - if (translate) c = translate[c]; } - -#define PATFETCH_RAW(c) \ - {if (p == pend) goto end_of_pattern; \ - c = * (unsigned char *) p++; } - -#define PATUNFETCH p-- - -/* This is not an arbitrary limit: the arguments which represent offsets - into the pattern are two bytes long. So if 2^16 bytes turns out to - be too small, many things would have to change. */ -#define MAX_BUF_SIZE (1 << 16) - - -/* Extend the buffer by twice its current size via realloc and - reset the pointers that pointed into the old block to point to the - correct places in the new one. If extending the buffer results in it - being larger than MAX_BUF_SIZE, then flag memory exhausted. */ -#define EXTEND_BUFFER \ - do { \ - char *old_buffer = bufp->buffer; \ - if (bufp->allocated == MAX_BUF_SIZE) \ - goto too_big; \ - bufp->allocated <<= 1; \ - if (bufp->allocated > MAX_BUF_SIZE) \ - bufp->allocated = MAX_BUF_SIZE; \ - bufp->buffer = (char *) realloc (bufp->buffer, bufp->allocated);\ - if (bufp->buffer == NULL) \ - goto memory_exhausted; \ - /* If the buffer moved, move all the pointers into it. */ \ - if (old_buffer != bufp->buffer) \ - { \ - b = (b - old_buffer) + bufp->buffer; \ - begalt = (begalt - old_buffer) + bufp->buffer; \ - if (fixup_jump) \ - fixup_jump = (fixup_jump - old_buffer) + bufp->buffer;\ - if (laststart) \ - laststart = (laststart - old_buffer) + bufp->buffer; \ - if (pending_exact) \ - pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ - } \ - } while (0) - -static void store_jump (), insert_jump (); - -char * -re_compile_pattern (pattern, size, bufp) - char *pattern; - int size; - struct re_pattern_buffer *bufp; -{ - register char *b = bufp->buffer; - register char *p = pattern; - char *pend = pattern + size; - register unsigned c, c1; - char *p1; - unsigned char *translate = (unsigned char *) bufp->translate; - - /* address of the count-byte of the most recently inserted "exactn" command. - This makes it possible to tell whether a new exact-match character - can be added to that command or requires a new "exactn" command. */ - - char *pending_exact = 0; - - /* address of the place where a forward-jump should go - to the end of the containing expression. - Each alternative of an "or", except the last, ends with a forward-jump - of this sort. */ - - char *fixup_jump = 0; - - /* address of start of the most recently finished expression. - This tells postfix * where to find the start of its operand. */ - - char *laststart = 0; - - /* In processing a repeat, 1 means zero matches is allowed */ - - char zero_times_ok; - - /* In processing a repeat, 1 means many matches is allowed */ - - char many_times_ok; - - /* address of beginning of regexp, or inside of last \( */ - - char *begalt = b; - - /* Stack of information saved by \( and restored by \). - Four stack elements are pushed by each \(: - First, the value of b. - Second, the value of fixup_jump. - Third, the value of regnum. - Fourth, the value of begalt. */ - - int stackb[40]; - int *stackp = stackb; - int *stacke = stackb + 40; - int *stackt; - - /* Counts \('s as they are encountered. Remembered for the matching \), - where it becomes the "register number" to put in the stop_memory command */ - - int regnum = 1; - - bufp->fastmap_accurate = 0; - -#ifndef emacs -#ifndef SYNTAX_TABLE - /* - * Initialize the syntax table. - */ - init_syntax_once(); -#endif -#endif - - if (bufp->allocated == 0) - { - bufp->allocated = 28; - if (bufp->buffer) - /* EXTEND_BUFFER loses when bufp->allocated is 0 */ - bufp->buffer = (char *) realloc (bufp->buffer, 28); - else - /* Caller did not allocate a buffer. Do it for him */ - bufp->buffer = (char *) malloc (28); - if (!bufp->buffer) goto memory_exhausted; - begalt = b = bufp->buffer; - } - - while (p != pend) - { - if (b - bufp->buffer > bufp->allocated - 10) - /* Note that EXTEND_BUFFER clobbers c */ - EXTEND_BUFFER; - - PATFETCH (c); - - switch (c) - { - case '$': - if (obscure_syntax & RE_TIGHT_VBAR) - { - if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend) - goto normal_char; - /* Make operand of last vbar end before this `$'. */ - if (fixup_jump) - store_jump (fixup_jump, jump, b); - fixup_jump = 0; - PATPUSH (endline); - break; - } - - /* $ means succeed if at end of line, but only in special contexts. - If randomly in the middle of a pattern, it is a normal character. */ - if (p == pend || *p == '\n' - || (obscure_syntax & RE_CONTEXT_INDEP_OPS) - || (obscure_syntax & RE_NO_BK_PARENS - ? *p == ')' - : *p == '\\' && p[1] == ')') - || (obscure_syntax & RE_NO_BK_VBAR - ? *p == '|' - : *p == '\\' && p[1] == '|')) - { - PATPUSH (endline); - break; - } - goto normal_char; - - case '^': - /* ^ means succeed if at beg of line, but only if no preceding pattern. */ - - if (laststart && p[-2] != '\n' - && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - if (obscure_syntax & RE_TIGHT_VBAR) - { - if (p != pattern + 1 - && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - PATPUSH (begline); - begalt = b; - } - else - PATPUSH (begline); - break; - - case '+': - case '?': - if (obscure_syntax & RE_BK_PLUS_QM) - goto normal_char; - handle_plus: - case '*': - /* If there is no previous pattern, char not special. */ - if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - /* If there is a sequence of repetition chars, - collapse it down to equivalent to just one. */ - zero_times_ok = 0; - many_times_ok = 0; - while (1) - { - zero_times_ok |= c != '+'; - many_times_ok |= c != '?'; - if (p == pend) - break; - PATFETCH (c); - if (c == '*') - ; - else if (!(obscure_syntax & RE_BK_PLUS_QM) - && (c == '+' || c == '?')) - ; - else if ((obscure_syntax & RE_BK_PLUS_QM) - && c == '\\') - { - int c1; - PATFETCH (c1); - if (!(c1 == '+' || c1 == '?')) - { - PATUNFETCH; - PATUNFETCH; - break; - } - c = c1; - } - else - { - PATUNFETCH; - break; - } - } - - /* Star, etc. applied to an empty pattern is equivalent - to an empty pattern. */ - if (!laststart) - break; - - /* Now we know whether 0 matches is allowed, - and whether 2 or more matches is allowed. */ - if (many_times_ok) - { - /* If more than one repetition is allowed, - put in a backward jump at the end. */ - store_jump (b, maybe_finalize_jump, laststart - 3); - b += 3; - } - insert_jump (on_failure_jump, laststart, b + 3, b); - pending_exact = 0; - b += 3; - if (!zero_times_ok) - { - /* At least one repetition required: insert before the loop - a skip over the initial on-failure-jump instruction */ - insert_jump (dummy_failure_jump, laststart, laststart + 6, b); - b += 3; - } - break; - - case '.': - laststart = b; - PATPUSH (anychar); - break; - - case '[': - while (b - bufp->buffer - > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH) - /* Note that EXTEND_BUFFER clobbers c */ - EXTEND_BUFFER; - - laststart = b; - if (*p == '^') - PATPUSH (charset_not), p++; - else - PATPUSH (charset); - p1 = p; - - PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH); - /* Clear the whole map */ - memset (b, '\0', (1 << BYTEWIDTH) / BYTEWIDTH); - /* Read in characters and ranges, setting map bits */ - while (1) - { - PATFETCH (c); - if (c == ']' && p != p1 + 1) break; - if (*p == '-' && p[1] != ']') - { - PATFETCH (c1); - PATFETCH (c1); - while (c <= c1) - b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++; - } - else - { - b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH); - } - } - /* Discard any bitmap bytes that are all 0 at the end of the map. - Decrement the map-length byte too. */ - while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) - b[-1]--; - b += b[-1]; - break; - - case '(': - if (! (obscure_syntax & RE_NO_BK_PARENS)) - goto normal_char; - else - goto handle_open; - - case ')': - if (! (obscure_syntax & RE_NO_BK_PARENS)) - goto normal_char; - else - goto handle_close; - - case '\n': - if (! (obscure_syntax & RE_NEWLINE_OR)) - goto normal_char; - else - goto handle_bar; - - case '|': - if (! (obscure_syntax & RE_NO_BK_VBAR)) - goto normal_char; - else - goto handle_bar; - - case '\\': - if (p == pend) goto invalid_pattern; - PATFETCH_RAW (c); - switch (c) - { - case '(': - if (obscure_syntax & RE_NO_BK_PARENS) - goto normal_backsl; - handle_open: - if (stackp == stacke) goto nesting_too_deep; - if (regnum < RE_NREGS) - { - PATPUSH (start_memory); - PATPUSH (regnum); - } - *stackp++ = b - bufp->buffer; - *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0; - *stackp++ = regnum++; - *stackp++ = begalt - bufp->buffer; - fixup_jump = 0; - laststart = 0; - begalt = b; - break; - - case ')': - if (obscure_syntax & RE_NO_BK_PARENS) - goto normal_backsl; - handle_close: - if (stackp == stackb) goto unmatched_close; - begalt = *--stackp + bufp->buffer; - if (fixup_jump) - store_jump (fixup_jump, jump, b); - if (stackp[-1] < RE_NREGS) - { - PATPUSH (stop_memory); - PATPUSH (stackp[-1]); - } - stackp -= 2; - fixup_jump = 0; - if (*stackp) - fixup_jump = *stackp + bufp->buffer - 1; - laststart = *--stackp + bufp->buffer; - break; - - case '|': - if (obscure_syntax & RE_NO_BK_VBAR) - goto normal_backsl; - handle_bar: - insert_jump (on_failure_jump, begalt, b + 6, b); - pending_exact = 0; - b += 3; - if (fixup_jump) - store_jump (fixup_jump, jump, b); - fixup_jump = b; - b += 3; - laststart = 0; - begalt = b; - break; - -#ifdef emacs - case '=': - PATPUSH (at_dot); - break; - - case 's': - laststart = b; - PATPUSH (syntaxspec); - PATFETCH (c); - PATPUSH (syntax_spec_code[c]); - break; - - case 'S': - laststart = b; - PATPUSH (notsyntaxspec); - PATFETCH (c); - PATPUSH (syntax_spec_code[c]); - break; -#endif /* emacs */ - - case 'w': - laststart = b; - PATPUSH (wordchar); - break; - - case 'W': - laststart = b; - PATPUSH (notwordchar); - break; - - case '<': - PATPUSH (wordbeg); - break; - - case '>': - PATPUSH (wordend); - break; - - case 'b': - PATPUSH (wordbound); - break; - - case 'B': - PATPUSH (notwordbound); - break; - - case '`': - PATPUSH (begbuf); - break; - - case '\'': - PATPUSH (endbuf); - break; - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - c1 = c - '0'; - if (c1 >= regnum) - goto normal_char; - for (stackt = stackp - 2; stackt > stackb; stackt -= 4) - if (*stackt == c1) - goto normal_char; - laststart = b; - PATPUSH (duplicate); - PATPUSH (c1); - break; - - case '+': - case '?': - if (obscure_syntax & RE_BK_PLUS_QM) - goto handle_plus; - - default: - normal_backsl: - /* You might think it would be useful for \ to mean - not to translate; but if we don't translate it - it will never match anything. */ - if (translate) c = translate[c]; - goto normal_char; - } - break; - - default: - normal_char: - if (!pending_exact || pending_exact + *pending_exact + 1 != b - || *pending_exact == 0177 || *p == '*' || *p == '^' - || ((obscure_syntax & RE_BK_PLUS_QM) - ? *p == '\\' && (p[1] == '+' || p[1] == '?') - : (*p == '+' || *p == '?'))) - { - laststart = b; - PATPUSH (exactn); - pending_exact = b; - PATPUSH (0); - } - PATPUSH (c); - (*pending_exact)++; - } - } - - if (fixup_jump) - store_jump (fixup_jump, jump, b); - - if (stackp != stackb) goto unmatched_open; - - bufp->used = b - bufp->buffer; - return 0; - - invalid_pattern: - return "Invalid regular expression"; - - unmatched_open: - return "Unmatched \\("; - - unmatched_close: - return "Unmatched \\)"; - - end_of_pattern: - return "Premature end of regular expression"; - - nesting_too_deep: - return "Nesting too deep"; - - too_big: - return "Regular expression too big"; - - memory_exhausted: - return "Memory exhausted"; -} - -/* Store where `from' points a jump operation to jump to where `to' points. - `opcode' is the opcode to store. */ - -static void -store_jump (from, opcode, to) - char *from, *to; - char opcode; -{ - from[0] = opcode; - from[1] = (to - (from + 3)) & 0377; - from[2] = (to - (from + 3)) >> 8; -} - -/* Open up space at char FROM, and insert there a jump to TO. - CURRENT_END gives te end of the storage no in use, - so we know how much data to copy up. - OP is the opcode of the jump to insert. - - If you call this function, you must zero out pending_exact. */ - -static void -insert_jump (op, from, to, current_end) - char op; - char *from, *to, *current_end; -{ - register char *pto = current_end + 3; - register char *pfrom = current_end; - while (pfrom != from) - *--pto = *--pfrom; - store_jump (from, op, to); -} - -/* Given a pattern, compute a fastmap from it. - The fastmap records which of the (1 << BYTEWIDTH) possible characters - can start a string that matches the pattern. - This fastmap is used by re_search to skip quickly over totally implausible text. - - The caller must supply the address of a (1 << BYTEWIDTH)-byte data area - as bufp->fastmap. - The other components of bufp describe the pattern to be used. */ - -void -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - unsigned char *pattern = (unsigned char *) bufp->buffer; - int size = bufp->used; - register char *fastmap = bufp->fastmap; - register unsigned char *p = pattern; - register unsigned char *pend = pattern + size; - register int j; - unsigned char *translate = (unsigned char *) bufp->translate; - - unsigned char *stackb[NFAILURES]; - unsigned char **stackp = stackb; - - memset (fastmap, '\0', (1 << BYTEWIDTH)); - bufp->fastmap_accurate = 1; - bufp->can_be_null = 0; - - while (p) - { - if (p == pend) - { - bufp->can_be_null = 1; - break; - } -#ifdef SWITCH_ENUM_BUG - switch ((int) ((enum regexpcode) *p++)) -#else - switch ((enum regexpcode) *p++) -#endif - { - case exactn: - if (translate) - fastmap[translate[p[1]]] = 1; - else - fastmap[p[1]] = 1; - break; - - case begline: - case before_dot: - case at_dot: - case after_dot: - case begbuf: - case endbuf: - case wordbound: - case notwordbound: - case wordbeg: - case wordend: - continue; - - case endline: - if (translate) - fastmap[translate['\n']] = 1; - else - fastmap['\n'] = 1; - if (bufp->can_be_null != 1) - bufp->can_be_null = 2; - break; - - case finalize_jump: - case maybe_finalize_jump: - case jump: - case dummy_failure_jump: - bufp->can_be_null = 1; - j = *p++ & 0377; - j += SIGN_EXTEND_CHAR (*(char *)p) << 8; - p += j + 1; /* The 1 compensates for missing ++ above */ - if (j > 0) - continue; - /* Jump backward reached implies we just went through - the body of a loop and matched nothing. - Opcode jumped to should be an on_failure_jump. - Just treat it like an ordinary jump. - For a * loop, it has pushed its failure point already; - if so, discard that as redundant. */ - if ((enum regexpcode) *p != on_failure_jump) - continue; - p++; - j = *p++ & 0377; - j += SIGN_EXTEND_CHAR (*(char *)p) << 8; - p += j + 1; /* The 1 compensates for missing ++ above */ - if (stackp != stackb && *stackp == p) - stackp--; - continue; - - case on_failure_jump: - j = *p++ & 0377; - j += SIGN_EXTEND_CHAR (*(char *)p) << 8; - p++; - *++stackp = p + j; - continue; - - case start_memory: - case stop_memory: - p++; - continue; - - case duplicate: - bufp->can_be_null = 1; - fastmap['\n'] = 1; - case anychar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (j != '\n') - fastmap[j] = 1; - if (bufp->can_be_null) - return; - /* Don't return; check the alternative paths - so we can set can_be_null if appropriate. */ - break; - - case wordchar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) == Sword) - fastmap[j] = 1; - break; - - case notwordchar: - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) != Sword) - fastmap[j] = 1; - break; - -#ifdef emacs - case syntaxspec: - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) == (enum syntaxcode) k) - fastmap[j] = 1; - break; - - case notsyntaxspec: - k = *p++; - for (j = 0; j < (1 << BYTEWIDTH); j++) - if (SYNTAX (j) != (enum syntaxcode) k) - fastmap[j] = 1; - break; -#endif /* emacs */ - - case charset: - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) - { - if (translate) - fastmap[translate[j]] = 1; - else - fastmap[j] = 1; - } - break; - - case charset_not: - /* Chars beyond end of map must be allowed */ - for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) - if (translate) - fastmap[translate[j]] = 1; - else - fastmap[j] = 1; - - for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) - if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) - { - if (translate) - fastmap[translate[j]] = 1; - else - fastmap[j] = 1; - } - break; - case unused: - case syntaxspec: - case notsyntaxspec: - default: - break; - } - - /* Get here means we have successfully found the possible starting characters - of one path of the pattern. We need not follow this path any farther. - Instead, look at the next alternative remembered in the stack. */ - if (stackp != stackb) - p = *stackp--; - else - break; - } -} - -/* Like re_search_2, below, but only one string is specified. */ - -int -re_search (pbufp, string, size, startpos, range, regs) - struct re_pattern_buffer *pbufp; - char *string; - int size, startpos, range; - struct re_registers *regs; -{ - return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size); -} - -/* Like re_match_2 but tries first a match starting at index STARTPOS, - then at STARTPOS + 1, and so on. - RANGE is the number of places to try before giving up. - If RANGE is negative, the starting positions tried are - STARTPOS, STARTPOS - 1, etc. - It is up to the caller to make sure that range is not so large - as to take the starting position outside of the input strings. - -The value returned is the position at which the match was found, - or -1 if no match was found, - or -2 if error (such as failure stack overflow). */ - -int -re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop) - struct re_pattern_buffer *pbufp; - char *string1, *string2; - int size1, size2; - int startpos; - register int range; - struct re_registers *regs; - int mstop; -{ - register char *fastmap = pbufp->fastmap; - register unsigned char *translate = (unsigned char *) pbufp->translate; - int total = size1 + size2; - int val; - - /* Update the fastmap now if not correct already */ - if (fastmap && !pbufp->fastmap_accurate) - re_compile_fastmap (pbufp); - - /* Don't waste time in a long search for a pattern - that says it is anchored. */ - if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf - && range > 0) - { - if (startpos > 0) - return -1; - else - range = 1; - } - - while (1) - { - /* If a fastmap is supplied, skip quickly over characters - that cannot possibly be the start of a match. - Note, however, that if the pattern can possibly match - the null string, we must test it at each starting point - so that we take the first null string we get. */ - - if (fastmap && startpos < total && pbufp->can_be_null != 1) - { - if (range > 0) - { - register int lim = 0; - register unsigned char *p; - int irange = range; - if (startpos < size1 && startpos + range >= size1) - lim = range - (size1 - startpos); - - p = ((unsigned char *) - &(startpos >= size1 ? string2 - size1 : string1)[startpos]); - - if (translate) - { - while (range > lim && !fastmap[translate[*p++]]) - range--; - } - else - { - while (range > lim && !fastmap[*p++]) - range--; - } - startpos += irange - range; - } - else - { - register unsigned char c; - if (startpos >= size1) - c = string2[startpos - size1]; - else - c = string1[startpos]; - c &= 0xff; - if (translate ? !fastmap[translate[c]] : !fastmap[c]) - goto advance; - } - } - - if (range >= 0 && startpos == total - && fastmap && pbufp->can_be_null == 0) - return -1; - - val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs, mstop); - if (0 <= val) - { - if (val == -2) - return -2; - return startpos; - } - -#ifdef C_ALLOCA - alloca (0); -#endif /* C_ALLOCA */ - - advance: - if (!range) break; - if (range > 0) range--, startpos++; else range++, startpos--; - } - return -1; -} - -#ifndef emacs /* emacs never uses this */ -int -re_match (pbufp, string, size, pos, regs) - struct re_pattern_buffer *pbufp; - char *string; - int size, pos; - struct re_registers *regs; -{ - return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size); -} -#endif /* emacs */ - -/* Maximum size of failure stack. Beyond this, overflow is an error. */ - -int re_max_failures = 2000; - -static int memcmp_translate(); -/* Match the pattern described by PBUFP - against data which is the virtual concatenation of STRING1 and STRING2. - SIZE1 and SIZE2 are the sizes of the two data strings. - Start the match at position POS. - Do not consider matching past the position MSTOP. - - If pbufp->fastmap is nonzero, then it had better be up to date. - - The reason that the data to match are specified as two components - which are to be regarded as concatenated - is so this function can be used directly on the contents of an Emacs buffer. - - -1 is returned if there is no match. -2 is returned if there is - an error (such as match stack overflow). Otherwise the value is the length - of the substring which was matched. */ - -int -re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop) - struct re_pattern_buffer *pbufp; - unsigned char *string1, *string2; - int size1, size2; - int pos; - struct re_registers *regs; - int mstop; -{ - register unsigned char *p = (unsigned char *) pbufp->buffer; - register unsigned char *pend = p + pbufp->used; - /* End of first string */ - unsigned char *end1; - /* End of second string */ - unsigned char *end2; - /* Pointer just past last char to consider matching */ - unsigned char *end_match_1, *end_match_2; - register unsigned char *d, *dend; - register int mcnt; - unsigned char *translate = (unsigned char *) pbufp->translate; - - /* Failure point stack. Each place that can handle a failure further down the line - pushes a failure point on this stack. It consists of two char *'s. - The first one pushed is where to resume scanning the pattern; - the second pushed is where to resume scanning the strings. - If the latter is zero, the failure point is a "dummy". - If a failure happens and the innermost failure point is dormant, - it discards that failure point and tries the next one. */ - - unsigned char *initial_stack[2 * NFAILURES]; - unsigned char **stackb = initial_stack; - unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES]; - - /* Information on the "contents" of registers. - These are pointers into the input strings; they record - just what was matched (on this attempt) by some part of the pattern. - The start_memory command stores the start of a register's contents - and the stop_memory command stores the end. - - At that point, regstart[regnum] points to the first character in the register, - regend[regnum] points to the first character beyond the end of the register, - regstart_seg1[regnum] is true iff regstart[regnum] points into string1, - and regend_seg1[regnum] is true iff regend[regnum] points into string1. */ - - unsigned char *regstart[RE_NREGS]; - unsigned char *regend[RE_NREGS]; - unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS]; - - /* Set up pointers to ends of strings. - Don't allow the second string to be empty unless both are empty. */ - if (!size2) - { - string2 = string1; - size2 = size1; - string1 = 0; - size1 = 0; - } - end1 = string1 + size1; - end2 = string2 + size2; - - /* Compute where to stop matching, within the two strings */ - if (mstop <= size1) - { - end_match_1 = string1 + mstop; - end_match_2 = string2; - } - else - { - end_match_1 = end1; - end_match_2 = string2 + mstop - size1; - } - - /* Initialize \) text positions to -1 - to mark ones that no \( or \) has been seen for. */ - - for (mcnt = 0; mcnt < sizeof (regend) / sizeof (*regend); mcnt++) - regend[mcnt] = (unsigned char *) -1; - - /* `p' scans through the pattern as `d' scans through the data. - `dend' is the end of the input string that `d' points within. - `d' is advanced into the following input string whenever necessary, - but this happens before fetching; - therefore, at the beginning of the loop, - `d' can be pointing at the end of a string, - but it cannot equal string2. */ - - if (pos <= size1) - d = string1 + pos, dend = end_match_1; - else - d = string2 + pos - size1, dend = end_match_2; - -/* Write PREFETCH; just before fetching a character with *d. */ -#define PREFETCH \ - while (d == dend) \ - { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \ - d = string2; /* end of string1 => advance to string2. */ \ - dend = end_match_2; } - - /* This loop loops over pattern commands. - It exits by returning from the function if match is complete, - or it drops through if match fails at this starting point in the input data. */ - - while (1) - { - if (p == pend) - /* End of pattern means we have succeeded! */ - { - /* If caller wants register contents data back, convert it to indices */ - if (regs) - { - regs->start[0] = pos; - if (dend == end_match_1) - regs->end[0] = d - string1; - else - regs->end[0] = d - string2 + size1; - for (mcnt = 1; mcnt < RE_NREGS; mcnt++) - { - if (regend[mcnt] == (unsigned char *) -1) - { - regs->start[mcnt] = -1; - regs->end[mcnt] = -1; - continue; - } - if (regstart_seg1[mcnt]) - regs->start[mcnt] = regstart[mcnt] - string1; - else - regs->start[mcnt] = regstart[mcnt] - string2 + size1; - if (regend_seg1[mcnt]) - regs->end[mcnt] = regend[mcnt] - string1; - else - regs->end[mcnt] = regend[mcnt] - string2 + size1; - } - } - if (dend == end_match_1) - return (d - string1 - pos); - else - return d - string2 + size1 - pos; - } - - /* Otherwise match next pattern command */ -#ifdef SWITCH_ENUM_BUG - switch ((int) ((enum regexpcode) *p++)) -#else - switch ((enum regexpcode) *p++) -#endif - { - - /* \( is represented by a start_memory, \) by a stop_memory. - Both of those commands contain a "register number" argument. - The text matched within the \( and \) is recorded under that number. - Then, \ turns into a `duplicate' command which - is followed by the numeric value of as the register number. */ - - case start_memory: - regstart[*p] = d; - regstart_seg1[*p++] = (dend == end_match_1); - break; - - case stop_memory: - regend[*p] = d; - regend_seg1[*p++] = (dend == end_match_1); - break; - - case duplicate: - { - int regno = *p++; /* Get which register to match against */ - register unsigned char *d2, *dend2; - - d2 = regstart[regno]; - dend2 = ((regstart_seg1[regno] == regend_seg1[regno]) - ? regend[regno] : end_match_1); - while (1) - { - /* Advance to next segment in register contents, if necessary */ - while (d2 == dend2) - { - if (dend2 == end_match_2) break; - if (dend2 == regend[regno]) break; - d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */ - } - /* At end of register contents => success */ - if (d2 == dend2) break; - - /* Advance to next segment in data being matched, if necessary */ - PREFETCH; - - /* mcnt gets # consecutive chars to compare */ - mcnt = dend - d; - if (mcnt > dend2 - d2) - mcnt = dend2 - d2; - /* Compare that many; failure if mismatch, else skip them. */ - if (translate ? memcmp_translate (d, d2, mcnt, translate) : memcmp (d, d2, mcnt)) - goto fail; - d += mcnt, d2 += mcnt; - } - } - break; - - case anychar: - /* fetch a data character */ - PREFETCH; - /* Match anything but a newline. */ - if ((translate ? translate[*d++] : *d++) == '\n') - goto fail; - break; - - case charset: - case charset_not: - { - /* Nonzero for charset_not */ - int not = 0; - register int c; - if (*(p - 1) == (unsigned char) charset_not) - not = 1; - - /* fetch a data character */ - PREFETCH; - - if (translate) - c = translate [*d]; - else - c = *d; - - if (c < *p * BYTEWIDTH - && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - - p += 1 + *p; - - if (!not) goto fail; - d++; - break; - } - - case begline: - if (d == string1 || d[-1] == '\n') - break; - goto fail; - - case endline: - if (d == end2 - || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n')) - break; - goto fail; - - /* "or" constructs ("|") are handled by starting each alternative - with an on_failure_jump that points to the start of the next alternative. - Each alternative except the last ends with a jump to the joining point. - (Actually, each jump except for the last one really jumps - to the following jump, because tensioning the jumps is a hassle.) */ - - /* The start of a stupid repeat has an on_failure_jump that points - past the end of the repeat text. - This makes a failure point so that, on failure to match a repetition, - matching restarts past as many repetitions have been found - with no way to fail and look for another one. */ - - /* A smart repeat is similar but loops back to the on_failure_jump - so that each repetition makes another failure point. */ - - case on_failure_jump: - if (stackp == stacke) - { - unsigned char **stackx; - if (stacke - stackb > re_max_failures * 2) - return -2; - stackx = (unsigned char **) alloca (2 * (stacke - stackb) - * sizeof (char *)); - memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *)); - stackp = stackx + (stackp - stackb); - stacke = stackx + 2 * (stacke - stackb); - stackb = stackx; - } - mcnt = *p++ & 0377; - mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; - p++; - *stackp++ = mcnt + p; - *stackp++ = d; - break; - - /* The end of a smart repeat has an maybe_finalize_jump back. - Change it either to a finalize_jump or an ordinary jump. */ - - case maybe_finalize_jump: - mcnt = *p++ & 0377; - mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; - p++; - { - register unsigned char *p2 = p; - /* Compare what follows with the begining of the repeat. - If we can establish that there is nothing that they would - both match, we can change to finalize_jump */ - while (p2 != pend - && (*p2 == (unsigned char) stop_memory - || *p2 == (unsigned char) start_memory)) - p2++; - if (p2 == pend) - p[-3] = (unsigned char) finalize_jump; - else if (*p2 == (unsigned char) exactn - || *p2 == (unsigned char) endline) - { - register int c = *p2 == (unsigned char) endline ? '\n' : p2[2]; - register unsigned char *p1 = p + mcnt; - /* p1[0] ... p1[2] are an on_failure_jump. - Examine what follows that */ - if (p1[3] == (unsigned char) exactn && p1[5] != c) - p[-3] = (unsigned char) finalize_jump; - else if (p1[3] == (unsigned char) charset - || p1[3] == (unsigned char) charset_not) - { - int not = p1[3] == (unsigned char) charset_not; - if (c < p1[4] * BYTEWIDTH - && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) - not = !not; - /* not is 1 if c would match */ - /* That means it is not safe to finalize */ - if (!not) - p[-3] = (unsigned char) finalize_jump; - } - } - } - p -= 2; - if (p[-1] != (unsigned char) finalize_jump) - { - p[-1] = (unsigned char) jump; - goto nofinalize; - } - - /* The end of a stupid repeat has a finalize-jump - back to the start, where another failure point will be made - which will point after all the repetitions found so far. */ - - case finalize_jump: - stackp -= 2; - - case jump: - nofinalize: - mcnt = *p++ & 0377; - mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8; - p += mcnt + 1; /* The 1 compensates for missing ++ above */ - break; - - case dummy_failure_jump: - if (stackp == stacke) - { - unsigned char **stackx - = (unsigned char **) alloca (2 * (stacke - stackb) - * sizeof (char *)); - memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *)); - stackp = stackx + (stackp - stackb); - stacke = stackx + 2 * (stacke - stackb); - stackb = stackx; - } - *stackp++ = 0; - *stackp++ = 0; - goto nofinalize; - - case wordbound: - if (d == string1 /* Points to first char */ - || d == end2 /* Points to end */ - || (d == end1 && size2 == 0)) /* Points to end */ - break; - if ((SYNTAX (d[-1]) == Sword) - != (SYNTAX (d == end1 ? *string2 : *d) == Sword)) - break; - goto fail; - - case notwordbound: - if (d == string1 /* Points to first char */ - || d == end2 /* Points to end */ - || (d == end1 && size2 == 0)) /* Points to end */ - goto fail; - if ((SYNTAX (d[-1]) == Sword) - != (SYNTAX (d == end1 ? *string2 : *d) == Sword)) - goto fail; - break; - - case wordbeg: - if (d == end2 /* Points to end */ - || (d == end1 && size2 == 0) /* Points to end */ - || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */ - goto fail; - if (d == string1 /* Points to first char */ - || SYNTAX (d[-1]) != Sword) /* prev char not letter */ - break; - goto fail; - - case wordend: - if (d == string1 /* Points to first char */ - || SYNTAX (d[-1]) != Sword) /* prev char not letter */ - goto fail; - if (d == end2 /* Points to end */ - || (d == end1 && size2 == 0) /* Points to end */ - || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */ - break; - goto fail; - -#ifdef emacs - case before_dot: - if (((d - string2 <= (unsigned) size2) - ? d - bf_p2 : d - bf_p1) - <= point) - goto fail; - break; - - case at_dot: - if (((d - string2 <= (unsigned) size2) - ? d - bf_p2 : d - bf_p1) - == point) - goto fail; - break; - - case after_dot: - if (((d - string2 <= (unsigned) size2) - ? d - bf_p2 : d - bf_p1) - >= point) - goto fail; - break; - - case wordchar: - mcnt = (int) Sword; - goto matchsyntax; - - case syntaxspec: - mcnt = *p++; - matchsyntax: - PREFETCH; - if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail; - break; - - case notwordchar: - mcnt = (int) Sword; - goto matchnotsyntax; - - case notsyntaxspec: - mcnt = *p++; - matchnotsyntax: - PREFETCH; - if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; - break; -#else - case wordchar: - PREFETCH; - if (SYNTAX (*d++) == 0) goto fail; - break; - - case notwordchar: - PREFETCH; - if (SYNTAX (*d++) != 0) goto fail; - break; -#endif /* not emacs */ - - case begbuf: - if (d == string1) /* Note, d cannot equal string2 */ - break; /* unless string1 == string2. */ - goto fail; - - case endbuf: - if (d == end2 || (d == end1 && size2 == 0)) - break; - goto fail; - - case exactn: - /* Match the next few pattern characters exactly. - mcnt is how many characters to match. */ - mcnt = *p++; - if (translate) - { - do - { - PREFETCH; - if (translate[*d++] != *p++) goto fail; - } - while (--mcnt); - } - else - { - do - { - PREFETCH; - if (*d++ != *p++) goto fail; - } - while (--mcnt); - } - break; - case unused: - case before_dot: - case at_dot: - case after_dot: - case syntaxspec: - case notsyntaxspec: - default: - break; - } - continue; /* Successfully matched one pattern command; keep matching */ - - /* Jump here if any matching operation fails. */ - fail: - if (stackp != stackb) - /* A restart point is known. Restart there and pop it. */ - { - if (!stackp[-2]) - { /* If innermost failure point is dormant, flush it and keep looking */ - stackp -= 2; - goto fail; - } - d = *--stackp; - p = *--stackp; - if (d >= string1 && d <= end1) - dend = end_match_1; - } - else break; /* Matching at this starting point really fails! */ - } - return -1; /* Failure to match */ -} - -static int -memcmp_translate (s1, s2, len, translate) - unsigned char *s1, *s2; - register int len; - unsigned char *translate; -{ - register unsigned char *p1 = s1, *p2 = s2; - while (len) - { - if (translate [*p1++] != translate [*p2++]) return 1; - len--; - } - return 0; -} - -/* Entry points compatible with bsd4.2 regex library */ - -#ifndef emacs - -static struct re_pattern_buffer re_comp_buf; - -char * -re_comp (s) - const char *s; -{ - if (!s) - { - if (!re_comp_buf.buffer) - return "No previous regular expression"; - return 0; - } - - if (!re_comp_buf.buffer) - { - if (!(re_comp_buf.buffer = (char *) malloc (200))) - return "Memory exhausted"; - re_comp_buf.allocated = 200; - if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH))) - return "Memory exhausted"; - } - return re_compile_pattern (s, strlen (s), &re_comp_buf); -} - -int -re_exec (s) - char *s; -{ - int len = strlen (s); - return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0); -} - -#endif /* emacs */ - -#ifdef test - -#include - -/* Indexed by a character, gives the upper case equivalent of the character */ - -static char upcase[0400] = - { 000, 001, 002, 003, 004, 005, 006, 007, - 010, 011, 012, 013, 014, 015, 016, 017, - 020, 021, 022, 023, 024, 025, 026, 027, - 030, 031, 032, 033, 034, 035, 036, 037, - 040, 041, 042, 043, 044, 045, 046, 047, - 050, 051, 052, 053, 054, 055, 056, 057, - 060, 061, 062, 063, 064, 065, 066, 067, - 070, 071, 072, 073, 074, 075, 076, 077, - 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, - 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, - 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, - 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, - 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, - 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, - 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, - 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, - 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, - 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, - 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, - 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, - 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, - 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, - 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, - 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, - 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, - 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, - 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, - 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, - 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, - 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377 - }; - -main (argc, argv) - int argc; - char **argv; -{ - char pat[80]; - struct re_pattern_buffer buf; - int i; - char c; - char fastmap[(1 << BYTEWIDTH)]; - - /* Allow a command argument to specify the style of syntax. */ - if (argc > 1) - obscure_syntax = atoi (argv[1]); - - buf.allocated = 40; - buf.buffer = (char *) malloc (buf.allocated); - buf.fastmap = fastmap; - buf.translate = upcase; - - while (1) - { - gets (pat); - - if (*pat) - { - re_compile_pattern (pat, strlen(pat), &buf); - - for (i = 0; i < buf.used; i++) - printchar (buf.buffer[i]); - - putchar_unfiltered ('\n'); - - printf_unfiltered ("%d allocated, %d used.\n", buf.allocated, buf.used); - - re_compile_fastmap (&buf); - printf_unfiltered ("Allowed by fastmap: "); - for (i = 0; i < (1 << BYTEWIDTH); i++) - if (fastmap[i]) printchar (i); - putchar_unfiltered ('\n'); - } - - gets (pat); /* Now read the string to match against */ - - i = re_match (&buf, pat, strlen (pat), 0, 0); - printf_unfiltered ("Match value %d.\n", i); - } -} - -#ifdef NOTDEF -print_buf (bufp) - struct re_pattern_buffer *bufp; -{ - int i; - - printf_unfiltered ("buf is :\n----------------\n"); - for (i = 0; i < bufp->used; i++) - printchar (bufp->buffer[i]); - - printf_unfiltered ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used); - - printf_unfiltered ("Allowed by fastmap: "); - for (i = 0; i < (1 << BYTEWIDTH); i++) - if (bufp->fastmap[i]) - printchar (i); - printf_unfiltered ("\nAllowed by translate: "); - if (bufp->translate) - for (i = 0; i < (1 << BYTEWIDTH); i++) - if (bufp->translate[i]) - printchar (i); - printf_unfiltered ("\nfastmap is%s accurate\n", bufp->fastmap_accurate ? "" : "n't"); - printf_unfiltered ("can %s be null\n----------", bufp->can_be_null ? "" : "not"); -} -#endif - -printchar (c) - char c; -{ - if (c < 041 || c >= 0177) - { - putchar_unfiltered ('\\'); - putchar_unfiltered (((c >> 6) & 3) + '0'); - putchar_unfiltered (((c >> 3) & 7) + '0'); - putchar_unfiltered ((c & 7) + '0'); - } - else - putchar_unfiltered (c); -} - -error (string) - char *string; -{ - puts_unfiltered (string); - exit (1); -} - -#endif /* test */ diff --git a/gdb/regex.h b/gdb/regex.h deleted file mode 100644 index 7b1a4af20cd..00000000000 --- a/gdb/regex.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Definitions for data structures callers pass the regex library. - Copyright (C) 1985, 1989 Free Software Foundation, Inc. - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* Define number of parens for which we record the beginnings and ends. - This affects how much space the `struct re_registers' type takes up. */ -#ifndef RE_NREGS -#define RE_NREGS 10 -#endif - -/* These bits are used in the obscure_syntax variable to choose among - alternative regexp syntaxes. */ - -/* 1 means plain parentheses serve as grouping, and backslash - parentheses are needed for literal searching. - 0 means backslash-parentheses are grouping, and plain parentheses - are for literal searching. */ -#define RE_NO_BK_PARENS 1 - -/* 1 means plain | serves as the "or"-operator, and \| is a literal. - 0 means \| serves as the "or"-operator, and | is a literal. */ -#define RE_NO_BK_VBAR 2 - -/* 0 means plain + or ? serves as an operator, and \+, \? are literals. - 1 means \+, \? are operators and plain +, ? are literals. */ -#define RE_BK_PLUS_QM 4 - -/* 1 means | binds tighter than ^ or $. - 0 means the contrary. */ -#define RE_TIGHT_VBAR 8 - -/* 1 means treat \n as an _OR operator - 0 means treat it as a normal character */ -#define RE_NEWLINE_OR 16 - -/* 0 means that a special characters (such as *, ^, and $) always have - their special meaning regardless of the surrounding context. - 1 means that special characters may act as normal characters in some - contexts. Specifically, this applies to: - ^ - only special at the beginning, or after ( or | - $ - only special at the end, or before ) or | - *, +, ? - only special when not after the beginning, (, or | */ -#define RE_CONTEXT_INDEP_OPS 32 - -/* Now define combinations of bits for the standard possibilities. */ -#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS) -#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR) -#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR) -#define RE_SYNTAX_EMACS 0 - -/* This data structure is used to represent a compiled pattern. */ - -struct re_pattern_buffer - { - char *buffer; /* Space holding the compiled pattern commands. */ - int allocated; /* Size of space that buffer points to */ - int used; /* Length of portion of buffer actually occupied */ - char *fastmap; /* Pointer to fastmap, if any, or zero if none. */ - /* re_search uses the fastmap, if there is one, - to skip quickly over totally implausible characters */ - char *translate; /* Translate table to apply to all characters before comparing. - Or zero for no translation. - The translation is applied to a pattern when it is compiled - and to data when it is matched. */ - char fastmap_accurate; - /* Set to zero when a new pattern is stored, - set to one when the fastmap is updated from it. */ - char can_be_null; /* Set to one by compiling fastmap - if this pattern might match the null string. - It does not necessarily match the null string - in that case, but if this is zero, it cannot. - 2 as value means can match null string - but at end of range or before a character - listed in the fastmap. */ - }; - -/* Structure to store "register" contents data in. - - Pass the address of such a structure as an argument to re_match, etc., - if you want this information back. - - start[i] and end[i] record the string matched by \( ... \) grouping i, - for i from 1 to RE_NREGS - 1. - start[0] and end[0] record the entire string matched. */ - -struct re_registers - { - int start[RE_NREGS]; - int end[RE_NREGS]; - }; - -/* These are the command codes that appear in compiled regular expressions, one per byte. - Some command codes are followed by argument bytes. - A command code can specify any interpretation whatever for its arguments. - Zero-bytes may appear in the compiled regular expression. */ - -enum regexpcode - { - unused, - exactn, /* followed by one byte giving n, and then by n literal bytes */ - begline, /* fails unless at beginning of line */ - endline, /* fails unless at end of line */ - jump, /* followed by two bytes giving relative address to jump to */ - on_failure_jump, /* followed by two bytes giving relative address of place - to resume at in case of failure. */ - finalize_jump, /* Throw away latest failure point and then jump to address. */ - maybe_finalize_jump, /* Like jump but finalize if safe to do so. - This is used to jump back to the beginning - of a repeat. If the command that follows - this jump is clearly incompatible with the - one at the beginning of the repeat, such that - we can be sure that there is no use backtracking - out of repetitions already completed, - then we finalize. */ - dummy_failure_jump, /* jump, and push a dummy failure point. - This failure point will be thrown away - if an attempt is made to use it for a failure. - A + construct makes this before the first repeat. */ - anychar, /* matches any one character */ - charset, /* matches any one char belonging to specified set. - First following byte is # bitmap bytes. - Then come bytes for a bit-map saying which chars are in. - Bits in each byte are ordered low-bit-first. - A character is in the set if its bit is 1. - A character too large to have a bit in the map - is automatically not in the set */ - charset_not, /* similar but match any character that is NOT one of those specified */ - start_memory, /* starts remembering the text that is matched - and stores it in a memory register. - followed by one byte containing the register number. - Register numbers must be in the range 0 through NREGS. */ - stop_memory, /* stops remembering the text that is matched - and stores it in a memory register. - followed by one byte containing the register number. - Register numbers must be in the range 0 through NREGS. */ - duplicate, /* match a duplicate of something remembered. - Followed by one byte containing the index of the memory register. */ - before_dot, /* Succeeds if before dot */ - at_dot, /* Succeeds if at dot */ - after_dot, /* Succeeds if after dot */ - begbuf, /* Succeeds if at beginning of buffer */ - endbuf, /* Succeeds if at end of buffer */ - wordchar, /* Matches any word-constituent character */ - notwordchar, /* Matches any char that is not a word-constituent */ - wordbeg, /* Succeeds if at word beginning */ - wordend, /* Succeeds if at word end */ - wordbound, /* Succeeds if at a word boundary */ - notwordbound, /* Succeeds if not at a word boundary */ - syntaxspec, /* Matches any character whose syntax is specified. - followed by a byte which contains a syntax code, Sword or such like */ - notsyntaxspec /* Matches any character whose syntax differs from the specified. */ - }; - -extern char *re_compile_pattern (); -/* Is this really advertised? */ -extern void re_compile_fastmap (); -extern int re_search (), re_search_2 (); -extern int re_match (), re_match_2 (); - -/* 4.2 bsd compatibility (yuck) */ -extern char *re_comp (); -extern int re_exec (); - -#ifdef SYNTAX_TABLE -extern char *re_syntax_table; -#endif - -extern int re_set_syntax (); diff --git a/gdb/symtab.c b/gdb/symtab.c index fa3d2e54e37..840efb0ac8f 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "objfiles.h" #include "gdbcmd.h" #include "call-cmds.h" -#include "regex.h" +#include "gnu-regex.h" #include "expression.h" #include "language.h" #include "demangle.h"