fpdoc.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. {
  2. FPDoc - Free Pascal Documentation Tool
  3. Copyright (C) 2000 - 2003 by
  4. Areca Systems GmbH / Sebastian Guenther, [email protected]
  5. 2005-2012 by
  6. various FPC contributors
  7. See the file COPYING, 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 FPDoc;
  14. uses
  15. {$ifdef Unix}
  16. CThreads,
  17. cwstring,
  18. {$endif}
  19. SysUtils, Classes, Gettext, custapp,
  20. dGlobals, // Global definitions, constants.
  21. fpdocclasstree, // Class tree builder
  22. dwriter, // TFPDocWriter definition.
  23. dwlinear, // Linear (abstract) writer
  24. dw_LaTeX, // TLaTex writer
  25. dw_XML, // XML writer
  26. dw_dxml, // Delphi XML doc.
  27. dw_HTML, // HTML writer
  28. dw_chm, // CHM Writer
  29. // dw_markdown, // Markdown writer
  30. dw_ipflin, // IPF writer (new linear output)
  31. dw_man, // Man page writer
  32. dw_linrtf, // linear RTF writer
  33. dw_txt, // TXT writer
  34. fpdocproj, mkfpdoc;
  35. Type
  36. { TFPDocApplication }
  37. TFPDocApplication = Class(TCustomApplication)
  38. private
  39. FCreator : TFPDocCreator;
  40. FPackage : TFPDocPackage;
  41. FDryRun,
  42. FProjectFile : Boolean;
  43. FWriteProjectFile : String;
  44. Protected
  45. procedure OutputLog(Sender: TObject; const Msg: String);
  46. procedure ParseCommandLine;
  47. procedure ParseOption(const S: String);
  48. Procedure Usage(AnExitCode : Byte);
  49. Procedure DoRun; override;
  50. Public
  51. Constructor Create(AOwner : TComponent); override;
  52. Destructor Destroy; override;
  53. Function SelectedPackage : TFPDocPackage;
  54. end;
  55. Procedure TFPDocApplication.Usage(AnExitCode : Byte);
  56. Var
  57. I,P : Integer;
  58. S : String;
  59. L : TStringList;
  60. C : TFPDocWriterClass;
  61. Backend : String;
  62. begin
  63. Writeln(Format(SCmdLineHelp,[ExtractFileName(Paramstr(0))]));
  64. Writeln(SUsageOption008);
  65. Writeln(SUsageOption009);
  66. Writeln(SUsageOption010);
  67. Writeln(SUsageOption020);
  68. Writeln(SUsageOption030);
  69. Writeln(SUsageOption035);
  70. Writeln(SUsageOption040);
  71. Writeln(SUsageOption050);
  72. Writeln(SUsageOption060);
  73. Writeln(SUsageOption070);
  74. Writeln(SUsageOption080);
  75. Writeln(SUsageOption090);
  76. Writeln(SUsageOption100);
  77. Writeln(SUsageOption110);
  78. Writeln(SUsageOption120);
  79. Writeln(SUsageOption130);
  80. Writeln(SUsageOption140);
  81. Writeln(SUsageOption145);
  82. Writeln(SUsageOption150);
  83. Writeln(SUsageOption160);
  84. Writeln(SUsageOption170);
  85. Writeln(SUsageOption180);
  86. Writeln(SUsageOption190);
  87. Writeln(SUsageOption200);
  88. Writeln(SUsageOption210);
  89. Writeln(SUsageOption215);
  90. Writeln(SUsageOption215A);
  91. Writeln(SUsageOption220);
  92. Writeln(SUsageOption230);
  93. Writeln(SUsageOption240);
  94. Writeln(SUsageOption250);
  95. Writeln(SUsageOption260);
  96. Writeln(SUsageOption270);
  97. Writeln(SUsageOption280);
  98. Writeln(SUsageOption290);
  99. Writeln(SUsageOption300);
  100. Writeln(SUsageOption310);
  101. Writeln(SUsageOption320);
  102. L:=TStringList.Create;
  103. Try
  104. Backend:=FCreator.OPtions.Backend;
  105. If (Backend='') then
  106. begin
  107. Writeln;
  108. Writeln(SUsageFormats);
  109. EnumWriters(L);
  110. For I:=0 to L.Count-1 do
  111. begin
  112. S:=L[i];
  113. P:=Pos('=',S);
  114. Writeln(Format(' %s - %s',[Copy(S,1,P-1)+Space(10-p),Copy(S,P+1,Length(S))]));
  115. end;
  116. Writeln(SUsageBackendHelp);
  117. end
  118. else
  119. begin
  120. Writeln;
  121. Writeln(Format(SUsageFormatSpecific,[Lowercase(backend)]));
  122. C:=GetWriterClass(Backend);
  123. C.Usage(L);
  124. If L.Count>0 then
  125. For I:=0 to (L.Count-1) div 2 do
  126. begin
  127. S:=L[i*2];
  128. Writeln(Format('%s %s',[S+Space(30-Length(S)),L[(i*2)+1]]));
  129. end;
  130. end;
  131. Finally
  132. L.Free;
  133. end;
  134. Halt(AnExitCode);
  135. end;
  136. destructor TFPDocApplication.Destroy;
  137. begin
  138. FreeAndNil(FCreator);
  139. Inherited;
  140. end;
  141. function TFPDocApplication.SelectedPackage: TFPDocPackage;
  142. var
  143. i:integer;
  144. begin
  145. Result:=FPackage;
  146. if (FPackage=Nil) or (FPackage.Name='') then
  147. begin
  148. Writeln(SNeedPackageName);
  149. if FCreator.Packages.Count>0 then
  150. begin
  151. if (FCreator.Packages[0].Name<>'') then
  152. Writeln(SAvailablePackages);
  153. for i:=0 to FCreator.Packages.Count-1 do
  154. begin
  155. Writeln(FCreator.Packages[i].Name);
  156. end;
  157. end;
  158. Usage(1);
  159. end;
  160. end;
  161. procedure TFPDocApplication.OutputLog(Sender: TObject; const Msg: String);
  162. begin
  163. Writeln(StdErr,Msg);
  164. end;
  165. procedure TFPDocApplication.ParseCommandLine;
  166. Const
  167. SOptProject = '--project=';
  168. SOptPackage = '--package=';
  169. SOptMacro = '--macro=';
  170. Function ProjectOpt(Const s : string) : boolean;
  171. begin
  172. Result:=(Copy(s,1,3)='-p=') or (Copy(s,1,Length(SOptProject))=SOptProject) or (Copy(s,1,Length(SOptMacro))=SOptMacro);
  173. end;
  174. Function PackageOpt(Const s : string) : boolean;
  175. begin
  176. Result:=((Copy(s,1,3)='-a=') or (Copy(s,1,Length(SOptPackage))=SOptPackage));
  177. end;
  178. var
  179. i : Integer;
  180. s : string;
  181. begin
  182. // Check project
  183. for i := 1 to ParamCount do
  184. begin
  185. s:=ParamStr(I);
  186. If ProjectOpt(S) then
  187. ParseOption(s);
  188. end;
  189. If (FCreator.Packages.Count=1) then
  190. FPackage:=FCreator.Packages[0]
  191. else if (FCreator.Options.DefaultPackageName<>'') then
  192. Fpackage:=FCreator.Packages.FindPackage(FCreator.Options.DefaultPackageName);
  193. If FCreator.Project.Packages.Count=0 then
  194. begin // Add default package if none defined
  195. FPackage:=FCreator.Packages.Add as TFPDocPackage;
  196. end;
  197. // Check package
  198. for i := 1 to ParamCount do
  199. begin
  200. s:=ParamStr(I);
  201. If PackageOpt(S) then
  202. ParseOption(s);
  203. end;
  204. for i := 1 to ParamCount do
  205. begin
  206. s:=ParamStr(I);
  207. If Not (ProjectOpt(s) or PackageOpt(S)) then
  208. ParseOption(s);
  209. end;
  210. SelectedPackage; // Will print error if none available.
  211. // Set defaults
  212. if FCreator.Options.BackEnd='' then
  213. FCreator.Options.BackEnd:='html';
  214. if SelectedPackage.Output='' then
  215. SelectedPackage.Output:=SelectedPackage.Name;
  216. end;
  217. procedure TFPDocApplication.ParseOption(Const S : String);
  218. procedure AddDirToFileList(List: TStrings; const ADirName, AMask: String);
  219. Var
  220. Info : TSearchRec;
  221. D : String;
  222. begin
  223. if (ADirName<>'') and not DirectoryExists(ADirName) then
  224. OutputLog(Self,'Directory '+ADirName+' does not exist')
  225. else
  226. begin
  227. if (ADirName='.') or (ADirName='') then
  228. D:=''
  229. else
  230. D:=IncludeTrailingPathDelimiter(ADirName);
  231. If (FindFirst(D+AMask,0,Info)=0) then
  232. try
  233. Repeat
  234. If (Info.Attr and faDirectory)=0 then
  235. List.Add(D+Info.name);
  236. Until FindNext(Info)<>0;
  237. finally
  238. FindClose(Info);
  239. end;
  240. end;
  241. end;
  242. procedure AddToFileList(List: TStrings; const FileName: String);
  243. var
  244. f: Text;
  245. s: String;
  246. begin
  247. if Copy(FileName, 1, 1) = '@' then
  248. begin
  249. AssignFile(f, Copy(FileName, 2, Length(FileName)));
  250. Reset(f);
  251. while not EOF(f) do
  252. begin
  253. ReadLn(f, s);
  254. List.Add(s);
  255. end;
  256. Close(f);
  257. end else
  258. List.Add(FileName);
  259. end;
  260. var
  261. i: Integer;
  262. Cmd, Arg: String;
  263. begin
  264. if (s = '-h') or (s = '--help') then
  265. Usage(0)
  266. else if s = '--hide-protected' then
  267. FCreator.Options.HideProtected := True
  268. else if s = '--warn-no-node' then
  269. FCreator.Options.WarnNoNode := True
  270. else if s = '--show-private' then
  271. FCreator.Options.ShowPrivate := True
  272. else if s = '--stop-on-parser-error' then
  273. FCreator.Options.StopOnParseError := True
  274. else if s = '--dont-trim' then
  275. FCreator.Options.DontTrim := True
  276. else
  277. begin
  278. i := Pos('=', s);
  279. if i > 0 then
  280. begin
  281. Cmd := Copy(s, 1, i - 1);
  282. Arg := Copy(s, i + 1, Length(s));
  283. end
  284. else
  285. begin
  286. Cmd := s;
  287. SetLength(Arg, 0);
  288. end;
  289. if (Cmd = '--project') or (Cmd='-p') then
  290. begin
  291. FProjectFile:=True;
  292. FCreator.LoadProjectFile(Arg);
  293. end
  294. else if (Cmd = '--descr') then
  295. AddToFileList(SelectedPackage.Descriptions, Arg)
  296. else if (Cmd = '--descr-dir') then
  297. AddDirToFileList(SelectedPackage.Descriptions, Arg, '*.xml')
  298. else if (Cmd = '--base-descr-dir') then
  299. FCreator.BaseDescrDir:=Arg
  300. else if (Cmd = '--macro') then
  301. begin
  302. If Pos('=',Arg)=0 then
  303. WriteLn(StdErr, Format(SCmdLineErrInvalidMacro, [Arg]));
  304. FCreator.ProjectMacros.Add(Arg);
  305. end
  306. else if (Cmd = '-f') or (Cmd = '--format') then
  307. begin
  308. Arg:=UpperCase(Arg);
  309. If FindWriterClass(Arg)=-1 then
  310. WriteLn(StdErr, Format(SCmdLineInvalidFormat, [Arg]))
  311. else
  312. FCreator.Options.BackEnd:=Arg;
  313. end
  314. else if (Cmd = '-l') or (Cmd = '--lang') then
  315. FCreator.Options.Language := Arg
  316. else if (Cmd = '-i') or (Cmd = '--input') then
  317. AddToFileList(SelectedPackage.Inputs, Arg)
  318. else if (Cmd = '--base-input-dir') then
  319. FCreator.BaseInputDir:=Arg
  320. else if (Cmd = '--input-dir') then
  321. begin
  322. AddDirToFileList(SelectedPackage.Inputs, Arg,'*.pp');
  323. AddDirToFileList(SelectedPackage.Inputs, Arg,'*.pas');
  324. end
  325. else if (Cmd = '-o') or (Cmd = '--output') then
  326. SelectedPackage.Output := Arg
  327. else if (Cmd = '-v') or (Cmd = '--verbose') then
  328. FCreator.Verbose:=true
  329. else if (Cmd = '-n') or (Cmd = '--dry-run') then
  330. FDryRun:=True
  331. else if (Cmd = '-t') or (Cmd = '--emit-notes') then
  332. FCreator.Options.EmitNotes := True
  333. else if Cmd = '--content' then
  334. SelectedPackage.ContentFile := Arg
  335. else if Cmd = '--import' then
  336. SelectedPackage.Imports.Add(Arg)
  337. else if Cmd = '--package' then
  338. begin
  339. If FProjectFile then
  340. FPackage:=FCreator.Packages.FindPackage(Arg)
  341. else
  342. FPackage.Name:=Arg;
  343. end
  344. else if Cmd = '--ostarget' then
  345. FCreator.Options.OSTarget := Arg
  346. else if Cmd = '--cputarget' then
  347. FCreator.Options.CPUTarget := Arg
  348. else if Cmd = '--mo-dir' then
  349. FCreator.Options.modir := Arg
  350. else if Cmd = '--parse-impl' then
  351. FCreator.Options.InterfaceOnly:=false
  352. else if Cmd = '--write-project' then
  353. FWriteProjectFile:=Arg
  354. else
  355. begin
  356. FCreator.Options.BackendOptions.Add(Cmd);
  357. FCreator.Options.BackendOptions.Add(Arg);
  358. end;
  359. end;
  360. end;
  361. Procedure TFPDocApplication.DoRun;
  362. begin
  363. ExceptionExitCode:=1;
  364. try
  365. {$IFDEF Unix}
  366. gettext.TranslateResourceStrings('/usr/local/share/locale/%s/LC_MESSAGES/fpdoc.mo');
  367. {$ELSE}
  368. gettext.TranslateResourceStrings('intl/fpdoc.%s.mo');
  369. {$ENDIF}
  370. WriteLn(STitle);
  371. WriteLn(Format(SVersion, [DefFPCVersion, DefFPCDate]));
  372. WriteLn(SCopyright1);
  373. WriteLn(SCopyright2);
  374. WriteLn;
  375. ParseCommandLine;
  376. if (FWriteProjectFile<>'') then
  377. FCreator.CreateProjectFile(FWriteProjectFile)
  378. else
  379. FCreator.CreateDocumentation(FPackage,FDryRun);
  380. WriteLn(SDone);
  381. Terminate;
  382. except
  383. ExitCode:=1;
  384. Raise;
  385. end;
  386. end;
  387. constructor TFPDocApplication.Create(AOwner: TComponent);
  388. begin
  389. inherited Create(AOwner);
  390. StopOnException:=true;
  391. FCreator:=TFPDocCreator.Create(Self);
  392. FCreator.OnLog:=@OutputLog;
  393. end;
  394. begin
  395. //AssignFile(Output, 'fpdoc.log');
  396. //rewrite(Output);
  397. With TFPDocApplication.Create(Nil) do
  398. try
  399. Run;
  400. finally
  401. Free;
  402. end;
  403. end.