2
0

fpdoc.pp 12 KB

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