mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 03:31:36 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			471 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			471 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {
 | |
|     $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
 | |
| 
 | |
| }
 | |
| 
 | 
