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