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