#LyX 2.5 created this file. For more info see https://www.lyx.org/
\lyxformat 643
\begin_document
\begin_header
\save_transient_properties true
\origin /systemlyxdir/examples/Modules/
\textclass article
\begin_preamble
\usepackage[pdftitle={LyX listerrors re-implemented},urlcolor=blue,linktocpage,letterpaper,colorlinks=true]{hyperref}
\@savsf=1% This is to get around a hyperref+noweb interaction problem
\hyphenpenalty 10000

%
% This (from the noweb FAQ) relaxes the constraint that chunks are never broken across pages.
%
\def\nwendcode{\endtrivlist \endgroup \vfil\penalty10\vfilneg}
\let\nwdocspar=\smallbreak
\end_preamble
\use_default_options false
\begin_modules
noweb
\end_modules
\maintain_unincluded_children no
\language english
\language_package default
\inputencoding utf8
\fontencoding auto
\font_roman "times" "default"
\font_sans "helvet" "default"
\font_typewriter "courier" "default"
\font_math "auto" "auto"
\font_default_family default
\use_non_tex_fonts false
\font_sc false
\font_roman_osf false
\font_sans_osf false
\font_typewriter_osf false
\font_sf_scale 100 100
\font_tt_scale 100 100
\use_microtype false
\use_dash_ligatures false
\graphics default
\default_output_format default
\output_sync 0
\bibtex_command default
\index_command default
\paperfontsize default
\spacing single
\use_hyperref false
\papersize default
\use_geometry false
\use_package amsmath 1
\use_package amssymb 1
\use_package cancel 1
\use_package esint 1
\use_package mathdots 1
\use_package mathtools 1
\use_package mhchem 1
\use_package stackrel 1
\use_package stmaryrd 1
\use_package undertilde 1
\cite_engine basic
\cite_engine_type default
\biblio_style plain
\use_bibtopic false
\use_indices false
\paperorientation portrait
\suppress_date false
\justification default
\crossref_package prettyref
\use_formatted_ref 0
\use_minted 0
\use_lineno 0
\backgroundcolor none
\fontcolor none
\notefontcolor lightgray
\boxbgcolor red
\table_border_color default
\table_odd_row_color default
\table_even_row_color default
\table_alt_row_colors_start 1
\index Index
\shortcut idx
\color #008000
\end_index
\secnumdepth 3
\tocdepth 3
\paragraph_separation indent
\paragraph_indentation default
\is_math_indent 0
\math_numbering_side default
\quotes_style english
\dynamic_quotes 0
\papercolumns 1
\papersides 1
\paperpagestyle default
\tablestyle default
\tracking_changes false
\output_changes false
\change_bars false
\postpone_fragile_content false
\html_math_output 0
\html_css_as_file 0
\html_be_strict false
\docbook_table_output 0
\docbook_mathml_prefix 1
\docbook_mathml_version 0
\end_header

\begin_body

\begin_layout Title
\SpecialChar LyX
 listerrors:
\begin_inset Newline newline
\end_inset

rewritten in Python
\end_layout

\begin_layout Author
Kayvan A.
 Sylvan
\begin_inset Newline newline
\end_inset


\begin_inset Flex URL
status collapsed

\begin_layout Plain Layout
mailto:kayvan@sylvan.com
\end_layout

\end_inset


\end_layout

\begin_layout Date
3/15/2002
\end_layout

\begin_layout Abstract
The listerrors program used to be compiled as a C program and installed as 
\emph on
BINDIR/listerrors
\emph default
 along with \SpecialChar LyX
 in order to perform some simple re-formatting of noweb and GCC error messages.
 This document describes and implements the Python version of the same program.
\end_layout

\begin_layout Standard
\begin_inset CommandInset toc
LatexCommand tableofcontents

\end_inset


\end_layout

\begin_layout Section
Introduction
\end_layout

\begin_layout Standard
The motivation for this program was \SpecialChar LyX
 bug 190
\begin_inset Foot
status collapsed

\begin_layout Plain Layout
Visit 
\begin_inset Flex URL
status collapsed

\begin_layout Plain Layout
https://www.lyx.org/trac/ticket/190
\end_layout

\end_inset

 for the details.
\end_layout

