From: "Aleksi Niemelä" Date: 2000-09-23T07:36:03+09:00 Subject: [ruby-talk:5078] Regex.c error reporting beautifier This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01C024E5.7AB73DD0 Content-Type: text/plain; charset="iso-8859-1" A patch (as an attachment) for friendlier regexp compilation problem reporting. To be precice, now Ruby tells better what's wrong with following cases. There's still some work to do. Two cases of invalid_pattern, that I didn't understand how to generate. And I didn't check the other error messages - I expect they're quite good already. The patch shouldn't be applied directly. The reason is that for some formatting with snprintf I needed a buffer, and I think it does not get cleaned up as I didn't knew how to clean it up. Anyway, all comments are welcome. - Aleksi ./ruby -e'p /++/.match("+++")[0]' Previously: -e:1: invalid regular expression: /++/ Now: -e:1: invalid regular expression; there's no previous pattern, to which '+' would define cardinality at 1: /++/ ruby -e'p /[/.match("foobar [")[0]' Previously: -e:1: invalid regular expression: /[/ Now: -e:1: invalid regular expression; '[' can't be the last character: /[/ ruby -e'p /[]/.match("")[0]' Previously: -e:1: invalid regular expression: /[]/ Now: -e:1: invalid regular expression; empty range: /[]/ /ruby -e'p /fo[[:/.match("fo[[:")[0]' Previously: -e:1: invalid regular expression: /fo[[:/ Now: -e:1: invalid regular expression; re can't end '[[:': /fo[[:/ ruby -e'p /[[:alpha:]-a]/.match("")[0]' Previously: -e:1: invalid regular expression: /[[:alpha:]-a]/ Now: -e:1: invalid regular expression; can't use character class as a start value of range: /[[:alpha:]-a]/ ruby -e'p /[[:foo:]]/.match("foo")[0]' Previously: -e:1: invalid regular expression: /[[:foo:]]/ Now: -e:1: invalid regular expression; foo is not a character class: /[[:foo:]]/ ruby -e'p /[[:alnum:]/.match("")[0]' Previously: -e:1: invalid regular expression: /[[:alnum:]/ Now: -e:1: invalid regular expression; range doesn't have ending ']' after a character class: /[[:alnum:]/ ruby -e'p /foo{/.match("foo")[0]' Previously: -e:1: invalid regular expression: /foo{/ Now: -e:1: invalid regular expression; '{' can't be last character: /foo{/ ruby -e'p /{a/.match("oo")[0]' Previously: -e:1: invalid regular expression: /{a/ Now: -e:1: invalid regular expression; there's no previous pattern, to which '{' would define cardinality at 1: /{a/ ruby -e'str="\\"; p %r{#{str}}.match("")[0]' Previously: -e:1: invalid regular expression: /\/ (RegexpError) Now: -e:1: invalid regular expression; '\' can't be last character: /\/ (RegexpError) ------_=_NextPart_000_01C024E5.7AB73DD0 Content-Type: application/octet-stream; name="regex.error_message.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="regex.error_message.patch" Index: regex.c=0A= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A= RCS file: /home/cvs/ruby/regex.c,v=0A= retrieving revision 1.31=0A= diff -u -r1.31 regex.c=0A= --- regex.c 2000/09/22 05:37:52 1.31=0A= +++ regex.c 2000/09/22 22:33:20=0A= @@ -1190,6 +1190,8 @@=0A= register unsigned int c, c1;=0A= const char *p0;=0A= int numlen;=0A= +#define ERROR_MSG_MAX_SIZE 200=0A= + char *error_msg;=0A= =0A= /* Address of the count-byte of the most recently inserted = `exactn'=0A= command. This makes it possible to tell whether a new = exact-match=0A= @@ -1262,6 +1264,11 @@=0A= int options =3D bufp->options;=0A= int old_options =3D 0;=0A= =0A= + error_msg =3D (char*)xmalloc(ERROR_MSG_MAX_SIZE+1); /* this memory = should be also =0A= + freeed to avoid leaks,=0A= + dunno how and where */=0A= + if(!error_msg) goto memory_exhausted;=0A= +=0A= bufp->fastmap_accurate =3D 0;=0A= bufp->must =3D 0;=0A= bufp->must_skip =3D 0;=0A= @@ -1318,7 +1325,10 @@=0A= case '*':=0A= /* If there is no previous pattern, char not special. */=0A= if (!laststart) {=0A= - goto invalid_pattern;=0A= + snprintf(error_msg, ERROR_MSG_MAX_SIZE, =0A= + "invalid regular expression; there's no previous pattern, to which = '%c' would define cardinality at %d", =0A= + c, p-pattern);=0A= + FREE_AND_RETURN(stackb, error_msg );=0A= }=0A= /* If there is a sequence of repetition chars,=0A= collapse it down to just one. */=0A= @@ -1400,7 +1410,7 @@=0A= =0A= case '[':=0A= if (p =3D=3D pend)=0A= - goto invalid_pattern;=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; '[' can't be the = last character ie. can't start range at the end of pattern");=0A= while ((b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH)=0A= > bufp->allocated)=0A= EXTEND_BUFFER;=0A= @@ -1441,7 +1451,7 @@=0A= if (c =3D=3D ']') {=0A= if (p =3D=3D p0 + 1) {=0A= if (p =3D=3D pend)=0A= - goto invalid_pattern;=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; empty = range");=0A= }=0A= else =0A= /* Stop if this isn't merely a ] inside a bracket=0A= @@ -1452,7 +1462,7 @@=0A= /* Look ahead to see if it's a range when the last thing=0A= was a character class. */=0A= if (had_char_class && c =3D=3D '-' && *p !=3D ']')=0A= - goto invalid_pattern;=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; can't use = character class as a start value of range");=0A= if (ismbchar(c)) {=0A= PATFETCH_MBC(c);=0A= had_mbchar++;=0A= @@ -1582,7 +1592,7 @@=0A= =0A= /* If pattern is `[[:'. */=0A= if (p =3D=3D pend) =0A= - goto invalid_pattern;=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; re can't end = '[[:'");=0A= =0A= for (;;) {=0A= PATFETCH (c);=0A= @@ -1611,14 +1621,17 @@=0A= char is_upper =3D STREQ(str, "upper");=0A= char is_xdigit =3D STREQ(str, "xdigit");=0A= =0A= - if (!IS_CHAR_CLASS(str))=0A= - goto invalid_pattern;=0A= + if (!IS_CHAR_CLASS(str)){=0A= + snprintf(error_msg, ERROR_MSG_MAX_SIZE, =0A= + "invalid regular expression; %s is not a character class", = str);=0A= + FREE_AND_RETURN(stackb, error_msg );=0A= + }=0A= =0A= /* Throw away the ] at the end of the character class. */=0A= PATFETCH(c);=0A= =0A= if (p =3D=3D pend) =0A= - goto invalid_pattern;=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; range = doesn't have ending ']' after a character class");=0A= =0A= for (ch =3D 0; ch < 1 << BYTEWIDTH; ch++) {=0A= if ( (is_alnum && ISALNUM(ch))=0A= @@ -1938,9 +1951,14 @@=0A= =0A= case '{':=0A= /* If there is no previous pattern, this is an invalid pattern. = */=0A= - if (!laststart || p =3D=3D pend) {=0A= - goto invalid_pattern;=0A= + if (!laststart) {=0A= + snprintf(error_msg, ERROR_MSG_MAX_SIZE, =0A= + "invalid regular expression; there's no previous pattern, to which = '{' would define cardinality at %d", =0A= + p-pattern);=0A= + FREE_AND_RETURN(stackb, error_msg );=0A= }=0A= + if( p =3D=3D pend)=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; '{' can't be = last character" );=0A= =0A= beg_interval =3D p - 1;=0A= =0A= @@ -2119,7 +2137,8 @@=0A= goto normal_char;=0A= =0A= case '\\':=0A= - if (p =3D=3D pend) goto invalid_pattern;=0A= + if (p =3D=3D pend)=0A= + FREE_AND_RETURN(stackb, "invalid regular expression; '\\' can't be = last character");=0A= /* Do not translate the character after the \, so that we can=0A= distinguish, e.g., \B from \b, even if we normally would=0A= translate, e.g., B to b. */=0A= ------_=_NextPart_000_01C024E5.7AB73DD0--