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