{ $Id$ Copyright (c) 1998-2000 by Florian Klaempfl and Pierre Muller Support routines for creating the browser log 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. **************************************************************************** } {$ifdef TP} {$N+,E+} {$endif} unit browlog; interface uses cobjects,globtype,files,symconst,symtable; const {$ifdef TP} logbufsize = 1024; {$else} logbufsize = 16384; {$endif} type pbrowserlog=^tbrowserlog; tbrowserlog=object fname : string; logopen : boolean; stderrlog : boolean; f : file; elements_to_list : pstringqueue; buf : pchar; bufidx : longint; identidx : longint; constructor init; destructor done; procedure setfilename(const fn:string); procedure createlog; procedure flushlog; procedure addlog(const s:string); procedure addlogrefs(p:pref); procedure closelog; procedure ident; procedure unident; procedure browse_symbol(const sr : string); procedure list_elements; procedure list_debug_infos; end; var browserlog : tbrowserlog; procedure WriteBrowserLog; procedure InitBrowserLog; procedure DoneBrowserLog; implementation uses comphook,globals,systems,verbose; function get_file_line(ref:pref): string; var inputfile : pinputfile; begin get_file_line:=''; with ref^ do begin inputfile:=get_source_file(moduleindex,posinfo.fileindex); if assigned(inputfile) then if status.use_gccoutput then { for use with rhide add warning so that it does not interpret this as an error !! } get_file_line:=lower(inputfile^.name^) +':'+tostr(posinfo.line)+': warning: '+tostr(posinfo.column)+':' else get_file_line:=inputfile^.name^ +'('+tostr(posinfo.line)+','+tostr(posinfo.column)+')' else if status.use_gccoutput then get_file_line:='file_unknown:' +tostr(posinfo.line)+': warning: '+tostr(posinfo.column)+':' else get_file_line:='file_unknown(' +tostr(posinfo.line)+','+tostr(posinfo.column)+')' end; end; {**************************************************************************** TBrowser ****************************************************************************} constructor tbrowserlog.init; begin fname:=FixFileName('browser.log'); logopen:=false; elements_to_list:=new(pstringqueue,init); end; destructor tbrowserlog.done; begin if logopen then closelog; dispose(elements_to_list,done); end; procedure tbrowserlog.setfilename(const fn:string); begin fname:=FixFileName(fn); end; procedure tbrowserlog.createlog; begin if logopen then closelog; assign(f,fname); {$I-} rewrite(f,1); {$I+} if ioresult<>0 then exit; logopen:=true; getmem(buf,logbufsize); bufidx:=0; identidx:=0; end; procedure tbrowserlog.flushlog; begin if logopen then if not stderrlog then blockwrite(f,buf^,bufidx) else begin buf[bufidx]:=#0; {$ifndef TP} write(stderr,buf); {$else TP} write(buf); {$endif TP} end; bufidx:=0; end; procedure tbrowserlog.closelog; begin if logopen then begin flushlog; close(f); freemem(buf,logbufsize); logopen:=false; end; end; procedure tbrowserlog.list_elements; begin stderrlog:=true; getmem(buf,logbufsize); logopen:=true; while not elements_to_list^.empty do browse_symbol(elements_to_list^.get); flushlog; logopen:=false; freemem(buf,logbufsize); stderrlog:=false; end; procedure tbrowserlog.list_debug_infos; {$ifndef debug} begin end; {$else debug} var hp : pmodule; ff : pinputfile; begin hp:=pmodule(loaded_units.first); while assigned(hp) do begin addlog('Unit '+hp^.modulename^+' has index '+tostr(hp^.unit_index)); ff:=hp^.sourcefiles^.files; while assigned(ff) do begin addlog('File '+ff^.name^+' index '+tostr(ff^.ref_index)); ff:=ff^.ref_next; end; hp:=pmodule(hp^.next); end; end; {$endif debug} procedure tbrowserlog.addlog(const s:string); begin if not logopen then exit; { add ident } if (identidx>0) and not stderrlog then begin if bufidx+identidx>logbufsize then flushlog; fillchar(buf[bufidx],identidx,' '); inc(bufidx,identidx); end; { add text } if bufidx+length(s)>logbufsize-2 then flushlog; move(s[1],buf[bufidx],length(s)); inc(bufidx,length(s)); { add crlf } buf[bufidx]:=target_os.newline[1]; inc(bufidx); if length(target_os.newline)=2 then begin buf[bufidx]:=target_os.newline[2]; inc(bufidx); end; end; procedure tbrowserlog.addlogrefs(p:pref); var ref : pref; begin ref:=p; Ident; while assigned(ref) do begin Browserlog.AddLog(get_file_line(ref)); ref:=ref^.nextref; end; Unident; end; procedure tbrowserlog.browse_symbol(const sr : string); var sym,symb : psym; symt : psymtable; hp : pmodule; s,ss : string; p : byte; procedure next_substring; begin p:=pos('.',s); if p>0 then begin ss:=copy(s,1,p-1); s:=copy(s,p+1,255); end else begin ss:=s; s:=''; end; addlog('substring : '+ss); end; begin { don't create a new reference when looking for the symbol !! } make_ref:=false; s:=sr; symt:=symtablestack; next_substring; if assigned(symt) then begin sym:=symt^.search(ss); if sym=nil then sym:=symt^.search(upper(ss)); end else sym:=nil; if assigned(sym) and (sym^.typ=unitsym) and (s<>'') then begin addlog('Unitsym found !'); symt:=punitsym(sym)^.unitsymtable; if assigned(symt) then begin next_substring; sym:=symt^.search(ss); end else sym:=nil; end; if not assigned(sym) then begin symt:=nil; { try all loaded_units } hp:=pmodule(loaded_units.first); while assigned(hp) do begin if hp^.modulename^=upper(ss) then begin symt:=hp^.globalsymtable; break; end; hp:=pmodule(hp^.next); end; if not assigned(symt) then begin addlog('!!!Symbol '+ss+' not found !!!'); make_ref:=true; exit; end else begin next_substring; sym:=symt^.search(ss); if sym=nil then sym:=symt^.search(upper(ss)); end; end; while assigned(sym) and (s<>'') do begin next_substring; case sym^.typ of typesym : begin if ptypesym(sym)^.restype.def^.deftype in [recorddef,objectdef] then begin if ptypesym(sym)^.restype.def^.deftype=recorddef then symt:=precorddef(ptypesym(sym)^.restype.def)^.symtable else symt:=pobjectdef(ptypesym(sym)^.restype.def)^.symtable; sym:=symt^.search(ss); if sym=nil then sym:=symt^.search(upper(ss)); end; end; varsym : begin if pvarsym(sym)^.vartype.def^.deftype in [recorddef,objectdef] then begin if pvarsym(sym)^.vartype.def^.deftype=recorddef then symt:=precorddef(pvarsym(sym)^.vartype.def)^.symtable else symt:=pobjectdef(pvarsym(sym)^.vartype.def)^.symtable; sym:=symt^.search(ss); if sym=nil then sym:=symt^.search(upper(ss)); end; end; procsym : begin symt:=pprocsym(sym)^.definition^.parast; symb:=symt^.search(ss); if symb=nil then symb:=symt^.search(upper(ss)); if not assigned(symb) then begin symt:=pprocsym(sym)^.definition^.parast; sym:=symt^.search(ss); if symb=nil then symb:=symt^.search(upper(ss)); end else sym:=symb; end; {else sym^.add_to_browserlog;} end; end; if assigned(sym) then sym^.add_to_browserlog else addlog('!!!Symbol '+ss+' not found !!!'); make_ref:=true; end; procedure tbrowserlog.ident; begin inc(identidx,2); end; procedure tbrowserlog.unident; begin dec(identidx,2); end; {**************************************************************************** Helpers ****************************************************************************} procedure WriteBrowserLog; var p : psymtable; hp : pmodule; begin browserlog.CreateLog; browserlog.list_debug_infos; hp:=pmodule(loaded_units.first); while assigned(hp) do begin p:=psymtable(hp^.globalsymtable); if assigned(p) then p^.writebrowserlog; if cs_local_browser in aktmoduleswitches then begin p:=psymtable(hp^.localsymtable); if assigned(p) then p^.writebrowserlog; end; hp:=pmodule(hp^.next); end; browserlog.CloseLog; end; procedure InitBrowserLog; begin browserlog.init; end; procedure DoneBrowserLog; begin browserlog.done; end; end. { $Log$ Revision 1.5 2000-01-07 01:14:20 peter * updated copyright to 2000 Revision 1.4 1999/11/30 10:40:42 peter + ttype, tsymlist Revision 1.3 1999/11/17 17:04:58 pierre * Notes/hints changes Revision 1.2 1999/08/03 22:02:30 peter * moved bitmask constants to sets * some other type/const renamings Revision 1.1 1999/01/12 14:25:24 peter + BrowserLog for browser.log generation + BrowserCol for browser info in TCollections * released all other UseBrowser }