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