\end_inset

 dealing with the 
\begin_inset Quotes eld
\end_inset

listerrors
\begin_inset Quotes erd
\end_inset

 executable.
\end_layout

\begin_layout Standard
What is 
\begin_inset Quotes eld
\end_inset

listerrors
\begin_inset Quotes erd
\end_inset

?
 Usually,
 \SpecialChar LyX
 has great support for parsing of error messages.
 For each error in the log file,
 \SpecialChar LyX
 pops up an error box at that location in the \SpecialChar LyX
 window.
 The error scanning routines expect these errors to be in a certain format (similar to \SpecialChar LaTeX
 errors).
 When dealing with Literate Programs,
 you have 
\begin_inset Quotes eld
\end_inset

noweb
\begin_inset Foot
status collapsed

\begin_layout Plain Layout
See 
\begin_inset Flex URL
status collapsed

\begin_layout Plain Layout
https://www.cs.tufts.edu/~nr/noweb/
\end_layout

\end_inset

 for more information about noweb.
\end_layout

\end_inset


\begin_inset Quotes erd
\end_inset

 as well as gcc error messages (and potentially others).
 The listerrors program attempts to standardize these error messages to a format that \SpecialChar LyX
 can parse and react to.
\end_layout

\begin_layout Standard
In a nutshell,
 the problems with the old implementation of listerrors that bug 190 refers to were::
\end_layout

\begin_layout Enumerate
It was a C program and it was installed in the user path in the same directory as \SpecialChar LyX
.
 Having such a generically named binary in,
 for example,
 
\emph on
/usr/bin
\emph default
,
 was potentially confusing.
\end_layout

\begin_layout Enumerate
It required that noweb be installed on the compiling machine (the source was extracted by noweb from 
\emph on
SRCDIR/examples/Literate.lyx
\emph default
,
 compiled and installed by 
\begin_inset Quotes eld
\end_inset

make install
\begin_inset Quotes erd
\end_inset

).
\end_layout

\begin_layout Standard
The new version deals with these problems in the following fashion:
\end_layout

\begin_layout Enumerate
Both the example file (this document) and the program are to be added to the \SpecialChar LyX
 CVS repository.
\end_layout

\begin_layout Enumerate
The program itself will be installed in 
\emph on
SHAREDIR/lyx/scripts
\emph default
,
 along with other \SpecialChar LyX
-specific helper scripts.
\end_layout

\begin_layout Standard
In the design and implementation of this new 
\begin_inset Quotes eld
\end_inset

listerrors
\begin_inset Quotes erd
\end_inset

,
 the Python
\begin_inset Foot
status collapsed

\begin_layout Plain Layout
See the Python home page (
\begin_inset Flex URL
status collapsed

\begin_layout Plain Layout
https://www.python.org
\end_layout

\end_inset

) for more information.
\end_layout

\end_inset

 language was chosen since it is fully multi-platform and provides a very uniform and easy to read syntax.
 This re-write also simplifies the code for 
\begin_inset Quotes eld
\end_inset

listerrors
\begin_inset Quotes erd
\end_inset

 greatly.
 Python is installed by default on all modern Linux systems and is freely available for all other platforms.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<listerrors>>=
\end_layout

\begin_layout Plain Layout
#!/usr/bin/python
\end_layout

\begin_layout Plain Layout
"""reformat noweb and compiler errors for LyX.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
Expects to read from stdin and output to stdout.
\end_layout

\begin_layout Plain Layout
"""
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
__author__ = "Kayvan A.
 Sylvan <kayvan@sylvan.com>"
\end_layout

\begin_layout Plain Layout
__date__ = "$Date:
 2005/07/18 09:42:26 $"
\end_layout

\begin_layout Plain Layout
__version__ = "$Revision:
 1.5 $"
\end_layout

\begin_layout Plain Layout
__credits__ = """Edmar Wienskoski Jr.
 <edmar-w-jr@technologist.com>
\end_layout

\begin_layout Plain Layout
    original Literate support for LyX.
\end_layout

\begin_layout Plain Layout
Bernard Michael Hurley <berhardh@westherts.ac.uk>
\end_layout

\begin_layout Plain Layout
    modifications to original listerrors."""
\end_layout

