468
|
1 %Start ErrorText ErrorMessage OtherText
|
|
2
|
|
3 EC [0-9][0-9][0-9][0-9]-[0-9][0-9][0-9]
|
|
4 D [0-9]
|
|
5 D3 [0-9 ][0-9 ][0-9]
|
|
6 D4 [0-9 ][0-9 ][0-9 ][0-9]
|
|
7 D5 [0-9 ][0-9 ][0-9 ][0-9 ][0-9]
|
|
8 DS [0-9 ]
|
|
9
|
|
10 %{
|
|
11 /*
|
|
12 * Hack to work around the AIX C compiler's brain-damaged error messages
|
|
13 * so that emacs can parse them. It runs /bin/cc as a subprocess, and
|
|
14 * tries to rearrange the error messages so that (a) each message contains
|
|
15 * both the filename and line number where the error occurred, and (b)
|
|
16 * the error message(s) for a particular line get displayed *before* the
|
|
17 * line itself.
|
|
18 *
|
|
19 * to compile:
|
|
20 * lex aixcc.lex
|
|
21 * cc -o aixcc lex.yy.c
|
|
22 *
|
|
23 *
|
|
24 * Copyright December 1991 by Keith Moore
|
|
25 *
|
|
26 * This program is free software; you can redistribute it and/or modify
|
|
27 * it under the terms of the GNU General Public License as published by
|
|
28 * the Free Software Foundation; either version 2 of the License, or
|
|
29 * (at your option) any later version.
|
|
30 *
|
|
31 * This program is distributed in the hope that it will be useful,
|
|
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
34 * GNU General Public License for more details.
|
|
35 *
|
|
36 * You should have received a copy of the GNU General Public License
|
|
37 * along with this program; if not, write to the Free Software
|
|
38 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
39 *
|
|
40 *
|
|
41 * TODO: figure out how the compiler counts file numbers for included
|
|
42 * files, keep track of which file corresponds to which number, and
|
|
43 * always output the right file name.
|
|
44 */
|
|
45
|
|
46 #include <stdio.h>
|
|
47 #include <string.h>
|
|
48
|
|
49 char *current_file;
|
|
50 int line;
|
|
51 int debug = 0;
|
|
52 char bigbuf[10240];
|
|
53 char *bufptr = bigbuf;
|
|
54 int last_line_was_error = 0;
|
|
55
|
|
56 spaces (s)
|
|
57 char *s;
|
|
58 {
|
|
59 while (*s++)
|
|
60 *bufptr++ = ' ';
|
|
61 }
|
|
62
|
|
63 char *
|
|
64 strsave (s)
|
|
65 char *s;
|
|
66 {
|
|
67 char *ptr = malloc (strlen (s) + 1);
|
|
68 strcpy (ptr, s);
|
|
69 return ptr;
|
|
70 }
|
|
71
|
|
72 yywrap ()
|
|
73 {
|
|
74 *bufptr = '\0';
|
|
75 bufptr = bigbuf;
|
|
76 while (*bufptr)
|
|
77 putc (*bufptr++, yyout);
|
|
78 return 1;
|
|
79 }
|
|
80
|
|
81 %}
|
|
82 %%
|
|
83 ^File\ Line\ Column\ Message\ text[^\n]* {
|
|
84 /*
|
|
85 * ignore this. don't treat it as error text
|
|
86 */
|
|
87 }
|
|
88
|
|
89 ^{DS}{DS}{DS}\ {D5}\ \| {
|
|
90 /*
|
|
91 * (optional) nesting level, followed by line number, followed
|
|
92 * by the source code fragment that caused the error
|
|
93 */
|
|
94
|
|
95 /*
|
|
96 * save the line number for later
|
|
97 */
|
|
98 line = atoi (yytext+4);
|
|
99
|
|
100 if (debug) {
|
|
101 fprintf (yyout, "line <= %d\n", line);
|
|
102 fprintf (yyout, "%s\n", yytext);
|
|
103 }
|
|
104
|
|
105 /*
|
|
106 * if the last line was an error message, to flush out all of
|
|
107 * the old source text before starting to save the new source text.
|
|
108 */
|
|
109 if (last_line_was_error) {
|
|
110 *bufptr = '\0';
|
|
111 bufptr = bigbuf;
|
|
112 while (*bufptr)
|
|
113 putc (*bufptr++, yyout);
|
|
114 bufptr = bigbuf;
|
|
115 last_line_was_error = 0;
|
|
116 }
|
|
117 /*
|
|
118 * stuff enough spaces in the text buffer so that the
|
|
119 * saved text will line up properly when displayed.
|
|
120 */
|
|
121 spaces (yytext);
|
|
122
|
|
123 BEGIN ErrorText; /* continue below */
|
|
124 }
|
|
125
|
|
126 <ErrorText>[^\n]*$ {
|
|
127 char *ptr;
|
|
128
|
|
129 /*
|
|
130 * Save the text until we see the error message(s), then print it.
|
|
131 * This because emacs puts the error message at the top of the
|
|
132 * window, and it's nice to be able to see the text below it.
|
|
133 */
|
|
134
|
|
135 ptr = yytext;
|
|
136 while (*ptr)
|
|
137 *bufptr++ = *ptr++;
|
|
138 *bufptr++ = '\n';
|
|
139
|
|
140 BEGIN 0;
|
|
141 }
|
|
142
|
|
143 ^Processing\ include\ file\ .*$ {
|
|
144 /*
|
|
145 * name of a new include file being processed. Increment file number
|
|
146 * and remember the file name corresponding to this file number.
|
|
147 */
|
|
148
|
|
149 current_file = strsave (yytext+24);
|
|
150
|
|
151 if (debug) {
|
|
152 fprintf (yyout, "current_file <= %s\n", current_file);
|
|
153 fprintf (yyout, "%s\n", yytext);
|
|
154 }
|
|
155 }
|
|
156
|
|
157 ^([a-z]\ -)?\ *{EC}: {
|
|
158 /*
|
|
159 * error message (which we print immediately) preceeded by an
|
|
160 * error code (which we ignore)
|
|
161 */
|
|
162
|
|
163 fprintf (yyout, "\"%s\", line %d: %c -", current_file, line, *yytext);
|
|
164 last_line_was_error = 1;
|
|
165 BEGIN ErrorMessage;
|
|
166 }
|
|
167
|
|
168 ^{D3}\ {D5}\ {D4}\ {EC}: {
|
|
169 /*
|
|
170 * (optional) nesting level, followed by line number, followed
|
|
171 * by column number, followed by error message text.
|
|
172 */
|
|
173
|
|
174 /*
|
|
175 * save the line number for later
|
|
176 */
|
|
177 line = atoi (yytext+4);
|
|
178
|
|
179 if (debug) {
|
|
180 fprintf (yyout, "line <= %d\n", line);
|
|
181 fprintf (yyout, "%s\n", yytext);
|
|
182 }
|
|
183
|
|
184 /*
|
|
185 * if the last line was an error message, flush out all of
|
|
186 * the old source text before printing this error message.
|
|
187 */
|
|
188 if (last_line_was_error) {
|
|
189 *bufptr = '\0';
|
|
190 bufptr = bigbuf;
|
|
191 while (*bufptr)
|
|
192 putc (*bufptr++, yyout);
|
|
193 bufptr = bigbuf;
|
|
194 last_line_was_error = 0;
|
|
195 }
|
|
196 fprintf (yyout, "\"%s\", line %d:", current_file, line);
|
|
197 last_line_was_error = 1;
|
|
198 BEGIN ErrorMessage;
|
|
199 }
|
|
200
|
|
201 <ErrorMessage>[^\n]*$ {
|
|
202 fprintf (yyout, "%s\n", yytext);
|
|
203 BEGIN 0;
|
|
204 }
|
|
205
|
|
206
|
|
207 ^[^ :]+".c:"\ *$ {
|
|
208 /* name of new source file being processed */
|
|
209
|
|
210 char *ptr;
|
|
211
|
|
212 if (current_file)
|
|
213 free (current_file);
|
|
214 ptr = strchr (yytext, ':');
|
|
215 *ptr = '\0';
|
|
216 current_file = strsave (yytext);
|
|
217 }
|
|
218
|
|
219 ^[^\n] {
|
|
220 /*
|
|
221 * other text starting with a newline. We have to break it up this
|
|
222 * way to keep this rule from matching any of the above patterns
|
|
223 */
|
|
224
|
|
225 if (last_line_was_error) {
|
|
226 *bufptr = '\0';
|
|
227 bufptr = bigbuf;
|
|
228 while (*bufptr)
|
|
229 putc (*bufptr++, yyout);
|
|
230 bufptr = bigbuf;
|
|
231 last_line_was_error = 0;
|
|
232 }
|
|
233
|
|
234 *bufptr++ = *yytext;
|
|
235 BEGIN OtherText;
|
|
236 }
|
|
237
|
|
238 <OtherText>[^\n]*$ {
|
|
239 char *ptr;
|
|
240
|
|
241 ptr = yytext;
|
|
242 while (*ptr)
|
|
243 *bufptr++ = *ptr++;
|
|
244 *bufptr++ = '\n';
|
|
245
|
|
246 BEGIN 0;
|
|
247 }
|
|
248
|
|
249 \n ;
|
|
250
|
|
251 %%
|
|
252
|
|
253 main (argc, argv)
|
|
254 char **argv;
|
|
255 {
|
|
256 int pfd[2];
|
|
257 int child_pid;
|
|
258 int i;
|
|
259
|
|
260 current_file = strsave ("/dev/null");
|
|
261
|
|
262 line = 0;
|
|
263
|
|
264 for (i = 1; i < argc; ++i) {
|
|
265 char *ptr = strrchr (argv[i], '.');
|
|
266 if (ptr && ptr[1] == 'c' && ptr[2] == '\0') {
|
|
267 current_file = strsave (argv[i]);
|
|
268 break;
|
|
269 }
|
|
270 }
|
|
271
|
|
272 if (pipe (pfd) < 0) {
|
|
273 perror ("pipe");
|
|
274 exit (1);
|
|
275 }
|
|
276 if ((child_pid = fork()) > 0) {
|
|
277 int status;
|
|
278
|
|
279 close (pfd[1]);
|
|
280 yyin = fdopen (pfd[0], "r");
|
|
281 yyout = stderr;
|
|
282 yylex();
|
|
283
|
|
284 wait (&status);
|
|
285 exit ((status >> 8) & 0xff);
|
|
286 }
|
|
287 else if (child_pid == 0) {
|
|
288 dup2 (pfd[1], 2);
|
|
289 close (pfd[0]);
|
|
290 close (pfd[1]);
|
|
291 argv[0] = "cc";
|
|
292 execv ("/bin/cc", argv);
|
|
293 perror ("/bin/cc");
|
|
294 exit (1);
|
|
295 }
|
|
296 else {
|
|
297 perror ("fork");
|
|
298 exit (1);
|
|
299 }
|
|
300 }
|