{ $Id$ Copyright (c) 1998-2000 by Peter Vreman This unit handles the verbose management 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. **************************************************************************** } unit verbose; {$i fpcdefs.inc} { Don't include messages in the executable } {.$define EXTERN_MSG} interface uses cutils, globals,finput, cmsgs; {$ifndef EXTERN_MSG} {$i msgtxt.inc} {$endif} {$i msgidx.inc} Const { <$10000 will show file and line } V_None = $0; V_Fatal = $1; V_Error = $2; V_Normal = $4; { doesn't show a text like Error: } V_Warning = $8; V_Note = $10; V_Hint = $20; V_Macro = $100; V_Procedure = $200; V_Conditional = $400; V_Assem = $800; V_Declarations = $1000; V_Info = $10000; V_Status = $20000; V_Used = $40000; V_Tried = $80000; V_Debug = $100000; V_Executable = $200000; V_ShowFile = $ffff; V_All = longint($ffffffff); V_Default = V_Fatal + V_Error + V_Normal; var msg : pmessage; const msgfilename : string = ''; procedure SetRedirectFile(const fn:string); function SetVerbosity(const s:string):boolean; procedure SetCompileModule(p:tmodulebase); procedure Stop; procedure ShowStatus; function ErrorCount:longint; procedure SetErrorFlags(const s:string); procedure GenerateError; procedure Internalerror(i:longint); procedure Comment(l:longint;s:string); function MessagePchar(w:longint):pchar; procedure Message(w:longint); procedure Message1(w:longint;const s1:string); procedure Message2(w:longint;const s1,s2:string); procedure Message3(w:longint;const s1,s2,s3:string); procedure Message4(w:longint;const s1,s2,s3,s4:string); procedure MessagePos(const pos:tfileposinfo;w:longint); procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string); procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string); procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string); procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:string); procedure InitVerbose; procedure DoneVerbose; implementation uses comphook; var current_module : tmodulebase; {**************************************************************************** Extra Handlers for default compiler ****************************************************************************} procedure DoneRedirectFile; begin if status.use_redir then begin close(status.redirfile); status.use_redir:=false; end; end; procedure SetRedirectFile(const fn:string); begin assign(status.redirfile,fn); {$I-} append(status.redirfile); if ioresult <> 0 then rewrite(status.redirfile); {$I+} status.use_redir:=(ioresult=0); end; function SetVerbosity(const s:string):boolean; var m : Longint; i : Integer; inverse : boolean; c : char; begin Setverbosity:=false; val(s,m,i); if (i=0) and (s<>'') then status.verbosity:=m else begin i:=1; while i<=length(s) do begin c:=upcase(s[i]); inverse:=false; { on/off ? } if (i0 then Loadprefix:=Copy(s,idx+1,255) else Loadprefix:=s; end; begin { Load the prefixes } fatalstr:=Loadprefix(general_i_fatal); errorstr:=Loadprefix(general_i_error); warningstr:=Loadprefix(general_i_warning); notestr:=Loadprefix(general_i_note); hintstr:=Loadprefix(general_i_hint); end; procedure LoadMsgFile(const fn:string); begin { reload the internal messages if not already loaded } {$ifndef EXTERN_MSG} if not msg^.msgintern then msg^.LoadIntern(@msgtxt,msgtxtsize); {$endif} if not msg^.LoadExtern(fn) then begin {$ifdef EXTERN_MSG} writeln('Fatal: Cannot find error message file.'); halt(3); {$else} msg^.LoadIntern(@msgtxt,msgtxtsize); {$endif} end; { reload the prefixes using the new messages } Loadprefixes; end; procedure MaybeLoadMessageFile; begin { Load new message file } if (msgfilename<>'') then begin LoadMsgFile(msgfilename); msgfilename:=''; end; end; procedure SetCompileModule(p:tmodulebase); begin current_module:=p; end; var lastfileidx, lastmoduleidx : longint; Procedure UpdateStatus; begin { fix status } status.currentline:=aktfilepos.line; status.currentcolumn:=aktfilepos.column; if assigned(current_module) and assigned(current_module.sourcefiles) and ((current_module.unit_index<>lastmoduleidx) or (aktfilepos.fileindex<>lastfileidx)) then begin { update status record } status.currentmodule:=current_module.modulename^; status.currentsource:=current_module.sourcefiles.get_file_name(aktfilepos.fileindex); status.currentsourcepath:=current_module.sourcefiles.get_file_path(aktfilepos.fileindex); { update lastfileidx only if name known PM } if status.currentsource<>'' then lastfileidx:=aktfilepos.fileindex else lastfileidx:=0; lastmoduleidx:=current_module.unit_index; end; if assigned(current_module) then status.compiling_current:=current_module.in_compile; end; procedure stop; begin do_stop{$ifdef FPCPROCVAR}(){$endif}; end; procedure ShowStatus; begin UpdateStatus; if do_status{$ifdef FPCPROCVAR}(){$endif} then stop; end; function ErrorCount:longint; begin ErrorCount:=status.errorcount; end; procedure SetErrorFlags(const s:string); var code : integer; i,j,l : longint; begin { empty string means error count = 1 for backward compatibility (PFV) } if s='' then begin status.maxerrorcount:=1; exit; end; i:=0; while (i0 then l:=1; status.maxerrorcount:=l; i:=j; end; 'w','W' : status.errorwarning:=true; 'n','N' : status.errornote:=true; 'h','H' : status.errorhint:=true; end; end; end; procedure GenerateError; begin inc(status.errorcount); end; procedure internalerror(i : longint); begin UpdateStatus; do_internalerror(i); inc(status.errorcount); stop; end; procedure Comment(l:longint;s:string); var dostop : boolean; begin dostop:=((l and V_Fatal)<>0); if ((l and V_Error)<>0) or (status.errorwarning and ((l and V_Warning)<>0)) or (status.errornote and ((l and V_Note)<>0)) or (status.errorhint and ((l and V_Hint)<>0)) then inc(status.errorcount); { check verbosity level } if (status.verbosity and l)<>l then exit; { Create status info } UpdateStatus; { Fix replacements } DefaultReplacements(s); { show comment } if do_comment(l,s) or dostop then stop; if (status.errorcount>=status.maxerrorcount) and not status.skip_error then begin Message1(unit_f_errors_in_unit,tostr(status.errorcount)); status.skip_error:=true; stop; end; end; Procedure Msg2Comment(s:string); var idx,i,v : longint; dostop : boolean; begin {Reset} dostop:=false; v:=0; {Parse options} idx:=pos('_',s); if idx=0 then v:=V_Normal else if (idx >= 1) And (idx <= 5) then begin for i:=1 to idx do begin case upcase(s[i]) of 'F' : begin v:=v or V_Fatal; inc(status.errorcount); dostop:=true; end; 'E' : begin v:=v or V_Error; inc(status.errorcount); end; 'O' : v:=v or V_Normal; 'W': begin v:=v or V_Warning; if status.errorwarning then inc(status.errorcount); end; 'N' : begin v:=v or V_Note; if status.errornote then inc(status.errorcount); end; 'H' : begin v:=v or V_Hint; if status.errorhint then inc(status.errorcount); end; 'I' : v:=v or V_Info; 'L' : v:=v or V_Status; 'U' : v:=v or V_Used; 'T' : v:=v or V_Tried; 'M' : v:=v or V_Macro; 'P' : v:=v or V_Procedure; 'C' : v:=v or V_Conditional; 'D' : v:=v or V_Debug; 'B' : v:=v or V_Declarations; 'X' : v:=v or V_Executable; 'Z' : v:=v or V_Assem; 'S' : dostop:=true; '_' : ; end; end; end; Delete(s,1,idx); { check verbosity level } if (status.verbosity and v)<>v then exit; { fix status } UpdateStatus; { Fix replacements } DefaultReplacements(s); { show comment } if do_comment(v,s) or dostop then stop; if (status.errorcount>=status.maxerrorcount) and not status.skip_error then begin Message1(unit_f_errors_in_unit,tostr(status.errorcount)); status.skip_error:=true; stop; end; end; function MessagePchar(w:longint):pchar; begin MaybeLoadMessageFile; MessagePchar:=msg^.GetPchar(w) end; procedure Message(w:longint); begin MaybeLoadMessageFile; Msg2Comment(msg^.Get(w)); end; procedure Message1(w:longint;const s1:string); begin MaybeLoadMessageFile; Msg2Comment(msg^.Get1(w,s1)); end; procedure Message2(w:longint;const s1,s2:string); begin MaybeLoadMessageFile; Msg2Comment(msg^.Get2(w,s1,s2)); end; procedure Message3(w:longint;const s1,s2,s3:string); begin MaybeLoadMessageFile; Msg2Comment(msg^.Get3(w,s1,s2,s3)); end; procedure Message4(w:longint;const s1,s2,s3,s4:string); begin MaybeLoadMessageFile; Msg2Comment(msg^.Get4(w,s1,s2,s3,s4)); end; procedure MessagePos(const pos:tfileposinfo;w:longint); var oldpos : tfileposinfo; begin oldpos:=aktfilepos; aktfilepos:=pos; MaybeLoadMessageFile; Msg2Comment(msg^.Get(w)); aktfilepos:=oldpos; end; procedure MessagePos1(const pos:tfileposinfo;w:longint;const s1:string); var oldpos : tfileposinfo; begin oldpos:=aktfilepos; aktfilepos:=pos; MaybeLoadMessageFile; Msg2Comment(msg^.Get1(w,s1)); aktfilepos:=oldpos; end; procedure MessagePos2(const pos:tfileposinfo;w:longint;const s1,s2:string); var oldpos : tfileposinfo; begin oldpos:=aktfilepos; aktfilepos:=pos; MaybeLoadMessageFile; Msg2Comment(msg^.Get2(w,s1,s2)); aktfilepos:=oldpos; end; procedure MessagePos3(const pos:tfileposinfo;w:longint;const s1,s2,s3:string); var oldpos : tfileposinfo; begin oldpos:=aktfilepos; aktfilepos:=pos; MaybeLoadMessageFile; Msg2Comment(msg^.Get3(w,s1,s2,s3)); aktfilepos:=oldpos; end; procedure MessagePos4(const pos:tfileposinfo;w:longint;const s1,s2,s3,s4:string); var oldpos : tfileposinfo; begin oldpos:=aktfilepos; aktfilepos:=pos; MaybeLoadMessageFile; Msg2Comment(msg^.Get4(w,s1,s2,s3,s4)); aktfilepos:=oldpos; end; procedure InitVerbose; begin { Init } msg:=new(pmessage,Init(20,msgidxmax)); if msg=nil then begin writeln('Fatal: MsgIdx Wrong'); halt(3); end; {$ifndef EXTERN_MSG} msg^.LoadIntern(@msgtxt,msgtxtsize); {$else EXTERN_MSG} LoadMsgFile(exepath+'errore.msg'); {$endif EXTERN_MSG} FillChar(Status,sizeof(TCompilerStatus),0); status.verbosity:=V_Default; Status.MaxErrorCount:=50; Loadprefixes; lastfileidx:=-1; lastmoduleidx:=-1; status.currentmodule:=''; status.currentsource:=''; status.currentsourcepath:=''; status.compiling_current:=false; end; procedure DoneVerbose; begin if assigned(msg) then begin dispose(msg,Done); msg:=nil; end; if status.use_redir then DoneRedirectFile; end; end. { $Log$ Revision 1.18 2002-05-16 19:46:47 carl + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand + try to fix temp allocation (still in ifdef) + generic constructor calls + start of tassembler / tmodulebase class cleanup Revision 1.16 2001/08/20 10:58:49 florian * renamed messages unit to cmsgs to avoid conflicts with the win32 messages unit Revision 1.15 2001/08/04 10:23:55 peter * updates so it works with the ide Revision 1.14 2001/05/27 14:30:55 florian + some widestring stuff added Revision 1.13 2001/04/13 01:22:17 peter * symtable change to classes * range check generation and errors fixed, make cycle DEBUG=1 works * memory leaks fixed Revision 1.12 2001/03/13 20:59:56 peter * message loading fixes from Sergey (merged) Revision 1.11 2000/12/26 15:58:29 peter * check for verbosity in verbose instead of comphook Revision 1.10 2000/12/25 00:07:30 peter + new tlinkedlist class (merge of old tstringqueue,tcontainer and tlinkedlist objects) Revision 1.9 2000/12/07 17:19:45 jonas * new constant handling: from now on, hex constants >$7fffffff are parsed as unsigned constants (otherwise, $80000000 got sign extended and became $ffffffff80000000), all constants in the longint range become longints, all constants >$7fffffff and <=cardinal($ffffffff) are cardinals and the rest are int64's. * added lots of longint typecast to prevent range check errors in the compiler and rtl * type casts of symbolic ordinal constants are now preserved * fixed bug where the original resulttype wasn't restored correctly after doing a 64bit rangecheck Revision 1.8 2000/11/29 00:30:43 florian * unused units removed from uses clause * some changes for widestrings Revision 1.7 2000/10/31 22:02:55 peter * symtable splitted, no real code changes Revision 1.6 2000/09/24 21:33:48 peter * message updates merges Revision 1.5 2000/09/24 15:06:33 peter * use defines.inc Revision 1.4 2000/08/27 16:11:55 peter * moved some util functions from globals,cobjects to cutils * splitted files into finput,fmodule Revision 1.3 2000/08/13 12:54:55 peter * class member decl wrong then no other error after it * -vb has now also line numbering * -vb is also used for interface/implementation different decls and doesn't list the current function (merged) Revision 1.2 2000/07/13 11:32:54 michael + removed logs }