% -*- SLang -*- % % run compiler in a subshell and/or parse error messages % % Changes made by Alexander Demenshin % Column support by Lutz Donnerhacke . % % Public functions: % compile_parse_errors parse next error % compile_previous_error parse previous error % compile_parse_buf parse current buffer as error messages % compile run program and parse it output % compile_select_compiler set compiler for parsing error messages % compile_add_compiler add a compiler to database % % Public variables: % Compile_Default_Compiler % % The file also contains a database for various compilers. %--------------------------------------------------------------------------- % These variables are public because they are used by acompile.sl variable Compile_Output_Buffer = "*shell-output*"; if (is_defined ("get_process_input")) { Compile_Output_Buffer = "*compile*"; } variable Compile_Line_Mark = 0; static variable Compile_Src_Dir = Null_String; static variable Error_Regexp; % % These variables are used when parsing GNU's Make output (directory changes). % I don't know what kind of output generated by other Make, so substitute % it if needed. % #ifdef UNIX static variable Compile_Dir_Enter = "^g?make\\[\\d+\\]: Entering directory `\\(.+\\)'"; static variable Compile_Dir_Leave = "^g?make\\[\\d+\\]: Leaving directory `\\(.+\\)'"; static define compile_parse_make_chdir () { variable beg_mark, end_mark; variable end_line; push_spot (); EXIT_BLOCK { pop_spot (); } beg_mark = create_user_mark (); end_mark = create_user_mark (); forever { goto_user_mark (end_mark); end_line = 0; if (re_bsearch (Compile_Dir_Leave)) { if (up_1 ()) end_line = what_line (); move_user_mark (end_mark); } goto_user_mark (beg_mark); !if (up_1 ()) return Null_String; if (re_bsearch (Compile_Dir_Enter)) { if (not(end_line) or (what_line () > end_line)) break; move_user_mark (beg_mark); } else return Null_String; } regexp_nth_match (1); } #endif static define compile_find_file (file, line, col) { #ifdef UNIX variable dir; dir = compile_parse_make_chdir (); if (strlen (dir) and (file[0] != '/')) file = dircat (dir, file); #endif if (1 != file_status (file)) { file = Compile_Src_Dir + file; while (1 != file_status (file)) { file = read_file_from_mini ("Find this file's errors:"); } } Compile_Src_Dir = path_dirname (file); () = find_file (file); widen_buffer (); goto_line (line); if (col > 0) goto_column_best_try (col); else bol_skip_white (); } static define compile_parse_errors_dir (next_error_fun, next_line_fun) { variable cbuf, obuf = Compile_Output_Buffer; variable line, file, col; Compile_Line_Mark = 0; !if (bufferp(obuf)) { flush ("Did you compile?"); return; } if (MINIBUFFER_ACTIVE) return; cbuf = pop2buf_whatbuf (obuf); if (@next_error_fun (&file, &line, &col)) { !if (strlen (line)) return; !if (strlen (col)) col = "0"; bol(); Compile_Line_Mark = create_line_mark (3); @next_line_fun (); line = strtrim_beg (line, " \t0"); col = strtrim_beg (col, " \t0"); compile_find_file (file, integer (line), integer (col)); cbuf = whatbuf (); sw2buf (obuf); } pop2buf (cbuf); } static define compile_find_next_error_fun (filep, linep, colp) { eol (); if (eobp ()) { message ("No more errors!"); return 0; } if (typeof (Error_Regexp) == Ref_Type) return @Error_Regexp (1, filep, linep, colp); bol (); !if (re_fsearch (Error_Regexp)) { eob (); return 0; } @filep = regexp_nth_match (1); % file name @linep = regexp_nth_match (2); % line number (string) @colp = regexp_nth_match (3); % column number (string) 1; } static define compile_find_prev_error_fun (filep, linep, colp) { bol (); if (bobp ()) { message ("No more errors!"); 0; } if (typeof (Error_Regexp) == Ref_Type) return @Error_Regexp (-1, filep, linep, colp); !if (re_bsearch (Error_Regexp)) { bob (); return 0; } @filep = regexp_nth_match (1); % file name @linep = regexp_nth_match (2); % line number (string) @colp = regexp_nth_match (3); % column number (string) 1; } public define compile_parse_errors () { compile_parse_errors_dir (&compile_find_next_error_fun, &go_down_1); } public define compile_previous_error () { compile_parse_errors_dir (&compile_find_prev_error_fun, &bol); } public define compile () { variable b, n; variable cmd = NULL; if (_NARGS != 0) cmd = (); b = whatbuf(); call ("save_some_buffers"); if (cmd == NULL) do_shell_cmd (); else shell_perform_cmd (cmd, 0); bob(); pop2buf(b); compile_parse_errors (); } % % Parse current buffer as error output % public define compile_parse_buf () { Compile_Output_Buffer = whatbuf(); bob (); compile_parse_errors (); } $1 = "acompile.sl"; if (is_defined ("get_process_input")) { () = evalfile ($1); } % The current implementation for the database uses an associative array. static variable Compiler_Database = Assoc_Type [Any_Type, NULL]; public define compile_select_compiler (name) { variable c; c = Compiler_Database[name]; if (c == NULL) verror ("Compiler %s is not supported. See compile.sl for more information", name); Error_Regexp = c; } public define compile_add_compiler (name, regexp) { Compiler_Database [name] = regexp; } %--------------------------------------------------------------------------- % Compiler database %--------------------------------------------------------------------------- %Borland bcc/tcc compilers %Error foo.c 4: Undefined symbol 'x' in function main %Warning foo.c 34: Possible use of 'y' before definition in function main compile_add_compiler ("bcc", "^[EW][a-r]+ \\(.+\\) \\(\\d+\\):\\(\\)"); compile_add_compiler ("tcc", "^[EW][a-r]+ \\(.+\\) \\(\\d+\\):\\(\\)"); %-------------------------------------------------------------------------- %Ultrix cc compiler %ccom: Error: t.c, line 14: LC_ALL undefined compile_add_compiler ("ultrix_cc", "[WE][ar][r][no][ir]n?g?: +\\(.+\\), line \\(\\d+\\):\\(\\)"); %-------------------------------------------------------------------------- %hp cc compiler %cc: "t.c", line 3: error 1588: "ddkldkjdldkj" undefined. compile_add_compiler ("hp_cc", "^cc: +\\\"\\(.+\\)\\\", line \\(\\d+\\):\\(\\)"); %-------------------------------------------------------------------------- %Sun acc compiler %"filename.c", line 123: error: buffer undefined %"filename.c", line 123: warning: fin not used compile_add_compiler ("sun_acc", "^\\\"\\(.+\\)\\\", line \\(\\d+\\):\\(\\)"); %-------------------------------------------------------------------------- %AIX compiler, which may be referenced under any of these names. %The Fortran compiler has the same format, so allow that too %"foo.c", line 13.4: 1506-045 (S) Undeclared identifier bar. %"foo.f", line 21.20: 1515-019 (S) Syntax is incorrect. %@aix; %@xlc; %@xlf; compile_add_compiler ("aix", "^\\\"\\(.+\\)\\\", line \\(\\d+\\)\\.\\(\\d+\\)"); compile_add_compiler ("xlc", "^\\\"\\(.+\\)\\\", line \\(\\d+\\)\\.\\(\\d+\\)"); compile_add_compiler ("xlf", "^\\\"\\(.+\\)\\\", line \\(\\d+\\)\\.\\(\\d+\\)"); %-------------------------------------------------------------------------- %The GNU compiler %cmds.adb:33:20: ';' expected. %cmds.c:33: warning: initialization of non-const * pointer... %cmds.c:1041 (cmds.o): Undefined symbol _Screen_Height referenced... %In file included from /usr/local/src/jed/src/xterm.c:10: compile_add_compiler ("gcc", "^\\([^ :]+\\):\\(\\d+\\)[^:]*:\\(\\d*\\)"); %-------------------------------------------------------------------------- %The WATCOM compiler wcc %keymap.c(71): Error! E1011: Symbol 'show_memory' has not been declared %event.c(22): Warning! W202: Symbol 'xx' has been defined, but not referenced %Warning(1028): PhGetMsgSize_ is an undefined reference %file event.o(/home/qnx/rwm/photon/event.c): undefined symbol PhAttach_ compile_add_compiler ("wcc", "^\\(.+\\)(\\(\\d+\\)): [EW].+[rg]! [EW]\\d+:\\(\\)"); %-------------------------------------------------------------------------- %The Java compiler javac %Test.java:151: Method getNumber() not found in class java.lang.String. %@javac; compile_add_compiler ("javac", "^\\(.+\\):\\(\\d+\\):\\(\\)"); %-------------------------------------------------------------------------- %Microsoft Visual C %cob.cpp(30) : warning C4091: no symbols were declared %cob.cpp(32) : error C2665: 'COBFileHeader::COBFileHeader' : none of the %2 overloads can convert parameter 1 from type 'char [34]' (new behavior; %please see help) %cob.cpp(38) : warning C4091: no symbols were declared %cob.cpp(45) : warning C4091: no symbols were declared %cob.cpp(50) : error C2239: unexpected token '{' following declaration of %'COBChunkHead' %@vc; %compile_add_compiler ("vc", "^\\(.+\\)(\\(\\d+\\)) : [ew].+:\\(\\)"); %-------------------------------------------------------------------------- %Microsoft Visual C %cob.cpp(30) : warning C4091: no symbols were declared %cob.cpp(32) : error C2665: 'COBFileHeader::COBFileHeader' : none of the %c:\work\library\terrain\lodland.h(12) : fatal error C1083: Cannot open include file: 'fallocr.h': No such file or directory %c:\work\library\terrain\lodvrtx.h(62) : see declaration of 'public: static class lodland_vertex_generator * lodvertex::gen' %@vc; compile_add_compiler ("vc", "^[ \t]*\\(.+\\)(\\(\\d+\\)) : .*"); %-------------------------------------------------------------------------- %rgbds gameboy assembler %*ERROR* GBC_Main.s(1) : %*ERROR* GBC_Main.s(10) -> GBC_Hardware.h(27) :=0D %*ERROR* : Worldsys.s(366) : Value must be 8-bit %@rgbds; compile_add_compiler ("rgbds", "^\\*ERROR\\*.*[\t ]\\(.+\\)(\\(\\d+\\))"); %--------------------------------------------------------------------------- % End of data base %--------------------------------------------------------------------------- %!%+ %\variable{Compile_Default_Compiler} %\usage{variable Compile_Default_Compiler = "gcc";} %\description % This variable specifies the default compiler to be assumed when parsing % error messages in the compile buffer. If not set, "gcc" is assumed. % Currently supported compilers include: %#v+ % gcc (GNU C Compiler) % bcc (Borland C Compiler) % tcc (Turbo C Compiler) % ultrix_cc (Ultrix C Compiler) % hp_cc (HP C compiler) % sun_acc (Sun ANSI C compiler) % aix, xlc, xlf (Various AIX C compilers) % wcc (Watcom C compiler) % javac (Java Compiler) % vc (Microsoft Visual C) %#v- %\notes % The primary purpose of this variable is to select a compiler prior to % loading compile.sl. Once compile.sl has been loaded, the value of this % variable has no effect. To switch compilers, the \var{compile_select_compiler} % function must be used. %\seealso{compile_select_compiler, compile_add_compiler} %!%- custom_variable ("Compile_Default_Compiler", "gcc"); compile_select_compiler (Compile_Default_Compiler);