data2inc.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. {
  2. $Id$
  3. Copyright (c) 1999 by Peter Vreman (msg2inc) and
  4. Marco van de Voort (data2inc)
  5. Placed under LGPL (See the file COPYING.FPC, included in this
  6. distribution, for details about the copyright)
  7. E-Mail Marco : [email protected]
  8. Homepage Marco: www.stack.nl/~marcov/xtdlib.htm
  9. Data2Inc is a heavily modified version of msg2inc.pp which compiles the
  10. inputfile to include files containing array of char( or byte) typed
  11. constants.
  12. (e.g. CONST xxx : ARRAY[0..xxx] OF CHAR =( aa,bb,cc,dd,ee); ,
  13. or the same but ARRAY OF BYTE )
  14. Two types of input file are allowed:
  15. 1 A special kind of textfile. Records start with '!'name and all following
  16. non empty and non comment (starting with '#',':' or '%') lines until
  17. the next line starting with '!' or EOF are the data. Data are either
  18. plain text (with \xxx ordinal constants) lines or a kinbd of
  19. Basic DATA command (these lines start with DATA).
  20. See demo.txt included with this package for a commented example.
  21. 2 (special parameter -b)
  22. An arbitrary binary file can get converted to constants. In this mode
  23. only one constant per include file is possible.
  24. This program has been working for three weeks now, all major bugs are fixed I
  25. hope. A different kind of (possible) problems are the amounts of memory
  26. allocated for the temporary buffer (MaxBuffersize variable), which
  27. is now initialised to 256000 bytes (for textfile type, per record), and 1 MB
  28. maximum for binary files. Also the program has to be compiled with a large
  29. enough heap (-CH parameter of FPC) to allow this. This is the case without
  30. modifying the default ppc386.cfg or adding -Ch parameters.
  31. This program is distributed in the hope that it will be useful,
  32. but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  34. **********************************************************************}
  35. program data2inc;
  36. uses strings;
  37. CONST
  38. version='0.99.13';
  39. { ************
  40. Simple service routines. These are copied from EPasStr.
  41. The program doesn't use EPasStr, because I want it to function
  42. BEFORE EPasStr is compiled, and distributable without XTDFPC.}
  43. TYPE CHARSET=SET OF CHAR;
  44. FUNCTION NextCharPos(CONST S : String;C:CHAR;Count:LONGINT):LONGINT;
  45. VAR I,J:LONGINT;
  46. BEGIN
  47. I:=ORD(S[0]);
  48. IF I=0 THEN
  49. J:=0
  50. ELSE
  51. BEGIN
  52. J:=Count;
  53. IF J>I THEN
  54. BEGIN
  55. NextCharPos:=0;
  56. EXIT
  57. END;
  58. WHILE (S[J]<>C) AND (J<=I) DO INC(J);
  59. IF (J>I) THEN
  60. J:=0;
  61. END;
  62. NextCharPos:=J;
  63. END;
  64. FUNCTION NextCharPosSet(CONST S : String;CONST C:CHARSET;Count:LONGINT):LONGINT;
  65. VAR I,J:LONGINT;
  66. BEGIN
  67. I:=Length(S);
  68. IF I=0 THEN
  69. J:=0
  70. ELSE
  71. BEGIN
  72. J:=Count;
  73. IF J>I THEN
  74. BEGIN
  75. NextCharPosSet:=0;
  76. EXIT;
  77. END;
  78. WHILE (j<=i) AND (NOT (S[J] IN C)) DO INC(J);
  79. IF (J>I) THEN
  80. J:=0; // NOT found.
  81. END;
  82. NextCharPosSet:=J;
  83. END;
  84. PROCEDURE RTrim(VAR P : String;Ch:Char);
  85. VAR I,J : LONGINT;
  86. BEGIN
  87. I:=ORD(P[0]); { Keeping length in local data eases optimalisations}
  88. IF (I>0) THEN
  89. BEGIN
  90. J:=I;
  91. WHILE (P[J]=Ch) AND (J>0) DO DEC(J);
  92. IF J<>I THEN
  93. Delete(P,J+1,I-J+1);
  94. END;
  95. END;
  96. PROCEDURE UpperCase(VAR S : String);
  97. VAR L,I : LONGINT;
  98. BEGIN
  99. L:=Length(S);
  100. IF L>0 THEN
  101. FOR I:=1 TO L DO
  102. IF (S[I]>CHR(96)) AND (S[I]<CHR(123)) THEN
  103. S[I]:=CHR(ORD(S[I])-32);
  104. END;
  105. PROCEDURE LTrim(VAR P : String;Ch:Char);
  106. VAR I,J : LONGINT;
  107. BEGIN
  108. I:=ORD(P[0]); { Keeping length in local data eases optimalisations}
  109. IF (I>0) THEN
  110. BEGIN
  111. J:=1;
  112. WHILE (P[J]=Ch) AND (J<=I) DO INC(J);
  113. IF J>1 THEN
  114. Delete(P,1,J-1);
  115. END;
  116. END;
  117. {---- End EPasStr routines ----}
  118. FUNCTION XlatString(Var S : String):BOOLEAN;
  119. {replaces \xxx in string S with #x, and \\ with \ (escaped)
  120. which can reduce size of string.
  121. Returns false when an error in the line exists}
  122. Function GetNumber(Position:LONGINT):LONGINT;
  123. VAR C,
  124. Value,
  125. I : LONGINT;
  126. BEGIN
  127. I:=0; Value:=0;
  128. WHILE I<3 DO
  129. BEGIN
  130. C:=ORD(S[Position+I]);
  131. IF (C>47) AND (C<56) THEN
  132. C:=C-48
  133. ELSE
  134. BEGIN
  135. GetNumber:=-1;
  136. EXIT;
  137. END;
  138. IF I=0 THEN
  139. C:=C SHL 6;
  140. IF I=1 THEN
  141. C:=C SHL 3;
  142. Value:=Value + C;
  143. INC(I);
  144. END;
  145. GetNumber:=Value;
  146. END;
  147. VAR S2:String;
  148. A,B : LONGINT;
  149. Value : LONGINT;
  150. BEGIN
  151. A:=1; B:=1;
  152. WHILE A<=Length(S) DO
  153. BEGIN
  154. IF S[A]='\' THEN
  155. IF S[A+1]='\' THEN
  156. BEGIN
  157. S2[B]:='\';
  158. INC (A,2); INC(B);
  159. END
  160. ELSE
  161. BEGIN
  162. Value:=GetNumber(A+1);
  163. IF Value=-1 THEN
  164. BEGIN
  165. XlatString:=FALSE;
  166. EXIT;
  167. END;
  168. S2[B]:=CHR(Value);
  169. INC(B); INC(A,4);
  170. END
  171. ELSE
  172. BEGIN
  173. S2[B]:=S[A];
  174. INC (A);
  175. INC (B);
  176. END;
  177. END;
  178. S2[0]:=CHR(B-1);
  179. S:=S2;
  180. XlatString:=TRUE;
  181. END;
  182. {Global equates}
  183. VAR
  184. Inname, {Name of input file}
  185. OutName, {Name of output (.inc) file}
  186. BinConstName: string; {(-b only) commandline name of constant}
  187. ArrayByte, {TRUE when output of ARRAY OF BYTE is desired
  188. ARRAY OF CHAR otherwise}
  189. I_Binary : BOOLEAN; {TRUE is binary input, FALSE textual}
  190. MsgTxt : pchar; {Temporary storage of data}
  191. msgsize : longint; {Bytes used in MsgTxt}
  192. maxbufsize : LONGINT; {Bytes allocated for MsgTxt}
  193. C : CHAR;
  194. {Dump the contents of MsgTxt (msgsize bytes) to file T (which has been opened),
  195. using CONSTNAME as the name of the ARRAY OF CHAR constant}
  196. procedure WriteCharFile(var t:text;constname:string);
  197. function createconst(b:byte):string;
  198. {decides whether to use the #xxx code or 'c' style for each char}
  199. begin
  200. if (b in [32..127]) and (b<>39) then
  201. createconst:=''''+chr(b)+''''
  202. else
  203. createconst:='#'+chr(b div 100+48)+chr((b mod 100) div 10+48)+chr(b mod 10+48)
  204. end;
  205. var
  206. cidx,i : longint;
  207. p : PCHAR;
  208. begin
  209. Writeln('Writing constant: ',constname,' to file '#39,outname,#39);
  210. {Open textfile}
  211. write(t,'const ',constname,' : array[0..'); Writeln(t,msgsize-1,'] of char=(');
  212. p:=msgtxt;
  213. cidx:=0;
  214. for i:=0 to msgsize-1 do
  215. begin
  216. if cidx=15 then
  217. begin
  218. if cidx>0 then
  219. writeln(t,',')
  220. else
  221. writeln(t,'');
  222. write(t,' ');
  223. cidx:=0;
  224. end
  225. else
  226. IF cidx>0 THEN
  227. write(t,',')
  228. ELSE
  229. Write(T,' ');
  230. write(t,createconst(ord(p^)));
  231. inc(cidx);
  232. inc(p);
  233. end;
  234. writeln(t,');');
  235. Writeln(T);
  236. end;
  237. {Dump the contents of MsgTxt (msgsize bytes) to file T (which has been opened),
  238. using CONSTNAME as the name of the ARRAY OF BYTE constant}
  239. procedure WriteByteFile(var t:text;constname:string);
  240. function createconst(b:byte):string;
  241. {Translates byte B to a $xx hex constant}
  242. VAR l : Byte;
  243. begin
  244. createconst[1]:='$'; createconst[0]:=#3;
  245. l:=ORD(B SHR 4) +48;
  246. IF l>57 THEN
  247. l:=L+7;
  248. createconst[2]:=CHR(l);
  249. l:=ORD(B and 15) +48;
  250. IF l>57 THEN
  251. INC(L,7);
  252. createconst[3]:=CHR(l);
  253. end;
  254. var
  255. cidx,i : longint;
  256. p : pchar;
  257. begin
  258. Writeln('Writing constant: ',constname,' to file '#39,outname,#39);
  259. {Open textfile}
  260. write(t,'const ',constname,' : array[0..'); Writeln(t,msgsize-1,'] of byte=(');
  261. p:=msgtxt;
  262. cidx:=0;
  263. for i:=0 to msgsize-1 do
  264. begin
  265. if cidx=15 then
  266. begin
  267. if cidx>0 then
  268. writeln(t,',')
  269. else
  270. writeln(t,'');
  271. write(t,' ');
  272. cidx:=0;
  273. end
  274. else
  275. IF cidx>0 THEN
  276. write(t,',')
  277. ELSE
  278. Write(T,' ');
  279. write(t,createconst(ord(p^)));
  280. inc(cidx);
  281. inc(p);
  282. end;
  283. writeln(t,');');
  284. Writeln(T);
  285. end;
  286. FUNCTION SpecialItem(S : String):LONGINT;
  287. { This procedure finds the next comma, (or the end of the string)
  288. but comma's within single or double quotes should be ignored.
  289. Single quotes within double quotes and vice versa are also ignored.}
  290. VAR DataItem : LONGINT;
  291. CONST xFcl : CHARSET = [',',#39,'"'];
  292. BEGIN
  293. DataItem:=0;
  294. REPEAT
  295. DataItem:=NextCharPosSet(S,xFcl,DataItem+1); {Find first " ' or ,}
  296. IF (DataItem<>0) AND ((S[DataItem]='"') OR (S[DataItem]=#39)) THEN { (double)Quote found?}
  297. DataItem:=NextCharPos(S,S[DataItem],DataItem+1); { then find other one}
  298. UNTIL (DataItem=0) OR (S[DataItem]=',');
  299. IF DataItem=0 THEN {Last data field of this line?}
  300. DataItem:=Length(S);
  301. SpecialItem:=DataItem;
  302. END;
  303. { Handles reading and processing of a textual file}
  304. procedure DoFile;
  305. var
  306. Infile,
  307. Outfile : text; {in and output textfiles}
  308. line, DataItem, {line number, position in DATA line}
  309. I1,I2, {4 temporary counters}
  310. I3,I4 : longint;
  311. s,S1 : string; {S is string after reading, S1 is temporary string or
  312. current DATA-item being processed }
  313. VarName : String; { Variable name of constant to be written}
  314. PROCEDURE ParseError;
  315. {Extremely simple errorhandler}
  316. BEGIN
  317. Writeln('Error in line : ',Line, ' Somewhere near :',#39,S1,#39);
  318. Close(InfIle); Close(Outfile);
  319. HALT;
  320. END;
  321. PROCEDURE FixDec;
  322. { Reads decimal value starting at S1[1].
  323. Value in I3, number of digits found in I1}
  324. BEGIN
  325. I1:=1;
  326. WHILE ((S1[I1]>#47) AND (S1[I1]<#58)) AND (I1<=Length(S1)) DO
  327. INC(I1);
  328. DEC(I1);
  329. IF I1=0 THEN
  330. ParseError;
  331. I3:=0;
  332. FOR I2:=1 TO I1 DO
  333. I3:=(I3*10)+ ORD(S1[I2])-48;
  334. {Calc no of bytes(1,2 or 4) required from no of digits found}
  335. IF (I1<3) THEN
  336. I2:=1
  337. ELSE
  338. IF (I1=3) AND (I3<256) THEN
  339. I2:=1
  340. ELSE
  341. BEGIN
  342. IF I1<5 THEN
  343. I2:=2
  344. ELSE
  345. IF (I1=5) AND (i3<65536) THEN
  346. I2:=2
  347. ELSE
  348. I2:=4;
  349. END;
  350. END;
  351. PROCEDURE DoChar;
  352. { Reads a #xxx constant at S1[1], and puts it in msgtxt array.
  353. Deletes #xxx constant from S1}
  354. BEGIN
  355. Delete(S1,1,1);
  356. FixDec;
  357. msgtxt[Msgsize]:=CHR(I3);
  358. inc(msgsize);
  359. Delete(S1,1,I1);
  360. END;
  361. PROCEDURE DoQuote;
  362. { Reads a quoted text-string ('xxx' or "xxx"). Quotechar is in S1[1]
  363. (always ' or "), any char except the quotechar is allowed between two
  364. quotechars.
  365. Deletes quoted textstring incl quotes from S1}
  366. VAR C : Char;
  367. BEGIN
  368. C:=S1[1];
  369. Delete(S1,1,1);
  370. I1:=Pos(C,S1); {Find other quote}
  371. IF I1=0 THEN
  372. ParseError; {Quotes have to be matched}
  373. Dec(I1);
  374. IF I1<>0 THEN
  375. BEGIN
  376. Move(S1[1],Msgtxt[Msgsize],I1);
  377. INC(msgsize,I1);
  378. END;
  379. Delete(S1,1,I1+1);
  380. LTrim(S1,' ');
  381. END;
  382. PROCEDURE FixHex(base2:LONGINT);
  383. { Reads a base 2,8 or 16 constant from S1.
  384. Parameter = 2Log of base (1,3 or 4 corresponding to base 2,8 and 16)
  385. Constant is processed, the number of digits estimated (1,2 or 4 bytes) and
  386. the value is appended to msgtxt accordingly}
  387. BEGIN
  388. I3:=0;
  389. I2:=1;
  390. WHILE (S1[I2] IN ['0'..'9','A'..'F','a'..'f']) AND (I2<=Length(S1)) DO
  391. BEGIN
  392. IF (S1[I2]>#47) AND (S1[I2]<#58) THEN
  393. I3:=(I3 SHL base2)+ ORD(S1[I2])-48
  394. ELSE
  395. IF (S1[I2]>#64) AND (S1[I2]<#71) THEN
  396. I3:=(I3 SHL base2)+ ORD(S1[I2])-55
  397. ELSE
  398. IF (S1[I2]>#96) AND (S1[I2]<#103) THEN
  399. I3:=(I3 SHL base2)+ ORD(S1[I2])-87
  400. ELSE
  401. ParseError;
  402. INC(I2);
  403. END;
  404. DEC(I2);
  405. CASE Base2 OF
  406. 4 : BEGIN
  407. I4:=(I2 SHR 1);
  408. IF ODD(I2) THEN
  409. INC(I4);
  410. IF I4=3 THEN I4:=4
  411. END;
  412. 3 : I4:=(I2*3 DIV 8)+1;
  413. 1 : BEGIN
  414. IF I2<9 THEN
  415. I4:=1
  416. ELSE
  417. IF I2<17 THEN
  418. I4:=2
  419. ELSE
  420. I4:=4;
  421. END;
  422. ELSE
  423. BEGIN
  424. Writeln(' severe internal error ');
  425. ParseError;
  426. END; {else}
  427. END; {Case}
  428. move(I3,msgtxt[Msgsize],i4);
  429. inc(msgsize,i4);
  430. END;
  431. PROCEDURE DoTextual;
  432. { processes aggregates of textual data like 'xxx'+#39"2143124"+'1234'#123}
  433. BEGIN
  434. REPEAT
  435. CASE S1[1] OF
  436. '#' : DoChar;
  437. '"',#39 : DoQuote; {Should I support octal codes here?}
  438. ELSE
  439. ParseError;
  440. END;
  441. LTrim(S1,' ');
  442. IF (S1[1]='+') THEN
  443. Delete(S1,1,1);
  444. LTrim(S1,' ');
  445. UNTIL Length(S1)=0;
  446. END;
  447. PROCEDURE FlushMsgTxt; {Flush MsgTxt array}
  448. BEGIN
  449. IF msgsize>0 THEN {In memory? Then flush}
  450. BEGIN
  451. IF ArrayByte THEN
  452. WriteByteFile(outfile,Varname)
  453. ELSE
  454. WriteCharFile(outfile,varname);
  455. msgsize:=0;
  456. END;
  457. END;
  458. {Actual DoFile}
  459. begin
  460. Getmem(msgtxt,maxbufsize);
  461. Writeln('processing file : ',inname);
  462. {Read the message file}
  463. assign(infile,inname);
  464. {$I-}
  465. reset(infile);
  466. {$I+}
  467. if ioresult<>0 then
  468. begin
  469. WriteLn('*** message file '+inname+' not found ***');
  470. exit;
  471. end;
  472. {Create output file}
  473. assign (outfile,outname);
  474. rewrite(outfile);
  475. msgsize:=0;
  476. Line:=0;
  477. while not eof(infile) do
  478. begin
  479. readln(infile,s); {Read a line}
  480. INC(Line);
  481. S1:=Copy(S,1,5);
  482. Uppercase(S1);
  483. IF S1='DATA ' THEN {DATA keyword?}
  484. BEGIN
  485. Delete(S,1,5);
  486. REPEAT
  487. DataItem:=SpecialItem(S); {Yes. Determine size of DATA field.}
  488. IF DataItem<>0 THEN
  489. BEGIN
  490. I1:=DataItem;
  491. IF DataItem=Length(S) THEN
  492. INC(i1); {DataItem fix for last field}
  493. S1:=Copy(S,1,I1-1); { copy field to S1}
  494. Delete(S,1,I1); {Delete field from S}
  495. LTrim(S1,' ');
  496. RTrim(S1,' ');
  497. LTrim(S,' ');
  498. CASE S1[1] OF {Select field type}
  499. #39,'"','#' : DoTextual; { handles textual aggregates
  500. e.g. #124"142"#123'sdgf''ads'}
  501. '$' : BEGIN {Handle $xxxx hex codes}
  502. Delete(S1,1,1);
  503. RTrim(S1,' ');
  504. IF Length(S1)>0 THEN
  505. FixHex(4)
  506. ELSE
  507. ParseError;
  508. END;
  509. '0'..'9' : BEGIN { handles 0x124,124124,124124H,234h,666o,353d,24b}
  510. IF (Length(S1)>1) AND (S1[2]='x') THEN {C style 0xABCD hex}
  511. BEGIN
  512. Delete(S1,1,2);
  513. FixHex(4);
  514. END
  515. ELSE {other types (HP notation suffix h,o,d and b (and upcase versions,
  516. and no suffix) }
  517. BEGIN
  518. CASE S1[Length(S1)] OF
  519. 'H','h' : FixHex(4); {Hex}
  520. 'o','O' : FixHex(3); {octal}
  521. 'B','b' : BEGIN {Binary}
  522. DEC(S1[0]); {avoid 'b' char being treated as
  523. hex B }
  524. FixHex(1);
  525. END;
  526. '0'..'9','d','D' : BEGIN {decimal versions}
  527. FixDec; {Fixdec is safe for trailing chars}
  528. {I1 =no of digits, I3=value, I2= no bytes needed}
  529. move(I3,msgtxt[Msgsize],i2);
  530. inc(msgsize,i2)
  531. END
  532. ELSE
  533. ParseError; {otherwise wrong suffix}
  534. END {Nested case}
  535. END; { IF S1[2]='x'}
  536. END; { '0'..'9'}
  537. '%' : BEGIN {%101010 binary constants}
  538. Delete(S1,1,1);
  539. FixHex(1);
  540. END;
  541. '\' : BEGIN {\xxx octal constants}
  542. Delete(S1,1,1);
  543. FixHex(3);
  544. END;
  545. END; {Case}
  546. END; {IF <>0}
  547. UNTIL {(DataItem:=Length(S)) OR} (DataItem=0); {parse until String is empty}
  548. END {S1='DATA'}
  549. ELSE
  550. BEGIN {Non DATA line}
  551. IF (Length(S)<>0) AND NOT (S[1] IN ['#',';','%']) THEN
  552. BEGIN
  553. C:=S[1];
  554. IF NOT XlatString(S) THEN {Expand \xxx octal constants}
  555. BEGIN
  556. Writeln('Some error with a \xxx constant or a stale (unescaped) backslash');
  557. ParseError;
  558. END;
  559. IF C='!' THEN { New variable}
  560. BEGIN
  561. FlushMsgTxt;
  562. I1:=1;
  563. ArrayByte:=FALSE;
  564. IF S[2]='$' THEN {Flag for ARRAY OF BYTE?}
  565. BEGIN
  566. INC(I1);
  567. ArrayByte:=TRUE;
  568. END;
  569. Delete(S,1,I1);
  570. VarName:=S;
  571. END
  572. ELSE
  573. BEGIN {Normal line}
  574. i1:=Length(S);
  575. move(s[1],msgtxt[Msgsize],i1);
  576. inc(msgsize,i1);
  577. END;
  578. END;
  579. END;
  580. end;
  581. close(infile);
  582. FlushMsgTxt; {Flush variable if msgtxt is occupied}
  583. Close(Outfile);
  584. end;
  585. procedure DoBinary;
  586. var
  587. Infile : File;
  588. Outfile : text;
  589. i : longint;
  590. begin
  591. Writeln('processing file : ',inname);
  592. {Read the message file}
  593. assign(infile,inname);
  594. {$I-}
  595. reset(infile,1);
  596. {$I+}
  597. if ioresult<>0 then
  598. begin
  599. WriteLn('*** message file '+inname+' not found ***');
  600. exit;
  601. end;
  602. assign (outfile,outname);
  603. rewrite(outfile);
  604. { First parse the file and count bytes needed }
  605. msgsize:=FileSize(InFile);
  606. IF Msgsize>1048576 THEN
  607. msgsize:=1048576;
  608. Getmem(msgtxt,msgsize);
  609. BlockRead(InFile,msgTxt[0],msgsize,i);
  610. IF I<>msgsize THEN
  611. BEGIN
  612. Writeln('Error while reading file',inName);
  613. HALT(1);
  614. END;
  615. IF ArrayByte THEN
  616. WriteByteFile(outfile,BinconstName)
  617. ELSE
  618. WriteCharFile(outfile,BinconstName);
  619. close(infile);
  620. Close(Outfile);
  621. end;
  622. {*****************************************************************************
  623. Main Program
  624. *****************************************************************************}
  625. procedure getpara;
  626. var
  627. ch : char;
  628. para : string;
  629. files,i : word;
  630. procedure helpscreen;
  631. begin
  632. writeln('usage : data2inc [Options] <msgfile> [incfile] [constname]');
  633. Writeln(' The constname parameter is only valid in combination');
  634. writeln(' with -b, otherwise the constname must be specified in the inputfile');
  635. Writeln;
  636. writeln('<Options> can be :');
  637. writeln(' -B File to read is binary.');
  638. writeln(' -A array of byte output (default is array of char)');
  639. writeln(' -V Show version');
  640. writeln(' -? or -H This HelpScreen');
  641. writeln;
  642. Writeln(' See data2inc.exm for a demonstration source');
  643. halt(1);
  644. end;
  645. begin
  646. I_binary:=FALSE;
  647. ArrayByte:=FALSE;
  648. FIles:=0;
  649. for i:=1to paramcount do
  650. begin
  651. para:=paramstr(i);
  652. if (para[1]='-') then
  653. begin
  654. ch:=upcase(para[2]);
  655. delete(para,1,2);
  656. case ch of
  657. 'B' : I_Binary:=TRUE;
  658. 'A' : Arraybyte:=TRUE;
  659. 'V' : begin
  660. Writeln('Data2Inc ',version,' (C) 1999 Peter Vreman and Marco van de Voort');
  661. Writeln;
  662. Halt;
  663. end;
  664. '?','H' : Helpscreen;
  665. end;
  666. end
  667. else
  668. begin
  669. inc(Files);
  670. if Files>3 then
  671. HelpScreen;
  672. case Files of
  673. 1 : InName:=Para;
  674. 2 : OutName:=Para;
  675. 3 : BinConstName:=Para;
  676. end;
  677. end;
  678. END;
  679. if (FIles<3) AND I_Binary then
  680. HelpScreen;
  681. IF Files<2 THEN
  682. HelpScreen;
  683. end;
  684. begin
  685. MaxBufSize:=100000;
  686. GetPara;
  687. IF I_Binary THEN
  688. DoBinary
  689. ELSE
  690. DoFile;
  691. end.
  692. {
  693. $Log$
  694. Revision 1.1 1999-11-09 14:40:50 peter
  695. * initial version
  696. }