File: //usr/share/jed/lib/compile.sl
% -*- SLang -*-
%
% run compiler in a subshell and/or parse error messages
%
% Changes made by Alexander Demenshin <aldem@barnet.kharkov.ua>
% Column support by Lutz Donnerhacke <lutz@iks-jena.de>.
%
% 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;
private variable Compile_Src_Dir = Null_String;
private 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. <aldem>
%
#ifdef UNIX
private variable Compile_Dir_Enter = "^g?make\\[\\d+\\]: Entering directory [`']\\(.+\\)'";
private variable Compile_Dir_Leave = "^g?make\\[\\d+\\]: Leaving directory [`']\\(.+\\)'";
private 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);
ifnot (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
private 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 = dircat (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 ();
}
private define filter_color_escape_seqs ()
{
push_spot ();
replace ("\e[K", "");
while (fsearch ("\e["))
{
push_mark ();
go_right (2);
skip_chars ("0-9;");
if (looking_at ("m"))
{
del();
del_region ();
continue;
}
pop_mark (0);
}
pop_spot();
}
private 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;
ifnot (bufferp(obuf))
{
flush ("Did you compile?");
return;
}
if (MINIBUFFER_ACTIVE) return;
cbuf = pop2buf_whatbuf (obuf);
filter_color_escape_seqs ();
if ((@next_error_fun)(&file, &line, &col))
{
ifnot (strlen (line)) return;
ifnot (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);
}
private 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 ();
ifnot (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;
}
private 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);
ifnot (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.
private 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);