]> git.lyx.org Git - lyx.git/blob - lib/examples/Literate.lyx
Cmake export tests: Handle attic files with now missing references to png graphics
[lyx.git] / lib / examples / Literate.lyx
1 #LyX 2.2 created this file. For more info see http://www.lyx.org/
2 \lyxformat 503
3 \begin_document
4 \begin_header
5 \origin /systemlyxdir/examples/
6 \textclass article
7 \use_default_options false
8 \begin_modules
9 noweb
10 \end_modules
11 \maintain_unincluded_children false
12 \language english
13 \language_package default
14 \inputencoding default
15 \fontencoding global
16 \font_roman "default" "default"
17 \font_sans "default" "default"
18 \font_typewriter "default" "default"
19 \font_math "auto" "auto"
20 \font_default_family default
21 \use_non_tex_fonts false
22 \font_sc false
23 \font_osf false
24 \font_sf_scale 100 100
25 \font_tt_scale 100 100
26 \graphics default
27 \default_output_format default
28 \output_sync 0
29 \bibtex_command default
30 \index_command default
31 \paperfontsize default
32 \spacing single
33 \use_hyperref false
34 \papersize default
35 \use_geometry false
36 \use_package amsmath 0
37 \use_package amssymb 0
38 \use_package cancel 0
39 \use_package esint 0
40 \use_package mathdots 1
41 \use_package mathtools 0
42 \use_package mhchem 1
43 \use_package stackrel 0
44 \use_package stmaryrd 0
45 \use_package undertilde 0
46 \cite_engine basic
47 \cite_engine_type default
48 \biblio_style plain
49 \use_bibtopic false
50 \use_indices false
51 \paperorientation portrait
52 \suppress_date false
53 \justification true
54 \use_refstyle 0
55 \index Index
56 \shortcut idx
57 \color #008000
58 \end_index
59 \secnumdepth 3
60 \tocdepth 3
61 \paragraph_separation indent
62 \paragraph_indentation default
63 \quotes_language english
64 \papercolumns 1
65 \papersides 1
66 \paperpagestyle default
67 \tracking_changes false
68 \output_changes false
69 \html_math_output 0
70 \html_css_as_file 0
71 \html_be_strict false
72 \end_header
73
74 \begin_body
75
76 \begin_layout Title
77 \SpecialCharNoPassThru LyX
78  and Literate Programming
79 \begin_inset Newline newline
80 \end_inset
81
82 An example program
83 \end_layout
84
85 \begin_layout Author
86 Edmar Wienskoski Jr.
87 \begin_inset Newline newline
88 \end_inset
89
90 edmar-w-jr@technologist.com
91 \begin_inset Foot
92 status collapsed
93
94 \begin_layout Plain Layout
95 Modified by Bernard Michael Hurley bernardh@westherts.ac.uk \threehyphens
96 - Don't blame
97  Edmar for any errors that have crept in!
98 \end_layout
99
100 \end_inset
101
102
103 \end_layout
104
105 \begin_layout Abstract
106
107 \series bold
108 Note:
109 \series default
110  This example program is provided for educational use only.
111  The functionality in this C program has been superceded by the equivalent
112  Python code in 
113 \emph on
114 examples/listerrors.lyx
115 \emph default
116  which should be installed in the \SpecialCharNoPassThru LyX
117  scripts directory.
118 \end_layout
119
120 \begin_layout Date
121 \begin_inset ERT
122 status collapsed
123
124 \begin_layout Plain Layout
125
126
127 \backslash
128 today
129 \end_layout
130
131 \end_inset
132
133
134 \end_layout
135
136 \begin_layout Standard
137 \begin_inset CommandInset toc
138 LatexCommand tableofcontents
139
140 \end_inset
141
142
143 \end_layout
144
145 \begin_layout Section
146 Introduction
147 \end_layout
148
149 \begin_layout Standard
150 After typesetting a document, \SpecialCharNoPassThru LyX
151  scans the \SpecialCharNoPassThru LaTeX
152  log file looking for errors.
153  For each error found, the line number is obtained and a error box is displayed
154  in the \SpecialCharNoPassThru LyX
155  screen at that position.
156 \end_layout
157
158 \begin_layout Standard
159 To use this feature to view compilation errors while working with literate
160  documents, we need a program that filters the compilation errors and puts
161  them in a format suitable for \SpecialCharNoPassThru LyX
162  reading it.
163  
164 \end_layout
165
166 \begin_layout Standard
167 In this document we present a filter that recognizes compilation error messages
168  from noweb, gnu C, and the IBM C compiler (xlc).
169 \end_layout
170
171 \begin_layout Standard
172 The filter is required to read from standard input, parse for error messages
173  and copy the error messages to the standard output.
174  During the output process, the filter must present the error messages in
175  a format that \SpecialCharNoPassThru LyX
176  can interpret, currently, the \SpecialCharNoPassThru LaTeX
177  error message format.
178  Of course, nothing will prevent future \SpecialCharNoPassThru LyX
179  releases from being able to
180  read other formats as well (like gcc error messages for example).
181  This mechanism is necessary to fully explore the literate programming tool's
182  capabilities.
183 \end_layout
184
185 \begin_layout Section
186 Algorithm
187 \end_layout
188
189 \begin_layout Standard
190 \begin_inset Flex Chunk
191 status open
192
193 \begin_layout Plain Layout
194
195 \begin_inset Argument 1
196 status open
197
198 \begin_layout Plain Layout
199 Function bodies
200 \end_layout
201
202 \end_inset
203
204 int
205 \end_layout
206
207 \begin_layout Plain Layout
208
209 main (int argc, char **argv)
210 \end_layout
211
212 \begin_layout Plain Layout
213
214 {
215 \end_layout
216
217 \begin_layout Plain Layout
218
219   if (argc == 2) {
220 \end_layout
221
222 \begin_layout Plain Layout
223
224     switch (argv[1][0]) {
225 \end_layout
226
227 \begin_layout Plain Layout
228
229     case 'n':
230 \end_layout
231
232 \begin_layout Plain Layout
233
234       <<Scan input for noweb error messages>>
235 \end_layout
236
237 \begin_layout Plain Layout
238
239       break;
240 \end_layout
241
242 \begin_layout Plain Layout
243
244     case 'x':
245 \end_layout
246
247 \begin_layout Plain Layout
248
249       <<Scan input for xlc error messages>>
250 \end_layout
251
252 \begin_layout Plain Layout
253
254       break;
255 \end_layout
256
257 \begin_layout Plain Layout
258
259     case 'a':
260 \end_layout
261
262 \begin_layout Plain Layout
263
264       <<AIX system using both noweb and xlc>>
265 \end_layout
266
267 \begin_layout Plain Layout
268
269       break;
270 \end_layout
271
272 \begin_layout Plain Layout
273
274     case 's':
275 \end_layout
276
277 \begin_layout Plain Layout
278
279     case 'b':
280 \end_layout
281
282 \begin_layout Plain Layout
283
284       <<Solaris and Linux systems using both noweb and gcc>>
285 \end_layout
286
287 \begin_layout Plain Layout
288
289       break;
290 \end_layout
291
292 \begin_layout Plain Layout
293
294     case 'g':
295 \end_layout
296
297 \begin_layout Plain Layout
298
299     default:
300 \end_layout
301
302 \begin_layout Plain Layout
303
304       <<Scan input for gcc error messages>>
305 \end_layout
306
307 \begin_layout Plain Layout
308
309       break;
310 \end_layout
311
312 \begin_layout Plain Layout
313
314     }
315 \end_layout
316
317 \begin_layout Plain Layout
318
319   } else {
320 \end_layout
321
322 \begin_layout Plain Layout
323
324     <<Scan input for gcc error messages>>
325 \end_layout
326
327 \begin_layout Plain Layout
328
329   }
330 \end_layout
331
332 \begin_layout Plain Layout
333
334 }
335 \end_layout
336
337 \end_inset
338
339
340 \end_layout
341
342 \begin_layout Standard
343 \begin_inset Flex Chunk
344 status open
345
346 \begin_layout Plain Layout
347
348 \begin_inset Argument 1
349 status open
350
351 \begin_layout Plain Layout
352 Function prototypes
353 \end_layout
354
355 \end_inset
356
357 int main (int argc, char **argv);
358 \end_layout
359
360 \end_inset
361
362
363 \end_layout
364
365 \begin_layout Section
366 Data Structures
367 \end_layout
368
369 \begin_layout Standard
370 We resort to some global variables to allow access from several different
371  routines.
372  These are the buffer and related pointers used during the parse of the
373  input.
374 \end_layout
375
376 \begin_layout Standard
377 \begin_inset ERT
378 status open
379
380 \begin_layout Plain Layout
381
382 <<Global variables>>=
383 \end_layout
384
385 \begin_layout Plain Layout
386
387 char    buffer[200][200];
388 \end_layout
389
390 \begin_layout Plain Layout
391
392 int     last_buf_line;
393 \end_layout
394
395 \begin_layout Plain Layout
396
397 int     last_err_line;
398 \end_layout
399
400 \begin_layout Plain Layout
401
402 int     err_line;@ 
403 \end_layout
404
405 \end_inset
406
407
408 \end_layout
409
410 \begin_layout Section
411 The output format
412 \end_layout
413
414 \begin_layout Standard
415 The output format mimics the \SpecialCharNoPassThru TeX
416  error messages format.
417  This function prints a number of lines residing in the global variable
418  
419 \family typewriter
420 buffer
421 \family default
422 , a program name and line number.
423  There is no special requirement on the input strings, they can be anything.
424 \begin_inset Foot
425 status collapsed
426
427 \begin_layout Plain Layout
428 This function has been slightly changed from EW's original to make scanning
429  a bit easier with \SpecialCharNoPassThru LaTeX
430 ::scanLogFile().
431  The test has been added because \SpecialCharNoPassThru LyX
432  can crash if empty lines are allowed
433  here \threehyphens
434  I can't figure out why! \threehyphens
435  BMH
436 \end_layout
437
438 \end_inset
439
440
441 \end_layout
442
443 \begin_layout Standard
444 \begin_inset Flex Chunk
445 status open
446
447 \begin_layout Plain Layout
448
449 \begin_inset Argument 1
450 status open
451
452 \begin_layout Plain Layout
453 Function bodies
454 \end_layout
455
456 \end_inset
457
458 void
459 \end_layout
460
461 \begin_layout Plain Layout
462
463 output_error (int buf_size, int error_line, char *tool)
464 \end_layout
465
466 \begin_layout Plain Layout
467
468 {
469 \end_layout
470
471 \begin_layout Plain Layout
472
473   int     i;
474 \end_layout
475
476 \begin_layout Plain Layout
477
478  
479 \end_layout
480
481 \begin_layout Plain Layout
482
483   fprintf(stdout, "! Build Error: ==> %s ==>
484 \backslash
485 n", tool);
486 \end_layout
487
488 \begin_layout Plain Layout
489
490   fprintf(stdout, " ...
491 \backslash
492 n
493 \backslash
494 nl.%d ...
495 \backslash
496 n", error_line);
497 \end_layout
498
499 \begin_layout Plain Layout
500
501  
502 \end_layout
503
504 \begin_layout Plain Layout
505
506   for (i=0; i<buf_size; i++)
507 \end_layout
508
509 \begin_layout Plain Layout
510
511     if (strlen(buffer[i]) != 0)
512 \end_layout
513
514 \begin_layout Plain Layout
515
516       fprintf(stdout, "%s", buffer[i]);
517 \end_layout
518
519 \begin_layout Plain Layout
520
521  
522 \end_layout
523
524 \begin_layout Plain Layout
525
526   fprintf(stdout, "
527 \backslash
528 n");
529 \end_layout
530
531 \begin_layout Plain Layout
532
533 }
534 \end_layout
535
536 \end_inset
537
538
539 \end_layout
540
541 \begin_layout Standard
542 \begin_inset Flex Chunk
543 status open
544
545 \begin_layout Plain Layout
546
547 \begin_inset Argument 1
548 status open
549
550 \begin_layout Plain Layout
551 Function prototypes
552 \end_layout
553
554 \end_inset
555
556 void output_error (int buf_size, int error_line, char *tool);
557 \end_layout
558
559 \end_inset
560
561
562 \end_layout
563
564 \begin_layout Section
565 Functions Implementation
566 \end_layout
567
568 \begin_layout Standard
569 Both noweave and notangle routines, always output one single line for each
570  error found, thus to scan the buffer for noweb error messages is enough
571  to exam one input line at a time.
572  Note that the noweb software does not provide a line error number, so all
573  errors boxes related to noweb messages will be displayed at the beginning
574  of the file.
575 \end_layout
576
577 \begin_layout Standard
578 \begin_inset Flex Chunk
579 status open
580
581 \begin_layout Plain Layout
582
583 \begin_inset Argument 1
584 status open
585
586 \begin_layout Plain Layout
587 Scan input for noweb error messages
588 \end_layout
589
590 \end_inset
591
592 {
593 \end_layout
594
595 \begin_layout Plain Layout
596
597   last_buf_line = 0;
598 \end_layout
599
600 \begin_layout Plain Layout
601
602   while (fgets(buffer[0], 200, stdin)) {
603 \end_layout
604
605 \begin_layout Plain Layout
606
607     if (noweb_try(0))
608 \end_layout
609
610 \begin_layout Plain Layout
611
612       output_error(1, err_line, "noweb");
613 \end_layout
614
615 \begin_layout Plain Layout
616
617   }
618 \end_layout
619
620 \begin_layout Plain Layout
621
622 }
623 \end_layout
624
625 \end_inset
626
627
628 \end_layout
629
630 \begin_layout Standard
631 The examination itself is very inefficient.
632  Unfortunately noweb doesn't have any characteristic that would help to
633  identify one of its error messages.
634  The solution is to collect all possible output messages in an array of
635  strings, and turn the examination process into a linear search in this
636  array.
637 \end_layout
638
639 \begin_layout Standard
640 \begin_inset Flex Chunk
641 status open
642
643 \begin_layout Plain Layout
644
645 \end_layout
646
647 \begin_layout Plain Layout
648
649 <<Global variables>>=
650 \end_layout
651
652 \begin_layout Plain Layout
653
654 char *noweb_msgs[] = {
655 \end_layout
656
657 \begin_layout Plain Layout
658
659   "couldn't open file",
660 \end_layout
661
662 \begin_layout Plain Layout
663
664   "couldn't open temporary file",
665 \end_layout
666
667 \begin_layout Plain Layout
668
669   "error writing temporary file",
670 \end_layout
671
672 \begin_layout Plain Layout
673
674   "ill-formed option",
675 \end_layout
676
677 \begin_layout Plain Layout
678
679   "unknown option",
680 \end_layout
681
682 \begin_layout Plain Layout
683
684   "Bad format sequence",
685 \end_layout
686
687 \begin_layout Plain Layout
688
689   "Can't open output file",
690 \end_layout
691
692 \begin_layout Plain Layout
693
694   "Can't open temporary file",
695 \end_layout
696
697 \begin_layout Plain Layout
698
699   "Capacity exceeded:",
700 \end_layout
701
702 \begin_layout Plain Layout
703
704   "Ignoring unknown option -",
705 \end_layout
706
707 \begin_layout Plain Layout
708
709   "This can't happen:",
710 \end_layout
711
712 \begin_layout Plain Layout
713
714   "non-numeric line number in"
715 \end_layout
716
717 \begin_layout Plain Layout
718
719 };
720 \end_layout
721
722 \begin_layout Plain Layout
723
724 \end_layout
725
726 \begin_layout Plain Layout
727
728 char *noweb_msgs_mimic_gcc[] = {
729 \end_layout
730
731 \begin_layout Plain Layout
732
733   ": unescaped << in documentation chunk"
734 \end_layout
735
736 \begin_layout Plain Layout
737
738 };
739 \end_layout
740
741 \end_inset
742
743
744 \end_layout
745
746 \begin_layout Standard
747 A noweb error message can be any string that contains a matching pair of
748  < <
749 \begin_inset space ~
750 \end_inset
751
752
753 \begin_inset space ~
754 \end_inset
755
756
757 \begin_inset space ~
758 \end_inset
759
760 > >, or any of the above strings
761 \end_layout
762
763 \begin_layout Standard
764 \begin_inset ERT
765 status open
766
767 \begin_layout Plain Layout
768
769 <<Function bodies>>=
770 \end_layout
771
772 \begin_layout Plain Layout
773
774 int noweb_try (int buf_line)
775 \end_layout
776
777 \begin_layout Plain Layout
778
779 {
780 \end_layout
781
782 \begin_layout Plain Layout
783
784   char    *s, *t, *b;
785 \end_layout
786
787 \begin_layout Plain Layout
788
789   int     i; 
790 \end_layout
791
792 \begin_layout Plain Layout
793
794 \end_layout
795
796 \begin_layout Plain Layout
797
798   b = buffer[buf_line];
799 \end_layout
800
801 \begin_layout Plain Layout
802
803   err_line = 0;
804 \end_layout
805
806 \begin_layout Plain Layout
807
808 \end_layout
809
810 \begin_layout Plain Layout
811
812   for (i=0; i<1; i++) {
813 \end_layout
814
815 \begin_layout Plain Layout
816
817       s = (char *)strstr (b, noweb_msgs_mimic_gcc[i]);
818 \end_layout
819
820 \begin_layout Plain Layout
821
822       if (s != NULL) {
823 \end_layout
824
825 \begin_layout Plain Layout
826
827         t = (char *)strchr(buffer[buf_line], ':');
828 \end_layout
829
830 \begin_layout Plain Layout
831
832         err_line = atoi(t+1);
833 \end_layout
834
835 \begin_layout Plain Layout
836
837         t = buffer[buf_line];
838 \end_layout
839
840 \begin_layout Plain Layout
841
842         ++s;
843 \end_layout
844
845 \begin_layout Plain Layout
846
847         while (*(t++) = *(s++));
848 \end_layout
849
850 \begin_layout Plain Layout
851
852         return 1;
853 \end_layout
854
855 \begin_layout Plain Layout
856
857       }
858 \end_layout
859
860 \begin_layout Plain Layout
861
862   }
863 \end_layout
864
865 \begin_layout Plain Layout
866
867   s = (char *)strstr(b, "<<");
868 \end_layout
869
870 \begin_layout Plain Layout
871
872   if (s != NULL) {
873 \end_layout
874
875 \begin_layout Plain Layout
876
877     s = (char *)strstr(s+2, ">>");
878 \end_layout
879
880 \begin_layout Plain Layout
881
882     if (s != NULL) {
883 \end_layout
884
885 \begin_layout Plain Layout
886
887       return 1;
888 \end_layout
889
890 \begin_layout Plain Layout
891
892     }
893 \end_layout
894
895 \begin_layout Plain Layout
896
897   } else { 
898 \end_layout
899
900 \begin_layout Plain Layout
901
902      for (i = 0; i < 12; ++i) {
903 \end_layout
904
905 \begin_layout Plain Layout
906
907         s = (char *)strstr (b, noweb_msgs[i]);
908 \end_layout
909
910 \begin_layout Plain Layout
911
912         if (s != NULL) {
913 \end_layout
914
915 \begin_layout Plain Layout
916
917            return 1;
918 \end_layout
919
920 \begin_layout Plain Layout
921
922         }
923 \end_layout
924
925 \begin_layout Plain Layout
926
927     }
928 \end_layout
929
930 \begin_layout Plain Layout
931
932   }
933 \end_layout
934
935 \begin_layout Plain Layout
936
937   return 0;
938 \end_layout
939
940 \begin_layout Plain Layout
941
942 }
943 \end_layout
944
945 \begin_layout Plain Layout
946
947 @
948 \end_layout
949
950 \end_inset
951
952
953 \end_layout
954
955 \begin_layout Standard
956 \begin_inset ERT
957 status open
958
959 \begin_layout Plain Layout
960
961 <<Function prototypes>>=
962 \end_layout
963
964 \begin_layout Plain Layout
965
966 int noweb_try (int buf_line);
967 \end_layout
968
969 \begin_layout Plain Layout
970
971 @
972 \end_layout
973
974 \end_inset
975
976
977 \end_layout
978
979 \begin_layout Standard
980 The xlc compiler always outputs one single line for each error found, thus
981  to scan the buffer for xlc error messages it is enough to exam one input
982  line at a time.
983 \end_layout
984
985 \begin_layout Standard
986 \begin_inset Flex Chunk
987 status open
988
989 \begin_layout Plain Layout
990
991 \begin_inset Argument 1
992 status open
993
994 \begin_layout Plain Layout
995 Scan input for xlc error messages
996 \end_layout
997
998 \end_inset
999
1000 {
1001 \end_layout
1002
1003 \begin_layout Plain Layout
1004
1005   last_buf_line = 0;
1006 \end_layout
1007
1008 \begin_layout Plain Layout
1009
1010   while (fgets(buffer[last_buf_line], 200, stdin)) {
1011 \end_layout
1012
1013 \begin_layout Plain Layout
1014
1015     if (xlc_try(0))
1016 \end_layout
1017
1018 \begin_layout Plain Layout
1019
1020       output_error(1, err_line, "xlc");
1021 \end_layout
1022
1023 \begin_layout Plain Layout
1024
1025   }
1026 \end_layout
1027
1028 \begin_layout Plain Layout
1029
1030 }
1031 \end_layout
1032
1033 \end_inset
1034
1035
1036 \end_layout
1037
1038 \begin_layout Standard
1039 A xlc error message is easy to identify.
1040  Every error message starts with a quoted string with no spaces, a comma,
1041  a space, the word 
1042 \begin_inset Quotes eld
1043 \end_inset
1044
1045 line
1046 \begin_inset Quotes erd
1047 \end_inset
1048
1049 , a space, and some variable text.
1050  The following routine tests if a given buffer line matches this criteria:
1051 \end_layout
1052
1053 \begin_layout Standard
1054 \begin_inset Flex Chunk
1055 status open
1056
1057 \begin_layout Plain Layout
1058
1059 \end_layout
1060
1061 \begin_layout Plain Layout
1062
1063 \end_layout
1064
1065 \begin_layout Plain Layout
1066
1067 <<Function bodies>>=
1068 \end_layout
1069
1070 \begin_layout Plain Layout
1071
1072 int 
1073 \end_layout
1074
1075 \begin_layout Plain Layout
1076
1077 xlc_try (int buf_line)
1078 \end_layout
1079
1080 \begin_layout Plain Layout
1081
1082 {
1083 \end_layout
1084
1085 \begin_layout Plain Layout
1086
1087   char    *s, *t;
1088 \end_layout
1089
1090 \begin_layout Plain Layout
1091
1092  
1093 \end_layout
1094
1095 \begin_layout Plain Layout
1096
1097   t = buffer[buf_line];
1098 \end_layout
1099
1100 \begin_layout Plain Layout
1101
1102   s = t+1;
1103 \end_layout
1104
1105 \begin_layout Plain Layout
1106
1107   while (*s != '"' && *s != ' ' && *s != '
1108 \backslash
1109 0')
1110 \end_layout
1111
1112 \begin_layout Plain Layout
1113
1114     s++;
1115 \end_layout
1116
1117 \begin_layout Plain Layout
1118
1119   if (*t != '"' || *s != '"' || strncmp(s+1, ", line ", 7) != 0)
1120 \end_layout
1121
1122 \begin_layout Plain Layout
1123
1124     return 0;
1125 \end_layout
1126
1127 \begin_layout Plain Layout
1128
1129   s += 8;
1130 \end_layout
1131
1132 \begin_layout Plain Layout
1133
1134   err_line = atoi(s);
1135 \end_layout
1136
1137 \begin_layout Plain Layout
1138
1139   return 1;
1140 \end_layout
1141
1142 \begin_layout Plain Layout
1143
1144 }
1145 \end_layout
1146
1147 \end_inset
1148
1149
1150 \end_layout
1151
1152 \begin_layout Standard
1153 \begin_inset Flex Chunk
1154 status open
1155
1156 \begin_layout Plain Layout
1157
1158 \begin_inset Argument 1
1159 status open
1160
1161 \begin_layout Plain Layout
1162 Function prototypes
1163 \end_layout
1164
1165 \end_inset
1166
1167 int xlc_try (int buf_line);
1168 \end_layout
1169
1170 \end_inset
1171
1172
1173 \end_layout
1174
1175 \begin_layout Standard
1176 The gcc compiler error messages are more complicated to scan.
1177  Each error can span more than one line in the buffer.
1178  The good news is that every buffer line on each error has the same pattern,
1179  and share the same line number.
1180  Thus the strategy will be to accumulate lines in the buffer while the reported
1181  line number is still the same.
1182  At the time they differ, all the accumulated lines, except the last one,
1183  will belong to one single error message, which now can be output-ed to
1184  \SpecialCharNoPassThru LyX
1185 .
1186 \end_layout
1187
1188 \begin_layout Standard
1189 Every gcc error message contains a string with no space followed by a 
1190 \begin_inset Quotes eld
1191 \end_inset
1192
1193 :
1194 \begin_inset Quotes eld
1195 \end_inset
1196
1197 .
1198  If the next character is a space, then this line is a header of a error
1199  message and the next line will detail the line number of the source code
1200  where the error was found.
1201  Otherwise, the next thing is a integer number followed by another 
1202 \begin_inset Quotes eld
1203 \end_inset
1204
1205 :
1206 \begin_inset Quotes eld
1207 \end_inset
1208
1209 .
1210 \end_layout
1211
1212 \begin_layout Standard
1213 \begin_inset Flex Chunk
1214 status open
1215
1216 \begin_layout Plain Layout
1217
1218 \begin_inset Argument 1
1219 status open
1220
1221 \begin_layout Plain Layout
1222 Scan input for gcc error messages
1223 \end_layout
1224
1225 \end_inset
1226
1227 {
1228 \end_layout
1229
1230 \begin_layout Plain Layout
1231
1232   char    *s, *t;
1233 \end_layout
1234
1235 \begin_layout Plain Layout
1236
1237  
1238 \end_layout
1239
1240 \begin_layout Plain Layout
1241
1242   last_buf_line = 0;
1243 \end_layout
1244
1245 \begin_layout Plain Layout
1246
1247   while (fgets(buffer[last_buf_line], 200, stdin)) {
1248 \end_layout
1249
1250 \begin_layout Plain Layout
1251
1252     /****** Skip lines until I find an error */
1253 \end_layout
1254
1255 \begin_layout Plain Layout
1256
1257     s = (char *)strpbrk(buffer[last_buf_line], " :");
1258 \end_layout
1259
1260 \begin_layout Plain Layout
1261
1262     if (s == NULL || *s == ' ')
1263 \end_layout
1264
1265 \begin_layout Plain Layout
1266
1267       continue; /* No gcc error found here */
1268 \end_layout
1269
1270 \begin_layout Plain Layout
1271
1272     do {
1273 \end_layout
1274
1275 \begin_layout Plain Layout
1276
1277       <<gcc error message criteria is to find a "...:999:" or a "...: ">>
1278 \end_layout
1279
1280 \begin_layout Plain Layout
1281
1282       /****** OK It is an error message, get line number */
1283 \end_layout
1284
1285 \begin_layout Plain Layout
1286
1287       err_line = atoi(s+1);
1288 \end_layout
1289
1290 \begin_layout Plain Layout
1291
1292       if (last_err_line == 0 || last_err_line == err_line) {
1293 \end_layout
1294
1295 \begin_layout Plain Layout
1296
1297         last_err_line = err_line;
1298 \end_layout
1299
1300 \begin_layout Plain Layout
1301
1302         continue; /* It's either a header or a continuation, don't output
1303  yet */
1304 \end_layout
1305
1306 \begin_layout Plain Layout
1307
1308       }
1309 \end_layout
1310
1311 \begin_layout Plain Layout
1312
1313       /****** Completed the scan of one error message, output it to \SpecialCharNoPassThru LyX
1314  */
1315 \end_layout
1316
1317 \begin_layout Plain Layout
1318
1319       discharge_buffer(1);
1320 \end_layout
1321
1322 \begin_layout Plain Layout
1323
1324       break;
1325 \end_layout
1326
1327 \begin_layout Plain Layout
1328
1329     } while (fgets(buffer[last_buf_line], 200, stdin));
1330 \end_layout
1331
1332 \begin_layout Plain Layout
1333
1334   }
1335 \end_layout
1336
1337 \begin_layout Plain Layout
1338
1339   /****** EOF completes the scan of whatever was being scanned */
1340 \end_layout
1341
1342 \begin_layout Plain Layout
1343
1344   discharge_buffer(0);
1345 \end_layout
1346
1347 \begin_layout Plain Layout
1348
1349 }
1350 \end_layout
1351
1352 \end_inset
1353
1354
1355 \end_layout
1356
1357 \begin_layout Standard
1358 \begin_inset Flex Chunk
1359 status open
1360
1361 \begin_layout Plain Layout
1362
1363 \begin_inset Argument 1
1364 status open
1365
1366 \begin_layout Plain Layout
1367 gcc error message criteria is to find a "...:999:" or a "...: "
1368 \end_layout
1369
1370 \end_inset
1371
1372 /****** Search first ":" in the error number */
1373 \end_layout
1374
1375 \begin_layout Plain Layout
1376
1377 s = (char *)strpbrk(buffer[last_buf_line], " :");
1378 \end_layout
1379
1380 \begin_layout Plain Layout
1381
1382 last_buf_line++;
1383 \end_layout
1384
1385 \begin_layout Plain Layout
1386
1387 if (s == NULL || *s == ' ') 
1388 \end_layout
1389
1390 \begin_layout Plain Layout
1391
1392   <<No gcc error found here, but it might terminate the scanning of a previous
1393  one>>
1394 \end_layout
1395
1396 \begin_layout Plain Layout
1397
1398 /****** Search second ":" in the error number */
1399 \end_layout
1400
1401 \begin_layout Plain Layout
1402
1403 t = (char *)strpbrk(s+1, " :");if (t == NULL || *t == ' ')  <<No gcc error
1404  found here, but it might terminate the scanning of a previous one>>/******
1405  Verify if is all digits between ":" */if (t != s+1+strspn(s+1, "0123456789"))
1406    <<No gcc error found here, but it might terminate the scanning of a previous
1407  one>>@
1408 \end_layout
1409
1410 \begin_layout Plain Layout
1411
1412 \end_layout
1413
1414 \begin_layout Plain Layout
1415
1416 \end_layout
1417
1418 \begin_layout Plain Layout
1419
1420 <<No gcc error found here, but it might terminate the scanning of a previous
1421  one>>=
1422 \end_layout
1423
1424 \begin_layout Plain Layout
1425
1426 {
1427 \end_layout
1428
1429 \begin_layout Plain Layout
1430
1431   err_line = 0;
1432 \end_layout
1433
1434 \begin_layout Plain Layout
1435
1436   discharge_buffer(1);
1437 \end_layout
1438
1439 \begin_layout Plain Layout
1440
1441   continue;
1442 \end_layout
1443
1444 \begin_layout Plain Layout
1445
1446 }
1447 \end_layout
1448
1449 \end_inset
1450
1451
1452 \end_layout
1453
1454 \begin_layout Standard
1455 As we mentioned, when the scan of one gcc error message is completed everything
1456  in the buffer except the last line is one single error message.
1457  But if the scan terminates with a EOF or through finding one line that
1458  does not match the gcc error message criteria, then there is no 
1459 \begin_inset Quotes eld
1460 \end_inset
1461
1462 last line
1463 \begin_inset Quotes erd
1464 \end_inset
1465
1466  in the buffer to be concerned with.
1467  In those cases we empty the buffer completely.
1468 \end_layout
1469
1470 \begin_layout Standard
1471 \begin_inset Flex Chunk
1472 status open
1473
1474 \begin_layout Plain Layout
1475
1476 \end_layout
1477
1478 \begin_layout Plain Layout
1479
1480 \end_layout
1481
1482 \begin_layout Plain Layout
1483
1484 <<Function bodies>>=
1485 \end_layout
1486
1487 \begin_layout Plain Layout
1488
1489 void
1490 \end_layout
1491
1492 \begin_layout Plain Layout
1493
1494 discharge_buffer (int save_last)
1495 \end_layout
1496
1497 \begin_layout Plain Layout
1498
1499 {
1500 \end_layout
1501
1502 \begin_layout Plain Layout
1503
1504  if (last_err_line != 0) { 
1505 \end_layout
1506
1507 \begin_layout Plain Layout
1508
1509    clean_gcc_messages();
1510 \end_layout
1511
1512 \begin_layout Plain Layout
1513
1514    if (save_last != 0) {
1515 \end_layout
1516
1517 \begin_layout Plain Layout
1518
1519       output_error(last_buf_line-1, last_err_line, "gcc");
1520 \end_layout
1521
1522 \begin_layout Plain Layout
1523
1524       strcpy (buffer[0], buffer[last_buf_line-1]);
1525 \end_layout
1526
1527 \begin_layout Plain Layout
1528
1529       last_err_line = err_line;
1530 \end_layout
1531
1532 \begin_layout Plain Layout
1533
1534       last_buf_line = 1;
1535 \end_layout
1536
1537 \begin_layout Plain Layout
1538
1539     } else { 
1540 \end_layout
1541
1542 \begin_layout Plain Layout
1543
1544       ++last_buf_line;
1545 \end_layout
1546
1547 \begin_layout Plain Layout
1548
1549       clean_gcc_messages();
1550 \end_layout
1551
1552 \begin_layout Plain Layout
1553
1554       output_error(last_buf_line-1, last_err_line, "gcc");
1555 \end_layout
1556
1557 \begin_layout Plain Layout
1558
1559       last_err_line = 0;
1560 \end_layout
1561
1562 \begin_layout Plain Layout
1563
1564       last_buf_line = 0;
1565 \end_layout
1566
1567 \begin_layout Plain Layout
1568
1569     }
1570 \end_layout
1571
1572 \begin_layout Plain Layout
1573
1574   }
1575 \end_layout
1576
1577 \begin_layout Plain Layout
1578
1579 }
1580 \end_layout
1581
1582 \end_inset
1583
1584
1585 \end_layout
1586
1587 \begin_layout Standard
1588 \begin_inset Flex Chunk
1589 status open
1590
1591 \begin_layout Plain Layout
1592
1593 \begin_inset Argument 1
1594 status open
1595
1596 \begin_layout Plain Layout
1597 Function prototypes
1598 \end_layout
1599
1600 \end_inset
1601
1602 void discharge_buffer (int save_last);
1603 \end_layout
1604
1605 \end_inset
1606
1607
1608 \end_layout
1609
1610 \begin_layout Standard
1611 The next function 
1612 \begin_inset Quotes eld
1613 \end_inset
1614
1615 cleans
1616 \begin_inset Quotes erd
1617 \end_inset
1618
1619  superfluous information from gcc messages, namely the name of the noweb
1620  file and the line number of the Error.
1621 \begin_inset Foot
1622 status collapsed
1623
1624 \begin_layout Plain Layout
1625 More could be done.
1626  For instance, some way of distinguishing between gcc Errors and Warnings
1627  should be devised.
1628 \end_layout
1629
1630 \end_inset
1631
1632
1633 \end_layout
1634
1635 \begin_layout Standard
1636 \begin_inset Flex Chunk
1637 status open
1638
1639 \begin_layout Plain Layout
1640
1641 \begin_inset Argument 1
1642 status open
1643
1644 \begin_layout Plain Layout
1645 Function bodies
1646 \end_layout
1647
1648 \end_inset
1649
1650 void
1651 \end_layout
1652
1653 \begin_layout Plain Layout
1654
1655 clean_gcc_messages ()
1656 \end_layout
1657
1658 \begin_layout Plain Layout
1659
1660 {
1661 \end_layout
1662
1663 \begin_layout Plain Layout
1664
1665   int index;
1666 \end_layout
1667
1668 \begin_layout Plain Layout
1669
1670   char search [30]; 
1671 \end_layout
1672
1673 \begin_layout Plain Layout
1674
1675   char *tail, *head; 
1676 \end_layout
1677
1678 \begin_layout Plain Layout
1679
1680   int search_len = sprintf(search, ".nw:%d:", last_err_line);
1681 \end_layout
1682
1683 \begin_layout Plain Layout
1684
1685   
1686 \end_layout
1687
1688 \begin_layout Plain Layout
1689
1690   for (index = 0; index < last_buf_line-1; index++) {
1691 \end_layout
1692
1693 \begin_layout Plain Layout
1694
1695     tail = (char *)strstr (buffer[index], search);
1696 \end_layout
1697
1698 \begin_layout Plain Layout
1699
1700     if ( tail == NULL) {
1701 \end_layout
1702
1703 \begin_layout Plain Layout
1704
1705        tail = (char *) strstr (buffer[index], ".nw:");
1706 \end_layout
1707
1708 \begin_layout Plain Layout
1709
1710        if (tail) {
1711 \end_layout
1712
1713 \begin_layout Plain Layout
1714
1715           tail += 4;
1716 \end_layout
1717
1718 \begin_layout Plain Layout
1719
1720        }
1721 \end_layout
1722
1723 \begin_layout Plain Layout
1724
1725     } else {
1726 \end_layout
1727
1728 \begin_layout Plain Layout
1729
1730        tail += search_len;
1731 \end_layout
1732
1733 \begin_layout Plain Layout
1734
1735     }
1736 \end_layout
1737
1738 \begin_layout Plain Layout
1739
1740     if (tail != NULL) {
1741 \end_layout
1742
1743 \begin_layout Plain Layout
1744
1745        head = buffer[index];
1746 \end_layout
1747
1748 \begin_layout Plain Layout
1749
1750        while (*(head++) = *(tail++));
1751 \end_layout
1752
1753 \begin_layout Plain Layout
1754
1755     }
1756 \end_layout
1757
1758 \begin_layout Plain Layout
1759
1760   }
1761 \end_layout
1762
1763 \begin_layout Plain Layout
1764
1765 }
1766 \end_layout
1767
1768 \end_inset
1769
1770
1771 \end_layout
1772
1773 \begin_layout Standard
1774 \begin_inset Flex Chunk
1775 status open
1776
1777 \begin_layout Plain Layout
1778
1779 \begin_inset Argument 1
1780 status open
1781
1782 \begin_layout Plain Layout
1783 Function prototypes
1784 \end_layout
1785
1786 \end_inset
1787
1788 void clean_gcc_messages ();
1789 \end_layout
1790
1791 \end_inset
1792
1793
1794 \end_layout
1795
1796 \begin_layout Standard
1797 To combine the scan of noweb error messages and xlc error messages is very
1798  simple.
1799  We just try each one for every input line:
1800 \end_layout
1801
1802 \begin_layout Standard
1803 \begin_inset ERT
1804 status open
1805
1806 \begin_layout Plain Layout
1807
1808 <<AIX system using both noweb and xlc>>=
1809 \end_layout
1810
1811 \begin_layout Plain Layout
1812
1813 {
1814 \end_layout
1815
1816 \begin_layout Plain Layout
1817
1818   last_buf_line = 0;
1819 \end_layout
1820
1821 \begin_layout Plain Layout
1822
1823   while (fgets(buffer[0], 200, stdin)) {
1824 \end_layout
1825
1826 \begin_layout Plain Layout
1827
1828    if (noweb_try(0))
1829 \end_layout
1830
1831 \begin_layout Plain Layout
1832
1833      output_error(1, err_line, "noweb");
1834 \end_layout
1835
1836 \begin_layout Plain Layout
1837
1838    else if (xlc_try(0))
1839 \end_layout
1840
1841 \begin_layout Plain Layout
1842
1843      output_error(1, err_line, "xlc");
1844 \end_layout
1845
1846 \begin_layout Plain Layout
1847
1848  }
1849 \end_layout
1850
1851 \begin_layout Plain Layout
1852
1853 }
1854 \end_layout
1855
1856 \begin_layout Plain Layout
1857
1858 @
1859 \end_layout
1860
1861 \end_inset
1862
1863
1864 \end_layout
1865
1866 \begin_layout Standard
1867 To combine the scan of noweb error messages and gcc error messages is simple
1868  if we realize that it is not possible to find a noweb error message in
1869  the middle of a gcc error message.
1870  So we just repeat the gcc procedure and test for noweb error messages in
1871  the beginning of the scan:
1872 \end_layout
1873
1874 \begin_layout Standard
1875 \begin_inset Flex Chunk
1876 status open
1877
1878 \begin_layout Plain Layout
1879
1880 \begin_inset Argument 1
1881 status open
1882
1883 \begin_layout Plain Layout
1884 Solaris and Linux systems using both noweb and gcc
1885 \end_layout
1886
1887 \end_inset
1888
1889 {
1890 \end_layout
1891
1892 \begin_layout Plain Layout
1893
1894   char    *s, *t;
1895 \end_layout
1896
1897 \begin_layout Plain Layout
1898
1899  
1900 \end_layout
1901
1902 \begin_layout Plain Layout
1903
1904   last_buf_line = 0;
1905 \end_layout
1906
1907 \begin_layout Plain Layout
1908
1909   while (fgets(buffer[last_buf_line], 200, stdin)) {
1910 \end_layout
1911
1912 \begin_layout Plain Layout
1913
1914     /****** Skip lines until I find an error */
1915 \end_layout
1916
1917 \begin_layout Plain Layout
1918
1919     if (last_buf_line == 0 && noweb_try(0)) {
1920 \end_layout
1921
1922 \begin_layout Plain Layout
1923
1924       output_error(1, err_line, "noweb");
1925 \end_layout
1926
1927 \begin_layout Plain Layout
1928
1929       continue;
1930 \end_layout
1931
1932 \begin_layout Plain Layout
1933
1934     }
1935 \end_layout
1936
1937 \begin_layout Plain Layout
1938
1939     s = (char *)strpbrk(buffer[last_buf_line], " :");
1940 \end_layout
1941
1942 \begin_layout Plain Layout
1943
1944     if (s == NULL || *s == ' ')
1945 \end_layout
1946
1947 \begin_layout Plain Layout
1948
1949       continue; /* No gcc error found here */
1950 \end_layout
1951
1952 \begin_layout Plain Layout
1953
1954     do {
1955 \end_layout
1956
1957 \begin_layout Plain Layout
1958
1959       <<gcc error message criteria is to find a "...:999:" or a "...: ">>
1960 \end_layout
1961
1962 \begin_layout Plain Layout
1963
1964       /****** OK It is an error, get line number */
1965 \end_layout
1966
1967 \begin_layout Plain Layout
1968
1969       err_line = atoi(s+1);
1970 \end_layout
1971
1972 \begin_layout Plain Layout
1973
1974       if (last_err_line == 0 || last_err_line == err_line) {
1975 \end_layout
1976
1977 \begin_layout Plain Layout
1978
1979         last_err_line = err_line;
1980 \end_layout
1981
1982 \begin_layout Plain Layout
1983
1984         continue; /* It's either a header or a continuation, don't output
1985  yet */
1986 \end_layout
1987
1988 \begin_layout Plain Layout
1989
1990       }
1991 \end_layout
1992
1993 \begin_layout Plain Layout
1994
1995       /****** Completed the scan of one error message, output it to \SpecialCharNoPassThru LyX
1996  */
1997 \end_layout
1998
1999 \begin_layout Plain Layout
2000
2001       discharge_buffer(1);
2002 \end_layout
2003
2004 \begin_layout Plain Layout
2005
2006       break;
2007 \end_layout
2008
2009 \begin_layout Plain Layout
2010
2011     } while (fgets(buffer[last_buf_line], 200, stdin));
2012 \end_layout
2013
2014 \begin_layout Plain Layout
2015
2016   }
2017 \end_layout
2018
2019 \begin_layout Plain Layout
2020
2021   /****** EOF completes the scan of whatever was being scanned */
2022 \end_layout
2023
2024 \begin_layout Plain Layout
2025
2026   discharge_buffer(0);
2027 \end_layout
2028
2029 \begin_layout Plain Layout
2030
2031 }
2032 \end_layout
2033
2034 \end_inset
2035
2036
2037 \end_layout
2038
2039 \begin_layout Section
2040 Wrapping the code into a file
2041 \end_layout
2042
2043 \begin_layout Standard
2044 \begin_inset Flex Chunk
2045 status open
2046
2047 \begin_layout Plain Layout
2048
2049 \begin_inset Argument 1
2050 status open
2051
2052 \begin_layout Plain Layout
2053 listerrors.c
2054 \end_layout
2055
2056 \end_inset
2057
2058 #include <stdio.h>
2059 \end_layout
2060
2061 \begin_layout Plain Layout
2062
2063 #include <strings.h>       
2064 \end_layout
2065
2066 \begin_layout Plain Layout
2067
2068  
2069 \end_layout
2070
2071 \begin_layout Plain Layout
2072
2073 <<Global variables>>
2074 \end_layout
2075
2076 \begin_layout Plain Layout
2077
2078 <<Function prototypes>>
2079 \end_layout
2080
2081 \begin_layout Plain Layout
2082
2083 <<Function bodies>>
2084 \end_layout
2085
2086 \end_inset
2087
2088
2089 \end_layout
2090
2091 \begin_layout Standard
2092 To build this program, we want to add the 
2093 \begin_inset Quotes eld
2094 \end_inset
2095
2096 -L
2097 \begin_inset Quotes erd
2098 \end_inset
2099
2100  option in the tangle command to force gdb to load the file 
2101 \family typewriter
2102 Literate.nw
2103 \family default
2104  instead of 
2105 \family typewriter
2106 listerrors.c
2107 \family default
2108 .
2109  In accordance with this, we pass the 
2110 \begin_inset Quotes eld
2111 \end_inset
2112
2113 -g
2114 \begin_inset Quotes erd
2115 \end_inset
2116
2117  option to gcc.
2118 \end_layout
2119
2120 \begin_layout Standard
2121 \begin_inset Flex Chunk
2122 status open
2123
2124 \begin_layout Plain Layout
2125
2126 \begin_inset Argument 1
2127 status open
2128
2129 \begin_layout Plain Layout
2130 build-script
2131 \end_layout
2132
2133 \end_inset
2134
2135 #!/bin/sh
2136 \end_layout
2137
2138 \begin_layout Plain Layout
2139
2140 if [ -z "$NOWEB_SOURCE" ]; then NOWEB_SOURCE=Literate.nw; fi
2141 \end_layout
2142
2143 \begin_layout Plain Layout
2144
2145 if [ -z "$NOWEB_OUTPUT_DIR" ]; then NOWEB_OUTPUT_DIR=.; fi
2146 \end_layout
2147
2148 \begin_layout Plain Layout
2149
2150 notangle -L -Rlisterrors.c ${NOWEB_SOURCE} > ${NOWEB_OUTPUT_DIR}/listerrors.c
2151 \end_layout
2152
2153 \begin_layout Plain Layout
2154
2155 gcc -g -o listerrors listerrors.c
2156 \end_layout
2157
2158 \end_inset
2159
2160
2161 \end_layout
2162
2163 \begin_layout Standard
2164 This project can be tangled and compiled from \SpecialCharNoPassThru LyX
2165  if you set 
2166 \family typewriter
2167
2168 \backslash
2169 build_command
2170 \family default
2171  to call a generic script that always extracts a chunk named 
2172 \family typewriter
2173 build-script
2174 \family default
2175  and executes it.
2176  Here is a example of such generic script:
2177 \end_layout
2178
2179 \begin_layout LyX-Code
2180 #!/bin/sh
2181 \begin_inset Newline newline
2182 \end_inset
2183
2184 notangle -Rbuild-script $1 | env NOWEB_SOURCE=$1 NOWEB_OUTPUT_DIR=$r sh
2185 \end_layout
2186
2187 \begin_layout LyX-Code
2188
2189 \end_layout
2190
2191 \end_body
2192 \end_document