fpdoc.pp 12 KB

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