30 Workaround for Noweb Bug

Aldor code sometimes contains << (less-than less-than). According to the documentation (man notangle) Noweb should treat such occurrences of << literally if they are not followed by >> on the same line. For notangle single occurrences cause problems since instead of a simple warning it reports an error. The problem is actually caused by /usr/lib/noweb/markup which emits a @fatal statement at the end. This is a bug of Noweb 2.10c. Noweb 2.11 has corrected this bug only partially, see end of this section.

We don’t want to escape such situation by manually adding a @ all the time, therefore we pass a .nw file first to a filter that adds the escape character @ if possible. This script escapes all unpaired and unescaped << and >>.

Call this script in the following way.

perl nwescape.pl < file.nw > file.nw.filtered

453a* 21+   422  456
#------------------------------------------------------------------
#---
#--- ALLPROSE
#--- Copyright (C) Ralf Hemmecke (ralf@hemmecke.de)
#--- http://www.hemmecke.de/aldor
#---
#------------------------------------------------------------------

while(<>) {
    if (/^<<.*>>=\s*/) {print; next}
    if (/^@ %def/)       {print; next;}
    chomp;
    $l=$_;
    escape in one line 453b
    print "$l\n";
}

We go through the line until no << or >> is left. Already escaped @, <<, and >> are left unchanged. Otherwise, if the brackets appear paired, they can be copied verbatim to the output. Finally, if the brackets are unpaired they are output with a leading @ sign.

453bescape in one line 453b  (453a)
while ($l =~ /<<|>>/) {
    if    ($l =~ /(.*?)(@@|@<<|@@>>)(.*)/) {print "$1$2";}
    elsif ($l =~ /(.*?)(<<.*?>>)(.*)/) {print "$1$2";}
    elsif ($l =~ /(.*?)(<<|>>)(.*)/)   {print "$1\@$2";}
    else {print STDERR "[[$l]]\n"; print STDERR; die "$0 failed.";}
    $l=$3;
}
To: Ralf Hemmecke <ralf@hemmecke.de>  
Subject: Re: noweb: unclosed module name  
Date: Tue, 20 Dec 2005 17:52:44 -0500  
From: Norman Ramsey <nr@eecs.harvard.edu>  
 
 > Dear Norman,  
 >  
 > I think, I have found the problem in markup.nw.  
 
Thanks for prodding me on this.  
Enclosed find a patch, which will become part of noweb 2.11.  
 
 
Norman  
 
 
===================================================================  
RCS file: RCS/markup.nw,v  
retrieving revision 2.17  
diff -r2.17 markup.nw  
25c25  
< static char rcsname[] = "$Name:  $";  
---  
> > static char rcsname[] = "$Name:  $";  
150c150,154  
< beginning of a code chunk is easy.  
---  
> > beginning of a code chunk is easy.  The only tricky bit is that if we  
> > see an unclosed, unescaped {\Tt{}<<\nwendquote} in a code chunk, this should be acceptable.  
> > Because in a documentation chunk, an unclosed, unescaped {\Tt{}<<\nwendquote} will  
> > already be caught with a ‘‘module name doesn’t end’’ message, the  
> > right thing to do here is silently to let an unclosed {\Tt{}<<\nwendquote} pass.  
161,162c165  
<     if (tail == NULL) <<error exit from {\Tt{}starts{\_}code\nwendquote}>>  
<     if (*tail++ != ’=’) return 0;  
---  
> >     if (tail == NULL || *tail++ != ’=’) return 0;  
178,182d180  
< <<error exit from {\Tt{}starts{\_}code\nwendquote}>>=  
< {  
<     errorat(filename, lineno, Error, "Module name doesn’t end", line);  
<     return 0;  
< }

Here is the essential part of a mail I sent to Norman Ramsey.

Date: Thu, 04 May 2006 17:43:57 +0200  
From: Ralf Hemmecke <ralf@hemmecke.de>  
To: Norman Ramsey <nr@eecs.harvard.edu>  
Subject: Bug in noweb-2.11  
 
Dear Norman,  
 
I think, I’ve found another bug in noweb.  
 
According to the documentation of NOWEB, it is OK if << appears  
unescaped on a line if there is no corresponding >> on the same line.  
 
With the following code  
 
%%%%% test.nw %%%%%  
stdout << "blah";  
 
<<*>>=  
-- Here comes some code  
<<: A -> B  
<<: (A, B) -> X  
\nwenddocs{}\nwbegindocs{5}%  
and we go on with the text.  
%%%%%% end test.nw %%%%  
 
I get the strange behaviour.  
 
notangle test.nw  
test.nw:2: unescaped << in documentation chunk  
echo $?  
1  
 
Hmm, notangle does not spit out any code chunk. :-(  
I am also not sure about the error code.