msg2inc.pp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. {
  2. $Id$
  3. This program is part of the Free Pascal run time library.
  4. Copyright (c) 1998-2000 by Peter Vreman
  5. Convert a .msg file to an .inc file with a const array of char
  6. And for the lazy docwriters it can also generate some TeX output
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. program msg2inc;
  14. uses
  15. crc,
  16. strings;
  17. const
  18. version='0.99.14';
  19. {$ifdef linux}
  20. eollen=1;
  21. {$else}
  22. eollen=2;
  23. {$endif}
  24. type
  25. TMode=(M_Char,M_Tex,M_Intel,M_String,M_Renumber);
  26. var
  27. InFile,
  28. OutFile,
  29. OutName : string;
  30. Mode : TMode;
  31. TexHeader : boolean;
  32. MsgTxt : pchar;
  33. EnumTxt : pchar;
  34. enumsize,
  35. msgsize : longint;
  36. function XlatString(Var S : String):boolean;
  37. {
  38. replaces \xxx in string S with #x, and \\ with \ (escaped)
  39. which can reduce size of string.
  40. Returns false when an error in the line exists
  41. }
  42. Function GetNumber(Position:longint):longint;
  43. var
  44. C,Value,i : longint;
  45. begin
  46. I:=0;
  47. Value:=0;
  48. while i<3 do
  49. begin
  50. C:=ord(S[Position+I]);
  51. if (C>47) and (C<56) then
  52. dec(C,48)
  53. else
  54. begin
  55. GetNumber:=-1;
  56. exit;
  57. end;
  58. if I=0 then
  59. C:=C shl 6;
  60. if I=1 then
  61. C:=C SHL 3;
  62. inc(Value,C);
  63. inc(I);
  64. end;
  65. GetNumber:=Value;
  66. end;
  67. var
  68. S2 : String;
  69. A,B,Value : longint;
  70. begin
  71. A:=1;
  72. B:=1;
  73. while A<=Length(S) do
  74. begin
  75. if (S[A]='\') and (a<length(s)) then
  76. begin
  77. if S[A+1]='\' then
  78. begin
  79. S2[B]:='\';
  80. Inc(A,2);
  81. Inc(B);
  82. end
  83. else
  84. begin
  85. Value:=GetNumber(A+1);
  86. if Value=-1 then
  87. begin
  88. XlatString:=false;
  89. exit;
  90. end;
  91. S2[B]:=Chr(Value);
  92. inc(B);
  93. inc(A,4);
  94. end;
  95. end
  96. else
  97. begin
  98. S2[B]:=S[A];
  99. inc(A);
  100. inc(B);
  101. end;
  102. end;
  103. S2[0]:=Chr(B-1);
  104. S:=S2;
  105. XlatString:=true;
  106. end;
  107. procedure LoadMsgFile(const fn:string);
  108. var
  109. f : text;
  110. line,i : longint;
  111. ptxt,
  112. penum : pchar;
  113. s,s1 : string;
  114. begin
  115. Writeln('Loading messagefile ',fn);
  116. {Read the message file}
  117. assign(f,fn);
  118. {$I-}
  119. reset(f);
  120. {$I+}
  121. if ioresult<>0 then
  122. begin
  123. WriteLn('*** message file '+fn+' not found ***');
  124. exit;
  125. end;
  126. { First parse the file and count bytes needed }
  127. line:=0;
  128. msgsize:=0;
  129. while not eof(f) do
  130. begin
  131. readln(f,s);
  132. inc(line);
  133. if not XlatString(S) then
  134. S:='';
  135. if (s<>'') and not(s[1] in ['#',';','%']) then
  136. begin
  137. i:=pos('=',s);
  138. if i>0 then
  139. begin
  140. inc(msgsize,length(s)-i+1);
  141. inc(enumsize,i);
  142. end
  143. else
  144. writeln('error in line: ',line,' skipping');
  145. end;
  146. end;
  147. { now read the buffer in mem }
  148. getmem(msgtxt,msgsize);
  149. ptxt:=msgtxt;
  150. getmem(enumtxt,enumsize);
  151. penum:=enumtxt;
  152. reset(f);
  153. while not eof(f) do
  154. begin
  155. readln(f,s);
  156. inc(line);
  157. if not XlatString(S) then
  158. S[0]:=#0;
  159. if (s<>'') and not(s[1] in ['#',';','%']) then
  160. begin
  161. i:=pos('=',s);
  162. if i>0 then
  163. begin
  164. {txt}
  165. s1:=Copy(s,i+1,255);
  166. { support <lf> for empty lines }
  167. if s1='<lf>' then
  168. begin
  169. s1:='';
  170. { update the msgsize also! }
  171. dec(msgsize,4);
  172. end;
  173. move(s1[1],ptxt^,length(s1));
  174. inc(ptxt,length(s1));
  175. ptxt^:=#0;
  176. inc(ptxt);
  177. {enum}
  178. move(s[1],penum^,i-1);
  179. inc(penum,i-1);
  180. penum^:=#0;
  181. inc(penum);
  182. end;
  183. end;
  184. end;
  185. close(f);
  186. end;
  187. {*****************************************************************************
  188. WriteEnumFile
  189. *****************************************************************************}
  190. procedure WriteEnumFile(const fn,typename:string);
  191. var
  192. t : text;
  193. {$ifdef DEBUGCRC}
  194. t2 : text;
  195. {$endif DEBUGCRC}
  196. i,crcvalue : longint;
  197. p : pchar;
  198. s : string;
  199. start : boolean;
  200. begin
  201. crcvalue:=longint($ffffffff);
  202. writeln('Writing enumfile '+fn);
  203. {Open textfile}
  204. assign(t,fn);
  205. rewrite(t);
  206. {$ifdef DEBUGCRC}
  207. assign(t2,'crc.tst');
  208. rewrite(t2);
  209. Writeln(t2,crcvalue);
  210. {$endif DEBUGCRC}
  211. writeln(t,'type t',typename,'=(');
  212. {Parse buffer in msgbuf and create indexs}
  213. p:=enumtxt;
  214. start:=true;
  215. for i:=1 to enumsize do
  216. begin
  217. if start then
  218. begin
  219. write(t,' ');
  220. s:=UpCase(strpas(p));
  221. crcvalue:=UpdateCRC32(crcvalue,s[1],length(s));
  222. {$ifdef DEBUGCRC}
  223. Writeln(t2,s);
  224. Writeln(t2,crcvalue);
  225. {$endif DEBUGCRC}
  226. start:=false;
  227. end;
  228. if p^=#0 then
  229. begin
  230. writeln(t,',');
  231. start:=true;
  232. end
  233. else
  234. begin
  235. write(t,p^);
  236. end;
  237. inc(p);
  238. end;
  239. writeln(t,'end',typename);
  240. writeln(t,');');
  241. writeln(t,'const');
  242. writeln(t,' MsgCRCValue : longint = ',crcvalue,';');
  243. close(t);
  244. {$ifdef DEBUGCRC}
  245. close(t2);
  246. {$endif DEBUGCRC}
  247. end;
  248. {*****************************************************************************
  249. WriteStringFile
  250. *****************************************************************************}
  251. procedure WriteStringFile(const fn,constname:string);
  252. const
  253. maxslen=240; { to overcome aligning problems }
  254. function l0(l:longint):string;
  255. var
  256. s : string[16];
  257. begin
  258. str(l,s);
  259. while (length(s)<5) do
  260. s:='0'+s;
  261. l0:=s;
  262. end;
  263. var
  264. t : text;
  265. f : file;
  266. slen,
  267. len,i : longint;
  268. p : pchar;
  269. s : string;
  270. start,
  271. quote : boolean;
  272. begin
  273. writeln('Writing stringfile ',fn);
  274. {Open textfile}
  275. assign(t,fn);
  276. rewrite(t);
  277. writeln(t,'{$ifdef Delphi}');
  278. writeln(t,'const '+constname+' : array[0..000000] of string[',maxslen,']=(');
  279. writeln(t,'{$else Delphi}');
  280. writeln(t,'const '+constname+' : array[0..000000,1..',maxslen,'] of char=(');
  281. write(t,'{$endif Delphi}');
  282. {Parse buffer in msgbuf and create indexs}
  283. p:=msgtxt;
  284. slen:=0;
  285. len:=0;
  286. quote:=false;
  287. start:=true;
  288. for i:=1 to msgsize do
  289. begin
  290. if slen>=maxslen then
  291. begin
  292. if quote then
  293. begin
  294. write(t,'''');
  295. quote:=false;
  296. end;
  297. write(t,',');
  298. slen:=0;
  299. inc(len);
  300. end;
  301. if (len>70) or (start) then
  302. begin
  303. if quote then
  304. begin
  305. write(t,'''');
  306. quote:=false;
  307. end;
  308. if slen>0 then
  309. writeln(t,'+')
  310. else
  311. writeln(t);
  312. len:=0;
  313. start:=false;
  314. end;
  315. if (len=0) then
  316. write(t,' ');
  317. if (ord(p^)>=32) and (p^<>#39) then
  318. begin
  319. if not quote then
  320. begin
  321. write(t,'''');
  322. quote:=true;
  323. inc(len);
  324. end;
  325. write(t,p^);
  326. inc(len);
  327. end
  328. else
  329. begin
  330. if quote then
  331. begin
  332. write(t,'''');
  333. inc(len);
  334. quote:=false;
  335. end;
  336. write(t,'#'+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
  337. inc(len,3);
  338. end;
  339. if p^=#0 then
  340. start:=true;
  341. inc(slen);
  342. inc(p);
  343. end;
  344. if quote then
  345. write(t,'''');
  346. writeln(t,'');
  347. writeln(t,');');
  348. close(t);
  349. {update arraysize}
  350. s:=l0(msgsize div maxslen); { we start with 0 }
  351. assign(f,fn);
  352. reset(f,1);
  353. seek(f,34+eollen+length(constname));
  354. blockwrite(f,s[1],5);
  355. seek(f,90+3*eollen+2*length(constname));
  356. blockwrite(f,s[1],5);
  357. close(f);
  358. end;
  359. {*****************************************************************************
  360. WriteCharFile
  361. *****************************************************************************}
  362. procedure WriteCharFile(const fn,constname:string);
  363. function l0(l:longint):string;
  364. var
  365. s : string[16];
  366. begin
  367. str(l,s);
  368. while (length(s)<5) do
  369. s:='0'+s;
  370. l0:=s;
  371. end;
  372. function createconst(b:byte):string;
  373. begin
  374. if (b in [32..127]) and (b<>39) then
  375. createconst:=''''+chr(b)+''''
  376. else
  377. createconst:='#'+chr(b div 100+48)+chr((b mod 100) div 10+48)+chr(b mod 10+48)
  378. end;
  379. var
  380. t : text;
  381. f : file;
  382. cidx,i : longint;
  383. p : pchar;
  384. s : string;
  385. begin
  386. writeln('Writing charfile '+fn);
  387. {Open textfile}
  388. assign(t,fn);
  389. rewrite(t);
  390. writeln(t,'const ',constname,' : array[1..00000] of char=(');
  391. {Parse buffer in msgbuf and create indexs}
  392. p:=msgtxt;
  393. cidx:=0;
  394. for i:=1to msgsize do
  395. begin
  396. if cidx=15 then
  397. begin
  398. if cidx>0 then
  399. writeln(t,',')
  400. else
  401. writeln(t,'');
  402. write(t,' ');
  403. cidx:=0;
  404. end
  405. else
  406. if cidx>0 then
  407. write(t,',')
  408. else
  409. write(t,' ');
  410. write(t,createconst(ord(p^)));
  411. inc(cidx);
  412. inc(p);
  413. end;
  414. writeln(t,');');
  415. close(t);
  416. {update arraysize}
  417. s:=l0(msgsize);
  418. assign(f,fn);
  419. reset(f,1);
  420. seek(f,18+length(constname));
  421. blockwrite(f,s[1],5);
  422. close(f);
  423. end;
  424. {*****************************************************************************
  425. WriteIntelFile
  426. *****************************************************************************}
  427. procedure WriteIntelFile(const fn,constname:string);
  428. var
  429. t : text;
  430. len,i : longint;
  431. p : pchar;
  432. start,
  433. quote : boolean;
  434. begin
  435. writeln('Writing Intelfile ',fn);
  436. {Open textfile}
  437. assign(t,fn);
  438. rewrite(t);
  439. writeln(t,'procedure '+constname+';assembler;');
  440. writeln(t,'asm');
  441. {Parse buffer in msgbuf and create indexs}
  442. p:=msgtxt;
  443. len:=0;
  444. start:=true;
  445. quote:=false;
  446. for i:=1to msgsize do
  447. begin
  448. if len>70 then
  449. begin
  450. if quote then
  451. begin
  452. write(t,'''');
  453. quote:=false;
  454. end;
  455. writeln(t,'');
  456. start:=true;
  457. end;
  458. if start then
  459. begin
  460. write(t,' db ''');
  461. len:=0;
  462. quote:=true;
  463. end;
  464. if (ord(p^)>=32) and (p^<>#39) then
  465. begin
  466. if not quote then
  467. begin
  468. write(t,',''');
  469. quote:=true;
  470. inc(len);
  471. end;
  472. write(t,p^);
  473. inc(len);
  474. end
  475. else
  476. begin
  477. if quote then
  478. begin
  479. write(t,'''');
  480. inc(len);
  481. quote:=false;
  482. end;
  483. write(t,','+chr(ord(p^) div 100+48)+chr((ord(p^) mod 100) div 10+48)+chr(ord(p^) mod 10+48));
  484. inc(len,4);
  485. end;
  486. inc(p);
  487. end;
  488. if quote then
  489. write(t,'''');
  490. writeln(t,'');
  491. writeln(t,'end;');
  492. close(t);
  493. end;
  494. {*****************************************************************************
  495. RenumberFile
  496. *****************************************************************************}
  497. procedure RenumberFile(const fn,name:string);
  498. var
  499. f,t : text;
  500. i : longint;
  501. s,s1 : string;
  502. begin
  503. Writeln('Renumbering ',fn);
  504. {Read the message file}
  505. assign(f,fn);
  506. {$I-}
  507. reset(f);
  508. {$I+}
  509. if ioresult<>0 then
  510. begin
  511. WriteLn('*** message file '+fn+' not found ***');
  512. exit;
  513. end;
  514. assign(t,'msg2inc.$$$');
  515. rewrite(t);
  516. i:=0;
  517. while not eof(f) do
  518. begin
  519. readln(f,s);
  520. if (copy(s,1,length(Name))=Name) and (s[3] in ['0'..'9']) then
  521. begin
  522. inc(i);
  523. str(i,s1);
  524. while length(s1)<3 do
  525. s1:='0'+s1;
  526. writeln(t,Name+s1+Copy(s,6,255));
  527. end
  528. else
  529. writeln(t,s);
  530. end;
  531. close(t);
  532. close(f);
  533. { rename new file }
  534. erase(f);
  535. rename(t,fn);
  536. end;
  537. {*****************************************************************************
  538. WriteTexFile
  539. *****************************************************************************}
  540. Function EscapeString (Const S : String) : String;
  541. Var
  542. I : longint;
  543. hs : string;
  544. begin
  545. hs:='';
  546. for i:=1 to length(s) do
  547. if S[i]='$' then
  548. hs:=hs+'arg'
  549. else
  550. hs:=hs+s[i];
  551. EscapeString:=hs;
  552. end;
  553. procedure WriteTexFile(const infn,outfn:string);
  554. var
  555. t,f : text;
  556. line,
  557. i,k : longint;
  558. s,s1 : string;
  559. texoutput : boolean;
  560. begin
  561. Writeln('Loading messagefile ',infn);
  562. writeln('Writing TeXfile ',outfn);
  563. { Open infile }
  564. assign(f,infn);
  565. {$I-}
  566. reset(f);
  567. {$I+}
  568. if ioresult<>0 then
  569. begin
  570. WriteLn('*** message file '+infn+' not found ***');
  571. exit;
  572. end;
  573. { Open outfile }
  574. assign(t,outfn);
  575. rewrite(t);
  576. If texheader then
  577. begin
  578. writeln (t,'\documentclass{article}');
  579. writeln (t,'\usepackage{html}');
  580. writeln (t,'\usepackage{fpc}');
  581. writeln (t,'\begin{document}');
  582. end;
  583. { Parse }
  584. line:=0;
  585. TexOutput:=False;
  586. while not eof(f) do
  587. begin
  588. readln(f,s);
  589. inc(line);
  590. If Pos ('# BeginOfTeX',S)=1 then
  591. TexOutPut:=True
  592. else if pos ('# EndOfTeX',S)=1 then
  593. TexOutPut:=False;
  594. if (s<>'') and not(s[1] in ['#',';']) and TeXOutPut then
  595. begin
  596. if s[1]='%' then
  597. begin
  598. Delete(s,1,1);
  599. writeln(t,s);
  600. end
  601. else
  602. begin
  603. i:=pos('=',s);
  604. if i>0 then
  605. begin
  606. inc(i);
  607. s1:='';
  608. k:=0;
  609. while (k<5) and (s[i+k]<>'_') do
  610. begin
  611. case s[i+k] of
  612. 'W' : s1:='Warning: ';
  613. 'E' : s1:='Error: ';
  614. 'F' : s1:='Fatal: ';
  615. 'N' : s1:='Note: ';
  616. 'I' : s1:='Info: ';
  617. 'H' : s1:='Hint: ';
  618. end;
  619. inc(k);
  620. end;
  621. if s[i+k]='_' then
  622. inc(i,k+1);
  623. writeln(t,'\item ['+s1+escapestring(Copy(s,i,255))+']');
  624. end
  625. else
  626. writeln('error in line: ',line,' skipping');
  627. end;
  628. end;
  629. end;
  630. If TexHeader then
  631. writeln (t,'\end{document}');
  632. close(t);
  633. close(f);
  634. end;
  635. {*****************************************************************************
  636. Main Program
  637. *****************************************************************************}
  638. procedure getpara;
  639. var
  640. ch : char;
  641. para : string;
  642. files,i : word;
  643. procedure helpscreen;
  644. begin
  645. writeln('usage : msg2inc [Options] <msgfile> <incfile> <constname>');
  646. writeln('<Options> can be : -T Create .doc TeX file');
  647. writeln(' -TS Create .doc TeX file (stand-alone)');
  648. writeln(' -I Intel style asm output');
  649. writeln(' -S array of string');
  650. writeln(' -C array of char');
  651. writeln(' -R renumber section <incfile>');
  652. writeln(' -V Show version');
  653. writeln(' -? or -H This HelpScreen');
  654. halt(1);
  655. end;
  656. begin
  657. Mode:=M_String;
  658. FIles:=0;
  659. for i:=1to paramcount do
  660. begin
  661. para:=paramstr(i);
  662. if (para[1]='-') then
  663. begin
  664. ch:=upcase(para[2]);
  665. delete(para,1,2);
  666. case ch of
  667. 'T' : begin
  668. case upcase(para[1]) of
  669. 'S' : TexHeader:=True;
  670. end;
  671. Mode:=M_Tex;
  672. end;
  673. 'I' : Mode:=M_Intel;
  674. 'S' : Mode:=M_String;
  675. 'C' : Mode:=M_Char;
  676. 'R' : Mode:=M_Renumber;
  677. 'V' : begin
  678. Writeln('Msg2Inc ',version,' for Free Pascal (C) 1998 Peter Vreman');
  679. Writeln;
  680. Halt;
  681. end;
  682. '?','H' : helpscreen;
  683. end;
  684. end
  685. else
  686. begin
  687. inc(Files);
  688. if Files>3 then
  689. HelpScreen;
  690. case Files of
  691. 1 : InFile:=Para;
  692. 2 : OutFile:=Para;
  693. 3 : OutName:=Para;
  694. end;
  695. end;
  696. end;
  697. case Mode of
  698. M_Renumber,
  699. M_Tex : if Files<2 then
  700. Helpscreen;
  701. else
  702. if FIles<3 then
  703. HelpScreen;
  704. end;
  705. end;
  706. begin
  707. GetPara;
  708. case Mode of
  709. M_Renumber : begin
  710. Renumberfile(Infile,OutFile);
  711. end;
  712. M_Tex : begin
  713. WriteTexFile(InFile,OutFile+'.tex');
  714. end;
  715. M_Intel : begin
  716. Loadmsgfile(InFile);
  717. WriteEnumFile(OutFile+'idx.inc',OutName+'const');
  718. WriteIntelFile(OutFile+'txt.inc',OutName+'txt');
  719. end;
  720. M_String : begin
  721. Loadmsgfile(InFile);
  722. WriteEnumFile(OutFile+'idx.inc',OutName+'const');
  723. WriteStringFile(OutFile+'txt.inc',OutName+'txt');
  724. end;
  725. M_Char : begin
  726. Loadmsgfile(InFile);
  727. WriteEnumFile(OutFile+'idx.inc',OutName+'const');
  728. WriteCharFile(OutFile+'txt.inc',OutName+'txt');
  729. end;
  730. end;
  731. end.
  732. {
  733. $Log$
  734. Revision 1.7 2000-05-26 18:20:38 peter
  735. * fixed wrong var parameter with @
  736. Revision 1.6 2000/05/15 13:14:48 pierre
  737. + calculate a CRC value for enums
  738. Revision 1.5 2000/02/09 13:23:11 peter
  739. * log truncated
  740. Revision 1.4 2000/01/27 11:29:15 peter
  741. * version 0.99.14
  742. Revision 1.3 2000/01/07 01:15:00 peter
  743. * updated copyright to 2000
  744. }