diff options
Diffstat (limited to 'lib-src')
-rw-r--r-- | lib-src/=aixcc.lex | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/lib-src/=aixcc.lex b/lib-src/=aixcc.lex new file mode 100644 index 00000000000..0729eea16c8 --- /dev/null +++ b/lib-src/=aixcc.lex @@ -0,0 +1,300 @@ +%Start ErrorText ErrorMessage OtherText + +EC [0-9][0-9][0-9][0-9]-[0-9][0-9][0-9] +D [0-9] +D3 [0-9 ][0-9 ][0-9] +D4 [0-9 ][0-9 ][0-9 ][0-9] +D5 [0-9 ][0-9 ][0-9 ][0-9 ][0-9] +DS [0-9 ] + +%{ +/* + * Hack to work around the AIX C compiler's brain-damaged error messages + * so that emacs can parse them. It runs /bin/cc as a subprocess, and + * tries to rearrange the error messages so that (a) each message contains + * both the filename and line number where the error occurred, and (b) + * the error message(s) for a particular line get displayed *before* the + * line itself. + * + * to compile: + * lex aixcc.lex + * cc -o aixcc lex.yy.c + * + * + * Copyright December 1991 by Keith Moore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * TODO: figure out how the compiler counts file numbers for included + * files, keep track of which file corresponds to which number, and + * always output the right file name. + */ + +#include <stdio.h> +#include <string.h> + +char *current_file; +int line; +int debug = 0; +char bigbuf[10240]; +char *bufptr = bigbuf; +int last_line_was_error = 0; + +spaces (s) +char *s; +{ + while (*s++) + *bufptr++ = ' '; +} + +char * +strsave (s) +char *s; +{ + char *ptr = malloc (strlen (s) + 1); + strcpy (ptr, s); + return ptr; +} + +yywrap () +{ + *bufptr = '\0'; + bufptr = bigbuf; + while (*bufptr) + putc (*bufptr++, yyout); + return 1; +} + +%} +%% +^File\ Line\ Column\ Message\ text[^\n]* { + /* + * ignore this. don't treat it as error text + */ +} + +^{DS}{DS}{DS}\ {D5}\ \| { + /* + * (optional) nesting level, followed by line number, followed + * by the source code fragment that caused the error + */ + + /* + * save the line number for later + */ + line = atoi (yytext+4); + + if (debug) { + fprintf (yyout, "line <= %d\n", line); + fprintf (yyout, "%s\n", yytext); + } + + /* + * if the last line was an error message, to flush out all of + * the old source text before starting to save the new source text. + */ + if (last_line_was_error) { + *bufptr = '\0'; + bufptr = bigbuf; + while (*bufptr) + putc (*bufptr++, yyout); + bufptr = bigbuf; + last_line_was_error = 0; + } + /* + * stuff enough spaces in the text buffer so that the + * saved text will line up properly when displayed. + */ + spaces (yytext); + + BEGIN ErrorText; /* continue below */ +} + +<ErrorText>[^\n]*$ { + char *ptr; + + /* + * Save the text until we see the error message(s), then print it. + * This because emacs puts the error message at the top of the + * window, and it's nice to be able to see the text below it. + */ + + ptr = yytext; + while (*ptr) + *bufptr++ = *ptr++; + *bufptr++ = '\n'; + + BEGIN 0; +} + +^Processing\ include\ file\ .*$ { + /* + * name of a new include file being processed. Increment file number + * and remember the file name corresponding to this file number. + */ + + current_file = strsave (yytext+24); + + if (debug) { + fprintf (yyout, "current_file <= %s\n", current_file); + fprintf (yyout, "%s\n", yytext); + } +} + +^([a-z]\ -)?\ *{EC}: { + /* + * error message (which we print immediately) preceeded by an + * error code (which we ignore) + */ + + fprintf (yyout, "\"%s\", line %d: %c -", current_file, line, *yytext); + last_line_was_error = 1; + BEGIN ErrorMessage; +} + +^{D3}\ {D5}\ {D4}\ {EC}: { + /* + * (optional) nesting level, followed by line number, followed + * by column number, followed by error message text. + */ + + /* + * save the line number for later + */ + line = atoi (yytext+4); + + if (debug) { + fprintf (yyout, "line <= %d\n", line); + fprintf (yyout, "%s\n", yytext); + } + + /* + * if the last line was an error message, flush out all of + * the old source text before printing this error message. + */ + if (last_line_was_error) { + *bufptr = '\0'; + bufptr = bigbuf; + while (*bufptr) + putc (*bufptr++, yyout); + bufptr = bigbuf; + last_line_was_error = 0; + } + fprintf (yyout, "\"%s\", line %d:", current_file, line); + last_line_was_error = 1; + BEGIN ErrorMessage; +} + +<ErrorMessage>[^\n]*$ { + fprintf (yyout, "%s\n", yytext); + BEGIN 0; +} + + +^[^ :]+".c:"\ *$ { + /* name of new source file being processed */ + + char *ptr; + + if (current_file) + free (current_file); + ptr = strchr (yytext, ':'); + *ptr = '\0'; + current_file = strsave (yytext); +} + +^[^\n] { + /* + * other text starting with a newline. We have to break it up this + * way to keep this rule from matching any of the above patterns + */ + + if (last_line_was_error) { + *bufptr = '\0'; + bufptr = bigbuf; + while (*bufptr) + putc (*bufptr++, yyout); + bufptr = bigbuf; + last_line_was_error = 0; + } + + *bufptr++ = *yytext; + BEGIN OtherText; +} + +<OtherText>[^\n]*$ { + char *ptr; + + ptr = yytext; + while (*ptr) + *bufptr++ = *ptr++; + *bufptr++ = '\n'; + + BEGIN 0; +} + +\n ; + +%% + +main (argc, argv) +char **argv; +{ + int pfd[2]; + int child_pid; + int i; + + current_file = strsave ("/dev/null"); + + line = 0; + + for (i = 1; i < argc; ++i) { + char *ptr = strrchr (argv[i], '.'); + if (ptr && ptr[1] == 'c' && ptr[2] == '\0') { + current_file = strsave (argv[i]); + break; + } + } + + if (pipe (pfd) < 0) { + perror ("pipe"); + exit (1); + } + if ((child_pid = fork()) > 0) { + int status; + + close (pfd[1]); + yyin = fdopen (pfd[0], "r"); + yyout = stderr; + yylex(); + + wait (&status); + exit ((status >> 8) & 0xff); + } + else if (child_pid == 0) { + dup2 (pfd[1], 2); + close (pfd[0]); + close (pfd[1]); + argv[0] = "cc"; + execv ("/bin/cc", argv); + perror ("/bin/cc"); + exit (1); + } + else { + perror ("fork"); + exit (1); + } +} |