Răsfoiți Sursa

* ppudump: Started implementation of JSON output. Output of unit header info has been implemented.

git-svn-id: trunk@24299 -
yury 12 ani în urmă
părinte
comite
85c2d144c5

+ 2 - 0
.gitattributes

@@ -691,6 +691,8 @@ compiler/utils/msg2inc.pp svneol=native#text/plain
 compiler/utils/msgdif.pp svneol=native#text/plain
 compiler/utils/msgused.pl svneol=native#text/plain
 compiler/utils/ppudump/ppudump.pp svneol=native#text/plain
+compiler/utils/ppudump/ppujson.pp svneol=native#text/plain
+compiler/utils/ppudump/ppuout.pp svneol=native#text/plain
 compiler/utils/ppufiles.pp svneol=native#text/plain
 compiler/utils/ppumove.pp svneol=native#text/plain
 compiler/utils/samplecfg svneol=native#text/plain

+ 76 - 13
compiler/utils/ppudump/ppudump.pp

@@ -35,7 +35,9 @@ uses
   globals,
   globtype,
   widestr,
-  tokens;
+  tokens,
+  ppuout,
+  ppujson;
 
 const
   Version   = 'Version 2.7.1';
@@ -185,6 +187,10 @@ var
   verbose     : longint;
   derefdata   : pbyte;
   derefdatalen : longint;
