chmcmd.lpr 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. { Copyright (C) <2005> <Andrew Haines> chmcmd.pas
  2. This library is free software; you can redistribute it and/or modify it
  3. under the terms of the GNU Library General Public License as published by
  4. the Free Software Foundation; either version 2 of the License, or (at your
  5. option) any later version.
  6. This program is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  8. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  9. for more details.
  10. You should have received a copy of the GNU Library General Public License
  11. along with this library; if not, write to the Free Software Foundation,
  12. Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  13. }
  14. {
  15. See the file COPYING, included in this distribution,
  16. for details about the copyright.
  17. }
  18. program chmcmd;
  19. {$mode objfpc}{$H+}
  20. {$IFDEF FPC_DOTTEDUNITS}
  21. uses
  22. {$ifdef Unix}UnixApi.CThreads, UnixApi.CWString, {$endif} System.Classes, System.SysUtils, Chm.FileWriter, System.GetOpts;
  23. {$ELSE FPC_DOTTEDUNITS}
  24. uses
  25. {$ifdef Unix}cthreads, cwstring, {$endif} Classes, Sysutils, chmfilewriter, GetOpts;
  26. {$ENDIF FPC_DOTTEDUNITS}
  27. Const
  28. CHMCMDVersion = {$I %FPCVERSION%};
  29. Procedure Usage;
  30. begin
  31. Writeln(StdErr,'Usage: chmcmd [options] <filename>');
  32. writeln(stderr);
  33. writeln(stderr,'The following options are available :');
  34. writeln(stderr,' --html-scan : scan html for missing files or alinks ');
  35. writeln(stderr,' --no-html-scan : don''t scan html for missing files or alinks ');
  36. writeln(stderr,' -h, --help : print this text');
  37. writeln(stderr,'--verbosity number : set verbosity level 0..5, 0 is least');
  38. writeln(stderr,'--generate-xml : (if .hhp file), also generate a xml project from .hhp');
  39. writeln(stderr);
  40. writeln(stderr,' .hhp projects are default scanned for html, .xml not');
  41. Halt(1);
  42. end;
  43. var
  44. theopts : array[1..7] of TOption;
  45. cores : Integer = 0;
  46. procedure InitOptions;
  47. begin
  48. with theopts[1] do
  49. begin
  50. name:='html-scan';
  51. has_arg:=0;
  52. flag:=nil;
  53. value:=#0;
  54. end;
  55. with theopts[2] do
  56. begin
  57. name:='no-html-scan';
  58. has_arg:=0;
  59. flag:=nil;
  60. value:=#0;
  61. end;
  62. with theopts[3] do
  63. begin
  64. name:='verbosity';
  65. has_arg:=1;
  66. flag:=nil;
  67. value:=#0;
  68. end;
  69. with theopts[4] do
  70. begin
  71. name:='generate-xml';
  72. has_arg:=0;
  73. flag:=nil;
  74. value:=#0;
  75. end;
  76. with theopts[5] do
  77. begin
  78. name:='help';
  79. has_arg:=0;
  80. flag:=nil;
  81. end;
  82. with theopts[6] do
  83. begin
  84. name:='cores';
  85. has_arg:=1;
  86. flag:=nil;
  87. end;
  88. with theopts[7] do
  89. begin
  90. name:='';
  91. has_arg:=0;
  92. flag:=nil;
  93. end;
  94. end;
  95. Type THtmlScanenum = (scandefault,scanforce,scanforcedno);
  96. var
  97. GenerateXMLForHHP : boolean = false;
  98. alloweddetaillevel : integer = 0; // show if msg.detaillevel<=allowdetaillevel
  99. htmlscan : THtmlScanEnum = Scandefault;
  100. procedure OnError (Project: TChmProject;errorkind:TChmProjectErrorKind;msg:rtlString;detailevel:integer=0);
  101. begin
  102. if (detailevel<=alloweddetaillevel) or (errorkind < chmnote) then
  103. if errorkind<>chmnone then
  104. writeln(ChmErrorKindText[errorkind],': ',msg)
  105. else
  106. writeln(msg);
  107. end;
  108. procedure Processfile(name:string);
  109. var
  110. OutStream: TFileStream;
  111. Project: TChmProject;
  112. xmlname: string;
  113. ishhp : boolean;
  114. begin
  115. ishhp:=uppercase(extractfileext(name))='.HHP';
  116. Project := TChmProject.Create;
  117. Project.ReadMeMessage:='Compiled by CHMCmd '+CHMCMDVersion;
  118. if ishhp then
  119. begin
  120. xmlname:=changefileext(name,'.hhp.xml');
  121. Project.OnError:=@OnError;
  122. try
  123. Project.LoadFromHHP(name,false) ; // we need a param for this second param later
  124. except
  125. on e:exception do
  126. begin
  127. Writeln('This HHP CHM project seems corrupt, please check it ',name,' (', e.message,')');
  128. halt(1);
  129. end;
  130. end;
  131. project.ScanHtmlContents:=htmlscan<>scanforcedno; // .hhp default SCAN
  132. end
  133. else
  134. begin
  135. try
  136. project.ScanHtmlContents:=htmlscan in [scanforce, scandefault]; // .hhp default SCAN
  137. Project.LoadFromFile(name);
  138. except
  139. on e:exception do
  140. begin
  141. Writeln('This XML CHM project seems corrupt, please check it ',name);
  142. halt(1);
  143. end;
  144. end;
  145. end;
  146. OutStream := TFileStream.Create(Project.OutputFileName, fmCreate);
  147. Project.WriteChm(OutStream);
  148. if Project.ScanHtmlContents then
  149. Project.ShowUndefinedAnchors;
  150. if ishhp and GenerateXMLForHHP then
  151. begin
  152. Writeln('Generating XML ',xmlname,'.');
  153. Project.SaveToFile(xmlname);
  154. end;
  155. OutStream.Free;
  156. Project.Free;
  157. end;
  158. var
  159. name : string;
  160. optionindex : integer;
  161. c : char;
  162. verbtemp : integer;
  163. verbbool : boolean;
  164. begin
  165. InitOptions;
  166. Writeln(stderr,'chmcmd, a CHM compiler. (c) 2010-2024 Free Pascal core.');
  167. Writeln(Stderr);
  168. repeat
  169. c:=getlongopts('h',@theopts[1],optionindex);
  170. case c of
  171. #0 : begin
  172. case optionindex-1 of
  173. 0 : htmlscan:=scanforce;
  174. 1 : htmlscan:=scanforcedno;
  175. 2 : begin
  176. verbbool:=trystrtoint(optarg,verbtemp);
  177. if verbbool then
  178. verbbool:=(verbtemp>=0) and (verbtemp<6);
  179. if verbbool then
  180. alloweddetaillevel:=verbtemp
  181. else
  182. begin
  183. Writeln('Illegal value for switch --verbosity :',optarg);
  184. Usage;
  185. Halt;
  186. end;
  187. end;
  188. 3 : GenerateXMLForHHP:=true;
  189. 4 : begin;
  190. Usage;
  191. Halt;
  192. end;
  193. 5 : begin
  194. if not trystrtoint(optarg,cores) then
  195. begin
  196. Writeln('Illegal value for switch --cores :',optarg);
  197. Usage;
  198. Halt;
  199. end;
  200. end;
  201. end;
  202. end;
  203. '?' : begin
  204. writeln('unknown option',optopt);
  205. usage;
  206. halt;
  207. end;
  208. end; { case }
  209. until c=endofoptions;
  210. if (paramcount-optind)=0 then // if equal, then 1 parameter
  211. begin
  212. name:=paramstr(optind);
  213. if not fileexists(name) then
  214. begin
  215. Writeln('Can''t find project file ',name);
  216. halt;
  217. end;
  218. ProcessFile(Name);
  219. end
  220. else
  221. begin
  222. Writeln('Invalid number of parameters :', paramcount-optind+1);
  223. Usage;
  224. halt;
  225. end;
  226. end.