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