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