123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- {
- This program is part of the Free Pascal run time library.
- Copyright (c) 1998-2002 by Peter Vreman
- Convert a .msg file to an .inc file with a const array of char
- And for the lazy docwriters it can also generate some TeX output
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- 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.
- **********************************************************************}
- {$H+}
- program msg2inc;
- {$ifdef unix}
- {$define EOL_ONE_CHAR}
- {$endif unix}
- {$ifdef amiga}
- {$define EOL_ONE_CHAR}
- {$endif amiga}
- {$ifdef morphos}
- {$define EOL_ONE_CHAR}
- {$endif}
- {$ifdef macos}
- {$define EOL_ONE_CHAR}
- {$endif}
- const
- version='1.00';
- {$ifdef EOL_ONE_CHAR}
- eollen=1;
- {$else}
- eollen=2;
- {$endif}
- msgparts = 20;
- type
- TMode=(M_Char,M_Tex,M_Intel,M_String,M_Renumber);
- var
- InFile,
- OutFile,
- OutName : string;
- Mode : TMode;
- TexHeader : boolean;
- MsgTxt : pchar;
- EnumTxt : pchar;
- enumsize,
- msgsize : longint;
- msgidxmax : array[1..msgparts] of longint;
- msgs : array[0..msgparts,0..999] of boolean;
- msgcodepage: TSystemCodePage;
- procedure LoadMsgFile(const fn:string);
- var
- f : text;
- error,
- multiline : boolean;
- code : word;
- numpart,numidx,
- line,i,j,num : longint;
- ptxt,
- penum : pchar;
- number,
- s,s1 : string;
- procedure err(const msgstr:string);
- begin
- writeln('error in line ',line,': ',msgstr);
- error:=true;
- end;
- begin
- Writeln('Loading messagefile ',fn);
- msgcodepage:=CP_ACP;
- {Read the message file}
- assign(f,fn);
- {$push} {$I-}
- reset(f);
- {$pop}
- if ioresult<>0 then
- begin
- WriteLn('fatal error: '+fn+' not found');
- halt(1);
- end;
- { First parse the file and count bytes needed }
- fillchar(msgidxmax,sizeof(msgidxmax),0);
- fillchar(msgs,sizeof(msgs),0);
- error:=false;
- line:=0;
- multiline:=false;
- msgsize:=0;
- while not eof(f) do
- begin
- readln(f,s);
- inc(line);
- if multiline then
- begin
- if s=']' then
- multiline:=false
- else if (s='') or (s[1] <> '#') then
- inc(msgsize,length(s)+1); { +1 for linebreak }
- end
- else
- begin
- if (s<>'') and not(s[1] in ['#',';','%']) then
- begin
- i:=pos('=',s);
- if i>0 then
- begin
- j:=i+1;
- if not(s[j] in ['0'..'9']) then
- err('no number found')
- else
- begin
- while (s[j] in ['0'..'9']) do
- inc(j);
- end;
- if j-i-1<>5 then
- err('number length is not 5');
- number:=Copy(s,i+1,j-i-1);
- { update the max index }
- val(number,num,code);
- numpart:=num div 1000;
- if numpart=0 then
- err('number should be > 1000');
- if code<>0 then
- err('illegal number: '+s);
- numidx:=num mod 1000;
- { duplicate ? }
- if msgs[numpart,numidx] then
- err('duplicate number found');
- msgs[numpart,numidx]:=true;
- { check range }
- if numpart > msgparts then
- err('number is to large')
- else
- if numidx > msgidxmax[numpart] then
- msgidxmax[numpart]:=numidx;
- if s[j+1]='[' then
- begin
- inc(msgsize,j-i);
- multiline:=true
- end
- else
- inc(msgsize,length(s)-i+1);
- inc(enumsize,j);
- end
- else
- err('no = found');
- end
- else if (Length(s)>11) and (Copy(s,1,11)='# CodePage ') then
- begin
- val(Copy(s,12,Length(s)-11),msgcodepage,code);
- if code<>0 then
- err('illegal code page number: '+s);
- end;
- end;
- end;
- if multiline then
- err('still in multiline mode');
- if error then
- begin
- close(f);
- writeln('aborting');
- halt(1);
- end;
- { alloc memory }
- getmem(msgtxt,msgsize);
- { no linebreak after last entry }
- dec(msgsize);
- ptxt:=msgtxt;
- getmem(enumtxt,enumsize);
- penum:=enumtxt;
- { now read the buffer in mem }
- reset(f);
- while not eof(f) do
- begin
- readln(f,s);
- if multiline then
- begin
- if s=']' then
- begin
- multiline:=false;
- { overwrite last eol }
- dec(ptxt);
- ptxt^:=#0;
- inc(ptxt);
- end
- else if (s='') or (s[1] <> '#') then
- begin
- move(s[1],ptxt^,length(s));
- inc(ptxt,length(s));
- ptxt^:=#10;
- inc(ptxt);
- end;
- end
- else
- begin
- if (s<>'') and not(s[1] in ['#',';','%']) then
- begin
- i:=pos('=',s);
- if i>0 then
- begin
- j:=i+1;
- while (s[j] in ['0'..'9']) do
- inc(j);
- {enum}
- move(s[1],penum^,i-1);
- inc(penum,i-1);
- penum^:='=';
- inc(penum);
- number:=Copy(s,i+1,j-i-1);
- move(number[1],penum^,length(number));
- inc(penum,length(number));
- penum^:=#0;
- inc(penum);
- { multiline start then no txt }
- if s[j+1]='[' then
- begin
- s1:=Copy(s,i+1,j-i);
- move(s1[1],ptxt^,length(s1));
- inc(ptxt,length(s1));
- multiline:=true;
- end
- else
- begin
- { txt including number }
- s1:=Copy(s,i+1,255);
- move(s1[1],ptxt^,length(s1));
- inc(ptxt,length(s1));
- ptxt^:=#0;
- inc(ptxt);
- end;
- end;
- end;
- end;
- end;
- close(f);
- end;
- {*****************************************************************************
- WriteEnumFile
- *****************************************************************************}
- procedure WriteEnumFile(const fn:string);
- var
- t : text;
- i : longint;
- p : pchar;
- start : boolean;
- begin
- writeln('Writing enumfile '+fn);
- {Open textfile}
- assign(t,fn);
- rewrite(t);
- writeln(t,'const');
- {Parse buffer in msgbuf and create indexs}
- p:=enumtxt;
- start:=true;
- for i:=1 to enumsize do
- begin
- if start then
- begin
- write(t,' ');
- start:=false;
- end;
- if p^=#0 then
- begin
- writeln(t,';');
- start:=true;
- end
- else
- begin
- write(t,p^);
- end;
- inc(p);
- end;
- writeln(t,'');
- { msgtxt size }
- writeln(t,' MsgTxtSize = ',msgsize,';');
- writeln(t,'');
- { max msg idx table }
- writeln(t,' MsgIdxMax : array[1..20] of longint=(');
- write(t,' ');
- for i:=1 to 20 do
- begin
- write(t,msgidxmax[i]+1);
- if i<20 then
- write(t,',');
- if i=10 then
- begin
- writeln(t,'');
- write(t,' ');
- end;
- end;
- writeln(t,'');
- writeln(t,' );');
- close(t);
- end;
- {*****************************************************************************
- WriteStringFile
- *****************************************************************************}
- procedure WriteStringFile(const fn,constname:string);
- const
- maxslen=240; { to overcome aligning problems }
- function l0(l:longint):string;
- var
- s : string[16];
- begin
- str(l,s);
- while (length(s)<5) do
- s:='0'+s;
- l0:=s;
- end;
- var
- t : text;
- f : file;
- slen,
- len,i : longint;
- p : pchar;
- s : string;
- start,
- quote : boolean;
- begin
- writeln('Writing stringfile ',fn);
- {Open textfile}
- assign(t,fn);
- rewrite(t);
- writeln(t,'const '+constname+'_codepage=',msgcodepage:5,';');
- writeln(t,'{$ifdef Delphi}');
- writeln(t,'const '+constname+' : array[0..000000] of string[',maxslen,']=(');
- writeln(t,'{$else Delphi}');
- writeln(t,'const '+constname+' : array[0..000000,1..',maxslen,'] of char=(');
- write(t,'{$endif Delphi}');
- {Parse buffer in msgbuf and create indexs}
- p:=msgtxt;
- slen:=0;
- len:=0;
- quote:=false;
- start:=true;
- for i:=1 to msgsize do
- begin
- if slen>=maxslen then
- begin
- if quote then
- begin
- write(t,'''');
- quote:=false;
- end;
- write(t,',');
- slen:=0;
- inc(len);
- end;
- if (len>70) or (start) then
- begin
- if quote then
- begin
- write(t,'''');
- quote:=false;
- end;
- if slen>0 then
- writeln(t,'+')
- else
- writeln(t);
- len:=0;
- start:=false;
- end;
- if (len=0) then
- write(t,' ');
- if (ord(p^)>=32) and (p^<>#39) then
- begin
- if not quote then
- begin
- write(t,'''');
- quote:=true;
- inc(len);
- end;
- write(t,p^);
- inc(len);
- end
- else
- begin
- if quote then
- begin
- write(t,'''');
- inc(len);
- quote:=false;
- end;
- write(t,'#'+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
- inc(len,3);
- end;
- if p^ in [#0,#10] then
- start:=true;
- inc(slen);
- inc(p);
- end;
- if quote then
- write(t,'''');
- writeln(t,'');
- writeln(t,');');
- close(t);
- {update arraysize}
- s:=l0((msgsize-1) div maxslen); { we start with 0 }
- assign(f,fn);
- reset(f,1);
- seek(f,22+34+2*eollen+2*length(constname));
- blockwrite(f,s[1],5);
- seek(f,22+90+4*eollen+3*length(constname));
- blockwrite(f,s[1],5);
- close(f);
- end;
- {*****************************************************************************
- WriteCharFile
- *****************************************************************************}
- procedure WriteCharFile(const fn,constname:string);
- function l0(l:longint):string;
- var
- s : string[16];
- begin
- str(l,s);
- while (length(s)<5) do
- s:='0'+s;
- l0:=s;
- end;
- function createconst(b:byte):string;
- begin
- if (b in [32..127]) and (b<>39) then
- createconst:=''''+chr(b)+''''
- else
- createconst:='#'+chr(b div 100+48)+chr((b mod 100) div 10+48)+chr(b mod 10+48)
- end;
- var
- t : text;
- f : file;
- cidx,i : longint;
- p : pchar;
- s : string;
- begin
- writeln('Writing charfile '+fn);
- {Open textfile}
- assign(t,fn);
- rewrite(t);
- writeln(t,'const ',constname,' : array[1..00000] of char=(');
- {Parse buffer in msgbuf and create indexs}
- p:=msgtxt;
- cidx:=0;
- for i:=1to msgsize do
- begin
- if cidx=15 then
- begin
- if cidx>0 then
- writeln(t,',')
- else
- writeln(t,'');
- write(t,' ');
- cidx:=0;
- end
- else
- if cidx>0 then
- write(t,',')
- else
- write(t,' ');
- write(t,createconst(ord(p^)));
- inc(cidx);
- inc(p);
- end;
- writeln(t,');');
- close(t);
- {update arraysize}
- s:=l0(msgsize);
- assign(f,fn);
- reset(f,1);
- seek(f,18+length(constname));
- blockwrite(f,s[1],5);
- close(f);
- end;
- {*****************************************************************************
- WriteIntelFile
- *****************************************************************************}
- procedure WriteIntelFile(const fn,constname:string);
- var
- t : text;
- len,i : longint;
- p : pchar;
- start,
- quote : boolean;
- begin
- writeln('Writing Intelfile ',fn);
- {Open textfile}
- assign(t,fn);
- rewrite(t);
- writeln(t,'procedure '+constname+';assembler;');
- writeln(t,'asm');
- {Parse buffer in msgbuf and create indexs}
- p:=msgtxt;
- len:=0;
- start:=true;
- quote:=false;
- for i:=1to msgsize do
- begin
- if len>70 then
- begin
- if quote then
- begin
- write(t,'''');
- quote:=false;
- end;
- writeln(t,'');
- start:=true;
- end;
- if start then
- begin
- write(t,' db ''');
- len:=0;
- quote:=true;
- end;
- if (ord(p^)>=32) and (p^<>#39) then
- begin
- if not quote then
- begin
- write(t,',''');
- quote:=true;
- inc(len);
- end;
- write(t,p^);
- inc(len);
- end
- else
- begin
- if quote then
- begin
- write(t,'''');
- inc(len);
- quote:=false;
- end;
- write(t,','+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
- inc(len,4);
- end;
- inc(p);
- end;
- if quote then
- write(t,'''');
- writeln(t,'');
- writeln(t,'end;');
- close(t);
- end;
- {*****************************************************************************
- RenumberFile
- *****************************************************************************}
- procedure RenumberFile(const fn,name:string);
- var
- f,t : text;
- i : longint;
- s,s1 : string;
- begin
- Writeln('Renumbering ',fn);
- {Read the message file}
- assign(f,fn);
- {$push} {$I-}
- reset(f);
- {$pop}
- if ioresult<>0 then
- begin
- WriteLn('*** message file '+fn+' not found ***');
- exit;
- end;
- assign(t,'msg2inc.$$$');
- rewrite(t);
- i:=0;
- while not eof(f) do
- begin
- readln(f,s);
- if (copy(s,1,length(Name))=Name) and (s[3] in ['0'..'9']) then
- begin
- inc(i);
- str(i,s1);
- while length(s1)<3 do
- s1:='0'+s1;
- writeln(t,Name+s1+Copy(s,6,255));
- end
- else
- writeln(t,s);
- end;
- close(t);
- close(f);
- { rename new file }
- erase(f);
- rename(t,fn);
- end;
- {*****************************************************************************
- WriteTexFile
- *****************************************************************************}
- Function EscapeString (Const S : String) : String;
- Var
- I : longint;
- hs : string;
- begin
- hs:='';
- i:=1;
- while i<=length(s) do
- begin
- case S[i] of
- '$' :
- if (s[i+1] in ['0'..'9']) then
- begin
- hs:=hs+'\textlangle arg. '+s[i+1]+'\textrangle{}';
- inc(i);
- end
- else
- hs:=hs+'\$';
- '&','{','}','#','_','%': // Escape these characters
- hs := hs + '\' + S[i];
- '~','^':
- hs := hs + '\'+S[i]+' ';
- '\':
- hs:=hs+'$\backslash$'
- else
- hs := hs + S[i];
- end;
- inc(i);
- end;
- EscapeString:=hs;
- end;
- procedure WriteTexFile(const infn,outfn:string);
- var
- t,f : text;
- line,
- i,k : longint;
- number,
- s,s1 : string;
- texoutput : boolean;
- begin
- Writeln('Loading messagefile ',infn);
- writeln('Writing TeXfile ',outfn);
- { Open infile }
- assign(f,infn);
- {$push} {$I-}
- reset(f);
- {$pop}
- if ioresult<>0 then
- begin
- WriteLn('*** message file '+infn+' not found ***');
- exit;
- end;
- { Open outfile }
- assign(t,outfn);
- rewrite(t);
- If texheader then
- begin
- writeln (t,'\documentclass{article}');
- writeln (t,'\usepackage{html}');
- writeln (t,'\usepackage{fpc}');
- writeln (t,'\begin{document}');
- end;
- { Parse }
- line:=0;
- TexOutput:=False;
- while not eof(f) do
- begin
- readln(f,s);
- inc(line);
- If Pos ('# BeginOfTeX',S)=1 then
- TexOutPut:=True
- else if pos ('# EndOfTeX',S)=1 then
- TexOutPut:=False;
- if (s<>'') and not(s[1] in ['#',';']) and TeXOutPut then
- begin
- if s[1]='%' then
- begin
- Delete(s,1,1);
- writeln(t,s);
- end
- else
- begin
- i:=pos('=',s);
- if i>0 then
- begin
- inc(i);
- number:='';
- while s[i] in ['0'..'9'] do
- begin
- number:=number+s[i];
- inc(i);
- end;
- { strip leading zeros }
- while number[1]='0' do
- Delete(number,1,1);
- inc(i);
- s1:='';
- k:=0;
- while (k<5) and (s[i+k]<>'_') do
- begin
- case s[i+k] of
- 'W' : s1:='Warning '+number+': ';
- 'E' : s1:='Error '+number+': ';
- 'F' : s1:='Fatal error '+number+': ';
- 'N' : s1:='Note '+number+': ';
- 'I' : s1:='Info '+number+': ';
- 'H' : s1:='Hint '+number+': ';
- end;
- inc(k);
- end;
- if s[i+k]='_' then
- inc(i,k+1);
- if number<>'' then
- writeln(t,'\index[msgnr]{',number,'}');
- writeln(t,'\index[msgtxt]{',escapestring(Copy(s,i,255)),'}');
- writeln(t,'\item ['+s1+escapestring(Copy(s,i,255))+'] \hfill \\');
- end
- else
- writeln('error in line: ',line,' skipping');
- end;
- end;
- end;
- If TexHeader then
- writeln (t,'\end{document}');
- close(t);
- close(f);
- end;
- {*****************************************************************************
- Main Program
- *****************************************************************************}
- procedure getpara;
- var
- ch : char;
- para : string;
- files,i : word;
- procedure helpscreen;
- begin
- writeln('usage : msg2inc [Options] <msgfile> <incfile> <constname>');
- writeln('<Options> can be : -T Create .doc TeX file');
- writeln(' -TS Create .doc TeX file (stand-alone)');
- writeln(' -I Intel style asm output');
- writeln(' -S array of string');
- writeln(' -C array of char');
- writeln(' -R renumber section <incfile>');
- writeln(' -V Show version');
- writeln(' -? or -H This HelpScreen');
- halt(1);
- end;
- begin
- Files:=0;
- for i:=1 to paramcount do
- begin
- para:=paramstr(i);
- if (para[1]='-') then
- begin
- ch:=upcase(para[2]);
- delete(para,1,2);
- case ch of
- 'T' : begin
- case upcase(para[1]) of
- 'S' : TexHeader:=True;
- end;
- Mode:=M_Tex;
- end;
- 'I' : Mode:=M_Intel;
- 'S' : Mode:=M_String;
- 'C' : Mode:=M_Char;
- 'R' : Mode:=M_Renumber;
- 'V' : begin
- Writeln('Msg2Inc ',version,' for Free Pascal (C) 1998-2002 Peter Vreman');
- Writeln;
- Halt;
- end;
- '?','H' : helpscreen;
- end;
- end
- else
- begin
- inc(Files);
- if Files>3 then
- HelpScreen;
- case Files of
- 1 : InFile:=Para;
- 2 : OutFile:=Para;
- 3 : OutName:=Para;
- end;
- end;
- end;
- case Mode of
- M_Renumber,
- M_Tex : if Files<2 then
- Helpscreen;
- else
- if Files<3 then
- HelpScreen;
- end;
- end;
- begin
- Mode:=M_String;
- OutFile:='';
- InFile:='';
- OutName:='';
- GetPara;
- case Mode of
- M_Renumber : begin
- Renumberfile(Infile,OutFile);
- end;
- M_Tex : begin
- WriteTexFile(InFile,Outfile);
- end;
- M_Intel : begin
- Loadmsgfile(InFile);
- WriteEnumFile(OutFile+'idx.inc');
- WriteIntelFile(OutFile+'txt.inc',OutName+'txt');
- end;
- M_String : begin
- Loadmsgfile(InFile);
- WriteEnumFile(OutFile+'idx.inc');
- WriteStringFile(OutFile+'txt.inc',OutName+'txt');
- end;
- M_Char : begin
- Loadmsgfile(InFile);
- WriteEnumFile(OutFile+'idx.inc');
- WriteCharFile(OutFile+'txt.inc',OutName+'txt');
- end;
- end;
- end.
|