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=======
-michaelchris@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