-- This file is part of SmartEiffel The GNU Eiffel Compiler. -- Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE -- Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr -- http://SmartEiffel.loria.fr -- SmartEiffel 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, or (at your option) any later -- version. SmartEiffel 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 SmartEiffel; see the file COPYING. If not, -- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- Boston, MA 02111-1307, USA. -- class ERROR_HANDLER -- -- The unique `error_handler' object for Warning, Error and Fatal Error -- handling. -- This handler use an assynchronous strategy. -- inherit GLOBALS feature error_counter, warning_counter: INTEGER -- Global counters. no_warning: BOOLEAN -- To avoid warning messages. is_empty: BOOLEAN is -- True when nothing stored in `explanation' and `positions'. do Result := explanation.is_empty and then positions.is_empty end set_no_warning is do no_warning := true end append(s: STRING) is -- Append text `s' to the current `explanation'. require not s.is_empty do explanation.append(s) ensure not is_empty end append_integer(i: INTEGER) is -- Append integer `i' to the current `explanation'. do i.append_in(explanation) ensure not is_empty end extend(c: CHARACTER) is -- Append `c' to the current `explanation'. do explanation.extend(c) ensure not is_empty end add_position(p: POSITION) is -- If necessary, add `p' to the already known `positions'. do if p.is_unknown then else positions.add_last(p) end end add_type(t: E_TYPE; tail: STRING) is require t /= Void do append(once "Type ") if t.is_run_type then append(t.run_time_mark) else append(t.written_mark) end append(tail) add_position(t.start_position) end feature_not_found(fn: FEATURE_NAME) is require fn /= Void do add_position(fn.start_position) append(fz_09) append(fn.to_string) append(fz_not_found) end add_feature_name(fn: FEATURE_NAME) is require fn /= Void local flag: BOOLEAN do add_position(fn.start_position) if fn.is_infix_name then append(fz_infix) flag := True elseif fn.is_prefix_name then append(fz_prefix) flag := True end if flag then append(" %"") end append(fn.to_string) if flag then extend('%"') end end add_context_info(ct: E_TYPE) is require ct.run_type = ct do append(once " (The validation context is ") append(ct.run_time_mark) append(once " . The validation context is used to compute all % %anchored type marks.)") end type_error(t1, t2: E_TYPE) is require t1 /= Void; t2 /= Void do add_type(t1,once " is not a kind of ") add_type(t2,fz_dot_blank) ensure not is_empty end print_as_warning is -- Print `explanation' as a Warning report. -- After printing, `explanation' and `positions' are reset. require not is_empty do if no_warning then cancel else do_print(once "Warning") end warning_counter := warning_counter + 1 ensure warning_counter = old warning_counter + 1 end print_as_error is -- Print `explanation' as an Error report. -- After printing, `explanation' and `positions' are reset. require not is_empty do do_print(once "Error") error_counter := error_counter + 1 if error_counter >= 6 then echo.w_put_string(fz_error_stars) echo.w_put_string(once "Too many errors.%N") die_with_code(exit_failure_code) end ensure error_counter = old error_counter + 1 end print_as_fatal_error is -- Print `explanation' as a Fatal Error. -- Execution is stopped after this call. do do_print(once "Fatal Error") die_with_code(exit_failure_code) end cancel is -- Cancel a prepared report without printing it. do explanation.clear positions.clear ensure is_empty end feature {NONE} explanation: STRING is -- Current `explanation' text to be print with next Warning, -- the next Error or the next Fatal Error. once !!Result.make(1024) end positions: FIXED_ARRAY[POSITION] is -- The list of `positions' to be shown with next Warning, -- the next Error or the next Fatal Error. once create Result.with_capacity(16) end do_print(heading: STRING) is local i, cpt: INTEGER; cc, previous_cc: CHARACTER; p: POSITION stop: BOOLEAN; class_name: STRING -- TO_DO: we should be clever enought to be able to print -- each line only once when there are more than one position -- on the very same line (by using more ^ on the same line). do echo.w_put_string(fz_error_stars) echo.w_put_string(heading) echo.w_put_character(':') echo.w_put_character(' ') from i := 1 cpt := 9 + heading.count until i > explanation.count loop previous_cc := cc cc := explanation.item(i) i := i + 1 if cpt > 60 then if cc = ' ' or else cc = '%N' then echo.w_put_character('%N') cpt := 0 else echo.w_put_character(cc) cpt := cpt + 1 end else echo.w_put_character(cc) inspect cc when '%N' then cpt := 0 else cpt := cpt + 1 end end end echo.w_put_character('%N') from until positions.is_empty loop p := positions.last positions.remove_last class_name := p.base_class_name.to_string if not smart_eiffel.no_file_for(class_name) then p.show end from stop := false until stop loop i := positions.fast_index_of(p) if positions.valid_index(i) then positions.remove(i) else stop := true end end end cancel echo.w_put_string(once "------%N") sedb_breakpoint ensure is_empty end singleton_memory: ERROR_HANDLER is once Result := Current end invariant is_real_singleton: Current = singleton_memory end -- ERROR_HANDLER