fpdoc.pp 12 KB

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