dragon@uw-june (Brian Matthews) (01/10/85)
In Raymond Dunn's C+ package (an excellent package, by the way), there is a variable you can set indicating whether you have the fix to the backward-paren bug (parentheses in comments are not ignored, and \\ and single quotes screw things up). Now, having this variable in there seems to imply there is in fact such a fix out there, so I was wondering if anyone has it. Thanx, Brian Matthews dragon@uw-june
michael@spar.UUCP (michael) (01/11/85)
In response to Brian Matthew's request, I have enclosed the output from `diff -c' -- syntax.c is the source file to be updated. I can no longer remember who originally provided this fix, but whoever it was has been a frequent contributor to this group. Somewhere in here (I think..) is an additional fix I made that you'll really want if you run Gosmacs on SUNs. SUN's C compiler has problems with register variables (doesn't everybody's?) that show up here.. Oh yes, many thanks to the originator of this fix! diff -c Oldsyntax.c syntax.c *** Original Unipress EMACS syntax.c --- With paren match correction *************** *** 116,126 /* Primitive function for paren matching. Leaves dot at enclosing left paren, or at top of buffer if none. Stops at a zero-level newline if ! StopAtNewline is set. Returns (to MLisp) 1 if it finds ! a match, 0 if not */ ! /* Bugs: doesn't correctly handle comments (it'll never really handle them ! correctly... */ ! static ParenScan (StopAtNewline, forward) { register ParenLevel = 0; --- 116,125 ----- /* Primitive function for paren matching. Leaves dot at enclosing left paren, or at top of buffer if none. Stops at a zero-level newline if ! StopAtNewline is set. Returns (to MLisp) 1 if it finds a match, ! 0 if not. */ ! /* Bug: if the stop-comment auxil character is also a quote, paren, or ! prefix quote, reverse scans will sometimes be wrong. */ static ParenScan (StopAtNewline, forward) { register struct SyntaxTable *s = bf_mode.md_syntax; *************** *** 122,134 correctly... */ static ! ParenScan (StopAtNewline, forward) { ! register ParenLevel = 0; ! register char c, ! pc; ! char parenstack[200]; ! int InString = 0; ! char MatchingQuote = 0; register struct SyntaxTable *s = bf_mode.md_syntax; register enum SyntaxKinds k; register on_on = 1; --- 121,127 ----- /* Bug: if the stop-comment auxil character is also a quote, paren, or prefix quote, reverse scans will sometimes be wrong. */ static ! ParenScan (StopAtNewline, forward) { register struct SyntaxTable *s = bf_mode.md_syntax; register enum SyntaxKinds k; register c, *************** *** 131,139 char MatchingQuote = 0; register struct SyntaxTable *s = bf_mode.md_syntax; register enum SyntaxKinds k; ! register on_on = 1; ! int start = (forward ? (dot + 1) : dot); ! int SavedDot = dot; parenstack[0] = 0; MLvalue -> exp_type = IsInteger; --- 124,138 ----- ParenScan (StopAtNewline, forward) { register struct SyntaxTable *s = bf_mode.md_syntax; register enum SyntaxKinds k; ! register c, ! pc, ! on_on = 1, ! ParenLevel = 0; ! char parenstack[200]; ! int InString = 0, ! InComment = 0, ! MatchingQuote, ! delta = 1; MLvalue -> exp_type = IsInteger; MLvalue -> exp_int = 0; *************** *** 135,141 int start = (forward ? (dot + 1) : dot); int SavedDot = dot; - parenstack[0] = 0; MLvalue -> exp_type = IsInteger; MLvalue -> exp_int = 0; if (StopAtNewline) { --- 134,139 ----- MatchingQuote, delta = 1; MLvalue -> exp_type = IsInteger; MLvalue -> exp_int = 0; if (forward != 0 && forward != 1) { *************** *** 138,153 parenstack[0] = 0; MLvalue -> exp_type = IsInteger; MLvalue -> exp_int = 0; ! if (StopAtNewline) { ! register p1, ! p2, ! dp; ! for (p1 = dot - 1, p2 = (forward ? NumCharacters : FirstCharacter), ! dp = (forward ? 1 : -1); ! (forward ? p1 < p2 : p1 > p2) ! && ((c = CharAt (p1)) == ' ' || c == '\t' || c == '\n'); ! p1 += dp); ! SetDot (p1 + 1); } while (on_on && !err) { if (forward) { --- 136,144 ----- MLvalue -> exp_type = IsInteger; MLvalue -> exp_int = 0; ! if (forward != 0 && forward != 1) { ! error ("panic: ParenScan"); ! return 0; } if (StopAtNewline) { /* Skip over whitespace */ pc = dot - 1; *************** *** 149,154 p1 += dp); SetDot (p1 + 1); } while (on_on && !err) { if (forward) { if (dot > NumCharacters) { --- 140,162 ----- error ("panic: ParenScan"); return 0; } + if (StopAtNewline) { /* Skip over whitespace */ + pc = dot - 1; + if (forward) + while (pc < NumCharacters) { + if ((c = CharAt (pc)) != ' ' && c != '\t' && c != '\n') + break; + pc++; + } + else + while (pc > FirstCharacter) { + if ((c = CharAt (pc)) != ' ' && c != '\t' && c != '\n') + break; + pc--; + } + SetDot (pc + 1); + } + /* Scan through buffer until done or error */ while (on_on && !err) { if (forward) { if (dot > NumCharacters) *************** *** 151,159 } while (on_on && !err) { if (forward) { ! if (dot > NumCharacters) { ! error ("No matching close parenthesis."); ! SetDot (SavedDot); return 0; } DotRight (1); --- 159,165 ----- /* Scan through buffer until done or error */ while (on_on && !err) { if (forward) { ! if (dot > NumCharacters) return 0; DotRight (delta); delta = 1; *************** *** 155,162 error ("No matching close parenthesis."); SetDot (SavedDot); return 0; ! } ! DotRight (1); } if (dot > 2) pc = CharAt (dot - 2); --- 161,168 ----- if (forward) { if (dot > NumCharacters) return 0; ! DotRight (delta); ! delta = 1; } else if (dot <= FirstCharacter) *************** *** 158,170 } DotRight (1); } ! if (dot > 2) ! pc = CharAt (dot - 2); ! else { ! pc = 0; ! if (dot <= FirstCharacter) { ! error ("No matching open parenthesis."); ! SetDot (SavedDot); return 0; } } --- 164,171 ----- DotRight (delta); delta = 1; } ! else ! if (dot <= FirstCharacter) return 0; c = CharAt (dot - 1); /* If in a comment, see if we are now out. If not in a comment, see *************** *** 166,171 error ("No matching open parenthesis."); SetDot (SavedDot); return 0; } } k = bf_mode.md_syntax -> s_table[c = CharAt (dot - 1)].s_kind; --- 167,185 ----- else if (dot <= FirstCharacter) return 0; + c = CharAt (dot - 1); + /* If in a comment, see if we are now out. If not in a comment, see + if we are now in. The comparisons to forward account for the fact + that reverse scans start comments on seeing the end-comment character, + and end comments on seeing the start-comment character. */ + /* The bug is in here: we should look at (dot-2) for two-character + end-comment strings when doing reverse scans, not at (dot-1). I + don't think it's worth the effort. */ + if (InComment != forward && s -> s_table[c].BeginComment || + InComment == forward && s -> s_table[c].EndComment) { + if ((pc = s -> s_table[c].CommentAux) == 0) { + InComment = !InComment; + goto advance; } if (dot <= NumCharacters && pc == CharAt (dot)) { if (forward) *************** *** 167,172 SetDot (SavedDot); return 0; } } k = bf_mode.md_syntax -> s_table[c = CharAt (dot - 1)].s_kind; if (bf_mode.md_syntax -> s_table[pc].s_kind == PrefixQuote) --- 181,192 ----- InComment = !InComment; goto advance; } + if (dot <= NumCharacters && pc == CharAt (dot)) { + if (forward) + delta++; + InComment = !InComment; + goto advance; + } } /* If in a comment, just continue on */ if (InComment) *************** *** 168,179 return 0; } } ! k = bf_mode.md_syntax -> s_table[c = CharAt (dot - 1)].s_kind; ! if (bf_mode.md_syntax -> s_table[pc].s_kind == PrefixQuote) ! k = WordChar; ! if ((!InString || c == MatchingQuote) && k == PairedQuote) { ! InString = !InString; ! MatchingQuote = c; } if (InString && c == '\n') return 0; --- 188,209 ----- goto advance; } } ! /* If in a comment, just continue on */ ! if (InComment) ! goto advance; ! /* See what kind of character we have. Carefully check for quoted ! quotes (and even for quoted quoters but no further; this takes ! care of things like "'\''" and "'\\'"). */ ! k = s -> s_table[c].s_kind; ! if (dot > 2 && s -> s_table[CharAt (dot-2)].s_kind == PrefixQuote && ! (dot==3 || s -> s_table[CharAt (dot-3)].s_kind != PrefixQuote)) ! k = WordChar; ! if (k == PairedQuote) { ! if (!InString) /* start quotes */ ! InString++, MatchingQuote = c; ! else /* end quotes (if it's the same quote) */ ! if (c == MatchingQuote) ! InString = 0; } if (c == '\n' && ParenLevel == 0 && StopAtNewline) return 0; *************** *** 175,181 InString = !InString; MatchingQuote = c; } ! if (InString && c == '\n') return 0; if (StopAtNewline && c == '\n' && ParenLevel == 0) return 0; --- 205,211 ----- if (c == MatchingQuote) InString = 0; } ! if (c == '\n' && ParenLevel == 0 && StopAtNewline) return 0; if (!InString && (k == EndParen || k == BeginParen)) { if (forward == (k == BeginParen))/* Push a paren */ *************** *** 177,184 } if (InString && c == '\n') return 0; - if (StopAtNewline && c == '\n' && ParenLevel == 0) - return 0; if (!InString && (k == EndParen || k == BeginParen)) { if ((forward == 0) == (k == EndParen)) { ParenLevel++; --- 207,212 ----- } if (c == '\n' && ParenLevel == 0 && StopAtNewline) return 0; if (!InString && (k == EndParen || k == BeginParen)) { if (forward == (k == BeginParen))/* Push a paren */ parenstack[ParenLevel++] = s -> s_table[c].MatchingParen; *************** *** 180,188 if (StopAtNewline && c == '\n' && ParenLevel == 0) return 0; if (!InString && (k == EndParen || k == BeginParen)) { ! if ((forward == 0) == (k == EndParen)) { ! ParenLevel++; ! parenstack[ParenLevel] = s -> s_table[c].MatchingParen; } else { if (ParenLevel > 0 && parenstack[ParenLevel] != c) --- 208,224 ----- if (c == '\n' && ParenLevel == 0 && StopAtNewline) return 0; if (!InString && (k == EndParen || k == BeginParen)) { ! if (forward == (k == BeginParen))/* Push a paren */ ! parenstack[ParenLevel++] = s -> s_table[c].MatchingParen; ! else { /* Pop a paren */ ! if (ParenLevel == 0) ! on_on = 0; /* Should maybe be error? */ ! else { ! if (parenstack[--ParenLevel] != c) ! error ("Parenthesis mismatch."); ! if (ParenLevel == 0 && !StopAtNewline) ! on_on = 0; ! } } } advance: *************** *** 184,200 ParenLevel++; parenstack[ParenLevel] = s -> s_table[c].MatchingParen; } - else { - if (ParenLevel > 0 && parenstack[ParenLevel] != c) - error ("Parenthesis mismatch."); - ParenLevel--; - } - /* if (pc == '\n' && ParenLevel > 0 && dot != start) { - error ("Parenthesis context across function boundary"); - return 0; - } */ - if (ParenLevel < 0 || (ParenLevel == 0 && !StopAtNewline)) - on_on = 0; } if (!forward) DotLeft (1); --- 220,225 ----- on_on = 0; } } } advance: if (!forward) { *************** *** 196,203 if (ParenLevel < 0 || (ParenLevel == 0 && !StopAtNewline)) on_on = 0; } ! if (!forward) ! DotLeft (1); } MLvalue -> exp_int = 1; return 0; --- 221,231 ----- } } } ! advance: ! if (!forward) { ! DotLeft (delta); ! delta = 1; ! } } MLvalue -> exp_int = 1; return 0; =======END OF DIFF======= -michael
chris@umcp-cs.UUCP (Chris Torek) (01/12/85)
Re: getting Gosling Emacs to match parens in, e.g., ("hi("'\\' /* { */): I have such a fix; I even recall sending it out. UniPress has the fix now too, so maybe it will appear in later versions of the commercial Emacs. I don't have the original code anymore, so the best I could do now is post just the paren matcher code, and let others figure out where it goes. (In other words, I can't send out diff listings.) -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland