mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-25 12:41:40 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			232 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| {$mode objfpc}
 | |
| {$h+}
 | |
| uses
 | |
|   sysutils,classes,dom,xmlread;
 | |
| 
 | |
| procedure error(const s : string);
 | |
|   begin
 | |
|     writeln('Error: ',s);
 | |
|     halt(1);
 | |
|   end;
 | |
| 
 | |
| var
 | |
|   doc : txmldocument;
 | |
|   root : TDomNode;
 | |
|   entry,
 | |
|   currentpath,
 | |
|   currentinfo : TDomNode;
 | |
|   hs,
 | |
|   dirprefix,
 | |
|   newlineprefix,
 | |
|   currentmsg,
 | |
|   currentauthor,
 | |
|   currentdate,
 | |
|   pathtemp,
 | |
|   currentrevision : string;
 | |
|   paths : tstringlist;
 | |
|   pathprefixes : tstringlist;
 | |
|   i,j,maxequal : integer;
 | |
|   firstpath : boolean;
 | |
| 
 | |
| begin
 | |
|   paths:=tstringlist.create;
 | |
|   paths.sorted:=true;
 | |
|   pathprefixes:=tstringlist.create;
 | |
|   pathprefixes.sorted:=true;
 | |
|   ReadXMLFile(doc,paramstr(1));
 | |
|   root:=doc.DocumentElement;
 | |
|   if root.haschildnodes and
 | |
|     (root.NodeName='log') then
 | |
|     begin
 | |
|       entry:=root.firstchild;
 | |
|       while assigned(entry) do
 | |
|         begin
 | |
|           if entry.NodeName<>'logentry' then
 | |
|             error('Only log entry entries supported, but '+entry.NodeName+' found.');
 | |
|           currentmsg:='';
 | |
|           currentauthor:='';
 | |
|           currentdate:='';
 | |
|           { get revision }
 | |
|           with entry as tdomelement do
 | |
|             currentrevision:=AttribStrings['revision'];
 | |
|           if entry.haschildnodes then
 | |
|             begin
 | |
|               currentinfo:=entry.firstchild;
 | |
|               while assigned(currentinfo) do
 | |
|                 begin
 | |
|                   if currentinfo.NodeName='author' then
 | |
|                     begin
 | |
|                       if currentinfo.haschildnodes and
 | |
|                         (currentinfo.firstchild is TDOMText) then
 | |
|                         currentauthor:=(currentinfo.firstchild as TDOMText).Data
 | |
|                       else
 | |
|                         error('Malformed author node');
 | |
|                     end
 | |
|                   else if currentinfo.NodeName='msg' then
 | |
|                     begin
 | |
|                       if currentinfo.haschildnodes then
 | |
|                         begin
 | |
|                           if (currentinfo.firstchild is TDOMText) then
 | |
|                             currentmsg:=(currentinfo.firstchild as TDOMText).Data
 | |
|                           else
 | |
|                             error('Malformed msg node');
 | |
|                         end
 | |
|                       else
 | |
|                         currentmsg:='<empty log message>';
 | |
|                     end
 | |
|                   else if currentinfo.NodeName='date' then
 | |
|                     begin
 | |
|                       if currentinfo.haschildnodes and
 | |
|                         (currentinfo.firstchild is TDOMText) then
 | |
|                         currentdate:=(currentinfo.firstchild as TDOMText).Data
 | |
|                       else
 | |
|                         error('Malformed date node');
 | |
|                     end
 | |
|                   else if currentinfo.NodeName='paths' then
 | |
|                     begin
 | |
|                       currentpath:=currentinfo.firstchild;
 | |
|                       paths.clear;
 | |
|                       pathprefixes.clear;
 | |
|                       while assigned(currentpath) do
 | |
|                         begin
 | |
|                           if currentpath.NodeName<>'path' then
 | |
|                             error('Path node expected');
 | |
|                           if currentpath.haschildnodes and
 | |
|                             (currentpath.firstchild is TDOMText) then
 | |
|                             begin
 | |
|                               paths.add((currentpath.firstchild as TDOMText).Data);
 | |
|                               hs:=ExtractFilePath((currentpath.firstchild as TDOMText).Data);
 | |
|                               if not pathprefixes.Find(hs,i) then
 | |
|                                 pathprefixes.add(hs);
 | |
|                             end
 | |
|                           else
 | |
|                             error('Malformed date node');
 | |
| 
 | |
|                           currentpath:=currentpath.NextSibling;
 | |
|                         end;
 | |
|                     end
 | |
|                   else
 | |
|                     error('Unknown logentry child '+currentinfo.NodeName+' found');
 | |
|                   currentinfo:=currentinfo.nextsibling;
 | |
|                 end;
 | |
|               currentdate:=copy(currentdate,1,16);
 | |
|               { replaced T }
 | |
|               currentdate[11]:=' ';
 | |
|               write(currentdate,' ',currentauthor);
 | |
|               if currentrevision<>'' then
 | |
