makeskel.pp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. {
  2. $Id$
  3. FPDoc - Free Pascal Documentation Tool
  4. Copyright (C) 2000 - 2003 by
  5. Areca Systems GmbH / Sebastian Guenther, [email protected]
  6. * Skeleton XML description file generator
  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 MakeSkel;
  14. uses
  15. SysUtils, Classes, Gettext,
  16. dGlobals, PasTree, PParser,PScanner;
  17. resourcestring
  18. STitle = 'MakeSkel - FPDoc skeleton XML description file generator';
  19. SCopyright = '(c) 2000 - 2003 Areca Systems GmbH / Sebastian Guenther, [email protected]';
  20. SCmdLineHelp = 'See documentation for usage.';
  21. SCmdLineInvalidOption = 'Ignoring unknown option "%s"';
  22. SNoPackageNameProvided = 'Please specify a package name with --package=<name>';
  23. SOutputMustNotBeDescr = 'Output file must be different from description filenames.';
  24. SDone = 'Done.';
  25. type
  26. TCmdLineAction = (actionHelp, actionConvert);
  27. TSkelEngine = class(TFPDocEngine)
  28. public
  29. function CreateElement(AClass: TPTreeElement; const AName: String;
  30. AParent: TPasElement; AVisibility :TPasMemberVisibility;
  31. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement; override;
  32. end;
  33. const
  34. CmdLineAction: TCmdLineAction = actionConvert;
  35. OSTarget: String = {$I %FPCTARGETOS%};
  36. CPUTarget: String = {$I %FPCTARGETCPU%};
  37. var
  38. InputFiles, DescrFiles: TStringList;
  39. DocLang: String;
  40. Engine: TSkelEngine;
  41. UpdateMode,
  42. DisableErrors,
  43. DisableSeealso,
  44. DisableArguments,
  45. DisableProtected,
  46. DisablePrivate,
  47. DisableFunctionResults: Boolean;
  48. EmitClassSeparator: Boolean;
  49. PackageName, OutputName: String;
  50. f: Text;
  51. function TSkelEngine.CreateElement(AClass: TPTreeElement; const AName: String;
  52. AParent: TPasElement; AVisibility : TPasMemberVisibility;
  53. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  54. Function WriteThisNode(APasElement : TPasElement) : Boolean;
  55. begin
  56. Result:=Assigned(AParent) and (Length(AName) > 0) and
  57. (not DisableArguments or (APasElement.ClassType <> TPasArgument)) and
  58. (not DisableFunctionResults or (APasElement.ClassType <> TPasResultElement)) and
  59. (not DisablePrivate or (AVisibility<>visPrivate)) and
  60. (not DisableProtected or (AVisibility<>visProtected));
  61. If Result and updateMode then
  62. begin
  63. Result:=FindDocNode(APasElement)=Nil;
  64. If Result then
  65. Writeln(stderr,'Creating documentation for new node ',APasElement.PathName);
  66. end;
  67. end;
  68. begin
  69. Result := AClass.Create(AName, AParent);
  70. if AClass.InheritsFrom(TPasModule) then
  71. CurModule := TPasModule(Result);
  72. if Result.ClassType = TPasModule then
  73. begin
  74. WriteLn(f);
  75. WriteLn(f, '<!--');
  76. WriteLn(f, ' ====================================================================');
  77. WriteLn(f, ' ', Result.Name);
  78. WriteLn(f, ' ====================================================================');
  79. WriteLn(f, '-->');
  80. WriteLn(f);
  81. WriteLn(f, '<module name="', Result.Name, '">');
  82. if not UpdateMode then
  83. begin
  84. WriteLn(f, '<short></short>');
  85. WriteLn(f, '<descr>');
  86. WriteLn(f, '</descr>');
  87. end;
  88. end
  89. else if WriteThisNode(Result) then
  90. begin
  91. WriteLn(f);
  92. if EmitClassSeparator and (Result.ClassType = TPasClassType) then
  93. begin
  94. WriteLn(f, '<!--');
  95. WriteLn(f, ' ********************************************************************');
  96. WriteLn(f, ' ', Result.PathName);
  97. WriteLn(f, ' ********************************************************************');
  98. WriteLn(f, '-->');
  99. WriteLn(f);
  100. end;
  101. Writeln(F,'<!-- ', Result.ElementTypeName,' Visibility: ',VisibilityNames[AVisibility], ' -->');
  102. WriteLn(f,'<element name="', Result.FullName, '">');
  103. WriteLn(f, '<short></short>');
  104. WriteLn(f, '<descr>');
  105. WriteLn(f, '</descr>');
  106. if not DisableErrors then
  107. begin
  108. WriteLn(f, '<errors>');
  109. WriteLn(f, '</errors>');
  110. end;
  111. if not DisableSeealso then
  112. begin
  113. WriteLn(f, '<seealso>');
  114. WriteLn(f, '</seealso>');
  115. end;
  116. WriteLn(f, '</element>');
  117. end;
  118. end;
  119. procedure InitOptions;
  120. begin
  121. InputFiles := TStringList.Create;
  122. DescrFiles := TStringList.Create;
  123. end;
  124. procedure FreeOptions;
  125. begin
  126. DescrFiles.Free;
  127. InputFiles.Free;
  128. end;
  129. procedure ParseOption(const s: String);
  130. procedure AddToFileList(List: TStringList; const FileName: String);
  131. var
  132. f: Text;
  133. s: String;
  134. begin
  135. if Copy(FileName, 1, 1) = '@' then
  136. begin
  137. Assign(f, Copy(FileName, 2, Length(FileName)));
  138. Reset(f);
  139. while not EOF(f) do
  140. begin
  141. ReadLn(f, s);
  142. List.Add(s);
  143. end;
  144. Close(f);
  145. end else
  146. List.Add(FileName);
  147. end;
  148. var
  149. i: Integer;
  150. Cmd, Arg: String;
  151. begin
  152. if (s = '-h') or (s = '--help') then
  153. CmdLineAction := actionHelp
  154. else if s = '--update' then
  155. UpdateMode := True
  156. else if s = '--disable-arguments' then
  157. DisableArguments := True
  158. else if s = '--disable-errors' then
  159. DisableErrors := True
  160. else if s = '--disable-function-results' then
  161. DisableFunctionResults := True
  162. else if s = '--disable-seealso' then
  163. DisableSeealso := True
  164. else if s = '--disable-private' then
  165. DisablePrivate := True
  166. else if s = '--disable-protected' then
  167. begin
  168. DisableProtected := True;
  169. DisablePrivate :=True;
  170. end
  171. else if s = '--emitclassseparator' then
  172. EmitClassSeparator := True
  173. else
  174. begin
  175. i := Pos('=', s);
  176. if i > 0 then
  177. begin
  178. Cmd := Copy(s, 1, i - 1);
  179. Arg := Copy(s, i + 1, Length(s));
  180. end else
  181. begin
  182. Cmd := s;
  183. SetLength(Arg, 0);
  184. end;
  185. if (Cmd = '-i') or (Cmd = '--input') then
  186. AddToFileList(InputFiles, Arg)
  187. else if (Cmd = '-l') or (Cmd = '--lang') then
  188. DocLang := Arg
  189. else if (Cmd = '-o') or (Cmd = '--output') then
  190. OutputName := Arg
  191. else if Cmd = '--package' then
  192. PackageName := Arg
  193. else if Cmd = '--descr' then
  194. begin
  195. if FileExists(Arg) then
  196. DescrFiles.Add(Arg);
  197. end
  198. else
  199. WriteLn(StdErr, Format(SCmdLineInvalidOption, [s]));
  200. end;
  201. end;
  202. procedure ParseCommandLine;
  203. Const
  204. {$IFDEF Unix}
  205. MoFileTemplate = '/usr/local/share/locale/%s/LC_MESSAGES/makeskel.mo';
  206. {$ELSE}
  207. MoFileTemplate ='intl/makeskel.%s.mo';
  208. {$ENDIF}
  209. var
  210. MOFilename: string;
  211. i: Integer;
  212. begin
  213. DocLang:='';
  214. for i := 1 to ParamCount do
  215. ParseOption(ParamStr(i));
  216. If (DocLang<>'') then
  217. begin
  218. MOFilename:=Format(MOFileTemplate,[DocLang]);
  219. if FileExists(MOFilename) then
  220. gettext.TranslateResourceStrings(MoFileName)
  221. else
  222. writeln('NOTE: unable to find tranlation file ',MOFilename);
  223. // Translate internal documentation strings
  224. TranslateDocStrings(DocLang);
  225. end;
  226. end;
  227. var
  228. i: Integer;
  229. Module: TPasModule;
  230. begin
  231. InitOptions;
  232. ParseCommandLine;
  233. WriteLn(STitle);
  234. WriteLn(SCopyright);
  235. WriteLn;
  236. if CmdLineAction = actionHelp then
  237. WriteLn(SCmdLineHelp)
  238. else
  239. begin
  240. // Action is to create the XML skeleton
  241. if Length(PackageName) = 0 then
  242. begin
  243. WriteLn(SNoPackageNameProvided);
  244. Halt(2);
  245. end;
  246. if DescrFiles.IndexOf(OutputName)<>-1 then
  247. begin
  248. Writeln(SOutputMustNotBeDescr);
  249. Halt(3)
  250. end;
  251. Assign(f, OutputName);
  252. Rewrite(f);
  253. WriteLn(f, '<?xml version="1.0" encoding="ISO8859-1"?>');
  254. WriteLn(f, '<fpdoc-descriptions>');
  255. WriteLn(f, '<package name="', PackageName, '">');
  256. // Process all source files
  257. for i := 0 to InputFiles.Count - 1 do
  258. begin
  259. Engine := TSkelEngine.Create;
  260. try
  261. try
  262. Engine.SetPackageName(PackageName);
  263. if UpdateMode then
  264. For I:=0 to DescrFiles.Count-1 do
  265. Engine.AddDocFile(DescrFiles[i]);
  266. Module := ParseSource(Engine, InputFiles[i], OSTarget, CPUTarget);
  267. WriteLn(f, '</module> <!-- ', Module.Name, ' -->');
  268. except
  269. on e:EFileNotFoundError do
  270. begin
  271. Writeln(StdErr,' file ', e.message, ' not found');
  272. close(f);
  273. Halt(1);
  274. end;
  275. end;
  276. finally
  277. Engine.Free;
  278. end;
  279. end;
  280. WriteLn(f, '</package>');
  281. WriteLn(f, '</fpdoc-descriptions>');
  282. Close(f);
  283. end;
  284. FreeOptions;
  285. WriteLn(SDone);
  286. end.
  287. {
  288. $Log$
  289. Revision 1.11 2004-08-28 18:18:59 michael
  290. + Do not write descr nodes for module when updating
  291. Revision 1.10 2004/08/28 18:15:14 michael
  292. + Check whether outputfile not in inputfilenames
  293. Revision 1.9 2004/08/28 18:04:06 michael
  294. + Added update mode
  295. Revision 1.8 2004/08/25 07:16:43 michael
  296. + Improved translation handling
  297. Revision 1.7 2004/08/24 14:48:25 michael
  298. + Translate now called correctly...
  299. Revision 1.6 2004/05/01 20:13:40 marco
  300. * got fed up with exceptions on file not found. Fileresolver now raises a
  301. EFileNotFound error, and makeskel catches and exists gracefully
  302. Revision 1.5 2003/11/28 12:51:37 sg
  303. * Added support for source references
  304. Revision 1.4 2003/09/02 13:26:47 mattias
  305. MG: makeskel now ignores missing translation file
  306. Revision 1.3 2003/05/07 16:31:32 sg
  307. * Fixed a severe memory corruption problem on termination
  308. Revision 1.2 2003/03/28 13:01:36 michael
  309. + Patch from Charlie/iNQ to work with new scanner/parser
  310. Revision 1.1 2003/03/17 23:03:20 michael
  311. + Initial import in CVS
  312. }