fpdoc.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. SOptDefine = '--define=';
  189. Function ProjectOpt(Const s : string) : boolean;
  190. begin
  191. Result:=(Copy(s,1,3)='-p=') or (Copy(s,1,Length(SOptProject))=SOptProject) or (Copy(s,1,Length(SOptMacro))=SOptMacro) or (Copy(s,1,Length(SOptDefine))=SOptDefine);
  192. end;
  193. Function PackageOpt(Const s : string) : boolean;
  194. begin
  195. Result:=((Copy(s,1,3)='-a=') or (Copy(s,1,Length(SOptPackage))=SOptPackage));
  196. end;
  197. var
  198. i : Integer;
  199. s : string;
  200. begin
  201. // Check project
  202. for i := 1 to ParamCount do
  203. begin
  204. s:=ParamStr(I);
  205. If ProjectOpt(S) then
  206. ParseOption(s);
  207. end;
  208. If (FCreator.Packages.Count=1) then
  209. FPackage:=FCreator.Packages[0]
  210. else if (FCreator.Options.DefaultPackageName<>'') then
  211. Fpackage:=FCreator.Packages.FindPackage(FCreator.Options.DefaultPackageName);
  212. If FCreator.Project.Packages.Count=0 then
  213. begin // Add default package if none defined
  214. FPackage:=FCreator.Packages.Add as TFPDocPackage;
  215. end;
  216. // Check package
  217. for i := 1 to ParamCount do
  218. begin
  219. s:=ParamStr(I);
  220. If PackageOpt(S) then
  221. ParseOption(s);
  222. end;
  223. for i := 1 to ParamCount do
  224. begin
  225. s:=ParamStr(I);
  226. If Not (ProjectOpt(s) or PackageOpt(S)) then
  227. ParseOption(s);
  228. end;
  229. SelectedPackage; // Will print error if none available.
  230. // Set defaults
  231. if FCreator.Options.BackEnd='' then
  232. FCreator.Options.BackEnd:='html';
  233. if SelectedPackage.Output='' then
  234. SelectedPackage.Output:=SelectedPackage.Name;
  235. end;
  236. procedure TFPDocApplication.ParseOption(Const S : String);
  237. procedure AddDirToFileList(List: TStrings; const ADirName, AMask: String);
  238. Var
  239. Info : TSearchRec;
  240. D : String;
  241. begin
  242. if (ADirName<>'') and not DirectoryExists(ADirName) then
  243. OutputLog(Self,'Directory '+ADirName+' does not exist')
  244. else
  245. begin
  246. if (ADirName='.') or (ADirName='') then
  247. D:=''
  248. else
  249. D:=IncludeTrailingPathDelimiter(ADirName);
  250. If (FindFirst(D+AMask,0,Info)=0) then
  251. try
  252. Repeat
  253. If (Info.Attr and faDirectory)=0 then
  254. List.Add(D+Info.name);
  255. Until FindNext(Info)<>0;
  256. finally
  257. FindClose(Info);
  258. end;
  259. end;
  260. end;
  261. procedure AddToFileList(List: TStrings; const FileName: String);
  262. var
  263. f: Text;
  264. s: String;
  265. begin
  266. if Copy(FileName, 1, 1) = '@' then
  267. begin
  268. AssignFile(f, Copy(FileName, 2, Length(FileName)));
  269. Reset(f);
  270. while not EOF(f) do
  271. begin
  272. ReadLn(f, s);
  273. List.Add(s);
  274. end;
  275. Close(f);
  276. end else
  277. List.Add(FileName);
  278. end;
  279. var
  280. i: Integer;
  281. Cmd, Arg: String;
  282. begin
  283. if (s = '-h') or (s = '--help') then
  284. Usage(0)
  285. else if s = '--hide-protected' then
  286. FCreator.Options.HideProtected := True
  287. else if s = '--fallback-seealso-links' Then
  288. FCreator.Options.FallBackSeeAlsoLinks := True
  289. else if s = '--warn-no-node' then
  290. FCreator.Options.WarnNoNode := True
  291. else if s = '--warn-documentation-empty' then
  292. FCreator.Options.WarnDocumentationEmpty := True
  293. else if s = '--info-used-file' then
  294. FCreator.Options.InfoUsedFile := True
  295. else if s = '--warn-XCT' then
  296. FCreator.Options.WarnXCT := True
  297. else if s = '--show-private' then
  298. FCreator.Options.ShowPrivate := True
  299. else if s = '--stop-on-parser-error' then
  300. FCreator.Options.StopOnParseError := True
  301. else if s = '--dont-trim' then
  302. FCreator.Options.DontTrim := True
  303. else
  304. begin
  305. i := Pos('=', s);
  306. if i > 0 then
  307. begin
  308. Cmd := Copy(s, 1, i - 1);
  309. Arg := Copy(s, i + 1, Length(s));
  310. end
  311. else
  312. begin
  313. Cmd := s;
  314. SetLength(Arg, 0);
  315. end;
  316. if (Cmd = '--project') or (Cmd='-p') then
  317. begin
  318. FProjectFile:=True;
  319. FCreator.LoadProjectFile(Arg);
  320. end
  321. else if (Cmd = '--examples-dir') then
  322. FCreator.ExamplesPath:=Arg
  323. else if (Cmd = '--descr') then
  324. AddToFileList(SelectedPackage.Descriptions, Arg)
  325. else if (Cmd = '--descr-dir') then
  326. AddDirToFileList(SelectedPackage.Descriptions, Arg, '*.xml')
  327. else if (Cmd = '--base-descr-dir') then
  328. FCreator.BaseDescrDir:=Arg
  329. else if (Cmd = '--define') then
  330. begin
  331. Writeln('Defining : ',Arg);
  332. FCreator.Defines.Add(Arg)
  333. end
  334. else if (Cmd = '--macro') then
  335. begin
  336. If Pos('=',Arg)=0 then
  337. WriteLn(StdErr, Format(SCmdLineErrInvalidMacro, [Arg]));
  338. FCreator.ProjectMacros.Add(Arg);
  339. end
  340. else if (Cmd = '-f') or (Cmd = '--format') then
  341. begin
  342. Arg:=UpperCase(Arg);
  343. If FindWriterClass(Arg)=-1 then
  344. WriteLn(StdErr, Format(SCmdLineInvalidFormat, [Arg]))
  345. else
  346. FCreator.Options.BackEnd:=Arg;
  347. end
  348. else if (Cmd = '-l') or (Cmd = '--lang') then
  349. FCreator.Options.Language := Arg
  350. else if (Cmd = '-i') or (Cmd = '--input') then
  351. AddToFileList(SelectedPackage.Inputs, Arg)
  352. else if (Cmd = '--base-input-dir') then
  353. FCreator.BaseInputDir:=Arg
  354. else if (Cmd = '--input-dir') then
  355. begin
  356. AddDirToFileList(SelectedPackage.Inputs, Arg,'*.pp');
  357. AddDirToFileList(SelectedPackage.Inputs, Arg,'*.pas');
  358. end
  359. else if (Cmd = '-o') or (Cmd = '--output') then
  360. SelectedPackage.Output := Arg
  361. else if (Cmd = '-v') or (Cmd = '--verbose') then
  362. FCreator.Verbose:=true
  363. else if (Cmd = '-n') or (Cmd = '--dry-run') then
  364. FDryRun:=True
  365. else if (Cmd = '-t') or (Cmd = '--emit-notes') then
  366. FCreator.Options.EmitNotes := True
  367. else if Cmd = '--content' then
  368. SelectedPackage.ContentFile := Arg
  369. else if Cmd = '--import' then
  370. SelectedPackage.Imports.Add(Arg)
  371. else if Cmd = '--package' then
  372. begin
  373. If FProjectFile then
  374. FPackage:=FCreator.Packages.FindPackage(Arg)
  375. else
  376. FPackage.Name:=Arg;
  377. end
  378. else if Cmd = '--ostarget' then
  379. FCreator.Options.OSTarget := Arg
  380. else if Cmd = '--cputarget' then
  381. FCreator.Options.CPUTarget := Arg
  382. else if Cmd = '--mo-dir' then
  383. FCreator.Options.modir := Arg
  384. else if Cmd = '--parse-impl' then
  385. FCreator.Options.InterfaceOnly:=false
  386. else if Cmd = '--write-project' then
  387. FWriteProjectFile:=Arg
  388. else
  389. begin
  390. FCreator.Options.BackendOptions.Add(Cmd);
  391. FCreator.Options.BackendOptions.Add(Arg);
  392. end;
  393. end;
  394. end;
  395. Procedure TFPDocApplication.DoRun;
  396. begin
  397. Terminate;
  398. ExceptionExitCode:=1;
  399. try
  400. {$IFDEF Unix}
  401. gettext.TranslateResourceStrings('/usr/local/share/locale/%s/LC_MESSAGES/fpdoc.mo');
  402. {$ELSE}
  403. gettext.TranslateResourceStrings('intl/fpdoc.%s.mo');
  404. {$ENDIF}
  405. WriteLn(STitle);
  406. WriteLn(Format(SVersion, [DefFPCVersion, DefFPCDate]));
  407. WriteLn(SCopyright1);
  408. WriteLn(SCopyright2);
  409. WriteLn;
  410. ParseCommandLine;
  411. if (FWriteProjectFile<>'') then
  412. FCreator.CreateProjectFile(FWriteProjectFile)
  413. else
  414. FCreator.CreateDocumentation(FPackage,FDryRun);
  415. WriteLn(SDone);
  416. except
  417. ExitCode:=1;
  418. Raise;
  419. end;
  420. end;
  421. constructor TFPDocApplication.Create(AOwner: TComponent);
  422. begin
  423. inherited Create(AOwner);
  424. // StopOnException:=false;
  425. FCreator:=TFPDocCreator.Create(Self);
  426. FCreator.OnLog:=@OutputLog;
  427. OnException:= @ExceptProc;
  428. end;
  429. begin
  430. //AssignFile(StdErr, 'fpdoc_err.log');
  431. //rewrite(StdErr);
  432. With TFPDocApplication.Create(Nil) do
  433. try
  434. Run;
  435. finally
  436. Free;
  437. end;
  438. end.