fpdoc.pp 12 KB

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