]> code.delx.au - gnu-emacs/blob - lib-src/aixcc.lex
Initial revision
[gnu-emacs] / lib-src / aixcc.lex
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 }