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