program profile; {$E-,C-,T- Read the file A:PROFILER.DAT created by a run of a program with execution-profiling set on. Format the data and write A:PROFILER.PRN, a histogram. The input file consists of a number of 16-bit integers in Pascal/Z format, i.e. BACKWARDS to the usual Intel, CP/M, etc way of storing an integer, with the most significant byte first. The first integer is the count of statements profiled. It may be zero -- if the T+ option was not on -- or it may be greater than "maxstmt," especially if the file is garbage. The second integer is the statement number of the first statement profiled (traced), and the third is the number of the last statement. Then follows the array of statement-count integers. } const maxstmt = 4000; { max number of statements allowed } type inum = record { binary integer in file } val : integer end; s_range = 1..maxstmt; var inf : file of inum; ouf : text; inname, otname : array[1..14] of char; data : array[s_range] of real; idata : array[s_range] of integer; lostmt, histmt, nstmt : s_range; sumexec : real; n : integer; { read the next integer from the file } function iread : integer; var i : inum; begin if not eof(inf) then begin read(inf,i); iread := i.val end else begin writeln('I boobed and read past EOF'); iread := 0 end end; { read an integer -- which might be over 32767 and hence "negative" -- and convert to real. } function fread : real; var r : real; begin r := iread; {implicit conversion to float} if r<0 then r := r+65536.0; fread := r end; { read all the statement counts and convert to float. sum all statement counts for scaling purposes. } procedure readem; var i : s_range; r : real; begin sumexec := 0.0; for i := 1 to nstmt do begin r := fread; sumexec := sumexec+r; data[i] := r end end; { Scale the data so that each point is on a scale of 0..50, a two-percent fraction of the total count of all statements executed. } procedure scalem; var i : s_range; r : real; begin for i := 1 to nstmt do begin r := 100.0 * ( data[i]/sumexec ); idata[i] := round(r) div 2 end end; { Print the scaled data, one line per profiled statement, formatted so: SSSS NNNNN|********* | where SSSS is the statement number, NNNNN is the raw count, and there are from 0 to 50 stars, as per the scaled data. } procedure printem; var i,s : s_range; aster : integer; j : 1..50; stars : array[1..50] of char; begin rewrite(otname,ouf); s := lostmt; for i := 1 to nstmt do begin write(ouf,s:4, data[i]:7:0,'|'); aster := idata[i]; for j := 1 to 50 do if j<=aster then stars[j]:='*' else stars[j]:=' '; write(ouf,stars); writeln(ouf,'|'); s := s+1 end end; { main routine } begin inname := 'A:PROFILER.DAT'; otname := 'A:PROFILER.PRN'; reset(inname,inf); if not eof(inf) then begin { file exists } n := iread; if n<=maxstmt then begin { ..and is probably valid } nstmt := n; lostmt := iread; histmt := iread; if nstmt>0 then begin { ..and has data in it } readem; scalem; printem end else writeln('No statements traced in ',inname) end else writeln('Too many statements traced -- ',n) end else writeln(inname,' not found or empty') end. .