\begin_layout Plain Layout
__copyright__ = "Copyright 2002 - Kayvan Sylvan."
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
import sys,
 string
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
<<Function Bodies>>
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
if __name__ == "__main__":
\end_layout

\begin_layout Plain Layout
  main()
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Section
\SpecialChar LaTeX
 style error message
\end_layout

\begin_layout Standard
The following function mimics the \SpecialChar TeX
 error message format.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
def write_error(msg,
 tool = "noweb",
 line_number = 1):
\end_layout

\begin_layout Plain Layout
  """Write out the given message in TeX error style.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  called like:
 write_error(msg,
 tool,
 line_number)."""
\end_layout

\begin_layout Plain Layout
  print "!
 Build Error:
 ==> %s ==>
\backslash
n" % (tool),
\end_layout

\begin_layout Plain Layout
  print " ...
\backslash
n
\backslash
nl.%d ...
\backslash
n" % (line_number),
\end_layout

\begin_layout Plain Layout
  if type(msg) == type("str"):
 # simple string
\end_layout

\begin_layout Plain Layout
    print msg
\end_layout

\begin_layout Plain Layout
  else:
 # some kind of list (sequence or tuple)
\end_layout

\begin_layout Plain Layout
    for m in msg:
\end_layout

\begin_layout Plain Layout
        if m != "":
 print m,
\end_layout

\begin_layout Plain Layout
    print
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
@ %def write_error
\end_layout

\end_inset


\end_layout

\begin_layout Section
Filtering errors
\end_layout

\begin_layout Standard
The only complication in our filtering code is that some parsers might need to push back lines that are read in to be read again later.
 We solve this problem by implementing a 
\begin_inset Quotes eld
\end_inset

getline
\begin_inset Quotes erd
\end_inset

 and 
\begin_inset Quotes eld
\end_inset

pushline
\begin_inset Quotes erd
\end_inset

 set of functions:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
__lines = [] # lines pushed back
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
def getline(file = sys.stdin):
\end_layout

\begin_layout Plain Layout
  """read a line from internal stack or from file.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  optional file argument defaults to sys.stdin."""
\end_layout

\begin_layout Plain Layout
  global __lines
\end_layout

\begin_layout Plain Layout
  lines = __lines
\end_layout

\begin_layout Plain Layout
  if lines:
\end_layout

\begin_layout Plain Layout
    line = lines.pop()
\end_layout

\begin_layout Plain Layout
  else:
\end_layout

\begin_layout Plain Layout
    line = file.readline()
\end_layout

\begin_layout Plain Layout
  return line
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
@ %def getline
\end_layout

\end_inset


\end_layout

\begin_layout Standard
And now for the corresponding pushline function:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
def pushline(line):
\end_layout

\begin_layout Plain Layout
  "push a line onto the pushback stack."
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  global __lines
\end_layout

\begin_layout Plain Layout
  lines = __lines
\end_layout

\begin_layout Plain Layout
lines.append(line)
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
@ %def pushline
\end_layout

\end_inset


\end_layout

\begin_layout Standard
The main() entry point function is extremely simple.
 Note that this version of 
\begin_inset Quotes eld
\end_inset

listerrors
\begin_inset Quotes erd
\end_inset

 takes no options and simply filters,
 attempting simply to match against the known error message patterns.
 The listerrors C program handled a single-character command-line argument that the current code no longer needs.
 
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
def main():
\end_layout

\begin_layout Plain Layout
  """Entry point for listerrors.
 Takes no options.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  Reads stdin and writes to stdout.
 Filter errors"""
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  while 1:
\end_layout

\begin_layout Plain Layout
    line = getline()
\end_layout

\begin_layout Plain Layout
    if line == "":
 break
\end_layout

\begin_layout Plain Layout
    <<Check line against patterns and take action>>
\end_layout

\begin_layout Plain Layout
@ %def main
\end_layout

\end_inset


\end_layout

\begin_layout Standard
For each line read in,
 we need to find out if it matches any of our tools (noweb,
 gcc,
 etc.) and act accordingly.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Check line against patterns and take action>>=
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
try_patterns_dispatch = [ noweb_try,
 gcc_try,
 xlc_try ]
\end_layout

