makeskel.pp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. WriteLn(f, '<short></short>');
  83. WriteLn(f, '<descr>');
  84. WriteLn(f, '</descr>');
  85. end
  86. else if WriteThisNode(Result) then
  87. begin
  88. WriteLn(f);
  89. if EmitClassSeparator and (Result.ClassType = TPasClassType) then
  90. begin
  91. WriteLn(f, '<!--');
  92. WriteLn(f, ' ********************************************************************');
  93. WriteLn(f, ' ', Result.PathName);
  94. WriteLn(f, ' ********************************************************************');
  95. WriteLn(f, '-->');
  96. WriteLn(f);
  97. end;
  98. Writeln(F,'<!-- ', Result.ElementTypeName,' Visibility: ',VisibilityNames[AVisibility], ' -->');
  99. WriteLn(f,'<element name="', Result.FullName, '">');
  100. WriteLn(f, '<short></short>');
  101. WriteLn(f, '<descr>');
  102. WriteLn(f, '</descr>');
  103. if not DisableErrors then
  104. begin
  105. WriteLn(f, '<errors>');
  106. WriteLn(f, '</errors>');
  107. end;
  108. if not DisableSeealso then
  109. begin
  110. WriteLn(f, '<seealso>');
  111. WriteLn(f, '</seealso>');
  112. end;
  113. WriteLn(f, '</element>');
  114. end;
  115. end;
  116. procedure InitOptions;
  117. begin
  118. InputFiles := TStringList.Create;
  119. DescrFiles := TStringList.Create;
  120. end;
  121. procedure FreeOptions;
  122. begin
  123. DescrFiles.Free;
  124. InputFiles.Free;
  125. end;
  126. procedure ParseOption(const s: String);
  127. procedure AddToFileList(List: TStringList; const FileName: String);
  128. var
  129. f: Text;
  130. s: String;
  131. begin
  132. if Copy(FileName, 1, 1) = '@' then
  133. begin
  134. Assign(f, Copy(FileName, 2, Length(FileName)));
  135. Reset(f);
  136. while not EOF(f) do
  137. begin
  138. ReadLn(f, s);
  139. List.Add(s);
  140. end;
  141. Close(f);
  142. end else
  143. List.Add(FileName);
  144. end;
  145. var
  146. i: Integer;
  147. Cmd, Arg: String;
  148. begin
  149. if (s = '-h') or (s = '--help') then
  150. CmdLineAction := actionHelp
  151. else if s = '--update' then
  152. UpdateMode := True
  153. else if s = '--disable-arguments' then
  154. DisableArguments := True
  155. else if s = '--disable-errors' then
  156. DisableErrors := True
  157. else if s = '--disable-function-results' then
  158. DisableFunctionResults := True
  159. else if s = '--disable-seealso' then
  160. DisableSeealso := True
  161. else if s = '--disable-private' then
  162. DisablePrivate := True
  163. else if s = '--disable-protected' then
  164. begin
  165. DisableProtected := True;
  166. DisablePrivate :=True;
  167. end
  168. else if s = '--emitclassseparator' then
  169. EmitClassSeparator := True
  170. else
  171. begin
  172. i := Pos('=', s);
  173. if i > 0 then
  174. begin
  175. Cmd := Copy(s, 1, i - 1);
  176. Arg := Copy(s, i + 1, Length(s));
  177. end else
  178. begin
  179. Cmd := s;
  180. SetLength(Arg, 0);
  181. end;
  182. if (Cmd = '-i') or (Cmd = '--input') then
  183. AddToFileList(InputFiles, Arg)
  184. else if (Cmd = '-l') or (Cmd = '--lang') then
  185. DocLang := Arg
  186. else if (Cmd = '-o') or (Cmd = '--output') then
  187. OutputName := Arg
  188. else if Cmd = '--package' then
  189. PackageName := Arg
  190. else if Cmd = '--descr' then
  191. begin
  192. if FileExists(Arg) then
  193. DescrFiles.Add(Arg);
  194. end
  195. else
  196. WriteLn(StdErr, Format(SCmdLineInvalidOption, [s]));
  197. end;
  198. end;
  199. procedure ParseCommandLine;
  200. Const
  201. {$IFDEF Unix}
  202. MoFileTemplate = '/usr/local/share/locale/%s/LC_MESSAGES/makeskel.mo';
  203. {$ELSE}
  204. MoFileTemplate ='intl/makeskel.%s.mo';
  205. {$ENDIF}
  206. var
  207. MOFilename: string;
  208. i: Integer;
  209. begin
  210. DocLang:='';
  211. for i := 1 to ParamCount do
  212. ParseOption(ParamStr(i));
  213. If (DocLang<>'') then
  214. begin
  215. MOFilename:=Format(MOFileTemplate,[DocLang]);
  216. if FileExists(MOFilename) then
  217. gettext.TranslateResourceStrings(MoFileName)
  218. else
  219. writeln('NOTE: unable to find tranlation file ',MOFilename);
  220. // Translate internal documentation strings
  221. TranslateDocStrings(DocLang);
  222. end;
  223. end;
  224. var
  225. i: Integer;
  226. Module: TPasModule;
  227. begin
  228. InitOptions;
  229. ParseCommandLine;
  230. WriteLn(STitle);
  231. WriteLn(SCopyright);
  232. WriteLn;
  233. if CmdLineAction = actionHelp then
  234. WriteLn(SCmdLineHelp)
  235. else
  236. begin
  237. // Action is to create the XML skeleton
  238. if Length(PackageName) = 0 then
  239. begin
  240. WriteLn(SNoPackageNameProvided);
  241. Halt(2);
  242. end;
  243. if DescrFiles.IndexOf(OutputName)<>-1 then
  244. begin
  245. Writeln(SOutputMustNotBeDescr);
  246. Halt(3)
  247. end;
  248. Assign(f, OutputName);
  249. Rewrite(f);
  250. WriteLn(f, '<?xml version="1.0" encoding="ISO8859-1"?>');
  251. WriteLn(f, '<fpdoc-descriptions>');
  252. WriteLn(f, '<package name="', PackageName, '">');
  253. // Process all source files
  254. for i := 0 to InputFiles.Count - 1 do
  255. begin
  256. Engine := TSkelEngine.Create;
  257. try
  258. try
  259. Engine.SetPackageName(PackageName);
  260. if UpdateMode then
  261. For I:=0 to DescrFiles.Count-1 do
  262. Engine.AddDocFile(DescrFiles[i]);
  263. Module := ParseSource(Engine, InputFiles[i], OSTarget, CPUTarget);
  264. WriteLn(f, '</module> <!-- ', Module.Name, ' -->');
  265. except
  266. on e:EFileNotFoundError do
  267. begin
  268. Writeln(StdErr,' file ', e.message, ' not found');
  269. close(f);
  270. Halt(1);
  271. end;
  272. end;
  273. finally
  274. Engine.Free;
  275. end;
  276. end;
  277. WriteLn(f, '</package>');
  278. WriteLn(f, '</fpdoc-descriptions>');
  279. Close(f);
  280. end;
  281. FreeOptions;
  282. WriteLn(SDone);
  283. end.
  284. {
  285. $Log$
  286. Revision 1.10 2004-08-28 18:15:14 michael
  287. + Check whether outputfile not in inputfilenames
  288. Revision 1.9 2004/08/28 18:04:06 michael
  289. + Added update mode
  290. Revision 1.8 2004/08/25 07:16:43 michael
  291. + Improved translation handling
  292. Revision 1.7 2004/08/24 14:48:25 michael
  293. + Translate now called correctly...
  294. Revision 1.6 2004/05/01 20:13:40 marco
  295. * got fed up with exceptions on file not found. Fileresolver now raises a
  296. EFileNotFound error, and makeskel catches and exists gracefully
  297. Revision 1.5 2003/11/28 12:51:37 sg
  298. * Added support for source references
  299. Revision 1.4 2003/09/02 13:26:47 mattias
  300. MG: makeskel now ignores missing translation file
  301. Revision 1.3 2003/05/07 16:31:32 sg
  302. * Fixed a severe memory corruption problem on termination
  303. Revision 1.2 2003/03/28 13:01:36 michael
  304. + Patch from Charlie/iNQ to work with new scanner/parser
  305. Revision 1.1 2003/03/17 23:03:20 michael
  306. + Initial import in CVS
  307. }