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