+  pout: TPpuOutput;
+  nostdout: boolean;
+  UnitList: TPpuContainerDef;
+  CurUnit: TPpuUnitDef;
 
 
 {****************************************************************************
@@ -277,6 +283,7 @@ const has_errors : boolean = false;
 
 procedure Write(const s: string);
 begin
+  if nostdout then exit;
   system.write(s);
 end;
 
@@ -284,6 +291,7 @@ procedure Write(const params: array of const);
 var
   i: integer;
 begin
+  if nostdout then exit;
   for i:=Low(params) to High(params) do
     with TVarRec(params[i]) do
       case VType of
@@ -305,11 +313,13 @@ end;
 
 procedure Writeln(const s: string = '');
 begin
+  if nostdout then exit;
   system.writeln(s);
 end;
 
 procedure Writeln(const params: array of const);
 begin
+  if nostdout then exit;
   Write(params);
   system.writeln;
 end;
@@ -674,14 +684,19 @@ end;
 procedure ReadLoadUnit;
 var
   ucrc,uintfcrc, indcrc : cardinal;
+  un: TPpuUnitDef;
 begin
   while not ppufile.EndOfEntry do
     begin
-      write(['Uses unit: ',ppufile.getstring]);
+      un:=TPpuUnitDef.Create(CurUnit.UsedUnits);
+      un.Name:=ppufile.getstring;
+      write(['Uses unit: ',un.Name]);
       ucrc:=cardinal(ppufile.getlongint);
       uintfcrc:=cardinal(ppufile.getlongint);
       indcrc:=cardinal(ppufile.getlongint);
       writeln([' (Crc: ',hexstr(ucrc,8),', IntfcCrc: ',hexstr(uintfcrc,8),', IndCrc: ',hexstr(indcrc,8),')']);
+      un.Crc:=ucrc;
+      un.IntfCrc:=uintfcrc;
     end;
 end;
 
@@ -692,8 +707,12 @@ var
 begin
   mapsize:=ppufile.getlongint;
   writeln(['DerefMapsize: ',mapsize]);
+  SetLength(CurUnit.RefUnits, mapsize);
   for i:=0 to mapsize-1 do
-    writeln(['DerefMap[',i,'] = ',ppufile.getstring]);
+    begin
+      CurUnit.RefUnits[i]:=ppufile.getstring;
+      writeln(['DerefMap[',i,'] = ',CurUnit.RefUnits[i]]);
+    end;
 end;
 
 
@@ -2797,7 +2816,7 @@ end;
 procedure readinterface;
 var
   b : byte;
-  sourcenumber : longint;
+  sourcenumber, i : longint;
 begin
   with ppufile do
    begin
@@ -2806,7 +2825,10 @@ begin
        case b of
 
          ibmodulename :
-           Writeln(['Module Name: ',getstring]);
+           begin
+             CurUnit.Name:=getstring;
+             Writeln(['Module Name: ',CurUnit.Name]);
+           end;
 
          ibmoduleoptions:
            readmoduleoptions('  ');
@@ -2816,7 +2838,14 @@ begin
              sourcenumber:=1;
              while not EndOfEntry do
               begin
-                Writeln(['Source file ',sourcenumber,' : ',getstring,' ',filetimestring(getlongint)]);
+                with TPpuSrcFile.Create(CurUnit.SourceFiles) do begin
+                  Name:=getstring;
+                  i:=getlongint;
+                  if i >= 0 then
+                    FileTime:=FileDateToDateTime(i);
+                  Writeln(['Source file ',sourcenumber,' : ',Name,' ',filetimestring(i)]);
+                end;
+
                 inc(sourcenumber);
               end;
            end;
@@ -2969,6 +2998,10 @@ begin
      SetHasErrors;
      exit;
    end;
+
+  CurUnit:=TPpuUnitDef.Create(UnitList);
+  CurUnit.Version:=ppuversion;
+
 { Write PPU Header Information }
   if (verbose and v_header)<>0 then
    begin
@@ -2991,6 +3024,15 @@ begin
         Writeln(['Symbols stored          : ',tostr(symlistsize)]);
       end;
    end;
+
+  with ppufile.header do
+    begin
+      CurUnit.Crc:=checksum;
+      CurUnit.IntfCrc:=interface_checksum;
+      CurUnit.TargetCPU:=Cpu2Str(cpu);
+      CurUnit.TargetOS:=Target2Str(target);
+    end;
+
 {read the general stuff}
   if (verbose and v_interface)<>0 then
    begin
@@ -3097,13 +3139,20 @@ begin
   Writeln;
 end;
 
-
+procedure WriteLogo;
+begin
+  writeln(Title+' '+Version);
+  writeln(Copyright);
+  writeln;
+end;
 
 procedure help;
 begin
+  WriteLogo;
   writeln('usage: ppudump [options] <filename1> <filename2>...');
   writeln;
   writeln('[options] can be:');
+  writeln('    -J output in JSON format');
   writeln('    -M Exit with ExitCode=2 if more information is available');
   writeln('    -V<verbose>  Set verbosity to <verbose>');
   writeln('                   H - Show header info');
@@ -3124,11 +3173,9 @@ var
 const
   error_on_more : boolean = false;
 begin
-  writeln(Title+' '+Version);
-  writeln(Copyright);
-  writeln;
   if paramcount<1 then
    begin
+     WriteLogo;
      writeln('usage: dumpppu [options] <filename1> <filename2>...');
      halt(1);
    end;
@@ -3140,6 +3187,10 @@ begin
    begin
      para:=paramstr(startpara);
      case upcase(para[2]) of
+      'J' : begin
+              nostdout:=True;
+              pout:=TPpuJsonOutput.Create(Output);
+            end;
       'M' : error_on_more:=true;
       'V' : begin
               verbose:=0;
@@ -3158,9 +3209,21 @@ begin
      end;
      inc(startpara);
    end;
-{ process files }
-  for nrfile:=startpara to paramcount do
-    dofile (paramstr(nrfile));
+
+  if not nostdout then
+    WriteLogo;
+
+  UnitList:=TPpuContainerDef.Create(nil);
+  try
+    { process files }
+    for nrfile:=startpara to paramcount do
+      dofile (paramstr(nrfile));
+    if not has_errors and (pout <> nil) then
+      UnitList.Write(pout);
+  finally
+    UnitList.Free;
+    pout.Free;
+  end;
   if has_errors then
     Halt(1);
   if error_on_more and has_more_infos then

+ 267 - 0
compiler/utils/ppudump/ppujson.pp

@@ -0,0 +1,267 @@
+{
+    Copyright (c) 2013 by Yury Sidorov and the FPC Development Team
+
+    JSON output of a PPU File
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+
+unit ppujson;
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  SysUtils, Classes, ppuout;
+
+type
+  { TPpuJsonOutput }
+
+  TPpuJsonOutput = class(TPpuOutput)
+  private
+    FNeedDelim: array of boolean;
+    function JsonStr(const s: string): string;
+    procedure BeforeWriteElement;
+    procedure WriteAttr(const AName, AValue: string);
+  protected
+    procedure WriteDefStart(Def: TPpuDef); override;
+    procedure WriteDefEnd(Def: TPpuDef); override;
+    procedure WriteSubItemsStart(Def: TPpuContainerDef); override;
+    procedure WriteSubItemsEnd(Def: TPpuContainerDef); override;
+    procedure WriteArrayStart(const AName: string); override;
+    procedure WriteArrayEnd(const AName: string); override;
+    procedure WriteStr(const AName, AValue: string); override;
+    procedure WriteInt(const AName: string; AValue: Int64); override;
+    procedure WriteFloat(const AName: string; AValue: extended); override;
+    procedure WriteBool(const AName: string; AValue: boolean); override;
+  public
+    constructor Create(var OutFile: Text); override;
+    procedure IncI; override;
+    procedure DecI; override;
+  end;
+
+implementation
+
+{ TPpuJsonOutput }
+
+function TPpuJsonOutput.JsonStr(const s: string): string;
+var
+  ws: widestring;
+  ps: PWideChar;
+  pd: PAnsiChar;
+  i, slen, dlen, dpos: integer;
+
+  procedure _AddChar(c: ansichar);
+  begin
+    if dpos = dlen then begin
+      dlen:=dlen*2;
+      SetLength(Result, dlen);
+      pd:=PAnsiChar(Result) + dpos;
+    end;
+    pd^:=c;
+    Inc(pd);
+    Inc(dpos);
+  end;
+
+var
+  c: widechar;
+  ss: shortstring;
+begin
+  ws:=UTF8Decode(s);
+  ps:=PWideChar(ws);
+  slen:=Length(ws);
+  dlen:=slen + 2;
+  SetLength(Result, dlen);
+  pd:=PAnsiChar(Result);
+  dpos:=0;
+  _AddChar('"');
+  while slen > 0 do begin
+    c:=ps^;
+    case c of
+      '"', '\', '/':
+        begin
+          _AddChar('\');
+          _AddChar(c);
+        end;
+      #8:
+        begin
+          _AddChar('\');
+          _AddChar('b');
+        end;
+      #9:
+        begin
+          _AddChar('\');
+          _AddChar('t');
+        end;
+      #10:
+        begin
+          _AddChar('\');
+          _AddChar('n');
+        end;
+      #13:
+        begin
+          _AddChar('\');
+          _AddChar('r');
+        end;
+      #12:
+        begin
+          _AddChar('\');
+          _AddChar('f');
+        end;
+      else
+        if (c < #32) or (c > #127) then begin
+          _AddChar('\');
+          _AddChar('u');
+          ss:=hexStr(integer(c), 4);
+          for i:=1 to 4 do
+            _AddChar(ss[i]);
+        end
+        else
+          _AddChar(c);
+    end;
+    Inc(ps);
+    Dec(slen);
+  end;
+  _AddChar('"');
+  SetLength(Result, dpos);
+end;
+
+procedure TPpuJsonOutput.BeforeWriteElement;
+begin
+  if FNeedDelim[Indent] then
+    WriteLn(',');
+  FNeedDelim[Indent]:=True;
+end;
+
+procedure TPpuJsonOutput.WriteAttr(const AName, AValue: string);
+begin
+  BeforeWriteElement;
+  if AName <> '' then
+    Write(Format('"%s": %s', [AName, AValue]))
+  else
+    Write(AValue);
+end;
+
+procedure TPpuJsonOutput.WriteDefStart(Def: TPpuDef);
+begin
+  if Def.Parent = nil then
+    // Top level container
+    exit;
+  WriteLn('{');
+  IncI;
+  if Def.DefType <> dtNone then
+    WriteStr('Type', Def.DefTypeName);
+  if Def.Name <> '' then
+    WriteStr('Name', Def.Name);
+end;
+
+procedure TPpuJsonOutput.WriteDefEnd(Def: TPpuDef);
+var
+  s: string;
+begin
+  if Def.Parent = nil then
+    // Top level container
+    exit;
+  DecI;
+  s:='}';
+  // Last def in list?
+  if (Def.Parent <> nil) and (Def.Parent[Def.Parent.Count - 1] <> Def) then
+    s:=s + ',';
+  WriteLn(s);
+end;
+
+procedure TPpuJsonOutput.WriteSubItemsStart(Def: TPpuContainerDef);
+begin
+  if Def.Parent = nil then begin
+    // Top level container
+    WriteLn('[');
+    exit;
+  end;
+  BeforeWriteElement;
+  WriteLn(Format('"%s": [', [Def.ItemsName]));
+end;
+
+procedure TPpuJsonOutput.WriteSubItemsEnd(Def: TPpuContainerDef);
+begin
+  Write(']');
+  if Def.Parent = nil then
+    // Top level container
+    WriteLn;
+end;
+
+procedure TPpuJsonOutput.WriteStr(const AName, AValue: string);
+begin
+  WriteAttr(AName, JsonStr(AValue));
+end;
+
+procedure TPpuJsonOutput.WriteInt(const AName: string; AValue: Int64);
+begin
+  WriteAttr(AName, IntToStr(AValue));
+end;
+
+procedure TPpuJsonOutput.WriteFloat(const AName: string; AValue: extended);
+var
+  s: string;
+begin
+  Str(AValue, s);
+  WriteAttr(AName, s);
+end;
+
+procedure TPpuJsonOutput.WriteBool(const AName: string; AValue: boolean);
+begin
+  if AValue then
+    WriteAttr(AName, 'true')
+  else
+    WriteAttr(AName, 'false');
+end;
+
+procedure TPpuJsonOutput.WriteArrayStart(const AName: string);
+begin
+  BeforeWriteElement;
+  WriteLn(Format('"%s": [', [AName]));
+  IncI;
+end;
+
+procedure TPpuJsonOutput.WriteArrayEnd(const AName: string);
+begin
+  DecI;
+  Write(']');
+end;
+
+constructor TPpuJsonOutput.Create(var OutFile: Text);
+begin
+  inherited Create(OutFile);
+  SetLength(FNeedDelim, 10);
+  FNeedDelim[0]:=False;
+end;
+
+procedure TPpuJsonOutput.IncI;
+begin
+  inherited IncI;
+  if Length(FNeedDelim) >= Indent then
+    SetLength(FNeedDelim, Indent + 1);
+  FNeedDelim[Indent]:=False;
+end;
+
+procedure TPpuJsonOutput.DecI;
+begin
+  if FNeedDelim[Indent] then
+    WriteLn;
+  inherited DecI;
+end;
+
+end.
+

+ 405 - 0
compiler/utils/ppudump/ppuout.pp

@@ -0,0 +1,405 @@
+{
+    Copyright (c) 2013 by Yury Sidorov and the FPC Development Team
+
+    Base classes for a custom output of a PPU File
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************}
+
+unit ppuout;
+{$mode objfpc}{$H+}
+
+interface
+
+uses SysUtils, Classes;
+
+type
+  TPpuDefType = (dtNone, dtUnit, dtClass, dtRecord, dtProc, dtField, dtProp, dtParam, dtVar,
+                 dtType, dtConst, dtProcType, dtEnum, dtSet);
+
+  TPpuDef = class;
+  TPpuContainerDef = class;
+
+  { TPpuOutput }
+
+  TPpuOutput = class
+  private
+    FOutFile: ^Text;
+    FIndent: integer;
+    FIndentSize: integer;
+    FIndStr: string;
+    FNoIndent: boolean;
+    procedure SetIndent(AValue: integer);
+    procedure SetIndentSize(AValue: integer);
+  protected
+    procedure WriteDefStart(Def: TPpuDef); virtual;
+    procedure WriteDefEnd(Def: TPpuDef); virtual;
+    procedure WriteSubItemsStart(Def: TPpuContainerDef); virtual;
+    procedure WriteSubItemsEnd(Def: TPpuContainerDef); virtual;
+    procedure WriteStr(const AName, AValue: string); virtual;
+    procedure WriteInt(const AName: string; AValue: Int64); virtual;
+    procedure WriteFloat(const AName: string; AValue: extended); virtual;
+    procedure WriteBool(const AName: string; AValue: boolean); virtual;
+    procedure WriteArrayStart(const AName: string); virtual;
+    procedure WriteArrayEnd(const AName: string); virtual;
+  public
+    constructor Create(var OutFile: Text); virtual;
+    destructor Destroy; override;
+    procedure Write(const s: string);
+    procedure WriteLn(const s: string = '');
+    procedure IncI; virtual;
+    procedure DecI; virtual;
+    property Indent: integer read FIndent write SetIndent;
+    property IndentSize: integer read FIndentSize write SetIndentSize;
+  end;
+
+  { TPpuDef }
+
+  TPpuDef = class
+  private
+    FParent: TPpuContainerDef;
+    function GetDefTypeName: string;
+    procedure SetProps(AValue: TStringList);
+
+  protected
+    procedure WriteDef(Output: TPpuOutput); virtual;
+
+  public
+    DefType: TPpuDefType;
+    Name: string;
+    DefId: integer;
+
+    constructor Create(AParent: TPpuContainerDef); virtual; reintroduce;
+    destructor Destroy; override;
+    procedure Write(Output: TPpuOutput);
+    property Parent: TPpuContainerDef read FParent;
+    property DefTypeName: string read GetDefTypeName;
+  end;
+
+  { TPpuContainerDef }
+
+  TPpuContainerDef = class(TPpuDef)
+  private
+    FItems: TList;
+    function GetCount: integer;
+    function GetItem(Index: Integer): TPpuDef;
+    procedure SetItem(Index: Integer; AValue: TPpuDef);
+
+  protected
+    procedure WriteDef(Output: TPpuOutput); override;
+
+  public
+    ItemsName: string;
+
+    constructor Create(AParent: TPpuContainerDef); override;
+    destructor Destroy; override;
+    function Add(Def: TPpuDef): integer;
+    property Items[Index: Integer]: TPpuDef read GetItem write SetItem; default;
+    property Count: integer read GetCount;
+  end;
+
+  { TPpuUnitDef }
+
+  TPpuUnitDef = class(TPpuContainerDef)
+  protected
+    procedure WriteDef(Output: TPpuOutput); override;
+  public
+    Version: cardinal;
+    Crc, IntfCrc: cardinal;
+    TargetOS, TargetCPU: string;
+    UsedUnits: TPpuContainerDef;
+    RefUnits: array of string;
+    SourceFiles: TPpuContainerDef;
+    constructor Create(AParent: TPpuContainerDef); override;
+    destructor Destroy; override;
+  end;
+
+  { TPpuSrcFile }
+
+  TPpuSrcFile = class(TPpuDef)
+  protected
+    procedure WriteDef(Output: TPpuOutput); override;
+  public
+    FileTime: TDateTime;
+  end;
+
+implementation
+
+const
+  DefTypeNames: array[TPpuDefType] of string =
+    ('', 'unit', 'class', 'record', 'procedure', 'field', 'property', 'parameter', 'variable',
+     'type', 'constant', 'proctype', 'enum', 'set');
+
+{ TPpuSrcFile }
+
+procedure TPpuSrcFile.WriteDef(Output: TPpuOutput);
+begin
+  inherited WriteDef(Output);
+  Output.WriteStr('Time', FormatDateTime('yyyy"-"mm"-"dd hh":"nn":"ss', FileTime));
+end;
+
+{ TPpuOutput }
+
+procedure TPpuOutput.SetIndent(AValue: integer);
+begin
+  if FIndent=AValue then Exit;
+  FIndent:=AValue;
+  if FIndent < 0 then
+    FIndent:=0;
+  SetLength(FIndStr, FIndent*IndentSize);
+  if FIndent > 0 then
+    FillChar(FIndStr[1], FIndent*IndentSize, ' ');
+end;
+
+procedure TPpuOutput.SetIndentSize(AValue: integer);
+begin
+  if FIndentSize=AValue then Exit;
+  FIndentSize:=AValue;
+end;
+
+procedure TPpuOutput.WriteDefStart(Def: TPpuDef);
+begin
+end;
+
+procedure TPpuOutput.WriteDefEnd(Def: TPpuDef);
+begin
+end;
+
+procedure TPpuOutput.WriteSubItemsStart(Def: TPpuContainerDef);
+begin
+end;
+
+procedure TPpuOutput.WriteSubItemsEnd(Def: TPpuContainerDef);
+begin
+end;
+
+procedure TPpuOutput.WriteStr(const AName, AValue: string);
+begin
+end;
+
+procedure TPpuOutput.WriteInt(const AName: string; AValue: Int64);
+begin
+  WriteStr(AName, IntToStr(AValue));
+end;
+
+procedure TPpuOutput.WriteFloat(const AName: string; AValue: extended);
+var
+  s: string;
+begin
+  Str(AValue, s);
+  WriteStr(AName, s);
+end;
+
+procedure TPpuOutput.WriteBool(const AName: string; AValue: boolean);
+var
+  s: string;
+begin
+  if AValue then
+    s:='1'
+  else
+    s:='0';
+  WriteStr(AName, s);
+end;
+
+procedure TPpuOutput.WriteArrayStart(const AName: string);
+begin
+end;
+
+procedure TPpuOutput.WriteArrayEnd(const AName: string);
+begin
+end;
+
+constructor TPpuOutput.Create(var OutFile: Text);
+begin
+  FOutFile:=@OutFile;
+  FIndentSize:=2;
+end;
+
+destructor TPpuOutput.Destroy;
+begin
+  inherited Destroy;
+end;
+
+procedure TPpuOutput.Write(const s: string);
+begin
+  if not FNoIndent then
+    System.Write(FOutFile^, FIndStr);
+  System.Write(FOutFile^, s);
+  FNoIndent:=True;
+end;
+
+procedure TPpuOutput.WriteLn(const s: string);
+begin
+  Self.Write(s + LineEnding);
+  FNoIndent:=False;
+end;
+
+procedure TPpuOutput.IncI;
+begin
+  Indent:=Indent + 1;
+end;
+
+procedure TPpuOutput.DecI;
+begin
+  Indent:=Indent - 1;
+end;
+
+{ TPpuUnitDef }
+
+procedure TPpuUnitDef.WriteDef(Output: TPpuOutput);
+var
+  i: integer;
+begin
+  with Output do begin
+    if Version <> 0 then
+      WriteInt('Version', Version);
+    if TargetCPU <> '' then
+      WriteStr('TargetCPU', TargetCPU);
+    if TargetOS <> '' then
+      WriteStr('TargetOS', TargetOS);
+    if Crc <> 0 then
+      WriteStr('Crc', hexStr(Crc, 8));
+    if IntfCrc <> 0 then
+      WriteStr('InterfaceCrc', hexStr(IntfCrc, 8));
+    UsedUnits.WriteDef(Output);
+    if Length(RefUnits) > 0 then begin
+      WriteArrayStart('RefUnits');
+      for i:=0 to High(RefUnits) do
+        WriteStr('', RefUnits[i]);
+      WriteArrayEnd('RefUnits');
+    end;
+    SourceFiles.WriteDef(Output);
+  end;
+  inherited WriteDef(Output);
+end;
+
+constructor TPpuUnitDef.Create(AParent: TPpuContainerDef);
+begin
+  inherited Create(AParent);
+  DefType:=dtUnit;
+  UsedUnits:=TPpuContainerDef.Create(nil);
+  UsedUnits.FParent:=Self;
+  UsedUnits.ItemsName:='UsedUnits';
+  SourceFiles:=TPpuContainerDef.Create(nil);
+  SourceFiles.FParent:=Self;
+  SourceFiles.ItemsName:='SrcFiles';
+end;
+
+destructor TPpuUnitDef.Destroy;
+begin
+  UsedUnits.Free;
+  SourceFiles.Free;
+  inherited Destroy;
+end;
+
+{ TPpuContainerDef }
+
+function TPpuContainerDef.GetCount: integer;
+begin
+  Result:=FItems.Count;
+end;
+
+function TPpuContainerDef.GetItem(Index: Integer): TPpuDef;
+begin
+  Result:=TPpuDef(FItems[Index]);
+end;
+
+procedure TPpuContainerDef.SetItem(Index: Integer; AValue: TPpuDef);
+begin
+  FItems[Index]:=AValue;
+end;
+
+procedure TPpuContainerDef.WriteDef(Output: TPpuOutput);
+var
+  i: integer;
+begin
+  inherited WriteDef(Output);
+  if Count = 0 then
+    exit;
+  Output.WriteSubItemsStart(Self);
+  if Parent <> nil then
+    Output.IncI;
+  for i:=0 to Count - 1 do
+    Items[i].Write(Output);
+  if Parent <> nil then
+    Output.DecI;
+  Output.WriteSubItemsEnd(Self);
+end;
+
+constructor TPpuContainerDef.Create(AParent: TPpuContainerDef);
+begin
+  inherited Create(AParent);
+  FItems:=TList.Create;
+  ItemsName:='Contents';
+end;
+
+destructor TPpuContainerDef.Destroy;
+var
+  i: integer;
+begin
+  for i:=0 to FItems.Count - 1 do
+    TObject(FItems[i]).Free;
+  FItems.Free;
+  inherited Destroy;
+end;
+
+function TPpuContainerDef.Add(Def: TPpuDef): integer;
+begin
+  Result:=FItems.Add(Def);
+  Def.FParent:=Self;
+end;
+
+{ TPpuDef }
+
+function TPpuDef.GetDefTypeName: string;
+begin
+  Result:=DefTypeNames[DefType];
+end;
+
+procedure TPpuDef.SetProps(AValue: TStringList);
+begin
+
+end;
+
+procedure TPpuDef.WriteDef(Output: TPpuOutput);
+begin
+  with Output do begin
+    if DefId >= 0 then
+      WriteInt('Id', DefId);
+  end;
+end;
+
+constructor TPpuDef.Create(AParent: TPpuContainerDef);
+begin
+  DefId:=-1;
+  if AParent <> nil then
+    AParent.Add(Self);
+end;
+
+destructor TPpuDef.Destroy;
+begin
+  inherited Destroy;
+end;
+
+procedure TPpuDef.Write(Output: TPpuOutput);
+begin
+  Output.WriteDefStart(Self);
+  WriteDef(Output);
+  Output.WriteDefEnd(Self);
+end;
+
+end.
+