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