fpdoc.pp 11 KB

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