ppuout.pp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820
  1. {
  2. Copyright (c) 2013 by Yury Sidorov and the FPC Development Team
  3. Base classes for a custom output of a PPU File
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************}
  16. unit ppuout;
  17. {$mode objfpc}{$H+}
  18. {$I+}
  19. interface
  20. uses SysUtils, cclasses, Classes;
  21. type
  22. TPpuDefType = (dtNone, dtUnit, dtObject, dtRecord, dtProc, dtField, dtProp, dtParam, dtVar,
  23. dtTypeRef, dtConst, dtProcType, dtEnum, dtSet);
  24. TPpuDef = class;
  25. TPpuContainerDef = class;
  26. TPpuUnitDef = class;
  27. { TPpuOutput }
  28. TPpuOutput = class
  29. private
  30. FOutFile: ^Text;
  31. FIndent: integer;
  32. FIndentSize: integer;
  33. FIndStr: string;
  34. FNoIndent: boolean;
  35. procedure SetIndent(AValue: integer);
  36. procedure SetIndentSize(AValue: integer);
  37. protected
  38. procedure WriteObjectStart(const AName: string; Def: TPpuDef = nil); virtual;
  39. procedure WriteObjectEnd(Def: TPpuDef = nil); virtual;
  40. procedure WriteArrayStart(const AName: string); virtual;
  41. procedure WriteArrayEnd; virtual;
  42. procedure WriteStr(const AName, AValue: string); virtual;
  43. procedure WriteInt(const AName: string; AValue: Int64); virtual;
  44. procedure WriteFloat(const AName: string; AValue: extended); virtual;
  45. procedure WriteBool(const AName: string; AValue: boolean); virtual;
  46. procedure WriteNull(const AName: string); virtual;
  47. public
  48. constructor Create(var OutFile: Text); virtual;
  49. destructor Destroy; override;
  50. procedure Write(const s: string);
  51. procedure WriteLn(const s: string = '');
  52. procedure IncI; virtual;
  53. procedure DecI; virtual;
  54. property Indent: integer read FIndent write SetIndent;
  55. property IndentSize: integer read FIndentSize write SetIndentSize;
  56. end;
  57. { TPpuRef }
  58. TPpuRef = class
  59. public
  60. UnitIndex: word;
  61. Id: cardinal;
  62. constructor Create;
  63. procedure Write(Output: TPpuOutput; const RefName: string);
  64. function IsCurUnit: boolean; inline;
  65. function IsNull: boolean; inline;
  66. end;
  67. TPpuFilePos = record
  68. FileIndex: dword;
  69. Line, Col: integer;
  70. end;
  71. TPpuDefVisibility = (dvPublic, dvPublished, dvProtected, dvPrivate);
  72. { TPpuDef }
  73. TPpuDef = class
  74. private
  75. FId: cardinal;
  76. FParent: TPpuContainerDef;
  77. FParentUnit: TPpuUnitDef;
  78. function GetDefTypeName: string;
  79. function GetId: cardinal;
  80. function GetParentUnit: TPpuUnitDef;
  81. procedure SetId(AValue: cardinal);
  82. procedure SetParent(AValue: TPpuContainerDef);
  83. protected
  84. procedure WriteDef(Output: TPpuOutput); virtual;
  85. public
  86. DefType: TPpuDefType;
  87. Name: string;
  88. FilePos: TPpuFilePos;
  89. // Symbol/definition reference
  90. Ref: TPpuRef;
  91. Visibility: TPpuDefVisibility;
  92. constructor Create(AParent: TPpuContainerDef); virtual; reintroduce;
  93. destructor Destroy; override;
  94. procedure Write(Output: TPpuOutput);
  95. function CanWrite: boolean; virtual;
  96. procedure SetSymId(AId: integer);
  97. property Parent: TPpuContainerDef read FParent write SetParent;
  98. property ParentUnit: TPpuUnitDef read GetParentUnit;
  99. property Id: cardinal read GetId write SetId;
  100. property DefTypeName: string read GetDefTypeName;
  101. end;
  102. { TPpuContainerDef }
  103. TPpuContainerDef = class(TPpuDef)
  104. private
  105. FItems: TList;
  106. function GetCount: integer;
  107. function GetItem(Index: Integer): TPpuDef;
  108. procedure SetItem(Index: Integer; AValue: TPpuDef);
  109. protected
  110. procedure WriteDef(Output: TPpuOutput); override;
  111. procedure BeforeWriteItems(Output: TPpuOutput); virtual;
  112. public
  113. ItemsName: string;
  114. constructor Create(AParent: TPpuContainerDef); override;
  115. destructor Destroy; override;
  116. function Add(Def: TPpuDef): integer;
  117. property Items[Index: Integer]: TPpuDef read GetItem write SetItem; default;
  118. property Count: integer read GetCount;
  119. end;
  120. { TPpuTypeRef }
  121. TPpuTypeRef = class(TPpuDef)
  122. protected
  123. procedure WriteDef(Output: TPpuOutput); override;
  124. public
  125. constructor Create(AParent: TPpuContainerDef); override;
  126. end;
  127. { TPpuUnitDef }
  128. TPpuUnitDef = class(TPpuContainerDef)
  129. private
  130. FIndexById: THashSet;
  131. protected
  132. procedure WriteDef(Output: TPpuOutput); override;
  133. public
  134. Version: cardinal;
  135. Crc, IntfCrc: cardinal;
  136. TargetOS, TargetCPU: string;
  137. UsedUnits: TPpuContainerDef;
  138. RefUnits: array of string;
  139. SourceFiles: TPpuContainerDef;
  140. constructor Create(AParent: TPpuContainerDef); override;
  141. destructor Destroy; override;
  142. function FindById(AId: integer; FindSym: boolean = False): TPpuDef;
  143. end;
  144. { TPpuSrcFile }
  145. TPpuSrcFile = class(TPpuDef)
  146. protected
  147. procedure WriteDef(Output: TPpuOutput); override;
  148. public
  149. FileTime: TDateTime;
  150. end;
  151. TPpuProcOption = (poProcedure, poFunction, poConstructor, poDestructor, poOperator,
  152. poClassMethod, poVirtual, poAbstract, poOverriding, poOverload, poInline);
  153. TPpuProcOptions = set of TPpuProcOption;
  154. { TPpuProcDef }
  155. TPpuProcDef = class(TPpuContainerDef)
  156. protected
  157. procedure BeforeWriteItems(Output: TPpuOutput); override;
  158. public
  159. ReturnType: TPpuRef;
  160. Options: TPpuProcOptions;
  161. constructor Create(AParent: TPpuContainerDef); override;
  162. destructor Destroy; override;
  163. end;
  164. { TPpuProcTypeDef }
  165. TPpuProcTypeDef = class(TPpuProcDef)
  166. public
  167. constructor Create(AParent: TPpuContainerDef); override;
  168. end;
  169. { TPpuVarDef }
  170. TPpuVarDef = class(TPpuDef)
  171. protected
  172. procedure WriteDef(Output: TPpuOutput); override;
  173. public
  174. VarType: TPpuRef;
  175. constructor Create(AParent: TPpuContainerDef); override;
  176. destructor Destroy; override;
  177. end;
  178. TPpuParamSpez = (psValue, psVar, psOut, psConst, psConstRef, psHidden);
  179. { TPpuParamDef }
  180. TPpuParamDef = class(TPpuVarDef)
  181. protected
  182. procedure WriteDef(Output: TPpuOutput); override;
  183. public
  184. Spez: TPpuParamSpez;
  185. constructor Create(AParent: TPpuContainerDef); override;
  186. function CanWrite: boolean; override;
  187. end;
  188. TPpuObjType = (otUnknown, otClass, otObject, otInterface, otHelper);
  189. TPpuObjOption = (ooIsAbstract);
  190. TPpuObjOptions = set of TPpuObjOption;
  191. { TPpuObjectDef }
  192. TPpuObjectDef = class(TPpuContainerDef)
  193. protected
  194. procedure BeforeWriteItems(Output: TPpuOutput); override;
  195. public
  196. ObjType: TPpuObjType;
  197. Ancestor: TPpuRef;
  198. Options: TPpuObjOptions;
  199. constructor Create(AParent: TPpuContainerDef); override;
  200. destructor Destroy; override;
  201. function CanWrite: boolean; override;
  202. end;
  203. { TPpuFieldDef }
  204. TPpuFieldDef = class(TPpuVarDef)
  205. public
  206. constructor Create(AParent: TPpuContainerDef); override;
  207. end;
  208. implementation
  209. const
  210. DefTypeNames: array[TPpuDefType] of string =
  211. ('', 'unit', 'obj', 'rec', 'proc', 'field', 'prop', 'param', 'var',
  212. 'type', 'const', 'proctype', 'enum', 'set');
  213. ProcOptionNames: array[TPpuProcOption] of string =
  214. ('procedure', 'function', 'constructor', 'destructor', 'operator',
  215. 'classmethod', 'virtual', 'abstract', 'overriding', 'overload', 'inline');
  216. DefVisibilityNames: array[TPpuDefVisibility] of string =
  217. ('public', 'published', 'protected', 'private');
  218. ParamSpezNames: array[TPpuParamSpez] of string =
  219. ('value', 'var', 'out', 'const', 'constref', '');
  220. ObjTypeNames: array[TPpuObjType] of string =
  221. ('', 'class', 'object', 'interface', 'helper');
  222. ObjOptionNames: array[TPpuObjOption] of string =
  223. ('abstract');
  224. SymIdBit = $80000000;
  225. InvalidId = cardinal(-1);
  226. InvalidUnit = word(-1);
  227. function IsSymId(Id: cardinal): boolean; inline;
  228. begin
  229. Result:=Id and SymIdBit <> 0;
  230. end;
  231. { TPpuTypeRef }
  232. procedure TPpuTypeRef.WriteDef(Output: TPpuOutput);
  233. begin
  234. inherited WriteDef(Output);
  235. Ref.Write(Output, 'TypeRef');
  236. end;
  237. constructor TPpuTypeRef.Create(AParent: TPpuContainerDef);
  238. begin
  239. inherited Create(AParent);
  240. DefType:=dtTypeRef;
  241. end;
  242. { TPpuFieldDef }
  243. constructor TPpuFieldDef.Create(AParent: TPpuContainerDef);
  244. begin
  245. inherited Create(AParent);
  246. DefType:=dtField;
  247. end;
  248. { TPpuParamDef }
  249. procedure TPpuParamDef.WriteDef(Output: TPpuOutput);
  250. begin
  251. inherited WriteDef(Output);
  252. if Spez <> psValue then
  253. Output.WriteStr('Spez', ParamSpezNames[Spez]);
  254. end;
  255. constructor TPpuParamDef.Create(AParent: TPpuContainerDef);
  256. begin
  257. inherited Create(AParent);
  258. DefType:=dtParam;
  259. Spez:=psValue;
  260. end;
  261. function TPpuParamDef.CanWrite: boolean;
  262. begin
  263. Result:=Spez <> psHidden;
  264. end;
  265. { TPpuVarDef }
  266. procedure TPpuVarDef.WriteDef(Output: TPpuOutput);
  267. begin
  268. inherited WriteDef(Output);
  269. VarType.Write(Output, 'VarType');
  270. end;
  271. constructor TPpuVarDef.Create(AParent: TPpuContainerDef);
  272. begin
  273. inherited Create(AParent);
  274. DefType:=dtVar;
  275. VarType:=TPpuRef.Create;
  276. end;
  277. destructor TPpuVarDef.Destroy;
  278. begin
  279. VarType.Free;
  280. inherited Destroy;
  281. end;
  282. { TPpuObjectDef }
  283. procedure TPpuObjectDef.BeforeWriteItems(Output: TPpuOutput);
  284. var
  285. opt: TPpuObjOption;
  286. begin
  287. inherited BeforeWriteItems(Output);
  288. if Options <> [] then begin
  289. Output.WriteArrayStart('Options');
  290. for opt:=Low(opt) to High(opt) do
  291. if opt in Options then
  292. Output.WriteStr('', ObjOptionNames[opt]);
  293. Output.WriteArrayEnd;
  294. end;
  295. Output.WriteStr('ObjType', ObjTypeNames[ObjType]);
  296. Ancestor.Write(Output, 'Ancestor');
  297. end;
  298. constructor TPpuObjectDef.Create(AParent: TPpuContainerDef);
  299. begin
  300. inherited Create(AParent);
  301. DefType:=dtObject;
  302. ItemsName:='Fields';
  303. ObjType:=otUnknown;
  304. Ancestor:=TPpuRef.Create;
  305. end;
  306. destructor TPpuObjectDef.Destroy;
  307. begin
  308. Ancestor.Free;
  309. inherited Destroy;
  310. end;
  311. function TPpuObjectDef.CanWrite: boolean;
  312. begin
  313. Result:=ObjType <> otUnknown;
  314. end;
  315. { TPpuRef }
  316. constructor TPpuRef.Create;
  317. begin
  318. UnitIndex:=InvalidUnit;
  319. Id:=InvalidId;
  320. end;
  321. procedure TPpuRef.Write(Output: TPpuOutput; const RefName: string);
  322. begin
  323. with Output do
  324. if IsNull then
  325. WriteNull(RefName)
  326. else begin
  327. WriteObjectStart(RefName);
  328. if not IsCurUnit then
  329. WriteInt('Unit', UnitIndex);
  330. WriteInt('Id', Id);
  331. WriteObjectEnd;
  332. end;
  333. end;
  334. function TPpuRef.IsCurUnit: boolean;
  335. begin
  336. Result:=UnitIndex = InvalidUnit;
  337. end;
  338. function TPpuRef.IsNull: boolean;
  339. begin
  340. Result:=Id = InvalidId;
  341. end;
  342. { TPpuProcTypeDef }
  343. constructor TPpuProcTypeDef.Create(AParent: TPpuContainerDef);
  344. begin
  345. inherited Create(AParent);
  346. DefType:=dtProcType;
  347. end;
  348. { TPpuProcDef }
  349. procedure TPpuProcDef.BeforeWriteItems(Output: TPpuOutput);
  350. var
  351. opt: TPpuProcOption;
  352. begin
  353. inherited BeforeWriteItems(Output);
  354. if Options <> [] then begin
  355. Output.WriteArrayStart('Options');
  356. for opt:=Low(opt) to High(opt) do
  357. if opt in Options then
  358. Output.WriteStr('', ProcOptionNames[opt]);
  359. Output.WriteArrayEnd;
  360. end;
  361. if Options*[poProcedure, poDestructor] = [] then
  362. ReturnType.Write(Output, 'RetType');
  363. end;
  364. constructor TPpuProcDef.Create(AParent: TPpuContainerDef);
  365. begin
  366. inherited Create(AParent);
  367. DefType:=dtProc;
  368. ItemsName:='Params';
  369. ReturnType:=TPpuRef.Create;
  370. end;
  371. destructor TPpuProcDef.Destroy;
  372. begin
  373. ReturnType.Free;
  374. inherited Destroy;
  375. end;
  376. { TPpuSrcFile }
  377. procedure TPpuSrcFile.WriteDef(Output: TPpuOutput);
  378. begin
  379. inherited WriteDef(Output);
  380. Output.WriteStr('Time', FormatDateTime('yyyy"-"mm"-"dd hh":"nn":"ss', FileTime));
  381. end;
  382. { TPpuOutput }
  383. procedure TPpuOutput.SetIndent(AValue: integer);
  384. begin
  385. if FIndent=AValue then Exit;
  386. FIndent:=AValue;
  387. if FIndent < 0 then
  388. FIndent:=0;
  389. SetLength(FIndStr, FIndent*IndentSize);
  390. if FIndent > 0 then
  391. FillChar(FIndStr[1], FIndent*IndentSize, ' ');
  392. end;
  393. procedure TPpuOutput.SetIndentSize(AValue: integer);
  394. begin
  395. if FIndentSize=AValue then Exit;
  396. FIndentSize:=AValue;
  397. end;
  398. procedure TPpuOutput.WriteStr(const AName, AValue: string);
  399. begin
  400. end;
  401. procedure TPpuOutput.WriteInt(const AName: string; AValue: Int64);
  402. begin
  403. WriteStr(AName, IntToStr(AValue));
  404. end;
  405. procedure TPpuOutput.WriteFloat(const AName: string; AValue: extended);
  406. var
  407. s: string;
  408. begin
  409. Str(AValue, s);
  410. WriteStr(AName, s);
  411. end;
  412. procedure TPpuOutput.WriteBool(const AName: string; AValue: boolean);
  413. begin
  414. if AValue then
  415. WriteStr(AName, '1')
  416. else
  417. WriteStr(AName, '0');
  418. end;
  419. procedure TPpuOutput.WriteNull(const AName: string);
  420. begin
  421. WriteStr(AName, '');
  422. end;
  423. procedure TPpuOutput.WriteArrayStart(const AName: string);
  424. begin
  425. IncI;
  426. end;
  427. procedure TPpuOutput.WriteArrayEnd;
  428. begin
  429. DecI;
  430. end;
  431. procedure TPpuOutput.WriteObjectStart(const AName: string; Def: TPpuDef);
  432. begin
  433. IncI;
  434. if Def = nil then
  435. exit;
  436. if Def.DefType <> dtNone then
  437. WriteStr('Type', Def.DefTypeName);
  438. if Def.Name <> '' then
  439. WriteStr('Name', Def.Name);
  440. end;
  441. procedure TPpuOutput.WriteObjectEnd(Def: TPpuDef);
  442. begin
  443. DecI;
  444. end;
  445. constructor TPpuOutput.Create(var OutFile: Text);
  446. begin
  447. FOutFile:=@OutFile;
  448. FIndentSize:=2;
  449. end;
  450. destructor TPpuOutput.Destroy;
  451. begin
  452. inherited Destroy;
  453. end;
  454. procedure TPpuOutput.Write(const s: string);
  455. begin
  456. if not FNoIndent then
  457. System.Write(FOutFile^, FIndStr);
  458. System.Write(FOutFile^, s);
  459. FNoIndent:=True;
  460. end;
  461. procedure TPpuOutput.WriteLn(const s: string);
  462. begin
  463. Self.Write(s + LineEnding);
  464. FNoIndent:=False;
  465. end;
  466. procedure TPpuOutput.IncI;
  467. begin
  468. Indent:=Indent + 1;
  469. end;
  470. procedure TPpuOutput.DecI;
  471. begin
  472. Indent:=Indent - 1;
  473. end;
  474. { TPpuUnitDef }
  475. procedure TPpuUnitDef.WriteDef(Output: TPpuOutput);
  476. var
  477. i: integer;
  478. begin
  479. with Output do begin
  480. if Version <> 0 then
  481. WriteInt('Version', Version);
  482. if TargetCPU <> '' then
  483. WriteStr('TargetCPU', TargetCPU);
  484. if TargetOS <> '' then
  485. WriteStr('TargetOS', TargetOS);
  486. if Crc <> 0 then
  487. WriteStr('CRC', hexStr(Crc, 8));
  488. if IntfCrc <> 0 then
  489. WriteStr('InterfaceCRC', hexStr(IntfCrc, 8));
  490. UsedUnits.WriteDef(Output);
  491. if Length(RefUnits) > 0 then begin
  492. WriteArrayStart('Units');
  493. for i:=0 to High(RefUnits) do
  494. WriteStr('', RefUnits[i]);
  495. WriteArrayEnd;
  496. end;
  497. SourceFiles.WriteDef(Output);
  498. end;
  499. inherited WriteDef(Output);
  500. end;
  501. constructor TPpuUnitDef.Create(AParent: TPpuContainerDef);
  502. begin
  503. inherited Create(AParent);
  504. DefType:=dtUnit;
  505. ItemsName:='Interface';
  506. UsedUnits:=TPpuContainerDef.Create(nil);
  507. UsedUnits.FParent:=Self;
  508. UsedUnits.ItemsName:='Uses';
  509. SourceFiles:=TPpuContainerDef.Create(nil);
  510. SourceFiles.FParent:=Self;
  511. SourceFiles.ItemsName:='Files';
  512. FIndexById:=THashSet.Create(64, True, False);
  513. end;
  514. destructor TPpuUnitDef.Destroy;
  515. begin
  516. UsedUnits.Free;
  517. SourceFiles.Free;
  518. FIndexById.Free;
  519. inherited Destroy;
  520. end;
  521. function TPpuUnitDef.FindById(AId: integer; FindSym: boolean): TPpuDef;
  522. var
  523. h: PHashSetItem;
  524. i: cardinal;
  525. begin
  526. Result:=nil;
  527. if AId = -1 then
  528. exit;
  529. i:=AId;
  530. if FindSym then
  531. i:=i or SymIdBit;
  532. h:=FIndexById.Find(@i, SizeOf(i));
  533. if h <> nil then
  534. Result:=TPpuDef(h^.Data)
  535. else
  536. Result:=nil;
  537. end;
  538. { TPpuContainerDef }
  539. function TPpuContainerDef.GetCount: integer;
  540. begin
  541. Result:=FItems.Count;
  542. end;
  543. function TPpuContainerDef.GetItem(Index: Integer): TPpuDef;
  544. begin
  545. Result:=TPpuDef(FItems[Index]);
  546. end;
  547. procedure TPpuContainerDef.SetItem(Index: Integer; AValue: TPpuDef);
  548. begin
  549. FItems[Index]:=AValue;
  550. end;
  551. procedure TPpuContainerDef.WriteDef(Output: TPpuOutput);
  552. var
  553. i: integer;
  554. begin
  555. inherited WriteDef(Output);
  556. BeforeWriteItems(Output);
  557. if Count = 0 then
  558. exit;
  559. Output.WriteArrayStart(ItemsName);
  560. for i:=0 to Count - 1 do
  561. Items[i].Write(Output);
  562. Output.WriteArrayEnd;
  563. end;
  564. procedure TPpuContainerDef.BeforeWriteItems(Output: TPpuOutput);
  565. begin
  566. end;
  567. constructor TPpuContainerDef.Create(AParent: TPpuContainerDef);
  568. begin
  569. inherited Create(AParent);
  570. FItems:=TList.Create;
  571. ItemsName:='Contents';
  572. end;
  573. destructor TPpuContainerDef.Destroy;
  574. var
  575. i: integer;
  576. begin
  577. for i:=0 to FItems.Count - 1 do
  578. TObject(FItems[i]).Free;
  579. FItems.Free;
  580. inherited Destroy;
  581. end;
  582. function TPpuContainerDef.Add(Def: TPpuDef): integer;
  583. begin
  584. Result:=FItems.Add(Def);
  585. Def.FParent:=Self;
  586. end;
  587. { TPpuDef }
  588. function TPpuDef.GetDefTypeName: string;
  589. begin
  590. Result:=DefTypeNames[DefType];
  591. end;
  592. function TPpuDef.GetId: cardinal;
  593. begin
  594. if FId = InvalidId then
  595. Result:=InvalidId
  596. else
  597. Result:=FId and not SymIdBit;
  598. end;
  599. function TPpuDef.GetParentUnit: TPpuUnitDef;
  600. var
  601. d: TPpuContainerDef;
  602. begin
  603. if FParentUnit = nil then begin
  604. d:=Parent;
  605. while (d <> nil) and (d.DefType <> dtUnit) do
  606. d:=d.Parent;
  607. FParentUnit:=TPpuUnitDef(d);
  608. end;
  609. Result:=FParentUnit;
  610. end;
  611. procedure TPpuDef.SetId(AValue: cardinal);
  612. var
  613. h: PHashSetItem;
  614. u: TPpuUnitDef;
  615. begin
  616. if FId = AValue then Exit;
  617. u:=ParentUnit;
  618. if (FId <> InvalidId) and (u <> nil) then begin
  619. h:=u.FIndexById.Find(@FId, SizeOf(FId));
  620. if h <> nil then
  621. u.FIndexById.Remove(h);
  622. end;
  623. FId:=AValue;
  624. if (FId <> InvalidId) and (u <> nil) then begin;
  625. h:=u.FIndexById.FindOrAdd(@FId, SizeOf(FId));
  626. h^.Data:=Self;
  627. end;
  628. end;
  629. procedure TPpuDef.SetParent(AValue: TPpuContainerDef);
  630. var
  631. i: cardinal;
  632. begin
  633. if FParent=AValue then Exit;
  634. if FParent <> nil then
  635. raise Exception.Create('Parent can not be modified.');
  636. AValue.Add(Self);
  637. if FId <> InvalidId then begin
  638. i:=FId;
  639. FId:=InvalidId;
  640. SetId(i);
  641. end;
  642. end;
  643. procedure TPpuDef.SetSymId(AId: integer);
  644. begin
  645. Id:=cardinal(AId) or SymIdBit;
  646. end;
  647. procedure TPpuDef.WriteDef(Output: TPpuOutput);
  648. begin
  649. with Output do begin
  650. if FId <> InvalidId then
  651. if IsSymId(FId) then
  652. WriteInt('SymId', Id)
  653. else begin
  654. WriteInt('Id', Id);
  655. if not Ref.IsNull then
  656. WriteInt('SymId', Ref.Id);
  657. end;
  658. if FilePos.Line > 0 then begin
  659. WriteObjectStart('Pos');
  660. if FilePos.FileIndex > 0 then
  661. WriteInt('File', FilePos.FileIndex);
  662. WriteInt('Line', FilePos.Line);
  663. WriteInt('Col', FilePos.Col);
  664. WriteObjectEnd;
  665. end;
  666. if Visibility <> dvPublic then
  667. WriteStr('Visibility', DefVisibilityNames[Visibility]);
  668. end;
  669. end;
  670. constructor TPpuDef.Create(AParent: TPpuContainerDef);
  671. begin
  672. FId:=InvalidId;
  673. Ref:=TPpuRef.Create;
  674. Visibility:=dvPublic;
  675. if AParent <> nil then
  676. AParent.Add(Self);
  677. end;
  678. destructor TPpuDef.Destroy;
  679. begin
  680. Ref.Free;
  681. inherited Destroy;
  682. end;
  683. procedure TPpuDef.Write(Output: TPpuOutput);
  684. begin
  685. if not CanWrite then
  686. exit;
  687. if Parent <> nil then
  688. Output.WriteObjectStart('', Self);
  689. WriteDef(Output);
  690. if Parent <> nil then
  691. Output.WriteObjectEnd(Self);
  692. end;
  693. function TPpuDef.CanWrite: boolean;
  694. begin
  695. Result:=True;
  696. end;
  697. end.