\begin_layout Plain Layout
for predicate in try_patterns_dispatch:
\end_layout

\begin_layout Plain Layout
  if predicate(line):
 break
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Section
Different Error Formats
\end_layout

\begin_layout Standard
The following sections handle the various error message formats that we recognize in this program.
 
\end_layout

\begin_layout Subsection
noweb errors
\end_layout

\begin_layout Standard
Noweb errors are output on a single line,
 so examining just the current line is enough.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
def noweb_try(line):
\end_layout

\begin_layout Plain Layout
  """see if line is a noweb error.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  Returns 1 on success,
 0 otherwise.
 Outputs on stdout."""
\end_layout

\begin_layout Plain Layout
  retval = 0
\end_layout

\begin_layout Plain Layout
  <<Look for the unescaped angle-brackets in documentation>>
\end_layout

\begin_layout Plain Layout
  <<Look for anything with double angle brackets>>
\end_layout

\begin_layout Plain Layout
  <<Last ditch effort scan for specific strings>>
\end_layout

\begin_layout Plain Layout
  return retval
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
@ %def noweb_try
\end_layout

\end_inset


\end_layout

\begin_layout Standard
First,
 we look for the 
\begin_inset Quotes eld
\end_inset

unescaped < < in documentation chunk
\begin_inset Quotes erd
\end_inset

 message.
 This is the only message with an associated line number from noweb.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
<<Look for the unescaped angle-brackets in documentation>>=
\end_layout

