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