| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826 | {    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. **********************************************************************}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;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);{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         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;      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         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,'{$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 div maxslen); { we start with 0 }  assign(f,fn);  reset(f,1);  seek(f,34+eollen+length(constname));  blockwrite(f,s[1],5);  seek(f,90+3*eollen+2*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:='';  for i:=1 to length(s) do    case S[i] of      '$' :        if (s[i+1] in ['0'..'9']) then          hs:=hs+'arg'        else          hs:=hs+'\$';      '&','{','}','#','_','%':            // Escape these characters        hs := hs + '\' + S[i];      '~','^':        hs := hs + '\'+S[i]+' ';      '\':        hs:=hs+'$\backslash$'    else      hs := hs + S[i];    end;  EscapeString:=hs;end;procedure WriteTexFile(const infn,outfn:string);var  t,f   : text;  line,  i,k   : longint;  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);              while s[i] in ['0'..'9'] do               inc(i);              inc(i);              s1:='';              k:=0;              while (k<5) and (s[i+k]<>'_') do               begin                 case s[i+k] of                  'W' : s1:='Warning: ';                  'E' : s1:='Error: ';                  'F' : s1:='Fatal: ';                  'N' : s1:='Note: ';                  'I' : s1:='Info: ';                  'H' : s1:='Hint: ';                 end;                 inc(k);               end;              if s[i+k]='_' then               inc(i,k+1);              writeln(t,'\item ['+s1+escapestring(Copy(s,i,255))+']');            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.
 |