fpclasschart.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. {
  2. FPClass chart - Free Pascal class chart generation tool
  3. Copyright (c) 2008 - Michael Van Canneyt, [email protected]
  4. * Free Pascal class chart generation tool
  5. See the file COPYING, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. }
  11. {$mode objfpc}
  12. {$h+}
  13. program fpclasschart;
  14. uses
  15. SysUtils, Classes, Typinfo, Gettext, dom, xmlread,
  16. dGlobals, PasTree, PParser,PScanner, xmlwrite, fpdocclasstree;
  17. resourcestring
  18. STitle = 'fpClassTree - Create class tree from pascal sources';
  19. SVersion = 'Version %s [%s]';
  20. SCopyright = '(c) 2008 - Michael Van Canneyt, [email protected]';
  21. SCmdLineHelp = 'See documentation for usage.';
  22. SCmdLineInvalidOption = 'Ignoring unknown option "%s"';
  23. SDone = 'Done.';
  24. SSkipMerge = 'Cannot merge %s into %s tree.';
  25. SErrNoSuchMergeFile = 'Merge file %s does not exist.';
  26. SMergedFile = 'Merged %d classes from file %s.';
  27. SClassesAdded = 'Added %d classes from %d files.';
  28. type
  29. { TClassTreeEngine }
  30. TClassTreeEngine = class(TFPDocEngine)
  31. Private
  32. FTree : TClassTreeBuilder;
  33. FObjects : TStringList;
  34. public
  35. Constructor Create(AClassTree : TXMLDocument; AObjectKind : TPasObjKind);
  36. Destructor Destroy; override;
  37. function CreateElement(AClass: TPTreeElement; const AName: String;
  38. AParent: TPasElement; AVisibility :TPasMemberVisibility;
  39. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement; override;
  40. end;
  41. { TClassChartFormatter }
  42. TClassMode = (cmNormal,cmSubClass,cmheadClass,cmFirstClass);
  43. TClassChartFormatter = Class (TObject)
  44. private
  45. FClassMode: TClassMode;
  46. FClassTree: TXMLDocument;
  47. FCurrentColCount: Integer;
  48. FCurrentRowCount: Integer;
  49. FFileName: String;
  50. FLargeHeadClassObjects: TStrings;
  51. FLevel: Integer;
  52. FMaxObjectsPerColumn: Integer;
  53. FStartColumnObjects: TStrings;
  54. Protected
  55. procedure FirstClass(E : TDomElement); virtual;
  56. procedure DoEmitClass(E : TDomElement); virtual;
  57. procedure DoHeadClass(E: TDomElement); virtual;
  58. procedure DoNextColumn(E: TDomElement); virtual;
  59. procedure EndSubClass(E: TDomElement; HasSiblings : Boolean); virtual;
  60. procedure StartSubClass(E: TDomElement); virtual;
  61. Procedure StartChart; virtual;
  62. Procedure EndChart; virtual;
  63. procedure EmitClass(E : TDomElement; HasSiblings : Boolean);
  64. Public
  65. Constructor Create (AXML : TXMLDocument); virtual;
  66. Destructor Destroy; override;
  67. Procedure CreateChart;
  68. Property CurrentColCount : Integer Read FCurrentColCount;
  69. Property CurrentRowCount : Integer Read FCurrentRowCount;
  70. Property ClassTree : TXMLDocument Read FClassTree;
  71. Property Level : Integer Read FLevel Write FLevel;
  72. Property ClassMode : TClassMode Read FClassMode;
  73. Published
  74. Property FileName : String Read FFileName Write FFilename;
  75. Property StartColumnObjects : TStrings Read FStartColumnObjects;
  76. Property LargeHeadClassObjects : TStrings Read FLargeHeadClassObjects;
  77. Property MaxObjectsPerColumn : Integer Read FMaxObjectsPerColumn Write FMaxObjectsPerColumn;
  78. end;
  79. { TClassTreeBuilder }
  80. { TChartFormatter }
  81. constructor TClassChartFormatter.Create(AXML: TXMLDocument);
  82. begin
  83. FClassTree:=AXML;
  84. MaxObjectsPerColumn:=60;
  85. FStartColumnObjects:=TStringList.Create;
  86. FLargeHeadClassObjects:=TStringList.Create;
  87. FLargeHeadClassObjects.Add('TPersistent');
  88. FLargeHeadClassObjects.Add('TComponent');
  89. end;
  90. destructor TClassChartFormatter.Destroy;
  91. begin
  92. FreeAndNil(FStartColumnObjects);
  93. FreeAndNil(FLargeHeadClassObjects);
  94. Inherited;
  95. end;
  96. procedure TClassChartFormatter.CreateChart;
  97. Var
  98. N : TDomNode;
  99. E : TDomElement;
  100. I : Integer;
  101. L : TFPList;
  102. begin
  103. (FStartColumnObjects as TStringList).Sorted:=False;
  104. (FLargeHeadClassObjects as TStringList).Sorted:=False;
  105. StartChart;
  106. try
  107. N:=FClassTree.DocumentElement.FirstChild;
  108. FCurrentColCount:=0;
  109. FCurrentRowCount:=0;
  110. FLevel:=0;
  111. L:=TFPList.Create;
  112. try
  113. While (N<>nil) do
  114. begin
  115. If (N.NodeType=ELEMENT_NODE) then
  116. L.Add(N);
  117. N:=N.NextSibling;
  118. end;
  119. If (L.Count>0) then
  120. begin
  121. FirstClass(TDomElement(L[0]));
  122. For I:=0 to L.Count-1 do
  123. EmitClass(TDomElement(L[i]),I<L.Count-1);
  124. end;
  125. finally
  126. L.Free;
  127. end;
  128. L:=TFPList.Create;
  129. try
  130. For I:=0 to FLargeHeadClassObjects.Count-1 do
  131. If Assigned(FLargeHeadClassObjects.Objects[i]) then
  132. L.Add(FLargeHeadClassObjects.Objects[i]);
  133. FLargeHeadClassObjects.Clear;
  134. For I:=0 to L.Count-1 do
  135. begin
  136. E:= TDomElement(L[i]);
  137. DoHeadClass(E);
  138. EmitClass(E,I<L.Count-1);
  139. end;
  140. finally
  141. L.Free;
  142. end;
  143. finally
  144. EndChart;
  145. end;
  146. end;
  147. procedure TClassChartFormatter.FirstClass(E : TDomElement);
  148. begin
  149. FClassMode:=cmFirstClass;
  150. end;
  151. procedure TClassChartFormatter.DoEmitClass(E : TDomElement);
  152. begin
  153. //Reset
  154. FClassMode:=cmNormal;
  155. end;
  156. procedure TClassChartFormatter.DoHeadClass(E : TDomElement);
  157. begin
  158. DoNextColumn(E);
  159. FClassMode:=cmHeadClass;
  160. // Do nothing
  161. end;
  162. procedure TClassChartFormatter.StartSubClass(E : TDomElement);
  163. begin
  164. FClassMode:=cmSubClass;
  165. end;
  166. procedure TClassChartFormatter.EndSubClass(E : TDomElement; HasSiblings : Boolean);
  167. begin
  168. FClassMode:=cmNormal;
  169. end;
  170. procedure TClassChartFormatter.DoNextColumn(E : TDomElement);
  171. begin
  172. Inc(FCurrentColCount);
  173. FCurrentRowCount:=0;
  174. end;
  175. procedure TClassChartFormatter.StartChart;
  176. begin
  177. // Do nothing
  178. end;
  179. procedure TClassChartFormatter.EndChart;
  180. begin
  181. // Do nothing
  182. end;
  183. procedure TClassChartFormatter.EmitClass(E : TDomElement; HasSiblings: Boolean);
  184. Var
  185. DidSub : Boolean;
  186. N : TDomNode;
  187. I : Integer;
  188. L : TFPList;
  189. begin
  190. Inc(Flevel);
  191. try
  192. I:=FStartColumnObjects.IndexOf(E.NodeName);
  193. if (-1<>I) or ((FCurrentRowCount>MaxObjectsPerColumn) and (FLevel=2)) then
  194. DoNextColumn(E)
  195. else
  196. begin
  197. I:=FLargeHeadClassObjects.IndexOf(E.NodeName);
  198. if (-1<>I) then
  199. begin
  200. FLargeHeadClassObjects.Objects[i]:=E;
  201. Exit; // Must be picked up later.
  202. end;
  203. end;
  204. DoEmitClass(E);
  205. N:=E.FirstChild;
  206. DidSub:=False;
  207. L:=TFPList.Create;
  208. try
  209. While (N<>Nil) do
  210. begin
  211. if (N.NodeType=ELEMENT_NODE) then
  212. L.Add(N);
  213. N:=N.NextSibling;
  214. end;
  215. If L.Count>0 then
  216. begin
  217. StartSubClass(TDomElement(L[0]));
  218. For I:=0 to L.Count-1 do
  219. begin
  220. EmitClass(TDomElement(L[i]),I<L.Count-1);
  221. FClassMode:=cmNormal;
  222. end;
  223. EndSubClass(E,HasSiblings);
  224. end;
  225. Finally
  226. L.Free;
  227. end;
  228. Inc(FCurrentRowCount);
  229. finally
  230. Dec(Flevel);
  231. end;
  232. end;
  233. Type
  234. { TPostScriptClassChartFormatter }
  235. TPostScriptClassChartFormatter = Class(TClassChartFormatter)
  236. FFile : Text;
  237. FMode : TClassMode;
  238. FIndent : Integer;
  239. Procedure EmitLine(S : String);
  240. Protected
  241. procedure DoEmitClass(E : TDomElement); override;
  242. procedure DoNextColumn(E: TDomElement); override;
  243. procedure DoHeadClass(E: TDomElement); override;
  244. procedure StartSubClass(E: TDomElement); override;
  245. procedure EndSubClass(E: TDomElement; HasSiblings : Boolean); override;
  246. Procedure StartChart; override;
  247. Procedure EndChart; override;
  248. end;
  249. { TPostScriptClassChartFormatter }
  250. procedure TPostScriptClassChartFormatter.EmitLine(S: String);
  251. begin
  252. Writeln(FFile,StringofChar(' ',Findent*2),S);
  253. end;
  254. procedure TPostScriptClassChartFormatter.DoEmitClass(E: TDomElement);
  255. begin
  256. Case ClassMode of
  257. cmFirstClass : EmitLine(Format('(%s) Ready drawlargebox',[E.NodeName]));
  258. cmNormal : EmitLine(Format('(%s) Ready newclass',[E.NodeName]));
  259. cmSubClass : EmitLine(Format('(%s) Ready newchildclass',[E.NodeName]));
  260. cmHeadClass : EmitLine(Format('(%s) Ready newlargeheadclass',[E.NodeName]));
  261. end;
  262. end;
  263. procedure TPostScriptClassChartFormatter.DoNextColumn(E: TDomElement);
  264. begin
  265. Inherited;
  266. FIndent:=0;
  267. EmitLine('newcolumn');
  268. end;
  269. procedure TPostScriptClassChartFormatter.DoHeadClass(E: TDomElement);
  270. begin
  271. // DoNextColumn(E);
  272. inherited DoHeadClass(E);
  273. end;
  274. procedure TPostScriptClassChartFormatter.EndSubClass(E: TDomElement; HasSiblings : Boolean);
  275. begin
  276. if HasSiblings then
  277. EmitLine('onelevelback')
  278. else
  279. EmitLine('onelevelbackempty');
  280. If FIndent>0 then
  281. Dec(Findent);
  282. end;
  283. procedure TPostScriptClassChartFormatter.StartSubClass(E: TDomElement);
  284. begin
  285. inherited StartSubClass(E);
  286. Inc(Findent);
  287. end;
  288. procedure TPostScriptClassChartFormatter.StartChart;
  289. begin
  290. Assign(FFile,FileName);
  291. Rewrite(FFile);
  292. end;
  293. procedure TPostScriptClassChartFormatter.EndChart;
  294. begin
  295. Close(FFile);
  296. end;
  297. type
  298. { TGraphVizClassChartFormatter }
  299. TGraphVizClassChartFormatter = class(TClassChartFormatter)
  300. FFile : Text;
  301. FMode : TClassMode;
  302. FIndent : integer;
  303. Procedure EmitLine(S : string);
  304. Protected
  305. procedure DoEmitClass(E : TDomElement); override;
  306. procedure DoNextColumn(E: TDomElement); override;
  307. procedure DoHeadClass(E: TDomElement); override;
  308. procedure StartSubClass(E: TDomElement); override;
  309. procedure EndSubClass(E: TDomElement; HasSiblings : Boolean); override;
  310. Procedure StartChart; override;
  311. Procedure EndChart; override;
  312. end;
  313. { TGraphVizClassChartFormatter }
  314. procedure TGraphVizClassChartFormatter.EmitLine(S: String);
  315. begin
  316. Writeln(FFile,StringofChar(' ',Findent*2),S);
  317. end;
  318. procedure TGraphVizClassChartFormatter.DoEmitClass(E: TDomElement);
  319. begin
  320. Case ClassMode of
  321. cmFirstClass : EmitLine(Format('%s -> %s', [E.ParentNode.NodeName, E.NodeName]));
  322. cmNormal : EmitLine(Format('%s -> %s', [E.ParentNode.NodeName, E.NodeName]));
  323. cmSubClass : EmitLine(Format('%s -> %s', [E.ParentNode.NodeName, E.NodeName]));
  324. cmHeadClass : EmitLine(Format('%s -> %s', [E.ParentNode.NodeName, E.NodeName]));
  325. end;
  326. end;
  327. procedure TGraphVizClassChartFormatter.DoNextColumn(E: TDomElement);
  328. begin
  329. Inherited;
  330. FIndent:=0;
  331. end;
  332. procedure TGraphVizClassChartFormatter.DoHeadClass(E: TDomElement);
  333. begin
  334. // DoNextColumn(E);
  335. inherited DoHeadClass(E);
  336. end;
  337. procedure TGraphVizClassChartFormatter.EndSubClass(E: TDomElement; HasSiblings : Boolean);
  338. begin
  339. If FIndent>0 then
  340. Dec(Findent);
  341. end;
  342. procedure TGraphVizClassChartFormatter.StartSubClass(E: TDomElement);
  343. begin
  344. inherited StartSubClass(E);
  345. Inc(Findent);
  346. end;
  347. procedure TGraphVizClassChartFormatter.StartChart;
  348. begin
  349. Assign(FFile,FileName);
  350. Rewrite(FFile);
  351. EmitLine('digraph G {');
  352. end;
  353. procedure TGraphVizClassChartFormatter.EndChart;
  354. begin
  355. EmitLine('}');
  356. Close(FFile);
  357. end;
  358. Type
  359. TOutputFormat = (ofXML,ofPostscript, ofGraphViz);
  360. Var
  361. OutputFormat : TOutputFormat = ofXML;
  362. const
  363. OSTarget: String = {$I %FPCTARGETOS%};
  364. CPUTarget: String = {$I %FPCTARGETCPU%};
  365. FPCVersion: String = {$I %FPCVERSION%};
  366. FPCDate: String = {$I %FPCDATE%};
  367. function TClassTreeEngine.CreateElement(AClass: TPTreeElement; const AName: String;
  368. AParent: TPasElement; AVisibility : TPasMemberVisibility;
  369. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  370. Var
  371. DN : TDocNode;
  372. begin
  373. Result := AClass.Create(AName, AParent);
  374. Result.Visibility:=AVisibility;
  375. if AClass.InheritsFrom(TPasModule) then
  376. CurModule := TPasModule(Result);
  377. If AClass.InheritsFrom(TPasClassType) then
  378. begin
  379. FObjects.AddObject(AName,Result);
  380. // Writeln('Added : ',AName);
  381. end;
  382. end;
  383. Constructor TClassTreeEngine.Create(AClassTree : TXMLDocument; AObjectKind : TPasObjKind);
  384. begin
  385. FPackage:=TPasPackage.Create('dummy',Nil);
  386. FTree:=TClassTreeBuilder.Create(FPackage,AObjectKind);
  387. FObjects:=TStringList.Create;
  388. Inherited Create;
  389. end;
  390. destructor TClassTreeEngine.Destroy;
  391. begin
  392. FreeAndNil(FTree);
  393. FreeAndNil(FPackage);
  394. FreeAndNil(FObjects);
  395. inherited Destroy;
  396. end;
  397. { ---------------------------------------------------------------------
  398. Main program. Document all units.
  399. ---------------------------------------------------------------------}
  400. Function MergeNodes(Doc : TXMLDocument;Dest,Source : TDomElement) : Integer;
  401. Var
  402. N : TDomNode;
  403. S,E : TDomElement;
  404. begin
  405. N:=Source.FirstChild;
  406. While (N<>Nil) do
  407. begin
  408. if (N.NodeType=ELEMENT_NODE) then
  409. begin
  410. S:=N as TDomElement;
  411. E:=Dest.FindNode(N.NodeName) as TDomElement;
  412. If (E=Nil) then
  413. begin
  414. E:=Doc.CreateElement(N.NodeName);
  415. If S['unit']<>'' then
  416. E['Unit']:=S['unit'];
  417. Dest.AppendChild(E);
  418. Inc(Result);
  419. end;
  420. Result:=Result+MergeNodes(Doc,E,S);
  421. end;
  422. N:=N.NextSibling;
  423. end;
  424. end;
  425. Function MergeTrees (Dest,Source : TXMLDocument) : Integer;
  426. Var
  427. S,D : TDomElement;
  428. Count : Integer;
  429. begin
  430. Result:=0;
  431. D:=Dest.DocumentElement;
  432. S:=Source.DocumentElement;
  433. If (S.NodeName=D.NodeName) then
  434. Result:=MergeNodes(Dest,D,S)
  435. else
  436. Writeln(StdErr,Format(SSkipMerge,[S.NodeName,D.NodeName]));
  437. end;
  438. Function AnalyseFiles(Const AOutputName : String; InputFiles,MergeFiles : TStrings; AObjectKind : TPasObjKind) : String;
  439. Var
  440. XML,XML2 : TXMLDocument;
  441. I,ACount : Integer;
  442. Engine: TClassTreeEngine;
  443. begin
  444. XML:=TXMLDocument.Create;
  445. Try
  446. //XML.
  447. XML.AppendChild(XML.CreateElement(ObjKindNames[AObjectKind]));
  448. For I:=0 to MergeFiles.Count-1 do
  449. begin
  450. XMl2:=TXMLDocument.Create;
  451. ReadXMLFile(XML2,MergeFiles[i]);
  452. try
  453. ACount:=MergeTrees(XML,XML2);
  454. WriteLn(StdErr,Format(SMergedFile,[ACount,MergeFiles[i]]));
  455. Finally
  456. FreeAndNil(XML2);
  457. end;
  458. end;
  459. ACount:=0;
  460. For I:=0 to InputFiles.Count-1 do
  461. begin
  462. Engine := TClassTreeEngine.Create(XML,AObjectKind);
  463. Try
  464. ParseSource(Engine,InputFiles[I],OSTarget,CPUTarget);
  465. ACount:=ACount+Engine.Ftree.BuildTree(Engine.FObjects);
  466. Finally
  467. FreeAndNil(Engine);
  468. end;
  469. end;
  470. Case OutputFormat of
  471. ofXML :
  472. WriteXMlFile(XML,AOutputName);
  473. ofPostScript :
  474. With TPostScriptClassChartFormatter.Create(XML) do
  475. try
  476. FileName:=AOutputName;
  477. CreateChart;
  478. finally
  479. Free;
  480. end;
  481. ofGraphViz :
  482. With TGraphVizClassChartFormatter.Create(XML) do
  483. try
  484. FileName:=AOutputName;
  485. CreateChart;
  486. finally
  487. Free;
  488. end;
  489. end;
  490. Writeln(StdErr,Format(SClassesAdded,[ACount,InputFiles.Count]));
  491. Finally
  492. XML.Free;
  493. end;
  494. end;
  495. { ---------------------------------------------------------------------
  496. Option management
  497. ---------------------------------------------------------------------}
  498. var
  499. cmdObjectKind : TPasObjKind;
  500. InputFiles,
  501. MergeFiles : TStringList;
  502. DocLang : String;
  503. PackageName,
  504. OutputName: String;
  505. procedure InitOptions;
  506. begin
  507. InputFiles := TStringList.Create;
  508. MergeFiles := TStringList.Create;
  509. end;
  510. procedure FreeOptions;
  511. begin
  512. MergeFiles.Free;
  513. InputFiles.Free;
  514. end;
  515. { ---------------------------------------------------------------------
  516. Usage
  517. ---------------------------------------------------------------------}
  518. Procedure Usage;
  519. begin
  520. Writeln('Usage : ',ExtractFileName(Paramstr(0)),' [options]');
  521. Writeln('Where [options] is one or more of :');
  522. Writeln(' --merge=filename Filename with object tree to merge.');
  523. Writeln(' --help Emit help.');
  524. Writeln(' --input=cmdline Input file to create skeleton for.');
  525. Writeln(' Use options are as for compiler.');
  526. Writeln(' --kind=objectkind Specify object kind. One of object, class, interface.');
  527. Writeln(' --lang=language Use selected language.');
  528. Writeln(' --output=filename Send output to file.');
  529. Writeln(' --format=name Kind of output to create: XML, PostScript, GraphViz.');
  530. end;
  531. procedure ParseOption(const s: String);
  532. procedure AddToFileList(List: TStringList; const FileName: String);
  533. var
  534. f: Text;
  535. s: String;
  536. begin
  537. if Copy(FileName, 1, 1) = '@' then
  538. begin
  539. Assign(f, Copy(FileName, 2, Length(FileName)));
  540. Reset(f);
  541. while not EOF(f) do
  542. begin
  543. ReadLn(f, s);
  544. List.Add(s);
  545. end;
  546. Close(f);
  547. end else
  548. List.Add(FileName);
  549. end;
  550. var
  551. i: Integer;
  552. Cmd, Arg: String;
  553. begin
  554. cmdObjectKind:=okClass;
  555. if (s = '-h') or (s = '--help') then
  556. begin
  557. Usage;
  558. Halt(0);
  559. end;
  560. i := Pos('=', s);
  561. if i > 0 then
  562. begin
  563. Cmd := Copy(s, 1, i - 1);
  564. Arg := Copy(s, i + 1, Length(s));
  565. end else
  566. begin
  567. Cmd := s;
  568. SetLength(Arg, 0);
  569. end;
  570. if (Cmd = '-i') or (Cmd = '--input') then
  571. AddToFileList(InputFiles, Arg)
  572. else if (Cmd = '-l') or (Cmd = '--lang') then
  573. DocLang := Arg
  574. else if (Cmd = '-o') or (Cmd = '--output') then
  575. OutputName := Arg
  576. else if (Cmd = '-k') or (Cmd = '--kind') then
  577. cmdObjectKind:=TPasObjKind(GetEnumValue(TypeInfo(TPasObjKind),'ok'+Arg))
  578. else if (Cmd = '-f') or (Cmd = '--format') then
  579. OutputFormat:=TOutputFormat(GetEnumValue(TypeInfo(TOutputFormat),'of'+Arg))
  580. else if Cmd = '--merge' then
  581. begin
  582. if FileExists(Arg) then
  583. MergeFiles.Add(Arg)
  584. else
  585. Writeln(StdErr,Format(SErrNoSuchMergeFile,[arg]));
  586. end
  587. else
  588. begin
  589. WriteLn(StdErr, Format(SCmdLineInvalidOption, [s]));
  590. Usage;
  591. Halt(1);
  592. end;
  593. end;
  594. Function ParseCommandLine : Integer;
  595. Const
  596. {$IFDEF Unix}
  597. MoFileTemplate = '/usr/local/share/locale/%s/LC_MESSAGES/makeskel.mo';
  598. {$ELSE}
  599. MoFileTemplate ='intl/makeskel.%s.mo';
  600. {$ENDIF}
  601. var
  602. MOFilename: string;
  603. i: Integer;
  604. begin
  605. Result:=0;
  606. if ParamCount=0 then
  607. begin
  608. Usage;
  609. Halt(0);
  610. end;
  611. DocLang:='';
  612. for i := 1 to ParamCount do
  613. ParseOption(ParamStr(i));
  614. If (DocLang<>'') then
  615. begin
  616. MOFilename:=Format(MOFileTemplate,[DocLang]);
  617. if FileExists(MOFilename) then
  618. gettext.TranslateResourceStrings(MoFileName)
  619. else
  620. writeln('NOTE: unable to find tranlation file ',MOFilename);
  621. // Translate internal documentation strings
  622. TranslateDocStrings(DocLang);
  623. end;
  624. end;
  625. { ---------------------------------------------------------------------
  626. Main Program
  627. ---------------------------------------------------------------------}
  628. Procedure Run;
  629. var
  630. E: Integer;
  631. begin
  632. WriteLn(STitle);
  633. WriteLn(Format(SVersion, [FPCVersion, FPCDate]));
  634. WriteLn(SCopyright);
  635. InitOptions;
  636. Try
  637. E:=ParseCommandLine;
  638. If E<>0 then
  639. Halt(E);
  640. WriteLn;
  641. AnalyseFiles(OutputName,InputFiles,MergeFiles,cmdObjectKind);
  642. WriteLn(StdErr,SDone);
  643. Finally
  644. FreeOptions;
  645. end;
  646. end;
  647. Begin
  648. Run;
  649. end.