Initial revision
[AROS-Contrib.git] / development / compilers / freepascal / compiler / utils / msgdif.pp
blobc6af00cda8d625844ab1eb33d3eccbbff9b08ede
2 $Id$
3 This program is part of the Free Pascal run time library.
4 Copyright (c) 1998-2000 by Peter Vreman
6 Show the differences between two .msg files
8 See the file COPYING.FPC, included in this distribution,
9 for details about the copyright.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 **********************************************************************}
16 Program messagedif;
18 Uses
19 Strings;
21 Type
22 TEnum = String;
23 TText = String;
25 PMsg = ^TMsg;
26 TMsg = Record
27 Line,cnb : Longint;
28 enum : TEnum;
29 text : TText;
30 comment : pchar;
31 Next,Prev : PMsg;
32 FileNext,
33 Equivalent : PMsg;
34 end;
35 Var
36 OrgFileName,DiffFileName : String;
37 OrgRoot,DiffRoot : PMsg;
38 OrgFirst,DiffFirst : PMsg;
39 Last : PMsg;
41 const
42 NewFileName = 'new.msg';
43 Is_interactive : boolean = false;
45 Procedure GetTranslation( p : PMsg);
46 var
47 s : string;
48 i,j : longint;
49 begin
50 i:=pos('_',p^.text);
51 if (i>0) and (i<=5) then
52 Writeln(P^.Enum,' type "',copy(p^.text,1,i-1),'" "',copy(p^.text,i+1,255),'"')
53 else
54 Writeln(P^.enum,' "',p^.text,'"');
55 Readln(s);
56 if s='' then
57 begin
58 Is_interactive:=false;
59 exit;
60 end;
61 j:=pos('_',s);
62 if (j>0) and (j<=5) then
63 begin
64 if copy(p^.text,1,i)<>copy(s,1,j) then
65 Writeln('Different verbosity !!');
66 p^.text:=s;
67 end
68 else
69 p^.text:=copy(p^.text,1,i)+s;
70 end;
72 Function NewMsg (Var RM : PMsg; L : Longint; Const E : TEnum;Const T : TText;C : pchar;NbLn : longint) : PMsg;
74 Var
75 P,R : PMsg;
77 begin
78 New(P);
79 with P^ do
80 begin
81 Line:=L;
82 Text:=T;
83 enum:=E;
84 comment:=c;
85 cnb:=NbLn;
86 next:=Nil;
87 prev:=Nil;
88 filenext:=nil;
89 equivalent:=nil;
90 if assigned(last) then
91 last^.FileNext:=P;
92 last:=P;
93 end;
94 R:=RM;
95 While (R<>Nil) and (UpCase(R^.enum)>UpCase(P^.Enum)) do
96 begin
97 P^.Prev:=R;
98 R:=R^.next;
99 end;
100 if assigned(R) and (UpCase(R^.Enum)=UpCase(P^.Enum)) then
101 Writeln('Error ',R^.Enum,' duplicate');
102 P^.Next:=R;
103 If R<>Nil then
104 R^.Prev:=P;
105 If P^.Prev<>Nil then
106 P^.Prev^.Next:=P
107 else
108 RM:=P;
109 NewMsg:=P;
110 end;
112 Procedure PrintList(const name : string;R : PMsg);
114 P : PMsg;
115 f : text;
116 begin
117 P:=R;
118 Assign(f,name);
119 Rewrite(f);
120 while assigned(P) do
121 begin
122 Writeln(f,UpCase(P^.Enum));
123 P:=P^.Next;
124 end;
125 Close(f);
126 end;
128 Procedure Usage;
130 begin
131 Writeln ('Usage : msgdif [-i] orgfile diffile');
132 Writeln(' optional -i option allows to enter translated messages interactivly');
133 Writeln('Generates ',NewFileName,' with updated messages');
134 halt(1)
135 end;
137 Procedure ProcessOptions;
139 i,count : longint;
140 begin
141 count:=paramcount;
142 if (count>0) and (UpCase(Paramstr(1))='-I') then
143 begin
144 dec(count);
145 i:=1;
146 Is_interactive:=true;
148 else
149 begin
150 i:=0;
151 Is_interactive:=false;
152 end;
153 If Count<>2 then
154 Usage;
155 OrgfileName:=Paramstr(i+1);
156 DiffFileName:=Paramstr(i+2);
157 if (OrgFileName=NewFileName) or (DiffFileName=NewFileName) then
158 begin
159 Writeln('The file names must be different from ',NewFileName);
160 Halt(1);
161 end;
162 end;
164 Procedure ProcessFile (FileName : String; Var Root,First : PMsg);
166 Const
167 ArrayLength = 65500;
168 Var F : Text;
169 S,prevS : String;
170 J,LineNo,Count,NbLn : Longint;
171 chararray : array[0..ArrayLength] of char;
172 currentindex : longint;
173 c : pchar;
174 begin
175 Assign(F,FileName);
176 Reset(F);
177 Write ('Processing: ',Filename,'...');
178 LineNo:=0;
179 NbLn:=0;
180 Count:=0;
181 currentindex:=0;
182 Root:=Nil;
183 First:=nil;
184 Last:=nil;
185 PrevS:='';
186 While not eof(f) do
187 begin
188 Readln(F,S);
189 Inc(LineNo);
190 If (length(S)>0) and Not (S[1] in ['%','#']) Then
191 begin
192 J:=Pos('=',S);
193 If j<1 then
194 writeln (Filename,'(',LineNo,') : Invalid entry')
195 else
196 begin
197 chararray[currentindex]:=#0;
198 c:=strnew(@chararray);
199 if PrevS<>'' then
200 NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
201 Copy(PrevS,Pos('=',PrevS)+1,255),c,NbLn);
202 currentindex:=0;
203 NbLn:=0;
204 PrevS:=S;
205 if First=nil then
206 First:=Root;
207 Inc(Count);
208 end;
210 else
211 begin
212 if currentindex+length(s)+1>ArrayLength then
213 Writeln('Comment too long : over ',ArrayLength,' chars')
214 else
215 begin
216 strpcopy(@chararray[currentindex],s+#10);
217 inc(currentindex,length(s)+1);
218 inc(NbLn);
219 end;
220 end;
221 end;
222 chararray[currentindex]:=#0;
223 c:=strnew(@chararray);
224 if PrevS<>'' then
225 NewMsg(Root,LineNo,Copy(PrevS,1,Pos('=',PrevS)-1),
226 Copy(PrevS,Pos('=',PrevS)+1,255),c,NbLn);
227 Writeln (' Done. Read ',LineNo,' lines, got ',Count,' constants.');
228 Close(f);
229 end;
231 Procedure ShowDiff (POrg,PDiff : PMsg);
234 count,orgcount,diffcount : longint;
236 Procedure NotFound (Org : Boolean; P : PMsg);
238 begin
239 With P^ do
240 If Org Then
241 Writeln ('Not found in ',DiffFileName,' : ',Enum,' ',OrgFileName,'(',Line,')')
242 else
243 Writeln ('Extra in ',DiffFileName,'(',line,') : ',enum);
244 if org then
245 inc(orgcount)
246 else
247 inc(diffcount);
248 end;
250 begin
251 orgcount:=0;
252 diffcount:=0;
253 count:=0;
254 While (Porg<>Nil) and (PDiff<>Nil) do
255 begin
256 // Writeln (POrg^.enum,'<=>',PDiff^.Enum);
257 If UpCase(Porg^.Enum)>UpCase(PDiff^.Enum) then
258 begin
259 NotFound (True,Porg);
260 POrg:=POrg^.Next
262 else If UpCase(POrg^.enum)=UpCase(PDiff^.Enum) then
263 begin
264 inc(count);
265 POrg^.Equivalent:=PDiff;
266 PDiff^.Equivalent:=POrg;
267 POrg:=POrg^.Next;
268 PDiff:=PDiff^.Next;
270 else
271 begin
272 NotFound (False,PDiff);
273 PDiff:=PDiff^.Next
274 end;
275 end;
276 While POrg<>Nil do
277 begin
278 NotFound(True,Porg);
279 POrg:=pOrg^.Next;
280 end;
281 While PDiff<>Nil do
282 begin
283 NotFound(False,PDiff);
284 PDiff:=PDiff^.Next;
285 end;
286 Writeln(count,' messages found in common to both files');
287 Writeln(orgcount,' messages only in ',OrgFileName);
288 Writeln(diffcount,' messages only in ',DiffFileName);
289 end;
291 procedure WriteReorderedFile(FileName : string;orgnext,diffnext : PMsg);
292 var t,t2,t3 : text;
293 i,ntcount : longint;
294 s,s2,s3 : string;
295 is_msg : boolean;
296 nextdiffkept : pmsg;
297 begin
298 ntcount:=0;
299 Assign(t,FileName);
300 Rewrite(t);
301 Writeln(t,'%%% Reordering of ',DiffFileName,' respective to ',OrgFileName);
302 Writeln(t,'%%% Contains all comments from ',DiffFileName);
303 Assign(t2,DiffFileName);
304 Reset(t2);
305 Assign(t3,OrgFileName);
306 Reset(t3);
307 i:=2;
308 s:='';s3:='';
309 nextdiffkept:=diffnext;
310 while assigned(nextdiffkept) and (nextdiffkept^.equivalent=nil) do
311 nextdiffkept:=nextdiffkept^.filenext;
312 { First write the header of diff }
313 repeat
314 Readln(t2,s);
315 is_msg:=(pos('=',s)>1) and (s[1]<>'%') and (s[1]<>'#');
316 if not is_msg then
317 begin
318 Writeln(t,s);
319 inc(i);
320 end;
321 until is_msg;
322 { Write all messages in Org order }
323 while assigned(orgnext) do
324 begin
325 if not assigned(orgnext^.equivalent) then
326 begin
327 { Insert a new error msg with the english comments }
328 Writeln('New error ',orgnext^.enum,' added');
329 If Is_interactive then
330 GetTranslation(orgnext);
331 Writeln(t,orgnext^.enum,'=',orgnext^.text);
332 inc(i);
333 Write(t,orgnext^.comment);
334 inc(i,orgnext^.cnb);
336 else
337 begin
338 inc(i);
339 if orgnext^.text=orgnext^.equivalent^.text then
340 begin
341 Writeln(FileName,'(',i,') ',orgnext^.enum,' not translated');
342 If Is_interactive then
343 GetTranslation(orgnext^.equivalent);
344 if orgnext^.text=orgnext^.equivalent^.text then
345 inc(ntcount);
346 end;
347 s2:=orgnext^.text;
348 s2:=upcase(copy(s2,1,pos('_',s2)));
349 s3:=orgnext^.equivalent^.text;
350 s3:=upcase(copy(s3,1,pos('_',s3)));
351 { that are the conditions in verbose unit }
352 if (length(s3)<5) and (s2<>s3) then
353 begin
354 Writeln('Warning: different options for ',orgnext^.enum);
355 Writeln('in ',orgFileName,' : ',s2);
356 Writeln('in ',diffFileName,' : ',s3);
357 If Is_interactive then
358 begin
359 Write('Use ',OrgFileName,' verbosity ? [y/n] ');
360 Readln(s);
361 if UpCase(s)<>'N' then
362 orgnext^.equivalent^.text:=s2+copy(orgnext^.equivalent^.text,
363 length(s3)+1,255);
364 end;
365 end;
367 Writeln(t,orgnext^.enum,'=',orgnext^.equivalent^.text);
368 if assigned(orgnext^.equivalent^.comment) and
369 (strlen(orgnext^.equivalent^.comment)>0) then
370 Write(t,orgnext^.equivalent^.comment)
371 else if assigned(orgnext^.comment) and
372 (strlen(orgnext^.comment)>0) then
373 begin
374 Writeln('Comment from ',OrgFileName,' for enum ',orgnext^.enum,' added');
375 Write(t,orgnext^.comment);
376 end;
377 inc(i,orgnext^.equivalent^.cnb);
378 end;
379 orgnext:=orgnext^.filenext;
380 end;
382 while assigned(diffnext) do
383 begin
384 if not assigned(diffnext^.Equivalent) then
385 begin
386 { Skip removed enum in errore.msg}
387 { maybe a renaming of an enum !}
388 Writeln(diffnext^.enum,' commented out');
389 Writeln(t,'%%% ',diffnext^.enum,'=',diffnext^.text);
390 inc(i);
391 Write(t,diffnext^.comment);
392 inc(i,diffnext^.cnb);
393 end;
394 diffnext:=diffnext^.filenext;
395 end;
396 Close(t);
397 Close(t2);
398 Close(t3);
399 Writeln(ntcount,' not translated items found');
400 end;
402 begin
403 ProcessOptions;
404 ProcessFile(OrgFileName,orgroot,orgfirst);
405 ProcessFile(DiffFileName,diffRoot,difffirst);
406 PrintList('Org.lst',OrgRoot);
407 PrintList('Diff.lst',DiffRoot);
408 ShowDiff (OrgRoot,DiffRoot);
409 WriteReorderedFile(NewFileName,orgfirst,difffirst);
410 end.
412 $Log$
413 Revision 1.1 2002/02/19 08:24:16 sasu
414 Initial revision
416 Revision 1.1 2000/07/13 06:30:14 michael
417 + Initial import
419 Revision 1.12 2000/05/12 15:03:44 pierre
420 + interactive mode for translation
422 Revision 1.11 2000/05/12 08:47:25 pierre
423 + add a warning if the error level is different in the two files
424 + force to keep the order of orgfile
426 Revision 1.10 2000/05/11 13:37:37 pierre
427 * ordering bugs fixed
429 Revision 1.9 2000/02/09 13:23:11 peter
430 * log truncated
432 Revision 1.8 2000/01/07 01:15:01 peter
433 * updated copyright to 2000