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