fpcres.pas 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. {$ifdef fpc}
  2. {$mode objfpc}
  3. {$endif}
  4. {$apptype console}
  5. {$H+}
  6. program fpcres;
  7. uses
  8. Classes, SysUtils, elfres, elfresfix;
  9. resourcestring
  10. SError = 'Error:';
  11. SErrUnknownParam = 'Unknown command-line parameter : %s';
  12. SErrNeedArgument = 'Option at pos %d (%s) needs an argument.';
  13. SErrNoInputFile = 'No input filename was specified';
  14. SErrNoOutputFile = 'Outputfile is not allowed when multiple input files are given';
  15. SErrOutputFileIllegal = 'Outputfile not allowed when fixing headers.';
  16. SUsage010 = 'fpcres - Free Pascal Resource to ELF object compiler';
  17. SUsage020 = 'Part of the Free Pascal and CrossFPC distributions';
  18. SUsage030 = 'Copyright (C) 2005 Simon Kissel';
  19. SUsage040 = '--------------------------------------------------------';
  20. SUsage050 = 'Usage: fpcres [options] -i inputfile [-i inputfile] [-o outputfile]';
  21. SUsage055 = ' where options are one or more of:';
  22. SUsage060 = ' -i --input=inputfile';
  23. SUsage065 = ' A file in windows .res resource format, ';
  24. SUsage070 = ' or a Delphi/Kylix form file in dfm/xfm ';
  25. SUsage080 = ' format (binary or text).';
  26. SUSage085 = ' More than one inputfile may be specified.';
  27. SUsage090 = ' -o --output=outputfile';
  28. SUsage095 = ' Name of the object file to generate. If ';
  29. SUsage100 = ' omitted, the name of the input file will';
  30. SUsage110 = ' be used, with .or as extension.';
  31. SUSage115 = ' (not allowed with multiple input files.)';
  32. SUsage116 = ' -e --extension=ext';
  33. SUsage117 = ' use ext as the extension for output filenames';
  34. SUsage120 = ' -h --help show this help message.';
  35. SUsage130 = ' -f --fixheader fix resource block header.';
  36. SUsage140 = ' -6 --64bit Use 64-bit elf resources.';
  37. SUsage150 = ' -v --verbose be verbose.';
  38. Type
  39. TRunMode = (rmCreateElfRes,rmFixHeader);
  40. Var
  41. RunMode : TRunMode;
  42. InputFiles : TStringList;
  43. OutputFileName : String;
  44. Use64bit : Boolean;
  45. BeVerbose : Boolean;
  46. UseExt : String;
  47. Procedure Usage(ExitStatus : Word);
  48. begin
  49. Writeln(SUsage010);
  50. Writeln(SUsage020);
  51. Writeln(SUsage030);
  52. Writeln(SUsage040);
  53. Writeln(SUsage050);
  54. Writeln(SUsage055);
  55. Writeln(SUsage060);
  56. Writeln(SUsage065);
  57. Writeln(SUsage070);
  58. Writeln(SUsage080);
  59. Writeln(SUSage085);
  60. Writeln(SUsage090);
  61. Writeln(SUsage095);
  62. Writeln(SUsage100);
  63. Writeln(SUsage110);
  64. Writeln(SUSage115);
  65. Writeln(SUSage116);
  66. Writeln(SUSage117);
  67. Writeln(SUsage120);
  68. Writeln(SUsage130);
  69. Writeln(SUsage140);
  70. Writeln(SUsage150);
  71. Halt(ExitStatus);
  72. end;
  73. Procedure DoError(Msg : String; Args : Array of const);
  74. begin
  75. Writeln(SError,' ',Format(Msg,Args));
  76. Usage(1);
  77. end;
  78. Procedure AnalyzeParams;
  79. Function CheckOption(Index : Integer;Short,Long : String): Boolean;
  80. var
  81. O : String;
  82. begin
  83. O:=Paramstr(Index);
  84. Result:=(O='-'+short) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
  85. end;
  86. Function OptionArg(Var Index : Integer) : String;
  87. Var
  88. P : Integer;
  89. begin
  90. if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
  91. begin
  92. If Index<ParamCount then
  93. begin
  94. Inc(Index);
  95. Result:=Paramstr(Index);
  96. end
  97. else
  98. DoError(SErrNeedArgument,[Index,ParamStr(Index)]);
  99. end
  100. else If length(ParamStr(Index))>2 then
  101. begin
  102. P:=Pos('=',Paramstr(Index));
  103. If (P=0) then
  104. DoError(SErrNeedArgument,[Index,ParamStr(Index)])
  105. else
  106. begin
  107. Result:=Paramstr(Index);
  108. Delete(Result,1,P);
  109. end;
  110. end;
  111. end;
  112. Var
  113. I : Integer;
  114. P : String;
  115. begin
  116. RunMode:=rmCreateElfres;
  117. Use64bit:=False;
  118. BeVerbose:=False;
  119. I:=0;
  120. While (I<ParamCount) do
  121. begin
  122. Inc(I);
  123. // Values.
  124. If Checkoption(I,'o','output') then
  125. OutPutFileName:=OptionArg(I)
  126. else if Checkoption(I,'i','input') then
  127. InputFiles.Add(OptionArg(I))
  128. else If Checkoption(I,'e','extension') then
  129. UseExt:=OptionArg(I)
  130. else if CheckOption(I,'f','fixheader') then
  131. RunMode:=rmFixHeader
  132. else if CheckOption(I,'6','64bit') then
  133. Use64bit:=True
  134. else if CheckOption(I,'h','help') then
  135. Usage(0)
  136. else if CheckOption(I,'v','verbose') then
  137. BeVerbose:=True
  138. else
  139. begin
  140. P:=ParamStr(I);
  141. if (Length(P)>0) and (P[1]<>'-') then
  142. begin
  143. if (I=ParamCount) then
  144. OutputFileName:=P
  145. else
  146. InputFiles.Add(P)
  147. end
  148. else
  149. begin
  150. DoError(SErrUnknownParam,[P]);
  151. Usage(1);
  152. end;
  153. end;
  154. end;
  155. If (InputFiles.Count=0) then
  156. DoError(SErrNoInputFile,[]);
  157. If (InputFiles.Count>1) and (OutputFileName<>'') then
  158. DoError(SErrNoOutputFile,[]);
  159. If (RunMode=rmFixHeader) and (OutputFileName<>'') then
  160. DoError(SErrOutputFileIllegal,[])
  161. end;
  162. Type
  163. TLogger = Class(TObject)
  164. Procedure Log(Const Msg : String);
  165. end;
  166. Procedure TLogger.Log(Const Msg : string);
  167. begin
  168. Writeln(Msg);
  169. end;
  170. Procedure FixHeader(AFileName : String);
  171. Var
  172. F : TElfResourceFixer;
  173. O : TLogger;
  174. begin
  175. if Use64bit then
  176. F:=TElf64ResourceFixer.Create
  177. else
  178. F:=TElf32ResourceFixer.Create;
  179. try
  180. F.Verbose:=BeVerbose;
  181. if BeVerbose then
  182. begin
  183. O:=TLogger.Create;
  184. F.OnVerbose:={$ifdef fpc}@{$endif}O.Log;
  185. end
  186. else
  187. O:=Nil;
  188. Try
  189. F.FixFile(AFileName);
  190. Finally
  191. O.Free;
  192. end;
  193. Finally
  194. F.Free;
  195. end;
  196. end;
  197. Procedure CreateRes(AFileName : String);
  198. Var
  199. C : TElfResCreator;
  200. begin
  201. If Use64Bit then
  202. C:=TElf64ResCreator.Create
  203. else
  204. C:=TElf32ResCreator.Create;
  205. With C do
  206. Try
  207. Verbose:=BeVerbose;
  208. If (UseExt<>'') then
  209. Extension:=UseExt;
  210. Convert(AFileName,OutputFileName);
  211. Finally
  212. Free;
  213. end;
  214. end;
  215. Procedure Run;
  216. Var
  217. I : Integer;
  218. begin
  219. Try
  220. Case RunMode of
  221. rmFixHeader:
  222. For I:=0 to InputFiles.Count-1 do
  223. FixHeader(InputFiles[i]);
  224. rmCreateElfRes:
  225. For I:=0 to InputFiles.Count-1 do
  226. CreateRes(InputFiles[i]);
  227. end;
  228. except
  229. On E : Exception do
  230. begin
  231. Writeln(SError,' ',E.Message);
  232. Halt(1);
  233. end;
  234. end;
  235. end;
  236. begin
  237. InputFiles:=TStringList.Create;
  238. Try
  239. AnalyzeParams;
  240. Run;
  241. Finally
  242. FreeAndNil(InputFiles);
  243. end;
  244. end.