|                 writeln(' r',currentrevision)
 | |
|               else
 | |
|                 writeln;
 | |
|               writeln;
 | |
| 
 | |
|               { search for common pathprefix }
 | |
|               if pathprefixes.Count>1 then
 | |
|                 begin
 | |
|                   maxequal:=65535;
 | |
|                   for i:=1 to pathprefixes.Count-1 do
 | |
|                     begin
 | |
|                       j:=1;
 | |
|                       while (pathprefixes[0][j]=pathprefixes[i][j]) and (j<=maxequal) do
 | |
|                         inc(j);
 | |
|                       dec(j);
 | |
|                       if j<maxequal then
 | |
|                         maxequal:=j;
 | |
|                     end;
 | |
| 
 | |
|                   { test/p1.pas test/p2.pas should use the prefix test/ instead of test/p }
 | |
|                   if maxequal<65535 then
 | |
|                     while (maxequal>0) and (pathprefixes[0][maxequal]<>'/') do
 | |
|                       dec(maxequal);
 | |
|                   Writeln('  '+Copy(pathprefixes[0],1,maxequal)+': ');
 | |
|                   dirprefix:='    ';
 | |
|                   newlineprefix:='      ';
 | |
|                 end
 | |
|               else
 | |
|                 begin
 | |
|                   maxequal:=0;
 | |
|                   dirprefix:='  ';
 | |
|                   newlineprefix:='    ';
 | |
|                 end;
 | |
| 
 | |
|               for i:=0 to pathprefixes.Count-1 do
 | |
|                 begin
 | |
|                   pathtemp:=dirprefix;
 | |
|                   if maxequal+1<length(pathprefixes[i]) then
 | |
|                     pathtemp:=pathtemp+Copy(pathprefixes[i],maxequal+1,65535)+': ';
 | |
|                   firstpath:=true;
 | |
|                   j:=0;
 | |
|                   while (j<paths.Count) do
 | |
|                     begin
 | |
|                       if ExtractFilePath(paths[j])=pathprefixes[i] then
 | |
|                         begin
 | |
|                           hs:=copy(paths[j],length(pathprefixes[i])+1,65535);
 | |
|                           if (length(pathtemp)+length(hs)>=78) and
 | |
|                              (pathtemp<>newlineprefix) then
 | |
|                             begin
 | |
|                               writeln(pathtemp+',');
 | |
|                               pathtemp:=newlineprefix;
 | |
|                               firstpath:=true;
 | |
|                             end;
 | |
|                           { non empty path but not first? }
 | |
|                           if firstpath then
 | |
|                             firstpath:=false
 | |
|                           else
 | |
|                             pathtemp:=pathtemp+', ';
 | |
|                           pathtemp:=pathtemp+hs;
 | |
|                           { delete already processed paths for performance }
 | |
|                           paths.delete(j);
 | |
|                         end
 | |
|                       else
 | |
|                         inc(j);
 | |
|                     end;
 | |
|                   if pathtemp<>newlineprefix then
 | |
|                     writeln(pathtemp);
 | |
|                 end;
 | |
| 
 | |
|               { truncate trailing spaces and new lines from log message }
 | |
|               i:=length(currentmsg);
 | |
|               while (i>0) and (currentmsg[i] in [#13,#10,#9,' ']) do
 | |
|                 dec(i);
 | |
|               delete(currentmsg,i+1,length(currentmsg)-i);
 | |
| 
 | |
|               { Pretty print message starting with at least 2 spaces each line }
 | |
|               writeln;
 | |
|               i:=0;
 | |
|               hs:=currentmsg;
 | |
|               while (hs<>'') do
 | |
|                 begin
 | |
|                   newlineprefix:='  ';
 | |
|                   i:=0;
 | |
|                   while (i<length(hs)) and not(hs[i+1] in [#13,#10]) do
 | |
|                     inc(i);
 | |
|                   j:=1;
 | |
|                   while (j<length(hs)) and
 | |
|                         (j<length(newlineprefix)) and
 | |
|                         (hs[j] in [' ']) do
 | |
|                     inc(j);
 | |
|                   writeln(newlineprefix,copy(hs,j,i-j+1));
 | |
|                   { remove eol and add additional empty lines }
 | |
|                   j:=0;
 | |
|                   while (i<length(hs)) and (hs[i+1] in [#13,#10]) do
 | |
|                     begin
 | |
|                       if hs[i+1]=#10 then
 | |
|                         begin
 | |
|                           inc(j);
 | |
|                           if j>2 then
 | |
|                             writeln;
 | |
|                         end;
 | |
|                       inc(i);
 | |
|                     end;
 | |
|                   delete(hs,1,i);
 | |
|                 end;
 | |
|               writeln;
 | |
|             end
 | |
|           else
 | |
|             error('Empty log entry found');
 | |
|           entry:=entry.nextsibling;
 | |
|         end;
 | |
|     end
 | |
|   else
 | |
|     error('log element not found/wrong xml format');
 | |
| end.
 | 
