ppuout.pp 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100
  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, dtClassRef, dtArray);
  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. private
  60. FId: cardinal;
  61. function GetId: cardinal;
  62. function GetIsSymId: boolean;
  63. procedure SetId(AValue: cardinal);
  64. procedure SetIsSymId(AValue: boolean);
  65. public
  66. UnitIndex: word;
  67. constructor Create;
  68. procedure Write(Output: TPpuOutput; const RefName: string);
  69. property Id: cardinal read GetId write SetId;
  70. property IsSymId: boolean read GetIsSymId write SetIsSymId;
  71. function IsCurUnit: boolean; inline;
  72. function IsNull: boolean; inline;
  73. end;
  74. TPpuFilePos = record
  75. FileIndex: dword;
  76. Line, Col: integer;
  77. end;
  78. TPpuDefVisibility = (dvPublic, dvPublished, dvProtected, dvPrivate, dvHidden);
  79. { TPpuDef }
  80. TPpuDef = class
  81. private
  82. FId: cardinal;
  83. FParent: TPpuContainerDef;
  84. FParentUnit: TPpuUnitDef;
  85. function GetDefTypeName: string;
  86. function GetId: cardinal;
  87. function GetParentUnit: TPpuUnitDef;
  88. procedure SetId(AValue: cardinal);
  89. procedure SetParent(AValue: TPpuContainerDef);
  90. protected
  91. procedure WriteDef(Output: TPpuOutput); virtual;
  92. public
  93. DefType: TPpuDefType;
  94. Name: string;
  95. FilePos: TPpuFilePos;
  96. // Symbol/definition reference
  97. Ref: TPpuRef;
  98. Visibility: TPpuDefVisibility;
  99. constructor Create(AParent: TPpuContainerDef); virtual; reintroduce;
  100. destructor Destroy; override;
  101. procedure Write(Output: TPpuOutput; const AttrName: string = '');
  102. function CanWrite: boolean; virtual;
  103. procedure SetSymId(AId: integer);
  104. property Parent: TPpuContainerDef read FParent write SetParent;
  105. property ParentUnit: TPpuUnitDef read GetParentUnit;
  106. property Id: cardinal read GetId write SetId;
  107. property DefTypeName: string read GetDefTypeName;
  108. end;
  109. { TPpuContainerDef }
  110. TPpuContainerDef = class(TPpuDef)
  111. private
  112. FItems: TList;
  113. function GetCount: integer;
  114. function GetItem(Index: Integer): TPpuDef;
  115. procedure SetItem(Index: Integer; AValue: TPpuDef);
  116. protected
  117. procedure WriteDef(Output: TPpuOutput); override;
  118. procedure BeforeWriteItems(Output: TPpuOutput); virtual;
  119. public
  120. ItemsName: string;
  121. constructor Create(AParent: TPpuContainerDef); override;
  122. destructor Destroy; override;
  123. function Add(Def: TPpuDef): integer;
  124. property Items[Index: Integer]: TPpuDef read GetItem write SetItem; default;
  125. property Count: integer read GetCount;
  126. end;
  127. { TPpuTypeRef }
  128. TPpuTypeRef = class(TPpuDef)
  129. protected
  130. procedure WriteDef(Output: TPpuOutput); override;
  131. public
  132. constructor Create(AParent: TPpuContainerDef); override;
  133. end;
  134. { TPpuUnitDef }
  135. TPpuUnitDef = class(TPpuContainerDef)
  136. private
  137. FIndexById: THashSet;
  138. protected
  139. procedure WriteDef(Output: TPpuOutput); override;
  140. public
  141. Version: cardinal;
  142. Crc, IntfCrc: cardinal;
  143. TargetOS, TargetCPU: string;
  144. UsedUnits: TPpuContainerDef;
  145. RefUnits: array of string;
  146. SourceFiles: TPpuContainerDef;
  147. constructor Create(AParent: TPpuContainerDef); override;
  148. destructor Destroy; override;
  149. function FindById(AId: integer; FindSym: boolean = False): TPpuDef;
  150. end;
  151. { TPpuSrcFile }
  152. TPpuSrcFile = class(TPpuDef)
  153. protected
  154. procedure WriteDef(Output: TPpuOutput); override;
  155. public
  156. FileTime: TDateTime;
  157. end;
  158. TPpuProcOption = (poProcedure, poFunction, poConstructor, poDestructor, poOperator,
  159. poClassMethod, poVirtual, poAbstract, poOverriding, poOverload, poInline);
  160. TPpuProcOptions = set of TPpuProcOption;
  161. { TPpuProcDef }
  162. TPpuProcDef = class(TPpuContainerDef)
  163. protected
  164. procedure BeforeWriteItems(Output: TPpuOutput); override;
  165. public
  166. ReturnType: TPpuRef;
  167. Options: TPpuProcOptions;
  168. constructor Create(AParent: TPpuContainerDef); override;
  169. destructor Destroy; override;
  170. end;
  171. { TPpuProcTypeDef }
  172. TPpuProcTypeDef = class(TPpuProcDef)
  173. public
  174. constructor Create(AParent: TPpuContainerDef); override;
  175. end;
  176. TPpuConstType = (ctInt, ctFloat, ctStr);
  177. { TPpuConstDef }
  178. TPpuConstDef = class(TPpuDef)
  179. protected
  180. procedure WriteDef(Output: TPpuOutput); override;
  181. public
  182. ConstType: TPpuConstType;
  183. TypeRef: TPpuRef;
  184. VInt: Int64;
  185. VFloat: extended;
  186. VStr: string;
  187. constructor Create(AParent: TPpuContainerDef); override;
  188. destructor Destroy; override;
  189. end;
  190. { TPpuVarDef }
  191. TPpuVarDef = class(TPpuDef)
  192. protected
  193. procedure WriteDef(Output: TPpuOutput); override;
  194. public
  195. VarType: TPpuRef;
  196. constructor Create(AParent: TPpuContainerDef); override;
  197. destructor Destroy; override;
  198. end;
  199. TPpuParamSpez = (psValue, psVar, psOut, psConst, psConstRef, psHidden);
  200. { TPpuParamDef }
  201. TPpuParamDef = class(TPpuVarDef)
  202. protected
  203. procedure WriteDef(Output: TPpuOutput); override;
  204. public
  205. Spez: TPpuParamSpez;
  206. DefaultValue: TPpuRef;
  207. constructor Create(AParent: TPpuContainerDef); override;
  208. destructor Destroy; override;
  209. function CanWrite: boolean; override;
  210. end;
  211. TPpuObjType = (otUnknown, otClass, otObject, otInterface, otHelper);
  212. TPpuObjOption = (ooIsAbstract, ooCopied);
  213. TPpuObjOptions = set of TPpuObjOption;
  214. { TPpuObjectDef }
  215. TPpuObjectDef = class(TPpuContainerDef)
  216. protected
  217. procedure BeforeWriteItems(Output: TPpuOutput); override;
  218. public
  219. ObjType: TPpuObjType;
  220. Ancestor: TPpuRef;
  221. Options: TPpuObjOptions;
  222. constructor Create(AParent: TPpuContainerDef); override;
  223. destructor Destroy; override;
  224. function CanWrite: boolean; override;
  225. end;
  226. { TPpuFieldDef }
  227. TPpuFieldDef = class(TPpuVarDef)
  228. public
  229. constructor Create(AParent: TPpuContainerDef); override;
  230. end;
  231. { TPpuPropDef }
  232. TPpuPropDef = class(TPpuContainerDef)
  233. protected
  234. procedure BeforeWriteItems(Output: TPpuOutput); override;
  235. public
  236. PropType: TPpuRef;
  237. Getter, Setter: TPpuRef;
  238. constructor Create(AParent: TPpuContainerDef); override;
  239. destructor Destroy; override;
  240. end;
  241. { TPpuRecordDef }
  242. TPpuRecordDef = class(TPpuObjectDef)
  243. protected
  244. procedure BeforeWriteItems(Output: TPpuOutput); override;
  245. public
  246. constructor Create(AParent: TPpuContainerDef); override;
  247. function CanWrite: boolean; override;
  248. end;
  249. { TPpuClassRefDef }
  250. TPpuClassRefDef = class(TPpuDef)
  251. protected
  252. procedure WriteDef(Output: TPpuOutput); override;
  253. public
  254. ClassRef: TPpuRef;
  255. constructor Create(AParent: TPpuContainerDef); override;
  256. destructor Destroy; override;
  257. end;
  258. TPpuArrayOption = (aoDynamic);
  259. TPpuArrayOptions = set of TPpuArrayOption;
  260. { TPpuArrayDef }
  261. TPpuArrayDef = class(TPpuDef)
  262. protected
  263. procedure WriteDef(Output: TPpuOutput); override;
  264. public
  265. ElType: TPpuRef;
  266. RangeType: TPpuRef;
  267. RangeLow, RangeHigh: Int64;
  268. Options: TPpuArrayOptions;
  269. constructor Create(AParent: TPpuContainerDef); override;
  270. destructor Destroy; override;
  271. function CanWrite: boolean; override;
  272. end;
  273. implementation
  274. const
  275. DefTypeNames: array[TPpuDefType] of string =
  276. ('', 'unit', 'obj', 'rec', 'proc', 'field', 'prop', 'param', 'var',
  277. 'type', 'const', 'proctype', 'enum', 'set', 'classref', 'array');
  278. ProcOptionNames: array[TPpuProcOption] of string =
  279. ('procedure', 'function', 'constructor', 'destructor', 'operator',
  280. 'classmethod', 'virtual', 'abstract', 'overriding', 'overload', 'inline');
  281. DefVisibilityNames: array[TPpuDefVisibility] of string =
  282. ('public', 'published', 'protected', 'private', '');
  283. ParamSpezNames: array[TPpuParamSpez] of string =
  284. ('value', 'var', 'out', 'const', 'constref', '');
  285. ObjTypeNames: array[TPpuObjType] of string =
  286. ('', 'class', 'object', 'interface', 'helper');
  287. ObjOptionNames: array[TPpuObjOption] of string =
  288. ('abstract','copied');
  289. ArrayOptionNames: array[TPpuArrayOption] of string =
  290. ('dynamic');
  291. ConstTypeNames: array[TPpuConstType] of string =
  292. ('int', 'float', 'string');
  293. SymIdBit = $80000000;
  294. InvalidId = cardinal(-1);
  295. InvalidUnit = word(-1);
  296. function IsSymId(Id: cardinal): boolean; inline;
  297. begin
  298. Result:=Id and SymIdBit <> 0;
  299. end;
  300. { TPpuConstDef }
  301. procedure TPpuConstDef.WriteDef(Output: TPpuOutput);
  302. var
  303. s: string;
  304. begin
  305. inherited WriteDef(Output);
  306. with Output do begin
  307. WriteStr('ValType', ConstTypeNames[ConstType]);
  308. s:='Value';
  309. case ConstType of
  310. ctInt:
  311. WriteInt(s, VInt);
  312. ctFloat:
  313. WriteFloat(s, VFloat);
  314. ctStr:
  315. WriteStr(s, VStr);
  316. end;
  317. end;
  318. if not TypeRef.IsNull then
  319. TypeRef.Write(Output, 'TypeRef');
  320. end;
  321. constructor TPpuConstDef.Create(AParent: TPpuContainerDef);
  322. begin
  323. inherited Create(AParent);
  324. DefType:=dtConst;
  325. TypeRef:=TPpuRef.Create;
  326. end;
  327. destructor TPpuConstDef.Destroy;
  328. begin
  329. TypeRef.Free;
  330. inherited Destroy;
  331. end;
  332. { TPpuArrayDef }
  333. procedure TPpuArrayDef.WriteDef(Output: TPpuOutput);
  334. var
  335. opt: TPpuArrayOption;
  336. begin
  337. inherited WriteDef(Output);
  338. if Options <> [] then begin
  339. Output.WriteArrayStart('Options');
  340. for opt:=Low(opt) to High(opt) do
  341. if opt in Options then
  342. Output.WriteStr('', ArrayOptionNames[opt]);
  343. Output.WriteArrayEnd;
  344. end;
  345. ElType.Write(Output, 'ElType');
  346. RangeType.Write(Output, 'RangeType');;
  347. Output.WriteInt('Low', RangeLow);
  348. Output.WriteInt('High', RangeHigh);
  349. end;
  350. constructor TPpuArrayDef.Create(AParent: TPpuContainerDef);
  351. begin
  352. inherited Create(AParent);
  353. DefType:=dtArray;
  354. ElType:=TPpuRef.Create;
  355. RangeType:=TPpuRef.Create;
  356. end;
  357. destructor TPpuArrayDef.Destroy;
  358. begin
  359. ElType.Free;
  360. RangeType.Free;
  361. inherited Destroy;
  362. end;
  363. function TPpuArrayDef.CanWrite: boolean;
  364. begin
  365. Result:=inherited CanWrite and (Name <> '');
  366. end;
  367. { TPpuClassRefDef }
  368. procedure TPpuClassRefDef.WriteDef(Output: TPpuOutput);
  369. begin
  370. inherited WriteDef(Output);
  371. ClassRef.Write(Output, 'Ref');
  372. end;
  373. constructor TPpuClassRefDef.Create(AParent: TPpuContainerDef);
  374. begin
  375. inherited Create(AParent);
  376. DefType:=dtClassRef;
  377. ClassRef:=TPpuRef.Create;
  378. end;
  379. destructor TPpuClassRefDef.Destroy;
  380. begin
  381. ClassRef.Free;
  382. inherited Destroy;
  383. end;
  384. { TPpuRecordDef }
  385. procedure TPpuRecordDef.BeforeWriteItems(Output: TPpuOutput);
  386. begin
  387. inherited BeforeWriteItems(Output);
  388. if ooCopied in Options then
  389. Ancestor.Write(Output, 'CopyFrom');
  390. end;
  391. constructor TPpuRecordDef.Create(AParent: TPpuContainerDef);
  392. begin
  393. inherited Create(AParent);
  394. DefType:=dtRecord;
  395. end;
  396. function TPpuRecordDef.CanWrite: boolean;
  397. begin
  398. Result:=True;
  399. end;
  400. { TPpuPropDef }
  401. procedure TPpuPropDef.BeforeWriteItems(Output: TPpuOutput);
  402. begin
  403. inherited BeforeWriteItems(Output);
  404. PropType.Write(Output, 'PropType');
  405. Getter.Write(Output, 'Getter');
  406. Setter.Write(Output, 'Setter');
  407. end;
  408. constructor TPpuPropDef.Create(AParent: TPpuContainerDef);
  409. begin
  410. inherited Create(AParent);
  411. DefType:=dtProp;
  412. ItemsName:='Params';
  413. PropType:=TPpuRef.Create;
  414. Getter:=TPpuRef.Create;
  415. Setter:=TPpuRef.Create;
  416. end;
  417. destructor TPpuPropDef.Destroy;
  418. begin
  419. Getter.Free;
  420. Setter.Free;
  421. PropType.Free;
  422. inherited Destroy;
  423. end;
  424. { TPpuTypeRef }
  425. procedure TPpuTypeRef.WriteDef(Output: TPpuOutput);
  426. begin
  427. inherited WriteDef(Output);
  428. Ref.Write(Output, 'Ref');
  429. end;
  430. constructor TPpuTypeRef.Create(AParent: TPpuContainerDef);
  431. begin
  432. inherited Create(AParent);
  433. DefType:=dtTypeRef;
  434. end;
  435. { TPpuFieldDef }
  436. constructor TPpuFieldDef.Create(AParent: TPpuContainerDef);
  437. begin
  438. inherited Create(AParent);
  439. DefType:=dtField;
  440. end;
  441. { TPpuParamDef }
  442. procedure TPpuParamDef.WriteDef(Output: TPpuOutput);
  443. var
  444. i, j: integer;
  445. d: TPpuDef;
  446. begin
  447. inherited WriteDef(Output);
  448. if Spez <> psValue then
  449. Output.WriteStr('Spez', ParamSpezNames[Spez]);
  450. if not DefaultValue.IsNull then begin
  451. j:=DefaultValue.Id;
  452. for i:=0 to Parent.Count - 1 do begin
  453. d:=Parent[i];
  454. if (d.DefType = dtConst) and (d.Id = j) then begin
  455. d.Visibility:=dvPublic;
  456. d.Name:='';
  457. d.Write(Output, 'Default');
  458. d.Visibility:=dvHidden;
  459. break;
  460. end;
  461. end;
  462. end;
  463. end;
  464. constructor TPpuParamDef.Create(AParent: TPpuContainerDef);
  465. begin
  466. inherited Create(AParent);
  467. DefType:=dtParam;
  468. Spez:=psValue;
  469. DefaultValue:=TPpuRef.Create;
  470. end;
  471. destructor TPpuParamDef.Destroy;
  472. begin
  473. DefaultValue.Free;
  474. inherited Destroy;
  475. end;
  476. function TPpuParamDef.CanWrite: boolean;
  477. begin
  478. Result:=inherited CanWrite and (Spez <> psHidden);
  479. end;
  480. { TPpuVarDef }
  481. procedure TPpuVarDef.WriteDef(Output: TPpuOutput);
  482. begin
  483. inherited WriteDef(Output);
  484. VarType.Write(Output, 'VarType');
  485. end;
  486. constructor TPpuVarDef.Create(AParent: TPpuContainerDef);
  487. begin
  488. inherited Create(AParent);
  489. DefType:=dtVar;
  490. VarType:=TPpuRef.Create;
  491. end;
  492. destructor TPpuVarDef.Destroy;
  493. begin
  494. VarType.Free;
  495. inherited Destroy;
  496. end;
  497. { TPpuObjectDef }
  498. procedure TPpuObjectDef.BeforeWriteItems(Output: TPpuOutput);
  499. var
  500. opt: TPpuObjOption;
  501. begin
  502. inherited BeforeWriteItems(Output);
  503. if ObjType <> otUnknown then begin
  504. Output.WriteStr('ObjType', ObjTypeNames[ObjType]);
  505. Ancestor.Write(Output, 'Ancestor');
  506. end;
  507. if Options <> [] then begin
  508. Output.WriteArrayStart('Options');
  509. for opt:=Low(opt) to High(opt) do
  510. if opt in Options then
  511. Output.WriteStr('', ObjOptionNames[opt]);
  512. Output.WriteArrayEnd;
  513. end;
  514. end;
  515. constructor TPpuObjectDef.Create(AParent: TPpuContainerDef);
  516. begin
  517. inherited Create(AParent);
  518. DefType:=dtObject;
  519. ItemsName:='Fields';
  520. ObjType:=otUnknown;
  521. Ancestor:=TPpuRef.Create;
  522. end;
  523. destructor TPpuObjectDef.Destroy;
  524. begin
  525. Ancestor.Free;
  526. inherited Destroy;
  527. end;
  528. function TPpuObjectDef.CanWrite: boolean;
  529. begin
  530. Result:=inherited CanWrite and (ObjType <> otUnknown);
  531. end;
  532. { TPpuRef }
  533. function TPpuRef.GetId: cardinal;
  534. begin
  535. if FId = InvalidId then
  536. Result:=InvalidId
  537. else
  538. Result:=FId and not SymIdBit;
  539. end;
  540. function TPpuRef.GetIsSymId: boolean;
  541. begin
  542. Result:=FId and SymIdBit <> 0;
  543. end;
  544. procedure TPpuRef.SetId(AValue: cardinal);
  545. begin
  546. if (FId = InvalidId) or (AValue = InvalidId) then
  547. FId:=AValue
  548. else
  549. FId:=AValue or (FId and SymIdBit);
  550. end;
  551. procedure TPpuRef.SetIsSymId(AValue: boolean);
  552. begin
  553. if AValue then
  554. FId:=FId or SymIdBit
  555. else
  556. FId:=FId and not SymIdBit;
  557. end;
  558. constructor TPpuRef.Create;
  559. begin
  560. UnitIndex:=InvalidUnit;
  561. FId:=InvalidId;
  562. end;
  563. procedure TPpuRef.Write(Output: TPpuOutput; const RefName: string);
  564. begin
  565. with Output do
  566. if IsNull then
  567. WriteNull(RefName)
  568. else begin
  569. WriteObjectStart(RefName);
  570. if not IsCurUnit then
  571. WriteInt('Unit', UnitIndex);
  572. if IsSymId then
  573. WriteInt('SymId', Id)
  574. else
  575. WriteInt('Id', Id);
  576. WriteObjectEnd;
  577. end;
  578. end;
  579. function TPpuRef.IsCurUnit: boolean;
  580. begin
  581. Result:=UnitIndex = InvalidUnit;
  582. end;
  583. function TPpuRef.IsNull: boolean;
  584. begin
  585. Result:=Id = InvalidId;
  586. end;
  587. { TPpuProcTypeDef }
  588. constructor TPpuProcTypeDef.Create(AParent: TPpuContainerDef);
  589. begin
  590. inherited Create(AParent);
  591. DefType:=dtProcType;
  592. end;
  593. { TPpuProcDef }
  594. procedure TPpuProcDef.BeforeWriteItems(Output: TPpuOutput);
  595. var
  596. opt: TPpuProcOption;
  597. begin
  598. inherited BeforeWriteItems(Output);
  599. if Options <> [] then begin
  600. Output.WriteArrayStart('Options');
  601. for opt:=Low(opt) to High(opt) do
  602. if opt in Options then
  603. Output.WriteStr('', ProcOptionNames[opt]);
  604. Output.WriteArrayEnd;
  605. end;
  606. if Options*[poProcedure, poDestructor] = [] then
  607. ReturnType.Write(Output, 'RetType');
  608. end;
  609. constructor TPpuProcDef.Create(AParent: TPpuContainerDef);
  610. begin
  611. inherited Create(AParent);
  612. DefType:=dtProc;
  613. ItemsName:='Params';
  614. ReturnType:=TPpuRef.Create;
  615. end;
  616. destructor TPpuProcDef.Destroy;
  617. begin
  618. ReturnType.Free;
  619. inherited Destroy;
  620. end;
  621. { TPpuSrcFile }
  622. procedure TPpuSrcFile.WriteDef(Output: TPpuOutput);
  623. begin
  624. inherited WriteDef(Output);
  625. Output.WriteStr('Time', FormatDateTime('yyyy"-"mm"-"dd hh":"nn":"ss', FileTime));
  626. end;
  627. { TPpuOutput }
  628. procedure TPpuOutput.SetIndent(AValue: integer);
  629. begin
  630. if FIndent=AValue then Exit;
  631. FIndent:=AValue;
  632. if FIndent < 0 then
  633. FIndent:=0;
  634. SetLength(FIndStr, FIndent*IndentSize);
  635. if FIndent > 0 then
  636. FillChar(FIndStr[1], FIndent*IndentSize, ' ');
  637. end;
  638. procedure TPpuOutput.SetIndentSize(AValue: integer);
  639. begin
  640. if FIndentSize=AValue then Exit;
  641. FIndentSize:=AValue;
  642. end;
  643. procedure TPpuOutput.WriteStr(const AName, AValue: string);
  644. begin
  645. end;
  646. procedure TPpuOutput.WriteInt(const AName: string; AValue: Int64);
  647. begin
  648. WriteStr(AName, IntToStr(AValue));
  649. end;
  650. procedure TPpuOutput.WriteFloat(const AName: string; AValue: extended);
  651. var
  652. s: string;
  653. begin
  654. Str(AValue, s);
  655. WriteStr(AName, s);
  656. end;
  657. procedure TPpuOutput.WriteBool(const AName: string; AValue: boolean);
  658. begin
  659. if AValue then
  660. WriteStr(AName, '1')
  661. else
  662. WriteStr(AName, '0');
  663. end;
  664. procedure TPpuOutput.WriteNull(const AName: string);
  665. begin
  666. WriteStr(AName, '');
  667. end;
  668. procedure TPpuOutput.WriteArrayStart(const AName: string);
  669. begin
  670. IncI;
  671. end;
  672. procedure TPpuOutput.WriteArrayEnd;
  673. begin
  674. DecI;
  675. end;
  676. procedure TPpuOutput.WriteObjectStart(const AName: string; Def: TPpuDef);
  677. begin
  678. IncI;
  679. if Def = nil then
  680. exit;
  681. if Def.DefType <> dtNone then
  682. WriteStr('Type', Def.DefTypeName);
  683. if Def.Name <> '' then
  684. WriteStr('Name', Def.Name);
  685. end;
  686. procedure TPpuOutput.WriteObjectEnd(Def: TPpuDef);
  687. begin
  688. DecI;
  689. end;
  690. constructor TPpuOutput.Create(var OutFile: Text);
  691. begin
  692. FOutFile:=@OutFile;
  693. FIndentSize:=2;
  694. end;
  695. destructor TPpuOutput.Destroy;
  696. begin
  697. inherited Destroy;
  698. end;
  699. procedure TPpuOutput.Write(const s: string);
  700. begin
  701. if not FNoIndent then
  702. System.Write(FOutFile^, FIndStr);
  703. System.Write(FOutFile^, s);
  704. FNoIndent:=True;
  705. end;
  706. procedure TPpuOutput.WriteLn(const s: string);
  707. begin
  708. Self.Write(s + LineEnding);
  709. FNoIndent:=False;
  710. end;
  711. procedure TPpuOutput.IncI;
  712. begin
  713. Indent:=Indent + 1;
  714. end;
  715. procedure TPpuOutput.DecI;
  716. begin
  717. Indent:=Indent - 1;
  718. end;
  719. { TPpuUnitDef }
  720. procedure TPpuUnitDef.WriteDef(Output: TPpuOutput);
  721. var
  722. i: integer;
  723. begin
  724. with Output do begin
  725. if Version <> 0 then
  726. WriteInt('Version', Version);
  727. if TargetCPU <> '' then
  728. WriteStr('TargetCPU', TargetCPU);
  729. if TargetOS <> '' then
  730. WriteStr('TargetOS', TargetOS);
  731. if Crc <> 0 then
  732. WriteStr('CRC', hexStr(Crc, 8));
  733. if IntfCrc <> 0 then
  734. WriteStr('InterfaceCRC', hexStr(IntfCrc, 8));
  735. UsedUnits.WriteDef(Output);
  736. if Length(RefUnits) > 0 then begin
  737. WriteArrayStart('Units');
  738. for i:=0 to High(RefUnits) do
  739. WriteStr('', RefUnits[i]);
  740. WriteArrayEnd;
  741. end;
  742. SourceFiles.WriteDef(Output);
  743. end;
  744. inherited WriteDef(Output);
  745. end;
  746. constructor TPpuUnitDef.Create(AParent: TPpuContainerDef);
  747. begin
  748. inherited Create(AParent);
  749. DefType:=dtUnit;
  750. ItemsName:='Interface';
  751. UsedUnits:=TPpuContainerDef.Create(nil);
  752. UsedUnits.FParent:=Self;
  753. UsedUnits.ItemsName:='Uses';
  754. SourceFiles:=TPpuContainerDef.Create(nil);
  755. SourceFiles.FParent:=Self;
  756. SourceFiles.ItemsName:='Files';
  757. FIndexById:=THashSet.Create(64, True, False);
  758. end;
  759. destructor TPpuUnitDef.Destroy;
  760. begin
  761. UsedUnits.Free;
  762. SourceFiles.Free;
  763. FIndexById.Free;
  764. inherited Destroy;
  765. end;
  766. function TPpuUnitDef.FindById(AId: integer; FindSym: boolean): TPpuDef;
  767. var
  768. h: PHashSetItem;
  769. i: cardinal;
  770. begin
  771. Result:=nil;
  772. if AId = -1 then
  773. exit;
  774. i:=AId;
  775. if FindSym then
  776. i:=i or SymIdBit;
  777. h:=FIndexById.Find(@i, SizeOf(i));
  778. if h <> nil then
  779. Result:=TPpuDef(h^.Data)
  780. else
  781. Result:=nil;
  782. end;
  783. { TPpuContainerDef }
  784. function TPpuContainerDef.GetCount: integer;
  785. begin
  786. Result:=FItems.Count;
  787. end;
  788. function TPpuContainerDef.GetItem(Index: Integer): TPpuDef;
  789. begin
  790. Result:=TPpuDef(FItems[Index]);
  791. end;
  792. procedure TPpuContainerDef.SetItem(Index: Integer; AValue: TPpuDef);
  793. begin
  794. FItems[Index]:=AValue;
  795. end;
  796. procedure TPpuContainerDef.WriteDef(Output: TPpuOutput);
  797. var
  798. i: integer;
  799. begin
  800. inherited WriteDef(Output);
  801. BeforeWriteItems(Output);
  802. if Count = 0 then
  803. exit;
  804. Output.WriteArrayStart(ItemsName);
  805. for i:=0 to Count - 1 do
  806. Items[i].Write(Output);
  807. Output.WriteArrayEnd;
  808. end;
  809. procedure TPpuContainerDef.BeforeWriteItems(Output: TPpuOutput);
  810. begin
  811. end;
  812. constructor TPpuContainerDef.Create(AParent: TPpuContainerDef);
  813. begin
  814. inherited Create(AParent);
  815. FItems:=TList.Create;
  816. ItemsName:='Contents';
  817. end;
  818. destructor TPpuContainerDef.Destroy;
  819. var
  820. i: integer;
  821. begin
  822. for i:=0 to FItems.Count - 1 do
  823. TObject(FItems[i]).Free;
  824. FItems.Free;
  825. inherited Destroy;
  826. end;
  827. function TPpuContainerDef.Add(Def: TPpuDef): integer;
  828. begin
  829. Result:=FItems.Add(Def);
  830. Def.FParent:=Self;
  831. end;
  832. { TPpuDef }
  833. function TPpuDef.GetDefTypeName: string;
  834. begin
  835. Result:=DefTypeNames[DefType];
  836. end;
  837. function TPpuDef.GetId: cardinal;
  838. begin
  839. if FId = InvalidId then
  840. Result:=InvalidId
  841. else
  842. Result:=FId and not SymIdBit;
  843. end;
  844. function TPpuDef.GetParentUnit: TPpuUnitDef;
  845. var
  846. d: TPpuContainerDef;
  847. begin
  848. if FParentUnit = nil then begin
  849. d:=Parent;
  850. while (d <> nil) and (d.DefType <> dtUnit) do
  851. d:=d.Parent;
  852. FParentUnit:=TPpuUnitDef(d);
  853. end;
  854. Result:=FParentUnit;
  855. end;
  856. procedure TPpuDef.SetId(AValue: cardinal);
  857. var
  858. h: PHashSetItem;
  859. u: TPpuUnitDef;
  860. begin
  861. if FId = AValue then Exit;
  862. u:=ParentUnit;
  863. if (FId <> InvalidId) and (u <> nil) then begin
  864. h:=u.FIndexById.Find(@FId, SizeOf(FId));
  865. if h <> nil then
  866. u.FIndexById.Remove(h);
  867. end;
  868. FId:=AValue;
  869. if (FId <> InvalidId) and (u <> nil) then begin;
  870. h:=u.FIndexById.FindOrAdd(@FId, SizeOf(FId));
  871. h^.Data:=Self;
  872. end;
  873. end;
  874. procedure TPpuDef.SetParent(AValue: TPpuContainerDef);
  875. var
  876. i: cardinal;
  877. begin
  878. if FParent=AValue then Exit;
  879. if FParent <> nil then
  880. raise Exception.Create('Parent can not be modified.');
  881. AValue.Add(Self);
  882. if FId <> InvalidId then begin
  883. i:=FId;
  884. FId:=InvalidId;
  885. SetId(i);
  886. end;
  887. end;
  888. procedure TPpuDef.SetSymId(AId: integer);
  889. begin
  890. Id:=cardinal(AId) or SymIdBit;
  891. end;
  892. procedure TPpuDef.WriteDef(Output: TPpuOutput);
  893. begin
  894. with Output do begin
  895. if FId <> InvalidId then
  896. if IsSymId(FId) then
  897. WriteInt('SymId', Id)
  898. else begin
  899. WriteInt('Id', Id);
  900. if not Ref.IsNull then
  901. WriteInt('SymId', Ref.Id);
  902. end;
  903. if FilePos.Line > 0 then begin
  904. WriteObjectStart('Pos');
  905. if FilePos.FileIndex > 0 then
  906. WriteInt('File', FilePos.FileIndex);
  907. WriteInt('Line', FilePos.Line);
  908. WriteInt('Col', FilePos.Col);
  909. WriteObjectEnd;
  910. end;
  911. if Visibility <> dvPublic then
  912. WriteStr('Visibility', DefVisibilityNames[Visibility]);
  913. end;
  914. end;
  915. constructor TPpuDef.Create(AParent: TPpuContainerDef);
  916. begin
  917. FId:=InvalidId;
  918. Ref:=TPpuRef.Create;
  919. Visibility:=dvPublic;
  920. if AParent <> nil then
  921. AParent.Add(Self);
  922. end;
  923. destructor TPpuDef.Destroy;
  924. begin
  925. Ref.Free;
  926. inherited Destroy;
  927. end;
  928. procedure TPpuDef.Write(Output: TPpuOutput; const AttrName: string);
  929. begin
  930. if not CanWrite then
  931. exit;
  932. if Parent <> nil then
  933. Output.WriteObjectStart(AttrName, Self);
  934. WriteDef(Output);
  935. if Parent <> nil then
  936. Output.WriteObjectEnd(Self);
  937. end;
  938. function TPpuDef.CanWrite: boolean;
  939. begin
  940. Result:=Visibility <> dvHidden;
  941. end;
  942. end.