]> git.lyx.org Git - lyx.git/blob - lib/examples/listerrors.lyx
Restore change from OpenOffice to LibreOffice.
[lyx.git] / lib / examples / listerrors.lyx
1 #LyX 2.0 created this file. For more info see http://www.lyx.org/
2 \lyxformat 413
3 \begin_document
4 \begin_header
5 \textclass literate-article
6 \begin_preamble
7 %
8 % ps2pdf stuff
9 %
10 \usepackage[ps2pdf,pdftitle={LyX listerrors re-implemented},urlcolor=blue,linktocpage,letterpaper,colorlinks=true]{hyperref}
11 \@savsf=1% This is to get around a hyperref+noweb interaction problem
12 \hyphenpenalty 10000
13
14 %
15 % This (from the noweb FAQ) relaxes the constraint that chunks are never broken across pages.
16 %
17 \def\nwendcode{\endtrivlist \endgroup \vfil\penalty10\vfilneg}
18 \let\nwdocspar=\smallbreak
19 \end_preamble
20 \use_default_options false
21 \maintain_unincluded_children false
22 \language english
23 \language_package default
24 \inputencoding auto
25 \fontencoding global
26 \font_roman times
27 \font_sans helvet
28 \font_typewriter courier
29 \font_default_family default
30 \use_non_tex_fonts false
31 \font_sc false
32 \font_osf false
33 \font_sf_scale 100
34 \font_tt_scale 100
35
36 \graphics default
37 \default_output_format default
38 \output_sync 0
39 \bibtex_command default
40 \index_command default
41 \paperfontsize default
42 \spacing single
43 \use_hyperref false
44 \papersize default
45 \use_geometry false
46 \use_amsmath 0
47 \use_esint 0
48 \use_mhchem 1
49 \use_mathdots 1
50 \cite_engine basic
51 \use_bibtopic false
52 \use_indices false
53 \paperorientation portrait
54 \suppress_date false
55 \use_refstyle 0
56 \index Index
57 \shortcut idx
58 \color #008000
59 \end_index
60 \secnumdepth 3
61 \tocdepth 3
62 \paragraph_separation indent
63 \paragraph_indentation default
64 \quotes_language english
65 \papercolumns 1
66 \papersides 1
67 \paperpagestyle default
68 \tracking_changes false
69 \output_changes false
70 \html_math_output 0
71 \html_css_as_file 0
72 \html_be_strict false
73 \end_header
74
75 \begin_body
76
77 \begin_layout Title
78 LyX listerrors:
79 \begin_inset Newline newline
80 \end_inset
81
82 rewritten in Python
83 \end_layout
84
85 \begin_layout Author
86 Kayvan A.
87  Sylvan
88 \begin_inset Newline newline
89 \end_inset
90
91
92 \begin_inset Flex URL
93 status collapsed
94
95 \begin_layout Plain Layout
96
97 mailto:kayvan@sylvan.com
98 \end_layout
99
100 \end_inset
101
102
103 \end_layout
104
105 \begin_layout Date
106 3/15/2002
107 \end_layout
108
109 \begin_layout Abstract
110 The listerrors program used to be compiled as a C program and installed
111  as 
112 \emph on
113 BINDIR/listerrors
114 \emph default
115  along with LyX in order to perform some simple re-formatting of noweb and
116  GCC error messages.
117  This document describes and implements the Python version of the same program.
118 \end_layout
119
120 \begin_layout Standard
121 \begin_inset CommandInset toc
122 LatexCommand tableofcontents
123
124 \end_inset
125
126
127 \end_layout
128
129 \begin_layout Section
130 Introduction
131 \end_layout
132
133 \begin_layout Standard
134 The motivation for this program was Bugzilla bug 190
135 \begin_inset Foot
136 status collapsed
137
138 \begin_layout Plain Layout
139 Visit 
140 \begin_inset Flex URL
141 status collapsed
142
143 \begin_layout Plain Layout
144
145 http://bugzilla.lyx.org/show_bug.cgi?id=190
146 \end_layout
147
148 \end_inset
149
150  for the details.
151 \end_layout
152
153 \end_inset
154
155  dealing with the 
156 \begin_inset Quotes eld
157 \end_inset
158
159 listerrors
160 \begin_inset Quotes erd
161 \end_inset
162
163  executable.
164 \end_layout
165
166 \begin_layout Standard
167 What is 
168 \begin_inset Quotes eld
169 \end_inset
170
171 listerrors
172 \begin_inset Quotes erd
173 \end_inset
174
175 ? Usually, LyX has great support for parsing of error messages.
176  For each error in the log file, LyX pops up an error box at that location
177  in the LyX window.
178  The error scanning routines expect these errors to be in a certain format
179  (similar to LaTeX errors).
180  When dealing with Literate Programs, you have 
181 \begin_inset Quotes eld
182 \end_inset
183
184 noweb
185 \begin_inset Foot
186 status collapsed
187
188 \begin_layout Plain Layout
189 See 
190 \begin_inset Flex URL
191 status collapsed
192
193 \begin_layout Plain Layout
194
195 http://www.eecs.harvard.edu/~nr/noweb
196 \end_layout
197
198 \end_inset
199
200  for more information about noweb.
201 \end_layout
202
203 \end_inset
204
205
206 \begin_inset Quotes erd
207 \end_inset
208
209  as well as gcc error messages (and potentially others).
210  The listerrors program attempts to standardize these error messages to
211  a format that LyX can parse and react to.
212 \end_layout
213
214 \begin_layout Standard
215 In a nutshell, the problems with the old implementation of listerrors that
216  bug 190 refers to were::
217 \end_layout
218
219 \begin_layout Enumerate
220 It was a C program and it was installed in the user path in the same directory
221  as LyX.
222  Having such a generically named binary in, for example, 
223 \emph on
224 /usr/bin
225 \emph default
226 , was potentially confusing.
227 \end_layout
228
229 \begin_layout Enumerate
230 It required that noweb be installed on the compiling machine (the source
231  was extracted by noweb from 
232 \emph on
233 SRCDIR/examples/Literate.lyx
234 \emph default
235 , compiled and installed by 
236 \begin_inset Quotes eld
237 \end_inset
238
239 make install
240 \begin_inset Quotes erd
241 \end_inset
242
243 ).
244 \end_layout
245
246 \begin_layout Standard
247 The new version deals with these problems in the following fashion:
248 \end_layout
249
250 \begin_layout Enumerate
251 Both the example file (this document) and the program are to be added to
252  the LyX CVS repository.
253 \end_layout
254
255 \begin_layout Enumerate
256 The program itself will be installed in 
257 \emph on
258 SHAREDIR/lyx/scripts
259 \emph default
260 , along with other LyX-specific helper scripts.
261 \end_layout
262
263 \begin_layout Standard
264 In the design and implementation of this new 
265 \begin_inset Quotes eld
266 \end_inset
267
268 listerrors
269 \begin_inset Quotes erd
270 \end_inset
271
272 , the Python
273 \begin_inset Foot
274 status collapsed
275
276 \begin_layout Plain Layout
277 See the Python home page (
278 \begin_inset Flex URL
279 status collapsed
280
281 \begin_layout Plain Layout
282
283 http://www.python.org
284 \end_layout
285
286 \end_inset
287
288 ) for more information.
289 \end_layout
290
291 \end_inset
292
293  language was chosen since it is fully multi-platform and provides a very
294  uniform and easy to read syntax.
295  This re-write also simplifies the code for 
296 \begin_inset Quotes eld
297 \end_inset
298
299 listerrors
300 \begin_inset Quotes erd
301 \end_inset
302
303  greatly.
304  Python is installed by default on all modern Linux systems and is freely
305  available for all other platforms.
306 \end_layout
307
308 \begin_layout Scrap
309 <<listerrors>>=
310 \end_layout
311
312 \begin_layout Scrap
313 #!/usr/bin/python -tt
314 \end_layout
315
316 \begin_layout Scrap
317 """reformat noweb and compiler errors for LyX.
318 \end_layout
319
320 \begin_layout Scrap
321
322 \end_layout
323
324 \begin_layout Scrap
325 Expects to read from stdin and output to stdout.
326 \end_layout
327
328 \begin_layout Scrap
329 """
330 \end_layout
331
332 \begin_layout Scrap
333
334 \end_layout
335
336 \begin_layout Scrap
337 __author__ = "Kayvan A.
338  Sylvan <kayvan@sylvan.com>"
339 \end_layout
340
341 \begin_layout Scrap
342 __date__ = "$Date: 2005/07/18 09:42:26 $"
343 \end_layout
344
345 \begin_layout Scrap
346 __version__ = "$Revision: 1.5 $"
347 \end_layout
348
349 \begin_layout Scrap
350 __credits__ = """Edmar Wienskoski Jr.
351  <edmar-w-jr@technologist.com>
352 \end_layout
353
354 \begin_layout Scrap
355     original Literate support for LyX.
356 \end_layout
357
358 \begin_layout Scrap
359 Bernard Michael Hurley <berhardh@westherts.ac.uk>
360 \end_layout
361
362 \begin_layout Scrap
363     modifications to original listerrors."""
364 \end_layout
365
366 \begin_layout Scrap
367 __copyright__ = "Copyright 2002 - Kayvan Sylvan."
368 \end_layout
369
370 \begin_layout Scrap
371
372 \end_layout
373
374 \begin_layout Scrap
375 import sys, string
376 \end_layout
377
378 \begin_layout Scrap
379
380 \end_layout
381
382 \begin_layout Scrap
383 <<Function Bodies>>
384 \end_layout
385
386 \begin_layout Scrap
387
388 \end_layout
389
390 \begin_layout Scrap
391 if __name__ == "__main__":
392 \end_layout
393
394 \begin_layout Scrap
395   main()
396 \end_layout
397
398 \begin_layout Scrap
399 @
400 \end_layout
401
402 \begin_layout Section
403 LaTeX style error message
404 \end_layout
405
406 \begin_layout Standard
407 The following function mimics the TeX error message format.
408 \end_layout
409
410 \begin_layout Scrap
411 <<Function Bodies>>=
412 \end_layout
413
414 \begin_layout Scrap
415 def write_error(msg, tool = "noweb", line_number = 1):
416 \end_layout
417
418 \begin_layout Scrap
419   """Write out the given message in TeX error style.
420 \end_layout
421
422 \begin_layout Scrap
423
424 \end_layout
425
426 \begin_layout Scrap
427
428 \end_layout
429
430 \begin_layout Scrap
431   called like: write_error(msg, tool, line_number)."""
432 \begin_inset Newline newline
433 \end_inset
434
435   print "! Build Error: ==> %s ==>
436 \backslash
437 n" % (tool),
438 \begin_inset Newline newline
439 \end_inset
440
441   print " ...
442 \backslash
443 n
444 \backslash
445 nl.%d ...
446 \backslash
447 n" % (line_number),
448 \begin_inset Newline newline
449 \end_inset
450
451   if type(msg) == type("str"): # simple string
452 \begin_inset Newline newline
453 \end_inset
454
455     print msg
456 \begin_inset Newline newline
457 \end_inset
458
459   else: # some kind of list (sequence or tuple)
460 \begin_inset Newline newline
461 \end_inset
462
463     for m in msg:
464 \begin_inset Newline newline
465 \end_inset
466
467         if m != "": print m,
468 \begin_inset Newline newline
469 \end_inset
470
471     print
472 \begin_inset Newline newline
473 \end_inset
474
475
476 \begin_inset Newline newline
477 \end_inset
478
479 @ %def write_error
480 \end_layout
481
482 \begin_layout Section
483 Filtering errors
484 \end_layout
485
486 \begin_layout Standard
487 The only complication in our filtering code is that some parsers might need
488  to push back lines that are read in to be read again later.
489  We solve this problem by implementing a 
490 \begin_inset Quotes eld
491 \end_inset
492
493 getline
494 \begin_inset Quotes erd
495 \end_inset
496
497  and 
498 \begin_inset Quotes eld
499 \end_inset
500
501 pushline
502 \begin_inset Quotes erd
503 \end_inset
504
505  set of functions:
506 \end_layout
507
508 \begin_layout Scrap
509 <<Function Bodies>>=
510 \end_layout
511
512 \begin_layout Scrap
513 __lines = [] # lines pushed back
514 \end_layout
515
516 \begin_layout Scrap
517
518 \end_layout
519
520 \begin_layout Scrap
521 def getline(file = sys.stdin):
522 \end_layout
523
524 \begin_layout Scrap
525   """read a line from internal stack or from file.
526 \end_layout
527
528 \begin_layout Scrap
529
530 \end_layout
531
532 \begin_layout Scrap
533   optional file argument defaults to sys.stdin."""
534 \end_layout
535
536 \begin_layout Scrap
537   global __lines
538 \end_layout
539
540 \begin_layout Scrap
541   lines = __lines
542 \end_layout
543
544 \begin_layout Scrap
545   if lines:
546 \end_layout
547
548 \begin_layout Scrap
549     line = lines.pop()
550 \end_layout
551
552 \begin_layout Scrap
553   else:
554 \end_layout
555
556 \begin_layout Scrap
557     line = file.readline()
558 \end_layout
559
560 \begin_layout Scrap
561   return line
562 \end_layout
563
564 \begin_layout Scrap
565
566 \end_layout
567
568 \begin_layout Scrap
569 @ %def getline
570 \end_layout
571
572 \begin_layout Standard
573 And now for the corresponding pushline function:
574 \end_layout
575
576 \begin_layout Scrap
577 <<Function Bodies>>=
578 \end_layout
579
580 \begin_layout Scrap
581 def pushline(line):
582 \end_layout
583
584 \begin_layout Scrap
585   "push a line onto the pushback stack."
586 \end_layout
587
588 \begin_layout Scrap
589
590 \end_layout
591
592 \begin_layout Scrap
593   global __lines
594 \begin_inset Newline newline
595 \end_inset
596
597   lines = __lines
598 \begin_inset Newline newline
599 \end_inset
600
601   lines.append(line)
602 \begin_inset Newline newline
603 \end_inset
604
605
606 \begin_inset Newline newline
607 \end_inset
608
609 @ %def pushline
610 \end_layout
611
612 \begin_layout Standard
613 The main() entry point function is extremely simple.
614  Note that this version of 
615 \begin_inset Quotes eld
616 \end_inset
617
618 listerrors
619 \begin_inset Quotes erd
620 \end_inset
621
622  takes no options and simply filters, attempting simply to match against
623  the known error message patterns.
624  The listerrors C program handled a single-character command-line argument
625  that the current code no longer needs.
626  
627 \end_layout
628
629 \begin_layout Scrap
630 <<Function Bodies>>=
631 \end_layout
632
633 \begin_layout Scrap
634 def main():
635 \end_layout
636
637 \begin_layout Scrap
638   """Entry point for listerrors.
639  Takes no options.
640 \end_layout
641
642 \begin_layout Scrap
643
644 \end_layout
645
646 \begin_layout Scrap
647   Reads stdin and writes to stdout.
648  Filter errors"""
649 \end_layout
650
651 \begin_layout Scrap
652
653 \end_layout
654
655 \begin_layout Scrap
656   while 1:
657 \end_layout
658
659 \begin_layout Scrap
660     line = getline()
661 \end_layout
662
663 \begin_layout Scrap
664     if line == "": break
665 \end_layout
666
667 \begin_layout Scrap
668     <<Check line against patterns and take action>>
669 \end_layout
670
671 \begin_layout Scrap
672 @ %def main
673 \end_layout
674
675 \begin_layout Standard
676 For each line read in, we need to find out if it matches any of our tools
677  (noweb, gcc, etc.) and act accordingly.
678 \end_layout
679
680 \begin_layout Scrap
681 <<Check line against patterns and take action>>=
682 \end_layout
683
684 \begin_layout Scrap
685
686 \end_layout
687
688 \begin_layout Scrap
689 try_patterns_dispatch = [ noweb_try, gcc_try, xlc_try ]
690 \begin_inset Newline newline
691 \end_inset
692
693 for predicate in try_patterns_dispatch:
694 \begin_inset Newline newline
695 \end_inset
696
697   if predicate(line): break
698 \begin_inset Newline newline
699 \end_inset
700
701 @
702 \end_layout
703
704 \begin_layout Section
705 Different Error Formats
706 \end_layout
707
708 \begin_layout Standard
709 The following sections handle the various error message formats that we
710  recognize in this program.
711  
712 \end_layout
713
714 \begin_layout Subsection
715 noweb errors
716 \end_layout
717
718 \begin_layout Standard
719 Noweb errors are output on a single line, so examining just the current
720  line is enough.
721 \end_layout
722
723 \begin_layout Scrap
724 <<Function Bodies>>=
725 \end_layout
726
727 \begin_layout Scrap
728 def noweb_try(line):
729 \end_layout
730
731 \begin_layout Scrap
732   """see if line is a noweb error.
733 \end_layout
734
735 \begin_layout Scrap
736
737 \end_layout
738
739 \begin_layout Scrap
740   Returns 1 on success, 0 otherwise.
741  Outputs on stdout."""
742 \end_layout
743
744 \begin_layout Scrap
745   retval = 0
746 \end_layout
747
748 \begin_layout Scrap
749   <<Look for the unescaped angle-brackets in documentation>>
750 \end_layout
751
752 \begin_layout Scrap
753   <<Look for anything with double angle brackets>>
754 \end_layout
755
756 \begin_layout Scrap
757   <<Last ditch effort scan for specific strings>>
758 \end_layout
759
760 \begin_layout Scrap
761   return retval
762 \end_layout
763
764 \begin_layout Scrap
765
766 \end_layout
767
768 \begin_layout Scrap
769 @ %def noweb_try
770 \end_layout
771
772 \begin_layout Standard
773 First, we look for the 
774 \begin_inset Quotes eld
775 \end_inset
776
777 unescaped < < in documentation chunk
778 \begin_inset Quotes erd
779 \end_inset
780
781  message.
782  This is the only message with an associated line number from noweb.
783 \end_layout
784
785 \begin_layout Scrap
786
787 \end_layout
788
789 \begin_layout Scrap
790 <<Look for the unescaped angle-brackets in documentation>>=
791 \end_layout
792
793 \begin_layout Scrap
794 if string.find(line, ": unescaped << in documentation chunk") != -1:
795 \end_layout
796
797 \begin_layout Scrap
798   line_parts = string.split(line, ':')
799 \end_layout
800
801 \begin_layout Scrap
802   num_str = line_parts[1]
803 \end_layout
804
805 \begin_layout Scrap
806   num_len = len(num_str)
807 \end_layout
808
809 \begin_layout Scrap
810   i = 0
811 \end_layout
812
813 \begin_layout Scrap
814   while i < num_len and (num_str[i] in string.digits): i = i + 1
815 \end_layout
816
817 \begin_layout Scrap
818   if i == num_len:
819 \end_layout
820
821 \begin_layout Scrap
822     write_error(":" + line_parts[2], "noweb", int(num_str))
823 \end_layout
824
825 \begin_layout Scrap
826     retval = 1
827 \end_layout
828
829 \begin_layout Scrap
830 @
831 \end_layout
832
833 \begin_layout Standard
834 Some noweb messages are simply about undefined scraps.
835  These can be seen by looking for matching double-angle-brackets.
836 \end_layout
837
838 \begin_layout Scrap
839 <<Look for anything with double angle brackets>>=
840 \end_layout
841
842 \begin_layout Scrap
843
844 \end_layout
845
846 \begin_layout Scrap
847 if (not retval):
848 \begin_inset Newline newline
849 \end_inset
850
851   left = string.find(line, "<<")
852 \begin_inset Newline newline
853 \end_inset
854
855   if (left != -1) and ((left + 2) < len(line)) and 
856 \backslash
857
858 \begin_inset Newline newline
859 \end_inset
860
861      (string.find(line[left+2:], ">>") != -1):
862 \begin_inset Newline newline
863 \end_inset
864
865     write_error(line, "noweb");
866 \begin_inset Newline newline
867 \end_inset
868
869     retval = 1;
870 \begin_inset Newline newline
871 \end_inset
872
873 @
874 \end_layout
875
876 \begin_layout Standard
877 Finally, here is an additional list of explicit strings to check for.
878 \end_layout
879
880 \begin_layout Scrap
881 <<Last ditch effort scan for specific strings>>=
882 \end_layout
883
884 \begin_layout Scrap
885 if (not retval):
886 \end_layout
887
888 \begin_layout Scrap
889   msgs_to_try = ("couldn't open file",
890 \end_layout
891
892 \begin_layout Scrap
893     "couldn't open temporary file",
894 \end_layout
895
896 \begin_layout Scrap
897     "error writing temporary file",
898 \end_layout
899
900 \begin_layout Scrap
901     "ill-formed option",
902 \end_layout
903
904 \begin_layout Scrap
905     "unknown option",
906 \end_layout
907
908 \begin_layout Scrap
909     "Bad format sequence",
910 \end_layout
911
912 \begin_layout Scrap
913     "Can't open output file",
914 \end_layout
915
916 \begin_layout Scrap
917     "Can't open temporary file",
918 \end_layout
919
920 \begin_layout Scrap
921     "Capacity exceeded:",
922 \end_layout
923
924 \begin_layout Scrap
925     "Ignoring unknown option -",
926 \end_layout
927
928 \begin_layout Scrap
929     "This can't happen:",
930 \end_layout
931
932 \begin_layout Scrap
933     "non-numeric line number in")
934 \end_layout
935
936 \begin_layout Scrap
937   for msg in msgs_to_try:
938 \end_layout
939
940 \begin_layout Scrap
941     if string.find(line, msg) != -1:
942 \end_layout
943
944 \begin_layout Scrap
945       write_error(line, "noweb")
946 \end_layout
947
948 \begin_layout Scrap
949       retval = 1
950 \end_layout
951
952 \begin_layout Scrap
953       break
954 \end_layout
955
956 \begin_layout Scrap
957 @
958 \end_layout
959
960 \begin_layout Subsection
961 gcc errors
962 \end_layout
963
964 \begin_layout Standard
965 The gcc errors can be multi-line, with the following format:
966 \end_layout
967
968 \begin_layout LyX-Code
969 foo.c: In function `main': 
970 \end_layout
971
972 \begin_layout Scrap
973 foo.c:3: `bar' undeclared (first use in this function) 
974 \end_layout
975
976 \begin_layout Scrap
977 foo.c:3: (Each undeclared identifier is reported only once 
978 \end_layout
979
980 \begin_layout Scrap
981
982 \end_layout
983
984 \begin_layout Scrap
985 foo.c:3: for each function it appears in.) 
986 \begin_inset Newline newline
987 \end_inset
988
989 foo.c:3: parse error before `x'
990 \end_layout
991
992 \begin_layout Standard
993 In order to parse this, the gcc error handler has to look ahead and return
994  any and all lines that do not match the expected pattern.
995 \end_layout
996
997 \begin_layout Scrap
998 <<Function Bodies>>=
999 \end_layout
1000
1001 \begin_layout Scrap
1002 def gcc_try(line):
1003 \end_layout
1004
1005 \begin_layout Scrap
1006   """See if line is a gcc error.
1007  Read ahead to handle all the lines.
1008 \end_layout
1009
1010 \begin_layout Scrap
1011
1012 \end_layout
1013
1014 \begin_layout Scrap
1015   Returns 1 on success, 0 otherwise.
1016  Outputs on stdout."""
1017 \end_layout
1018
1019 \begin_layout Scrap
1020   retval = 0
1021 \end_layout
1022
1023 \begin_layout Scrap
1024   <<Handle the gcc error message>>
1025 \end_layout
1026
1027 \begin_layout Scrap
1028   return retval
1029 \end_layout
1030
1031 \begin_layout Scrap
1032
1033 \end_layout
1034
1035 \begin_layout Scrap
1036 @ %def gcc_try
1037 \end_layout
1038
1039 \begin_layout Standard
1040 The error message starts with a gcc header (as above) without an associated
1041  line number.
1042 \end_layout
1043
1044 \begin_layout Scrap
1045 <<Handle the gcc error message>>= 
1046 \begin_inset Newline newline
1047 \end_inset
1048
1049 first_space = string.find(line, ' ')
1050 \begin_inset Newline newline
1051 \end_inset
1052
1053 if first_space > 1: # The smallest would be "X: "
1054 \begin_inset Newline newline
1055 \end_inset
1056
1057   if line[first_space - 1] == ':':
1058 \begin_inset Newline newline
1059 \end_inset
1060
1061     header_to_see = line[:first_space - 1]
1062 \begin_inset Newline newline
1063 \end_inset
1064
1065     next_line = getline()
1066 \begin_inset Newline newline
1067 \end_inset
1068
1069     if next_line and next_line[:first_space - 1] == header_to_see:
1070 \begin_inset Newline newline
1071 \end_inset
1072
1073       num_end = first_space
1074 \begin_inset Newline newline
1075 \end_inset
1076
1077       while next_line[num_end] in string.digits: num_end = num_end + 1
1078 \begin_inset Newline newline
1079 \end_inset
1080
1081       if num_end > first_space: # good!
1082 \begin_inset Newline newline
1083 \end_inset
1084
1085         <<Accumulate gcc error lines and print it>>
1086 \begin_inset Newline newline
1087 \end_inset
1088
1089       else: # oops! Not a gcc error.
1090 \begin_inset Newline newline
1091 \end_inset
1092
1093         pushline(next_line)
1094 \begin_inset Newline newline
1095 \end_inset
1096
1097     elif next_line:
1098 \begin_inset Newline newline
1099 \end_inset
1100
1101       pushline(next_line) # return this line to input stream
1102 \begin_inset Newline newline
1103 \end_inset
1104
1105 @
1106 \end_layout
1107
1108 \begin_layout Standard
1109 At the point in the code that we know that we are in the middle of an error
1110  message, we do the following:
1111 \end_layout
1112
1113 \begin_layout Scrap
1114 <<Accumulate gcc error lines and print it>>=
1115 \end_layout
1116
1117 \begin_layout Scrap
1118 num_str = next_line[first_space:num_end]
1119 \end_layout
1120
1121 \begin_layout Scrap
1122 msgs = [line[first_space:]]
1123 \end_layout
1124
1125 \begin_layout Scrap
1126 msgs.append(next_line[num_end + 1:])
1127 \end_layout
1128
1129 \begin_layout Scrap
1130 header_to_see = next_line[:num_end]
1131 \end_layout
1132
1133 \begin_layout Scrap
1134 next_line = getline()
1135 \end_layout
1136
1137 \begin_layout Scrap
1138 while next_line and next_line[:num_end] == header_to_see:
1139 \end_layout
1140
1141 \begin_layout Scrap
1142   msgs.append(next_line[num_end + 1:])
1143 \end_layout
1144
1145 \begin_layout Scrap
1146   next_line = getline()
1147 \end_layout
1148
1149 \begin_layout Scrap
1150 if next_line: pushline(next_line)
1151 \end_layout
1152
1153 \begin_layout Scrap
1154 write_error(msgs, "gcc", int(num_str))
1155 \end_layout
1156
1157 \begin_layout Scrap
1158 retval = 1
1159 \end_layout
1160
1161 \begin_layout Scrap
1162 @
1163 \end_layout
1164
1165 \begin_layout Subsection
1166 xlc errors
1167 \end_layout
1168
1169 \begin_layout Standard
1170 A xlc error message is easy to identify.
1171  Every error message starts with a quoted string with no spaces, a comma,
1172  a space, the word 
1173 \begin_inset Quotes eld
1174 \end_inset
1175
1176 line
1177 \begin_inset Quotes erd
1178 \end_inset
1179
1180 , a space, and some variable text.
1181  The following routine tests if a given buffer line matches this criteria
1182  (this code would probably be simpler if I used the 
1183 \begin_inset Quotes eld
1184 \end_inset
1185
1186 re
1187 \begin_inset Quotes erd
1188 \end_inset
1189
1190  regexp module, but we don't really need the full regular expression engine
1191  here).
1192  
1193 \end_layout
1194
1195 \begin_layout Scrap
1196
1197 \end_layout
1198
1199 \begin_layout Scrap
1200
1201 \end_layout
1202
1203 \begin_layout Scrap
1204 <<Function Bodies>>=
1205 \end_layout
1206
1207 \begin_layout Scrap
1208 def xlc_try(line):
1209 \end_layout
1210
1211 \begin_layout Scrap
1212   """see if line is an xlc error.
1213 \end_layout
1214
1215 \begin_layout Scrap
1216
1217 \end_layout
1218
1219 \begin_layout Scrap
1220   Returns 1 on success, 0 otherwise.
1221  Outputs on stdout."""
1222 \end_layout
1223
1224 \begin_layout Scrap
1225   retval = 0
1226 \end_layout
1227
1228 \begin_layout Scrap
1229   if line[0] == '"': # This is the first character of all xlc errors
1230 \end_layout
1231
1232 \begin_layout Scrap
1233     next_quote = string.find(line, '"', 1)
1234 \end_layout
1235
1236 \begin_layout Scrap
1237     first_space = string.find(line, ' ')
1238 \end_layout
1239
1240 \begin_layout Scrap
1241     if (next_quote != -1) and (first_space > next_quote): # no space inisde
1242  quotes
1243 \end_layout
1244
1245 \begin_layout Scrap
1246       if line[first_space - 1:first_space + 6] == ", line ":
1247 \end_layout
1248
1249 \begin_layout Scrap
1250         num_start = num_end = first_space + 6
1251 \end_layout
1252
1253 \begin_layout Scrap
1254         while line[num_end] in string.digits: num_end = num_end + 1
1255 \end_layout
1256
1257 \begin_layout Scrap
1258         if num_end > num_start:
1259 \end_layout
1260
1261 \begin_layout Scrap
1262           write_error(line, "xlc", int(line[num_start : num_end]))
1263 \end_layout
1264
1265 \begin_layout Scrap
1266           retval = 1
1267 \end_layout
1268
1269 \begin_layout Scrap
1270   return retval
1271 \end_layout
1272
1273 \begin_layout Scrap
1274   
1275 \end_layout
1276
1277 \begin_layout Scrap
1278 @ %def xlc_try
1279 \end_layout
1280
1281 \begin_layout Section
1282 Extracting the code
1283 \end_layout
1284
1285 \begin_layout Standard
1286 This project can be tangled from LyX if you set your 
1287 \begin_inset Quotes eld
1288 \end_inset
1289
1290 Program
1291 \begin_inset Quotes erd
1292 \end_inset
1293
1294  convertor to call a generic script that always extracts a scrap named 
1295 \family typewriter
1296 build-script
1297 \family default
1298  and executes it.
1299  Here is an example of such a generic script:
1300 \end_layout
1301
1302 \begin_layout LyX-Code
1303 #!/bin/sh
1304 \begin_inset Newline newline
1305 \end_inset
1306
1307 notangle -Rbuild-script $1 | env NOWEB_SOURCE=$1 sh
1308 \end_layout
1309
1310 \begin_layout Standard
1311 This section defines our build-script, which extracts the code.
1312 \end_layout
1313
1314 \begin_layout Scrap
1315 <<build-script>>=
1316 \end_layout
1317
1318 \begin_layout Scrap
1319 #!/bin/sh
1320 \end_layout
1321
1322 \begin_layout Scrap
1323 if [ -z "$NOWEB_SOURCE" ]; then NOWEB_SOURCE=listerrors.nw; fi
1324 \end_layout
1325
1326 \begin_layout Scrap
1327 notangle -Rlisterrors ${NOWEB_SOURCE} > listerrors
1328 \end_layout
1329
1330 \begin_layout Scrap
1331 chmod +x listerrors
1332 \end_layout
1333
1334 \begin_layout Scrap
1335 @
1336 \end_layout
1337
1338 \begin_layout Section
1339 Indices
1340 \end_layout
1341
1342 \begin_layout Standard
1343 This section provides cross-references into the rest of the program.
1344 \end_layout
1345
1346 \begin_layout Subsection
1347 Macros
1348 \end_layout
1349
1350 \begin_layout Standard
1351 \begin_inset ERT
1352 status collapsed
1353
1354 \begin_layout Plain Layout
1355
1356
1357 \backslash
1358 nowebchunks
1359 \end_layout
1360
1361 \end_inset
1362
1363
1364 \end_layout
1365
1366 \begin_layout Subsection
1367 Identifiers
1368 \end_layout
1369
1370 \begin_layout Standard
1371 \begin_inset ERT
1372 status collapsed
1373
1374 \begin_layout Plain Layout
1375
1376
1377 \backslash
1378 nowebindex
1379 \end_layout
1380
1381 \end_inset
1382
1383
1384 \end_layout
1385
1386 \end_body
1387 \end_document