msgdif.pp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. {
  2. $Id$
  3. This program is part of the Free Pascal run time library.
  4. Copyright (c) 1998-2000 by Peter Vreman
  5. Show the differences between two .msg files
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. Program messagedif;
  13. Uses
  14. Strings;
  15. Type
  16. TEnum = String;
  17. TText = String;
  18. PMsg = ^TMsg;
  19. TMsg = Record
  20. Line,cnb : Longint;
  21. enum : TEnum;
  22. text : TText;
  23. comment : pchar;
  24. Next,Prev : PMsg;
  25. FileNext,
  26. Equivalent : PMsg;
  27. end;
  28. Var
  29. OrgFileName,DiffFileName : String;
  30. OrgRoot,DiffRoot : PMsg;
  31. OrgFirst,DiffFirst : PMsg;
  32. Last : PMsg;
  33. Function NewMsg (Var RM : PMsg; L : Longint; Const E : TEnum;Const T : TText;C : pchar;NbLn : longint) : PMsg;
  34. Var
  35. P,R : PMsg;
  36. begin
  37. New(P);
  38. with P^ do
  39. begin
  40. Line:=L;
  41. Text:=T;
  42. enum:=E;
  43. comment:=c;
  44. cnb:=NbLn;
  45. next:=Nil;
  46. prev:=Nil;
  47. filenext:=nil;
  48. equivalent:=nil;
  49. if assigned(last) then
  50. last^.FileNext:=P;
  51. last:=P;
  52. end;
  53. R:=RM;
  54. While (R<>Nil) and (UpCase(R^.enum)>UpCase(P^.Enum)) do
  55. begin
  56. P^.Prev:=R;
  57. R:=R^.next;
  58. end;
  59. if assigned(R) and (UpCase(R^.Enum)=UpCase(P^.Enum)) then
  60. Writeln('Error ',R^.Enum,' duplicate');
  61. P^.Next:=R;
  62. If R<>Nil then
  63. R^.Prev:=P;
  64. If P^.Prev<>Nil then
  65. P^.Prev^.Next:=P
  66. else
  67. RM:=P;
  68. NewMsg:=P;
  69. end;
  70. Procedure PrintList(const name : string;R : PMsg);
  71. var
  72. P : PMsg;
  73. f : text;
  74. begin
  75. P:=R;
  76. Assign(f,name);
  77. Rewrite(f);
  78. while assigned(P) do
  79. begin
  80. Writeln(f,UpCase(P^.Enum));
  81. P:=P^.Next;
  82. end;
  83. Close(f);
  84. end;
  85. Procedure Usage;
  86. begin
  87. Writeln ('Usage : msgdif orgfile diffile');
  88. halt(1)
  89. end;
  90. Procedure ProcessOptions;
  91. begin
  92. If ParamCount<>2 then
  93. Usage;
  94. OrgfileName:=Paramstr(1);
  95. DiffFileName:=Paramstr(2);
  96. end;
  97. Procedure ProcessFile (FileName : String; Var Root,First : PMsg);
  98. Const
  99. ArrayLength = 65500;
  100. Var F : Text;
  101. S,prevS : String;
  102. J,LineNo,Count,NbLn : Longint;
  103. chararray : array[0..ArrayLength] of char;
  104. currentindex : longint;
  105. c : pchar;
  106. begin
  107. Assign(F,FileName);
  108. Reset(F);
  109. Write ('Processing: ',Filename,'...');
  110. LineNo:=0;
  111. NbLn:=0;
  112. Count:=0;
  113. currentindex:=0;
  114. Root:=Nil;
  115. First:=nil;
  116. Last:=nil;
  117. PrevS:='';
  118. While not eof(f) do
  119. begin
  120. Readln(F,S);
  121. Inc(LineNo);
  122. If (length(S)>0) and Not (S[1] in ['%','#']) Then
  123. begin
  124. J:=Pos('=',S);
  125. If j<1 then
  126. writeln (Filename,'(',LineNo,') : Invalid entry')
  127. else
  128. begin
  129. chararray[currentindex]:=#0;
  130. c:=strnew(@chararray);
  131. if PrevS<>'' then
  132. NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
  133. Copy(PrevS,Pos('=',PrevS)+1,255),c,NbLn);
  134. currentindex:=0;
  135. NbLn:=0;
  136. PrevS:=S;
  137. if First=nil then
  138. First:=Root;
  139. Inc(Count);
  140. end;
  141. end
  142. else
  143. begin
  144. if currentindex+length(s)+1>ArrayLength then
  145. Writeln('Comment too long : over ',ArrayLength,' chars')
  146. else
  147. begin
  148. strpcopy(@chararray[currentindex],s+#10);
  149. inc(currentindex,length(s)+1);
  150. inc(NbLn);
  151. end;
  152. end;
  153. end;
  154. chararray[currentindex]:=#0;
  155. c:=strnew(@chararray);
  156. if PrevS<>'' then
  157. NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
  158. Copy(PrevS,Pos('=',PrevS)+1,255),c,NbLn);
  159. Writeln (' Done. Read ',LineNo,' lines, got ',Count,' constants.');
  160. Close(f);
  161. end;
  162. Procedure ShowDiff (POrg,PDiff : PMsg);
  163. Var
  164. count,orgcount,diffcount : longint;
  165. Procedure NotFound (Org : Boolean; P : PMsg);
  166. begin
  167. With P^ do
  168. If Org Then
  169. Writeln ('Not found in ',DiffFileName,' : ',Enum,' ',OrgFileName,'(',Line,')')
  170. else
  171. Writeln ('Extra in ',DiffFileName,'(',line,') : ',enum);
  172. if org then
  173. inc(orgcount)
  174. else
  175. inc(diffcount);
  176. end;
  177. begin
  178. orgcount:=0;
  179. diffcount:=0;
  180. count:=0;
  181. While (Porg<>Nil) and (PDiff<>Nil) do
  182. begin
  183. // Writeln (POrg^.enum,'<=>',PDiff^.Enum);
  184. If UpCase(Porg^.Enum)>UpCase(PDiff^.Enum) then
  185. begin
  186. NotFound (True,Porg);
  187. POrg:=POrg^.Next
  188. end
  189. else If UpCase(POrg^.enum)=UpCase(PDiff^.Enum) then
  190. begin
  191. inc(count);
  192. POrg^.Equivalent:=PDiff;
  193. PDiff^.Equivalent:=POrg;
  194. POrg:=POrg^.Next;
  195. PDiff:=PDiff^.Next;
  196. end
  197. else
  198. begin
  199. NotFound (False,PDiff);
  200. PDiff:=PDiff^.Next
  201. end;
  202. end;
  203. While POrg<>Nil do
  204. begin
  205. NotFound(True,Porg);
  206. POrg:=pOrg^.Next;
  207. end;
  208. While PDiff<>Nil do
  209. begin
  210. NotFound(False,PDiff);
  211. PDiff:=PDiff^.Next;
  212. end;
  213. Writeln(count,' messages found in common to both files');
  214. Writeln(orgcount,' messages only in ',OrgFileName);
  215. Writeln(diffcount,' messages only in ',DiffFileName);
  216. end;
  217. procedure WriteReorderedFile(FileName : string;orgnext,diffnext : PMsg);
  218. var t,t2,t3 : text;
  219. i,ntcount : longint;
  220. s,s2,s3 : string;
  221. is_msg : boolean;
  222. nextdiffkept : pmsg;
  223. begin
  224. ntcount:=0;
  225. Assign(t,FileName);
  226. Rewrite(t);
  227. Writeln(t,'%%% Reordering of ',DiffFileName,' respective to ',OrgFileName);
  228. Writeln(t,'%%% Contains all comments from ',DiffFileName);
  229. Assign(t2,DiffFileName);
  230. Reset(t2);
  231. Assign(t3,OrgFileName);
  232. Reset(t3);
  233. i:=2;
  234. s:='';s3:='';
  235. nextdiffkept:=diffnext;
  236. while assigned(nextdiffkept) and (nextdiffkept^.equivalent=nil) do
  237. nextdiffkept:=nextdiffkept^.filenext;
  238. { First write the header of diff }
  239. repeat
  240. Readln(t2,s);
  241. is_msg:=(pos('=',s)>1) and (s[1]<>'%') and (s[1]<>'#');
  242. if not is_msg then
  243. begin
  244. Writeln(t,s);
  245. inc(i);
  246. end;
  247. until is_msg;
  248. { Write all messages in Org order }
  249. while assigned(orgnext) do
  250. begin
  251. if not assigned(orgnext^.equivalent) then
  252. begin
  253. { Insert a new error msg with the english comments }
  254. Writeln('New error ',orgnext^.enum,' added');
  255. Writeln(t,orgnext^.enum,'=',orgnext^.text);
  256. inc(i);
  257. Write(t,orgnext^.comment);
  258. inc(i,orgnext^.cnb);
  259. end
  260. else
  261. begin
  262. Writeln(t,orgnext^.enum,'=',orgnext^.equivalent^.text);
  263. s2:=orgnext^.text;
  264. s2:=upcase(copy(s2,1,pos('_',s2)));
  265. s3:=orgnext^.equivalent^.text;
  266. s3:=upcase(copy(s3,1,pos('_',s3)));
  267. { that are the conditions in verbose unit }
  268. if (length(s3)<5) and (s2<>s3) then
  269. begin
  270. Writeln('Warning: different options for ',orgnext^.enum);
  271. Writeln('in ',orgFileName,' : ',s2);
  272. Writeln('in ',diffFileName,' : ',s3);
  273. end;
  274. inc(i);
  275. if orgnext^.text=orgnext^.equivalent^.text then
  276. begin
  277. Writeln(FileName,'(',i,') ',orgnext^.enum,' not translated');
  278. inc(ntcount);
  279. end;
  280. if assigned(orgnext^.equivalent^.comment) and
  281. (strlen(orgnext^.equivalent^.comment)>0) then
  282. Write(t,orgnext^.equivalent^.comment)
  283. else if assigned(orgnext^.comment) and
  284. (strlen(orgnext^.comment)>0) then
  285. begin
  286. Writeln('Comment from ',OrgFileName,' for enum ',orgnext^.enum,' added');
  287. Write(t,orgnext^.comment);
  288. end;
  289. inc(i,orgnext^.equivalent^.cnb);
  290. end;
  291. orgnext:=orgnext^.filenext;
  292. end;
  293. while assigned(diffnext) do
  294. begin
  295. if not assigned(diffnext^.Equivalent) then
  296. begin
  297. { Skip removed enum in errore.msg}
  298. { maybe a renaming of an enum !}
  299. Writeln(diffnext^.enum,' commented out');
  300. Writeln(t,'%%% ',diffnext^.enum,'=',diffnext^.text);
  301. inc(i);
  302. Write(t,diffnext^.comment);
  303. inc(i,diffnext^.cnb);
  304. end;
  305. diffnext:=diffnext^.filenext;
  306. end;
  307. Close(t);
  308. Close(t2);
  309. Close(t3);
  310. Writeln(ntcount,' not translated items found');
  311. end;
  312. begin
  313. ProcessOptions;
  314. ProcessFile(OrgFileName,orgroot,orgfirst);
  315. ProcessFile(DiffFileName,diffRoot,difffirst);
  316. PrintList('Org.lst',OrgRoot);
  317. PrintList('Diff.lst',DiffRoot);
  318. ShowDiff (OrgRoot,DiffRoot);
  319. WriteReorderedFile('new.msg',orgfirst,difffirst);
  320. end.
  321. {
  322. $Log$
  323. Revision 1.11 2000-05-12 08:47:25 pierre
  324. + add a warning if the error level is different in the two files
  325. + force to keep the order of orgfile
  326. Revision 1.10 2000/05/11 13:37:37 pierre
  327. * ordering bugs fixed
  328. Revision 1.9 2000/02/09 13:23:11 peter
  329. * log truncated
  330. Revision 1.8 2000/01/07 01:15:01 peter
  331. * updated copyright to 2000
  332. }