\begin_layout Plain Layout
if string.find(line,
 ":
 unescaped << in documentation chunk") != -1:
\end_layout

\begin_layout Plain Layout
  line_parts = string.split(line,
 ':')
\end_layout

\begin_layout Plain Layout
  num_str = line_parts[1]
\end_layout

\begin_layout Plain Layout
  num_len = len(num_str)
\end_layout

\begin_layout Plain Layout
  i = 0
\end_layout

\begin_layout Plain Layout
  while i < num_len and (num_str[i] in string.digits):
 i = i + 1
\end_layout

\begin_layout Plain Layout
  if i == num_len:
\end_layout

\begin_layout Plain Layout
    write_error(":" + line_parts[2],
 "noweb",
 int(num_str))
\end_layout

\begin_layout Plain Layout
    retval = 1
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Standard
Some noweb messages are simply about undefined chunks.
 These can be seen by looking for matching double-angle-brackets.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Look for anything with double angle brackets>>=
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
if (not retval):
\end_layout

\begin_layout Plain Layout
  left = string.find(line,
 "<<")
\end_layout

\begin_layout Plain Layout
  if (left != -1) and ((left + 2) < len(line)) and 
\backslash

\end_layout

\begin_layout Plain Layout
     (string.find(line[left+2:],
 ">>") != -1):
\end_layout

\begin_layout Plain Layout
    write_error(line,
 "noweb");
\end_layout

\begin_layout Plain Layout
    retval = 1;
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Standard
Finally,
 here is an additional list of explicit strings to check for.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Last ditch effort scan for specific strings>>=
\end_layout

\begin_layout Plain Layout
if (not retval):
\end_layout

\begin_layout Plain Layout
  msgs_to_try = ("couldn't open file",
\end_layout

\begin_layout Plain Layout
    "couldn't open temporary file",
\end_layout

\begin_layout Plain Layout
    "error writing temporary file",
\end_layout

\begin_layout Plain Layout
    "ill-formed option",
\end_layout

\begin_layout Plain Layout
    "unknown option",
\end_layout

\begin_layout Plain Layout
    "Bad format sequence",
\end_layout

\begin_layout Plain Layout
    "Can't open output file",
\end_layout

\begin_layout Plain Layout
    "Can't open temporary file",
\end_layout

\begin_layout Plain Layout
    "Capacity exceeded:",
\end_layout

\begin_layout Plain Layout
    "Ignoring unknown option -",
\end_layout

\begin_layout Plain Layout
    "This can't happen:",
\end_layout

\begin_layout Plain Layout
    "non-numeric line number in")
\end_layout

\begin_layout Plain Layout
  for msg in msgs_to_try:
\end_layout

\begin_layout Plain Layout
    if string.find(line,
 msg) != -1:
\end_layout

\begin_layout Plain Layout
      write_error(line,
 "noweb")
\end_layout

\begin_layout Plain Layout
      retval = 1
\end_layout

\begin_layout Plain Layout
      break
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Subsection
gcc errors
\end_layout

\begin_layout Standard
The gcc errors can be multi-line,
 with the following format:
\end_layout

\begin_layout LyX-Code
foo.c:
 In function `main':
 
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
foo.c:3:
 `bar' undeclared (first use in this function) 
\end_layout

\begin_layout Plain Layout
foo.c:3:
 (Each undeclared identifier is reported only once 
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
foo.c:3:
 for each function it appears in.) 
\end_layout

\begin_layout Plain Layout
foo.c:3:
 parse error before `x'
\end_layout

\end_inset


\end_layout

\begin_layout Standard
In order to parse this,
 the gcc error handler has to look ahead and return any and all lines that do not match the expected pattern.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
def gcc_try(line):
\end_layout

\begin_layout Plain Layout
  """See if line is a gcc error.
 Read ahead to handle all the lines.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  Returns 1 on success,
 0 otherwise.
 Outputs on stdout."""
\end_layout

\begin_layout Plain Layout
  retval = 0
\end_layout

\begin_layout Plain Layout
  <<Handle the gcc error message>>
\end_layout

\begin_layout Plain Layout
  return retval
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
@ %def gcc_try
\end_layout

\end_inset


\end_layout

\begin_layout Standard
The error message starts with a gcc header (as above) without an associated line number.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Handle the gcc error message>>= 
\end_layout

\begin_layout Plain Layout
first_space = string.find(line,
 ' ')
\end_layout

\begin_layout Plain Layout
if first_space > 1:
 # The smallest would be "X:
 "
\end_layout

\begin_layout Plain Layout
  if line[first_space - 1] == ':':
\end_layout

\begin_layout Plain Layout
    header_to_see = line[:first_space - 1]
\end_layout

\begin_layout Plain Layout
    next_line = getline()
\end_layout

\begin_layout Plain Layout
    if next_line and next_line[:first_space - 1] == header_to_see:
\end_layout

\begin_layout Plain Layout
      num_end = first_space
\end_layout

\begin_layout Plain Layout
      while next_line[num_end] in string.digits:
 num_end = num_end + 1
\end_layout

\begin_layout Plain Layout
      if num_end > first_space:
 # good!
\end_layout

\begin_layout Plain Layout
        <<Accumulate gcc error lines and print it>>
\end_layout

\begin_layout Plain Layout
      else:
 # oops!
 Not a gcc error.
\end_layout

\begin_layout Plain Layout
        pushline(next_line)
\end_layout

\begin_layout Plain Layout
    elif next_line:
\end_layout

\begin_layout Plain Layout
      pushline(next_line) # return this line to input stream
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Standard
At the point in the code that we know that we are in the middle of an error message,
 we do the following:
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<Accumulate gcc error lines and print it>>=
\end_layout

\begin_layout Plain Layout
num_str = next_line[first_space:num_end]
\end_layout

\begin_layout Plain Layout
msgs = [line[first_space:]]
\end_layout

\begin_layout Plain Layout
msgs.append(next_line[num_end + 1:])
\end_layout

\begin_layout Plain Layout
header_to_see = next_line[:num_end]
\end_layout

\begin_layout Plain Layout
next_line = getline()
\end_layout

\begin_layout Plain Layout
while next_line and next_line[:num_end] == header_to_see:
\end_layout

\begin_layout Plain Layout
  msgs.append(next_line[num_end + 1:])
\end_layout

\begin_layout Plain Layout
  next_line = getline()
\end_layout

\begin_layout Plain Layout
if next_line:
 pushline(next_line)
\end_layout

\begin_layout Plain Layout
write_error(msgs,
 "gcc",
 int(num_str))
\end_layout

\begin_layout Plain Layout
retval = 1
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Subsection
xlc errors
\end_layout

\begin_layout Standard
A xlc error message is easy to identify.
 Every error message starts with a quoted string with no spaces,
 a comma,
 a space,
 the word 
\begin_inset Quotes eld
\end_inset

line
\begin_inset Quotes erd
\end_inset

,
 a space,
 and some variable text.
 The following routine tests if a given buffer line matches this criteria (this code would probably be simpler if I used the 
\begin_inset Quotes eld
\end_inset

re
\begin_inset Quotes erd
\end_inset

 regexp module,
 but we don't really need the full regular expression engine here).
 
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
<<Function Bodies>>=
\end_layout

\begin_layout Plain Layout
def xlc_try(line):
\end_layout

\begin_layout Plain Layout
  """see if line is an xlc error.
\end_layout

\begin_layout Plain Layout

\end_layout

\begin_layout Plain Layout
  Returns 1 on success,
 0 otherwise.
 Outputs on stdout."""
\end_layout

\begin_layout Plain Layout
  retval = 0
\end_layout

\begin_layout Plain Layout
  if line[0] == '"':
 # This is the first character of all xlc errors
\end_layout

\begin_layout Plain Layout
    next_quote = string.find(line,
 '"',
 1)
\end_layout

\begin_layout Plain Layout
    first_space = string.find(line,
 ' ')
\end_layout

\begin_layout Plain Layout
    if (next_quote != -1) and (first_space > next_quote):
 # no space inisde quotes
\end_layout

\begin_layout Plain Layout
      if line[first_space - 1:first_space + 6] == ",
 line ":
\end_layout

\begin_layout Plain Layout
        num_start = num_end = first_space + 6
\end_layout

\begin_layout Plain Layout
        while line[num_end] in string.digits:
 num_end = num_end + 1
\end_layout

\begin_layout Plain Layout
        if num_end > num_start:
\end_layout

\begin_layout Plain Layout
          write_error(line,
 "xlc",
 int(line[num_start :
 num_end]))
\end_layout

\begin_layout Plain Layout
          retval = 1
\end_layout

\begin_layout Plain Layout
  return retval
\end_layout

\begin_layout Plain Layout
  
\end_layout

\begin_layout Plain Layout
@ %def xlc_try
\end_layout

\end_inset


\end_layout

\begin_layout Section
Extracting the code
\end_layout

\begin_layout Standard
This project can be tangled from \SpecialChar LyX
 if you set your 
\begin_inset Quotes eld
\end_inset

Program
\begin_inset Quotes erd
\end_inset

 convertor to call a generic script that always extracts a chunk named 
\family typewriter
build-script
\family default
 and executes it.
 Here is an example of such a generic script:
\end_layout

\begin_layout LyX-Code
#!/bin/sh
\end_layout

\begin_layout LyX-Code
notangle -Rbuild-script $1 | env NOWEB_SOURCE=$1 NOWEB_OUTPUT_DIR=$2 sh
\end_layout

\begin_layout Standard
This section defines our build-script,
 which extracts the code.
\end_layout

\begin_layout Standard
\begin_inset ERT
status open

\begin_layout Plain Layout
<<build-script>>=
\end_layout

\begin_layout Plain Layout
#!/bin/sh
\end_layout

\begin_layout Plain Layout
if [ -z "$NOWEB_SOURCE" ];
 then NOWEB_SOURCE=listerrors.nw;
 fi
\end_layout

\begin_layout Plain Layout
if [ -z "$NOWEB_OUTPUT_DIR" ];
 then NOWEB_OUTPUT_DIR=.;
 fi
\end_layout

\begin_layout Plain Layout
notangle -Rlisterrors ${NOWEB_SOURCE} > ${NOWEB_OUTPUT_DIR}/listerrors
\end_layout

\begin_layout Plain Layout
chmod +x ${NOWEB_OUTPUT_DIR}/listerrors
\end_layout

\begin_layout Plain Layout
@
\end_layout

\end_inset


\end_layout

\begin_layout Section
Indices
\end_layout

\begin_layout Standard
This section provides cross-references into the rest of the program.
\end_layout

\begin_layout Subsection
Macros
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Plain Layout

\backslash
nowebchunks
\end_layout

\end_inset


\end_layout

\begin_layout Subsection
Identifiers
\end_layout

\begin_layout Standard
\begin_inset ERT
status collapsed

\begin_layout Plain Layout

\backslash
nowebindex
\end_layout

\end_inset


\end_layout

\end_body
\end_document
