Added some code to create c and pascal files to test type sizes.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1994 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
drewski207
2011-09-24 00:21:23 +00:00
parent d4c63d5b73
commit ae75be9603
6 changed files with 194 additions and 36 deletions

View File

@ -23,6 +23,7 @@
</BuildModes> </BuildModes>
<PublishOptions> <PublishOptions>
<Version Value="2"/> <Version Value="2"/>
<DestinationDirectory Value="/tmp/publishedproject/"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/> <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions> </PublishOptions>
@ -30,7 +31,7 @@
<local> <local>
<FormatVersion Value="1"/> <FormatVersion Value="1"/>
<CommandLineParams Value="-i /usr/share/gir-1.0/Gtk-3.0.gir -o /tmp/gir-out -w"/> <CommandLineParams Value="-i /usr/share/gir-1.0/Gtk-3.0.gir -o /tmp/gir-out -w"/>
<LaunchingApplication Use="True" PathPlusParams="/usr/bin/gnome-terminal -t 'Lazarus Run Output' -e '$(LazarusDir)/tools/runwait.sh $(TargetCmdLine)'"/> <LaunchingApplication PathPlusParams="/usr/bin/gnome-terminal -t 'Lazarus Run Output' -e '$(LazarusDir)/tools/runwait.sh $(TargetCmdLine)'"/>
</local> </local>
</RunParams> </RunParams>
<Units Count="8"> <Units Count="8">

View File

@ -38,6 +38,7 @@ type
FOutPutDirectory : String; FOutPutDirectory : String;
FFileToConvert: String; FFileToConvert: String;
FOverWriteFiles: Boolean; FOverWriteFiles: Boolean;
FWantTest: Boolean;
procedure AddDefaultPaths; procedure AddDefaultPaths;
procedure AddPaths(APaths: String); procedure AddPaths(APaths: String);
procedure VerifyOptions; procedure VerifyOptions;
@ -45,7 +46,8 @@ type
//callbacks //callbacks
function NeedGirFile(AGirFile: TObject; NamespaceName: String) : TXMLDocument; function NeedGirFile(AGirFile: TObject; NamespaceName: String) : TXMLDocument;
procedure WritePascalFile(Sender: TObject; AUnitName: String; AStream: TStringStream); // AName is the whole name unit.pas or file.c
procedure WriteFile(Sender: TObject; AName: String; AStream: TStringStream);
protected protected
procedure DoRun; override; procedure DoRun; override;
public public
@ -110,14 +112,13 @@ begin
end; end;
end; end;
procedure TGirConsoleConverter.WritePascalFile(Sender: TObject; procedure TGirConsoleConverter.WriteFile(Sender: TObject; AName: String; AStream: TStringStream);
AUnitName: String; AStream: TStringStream);
var var
SStream: TFileStream; SStream: TFileStream;
OutFileName: String; OutFileName: String;
begin begin
Inc(FWriteCount); Inc(FWriteCount);
OutFileName:=FOutPutDirectory+LowerCase(AUnitName)+'.pas'; OutFileName:=FOutPutDirectory+LowerCase(AName);
if not FileExists(OutFileName) if not FileExists(OutFileName)
or (FileExists(OutFileName) and FOverWriteFiles) then or (FileExists(OutFileName) and FOverWriteFiles) then
begin begin
@ -152,8 +153,8 @@ begin
girFile.ParseXMLDocument(Doc); girFile.ParseXMLDocument(Doc);
Doc.Free; Doc.Free;
Writer := TgirPascalWriter.Create(girFile.NameSpaces); Writer := TgirPascalWriter.Create(girFile.NameSpaces, FWantTest);
Writer.OnUnitWriteEvent:= @WritePascalFile; Writer.OnUnitWriteEvent:= @WriteFile;
Writer.GenerateUnits; Writer.GenerateUnits;
Writer.Free; Writer.Free;
@ -168,7 +169,7 @@ var
ErrorMsg: String; ErrorMsg: String;
begin begin
// quick check parameters // quick check parameters
ErrorMsg:=CheckOptions('hnp:o:i:w',['help','no-default','paths','output-directory', 'input', 'overwrite-files']); ErrorMsg:=CheckOptions('hnp:o:i:wt',['help','no-default','paths','output-directory', 'input', 'overwrite-files', 'test']);
if ErrorMsg<>'' then begin if ErrorMsg<>'' then begin
ShowException(Exception.Create(ErrorMsg)); ShowException(Exception.Create(ErrorMsg));
Terminate; Terminate;
@ -198,6 +199,8 @@ begin
if HasOption('w', 'overwrite-files') then if HasOption('w', 'overwrite-files') then
FOverWriteFiles:=True; FOverWriteFiles:=True;
FWantTest := HasOption('t', 'test');
VerifyOptions; VerifyOptions;
// does all the heavy lifting // does all the heavy lifting
@ -232,6 +235,7 @@ begin
Writeln(' -n --no-default /usr/share/gir-1.0 is not added as a search location for '); Writeln(' -n --no-default /usr/share/gir-1.0 is not added as a search location for ');
Writeln(' needed .gir files.'); Writeln(' needed .gir files.');
Writeln(' -p --paths= List of paths seperated by ":" to search for needed .gir files.'); Writeln(' -p --paths= List of paths seperated by ":" to search for needed .gir files.');
Writeln(' -t --test Creates a test program and a test c file per unit to verify struct sizes.');
Writeln(''); Writeln('');
end; end;

View File

@ -59,32 +59,33 @@ uses girErrors, girTokens;
procedure TgirFile.ParseNode(ANode: TDomNode); procedure TgirFile.ParseNode(ANode: TDomNode);
var var
Node: TDomNode;
NS: TgirNamespace; NS: TgirNamespace;
Includes: TList; Includes: TList;
begin begin
if ANode.NodeName <> 'repository' then if ANode.NodeName <> 'repository' then
girError(geError, 'Not a Valid Document Type!'); girError(geError, 'Not a Valid Document Type!');
ANode := Anode.FirstChild; Node := Anode.FirstChild;
Ns := nil; Ns := nil;
Includes := TList.Create; Includes := TList.Create;
while ANode <> nil do begin while Node <> nil do begin
case GirTokenNameToToken(ANode.NodeName) of case GirTokenNameToToken(Node.NodeName) of
gtInclude: ParseIncludeNode(ANode, Includes); gtInclude: ParseIncludeNode(Node, Includes);
gtNameSpace: gtNameSpace:
begin begin
NS := TgirNamespace.CreateFromNamespaceNode(NameSpaces, ANode, Includes); NS := TgirNamespace.CreateFromRepositoryNode(NameSpaces, ANode, Includes);
girError(geDebug, 'Adding Namespace '+NS.NameSpace+' to NameSpaces'); girError(geDebug, 'Adding Namespace '+NS.NameSpace+' to NameSpaces');
FNameSpaces.Add(NS); FNameSpaces.Add(NS);
girError(geDebug, 'Added Namespace '+NS.NameSpace); girError(geDebug, 'Added Namespace '+NS.NameSpace);
NS.ParseNode(ANode); NS.ParseNode(Node);
end; end;
gtPackage, gtCInclude: ;// ignore for now gtPackage, gtCInclude: ;// ignore for now
else else
girError(geDebug, 'Unknown Node Type for Reposiotory: '+ Anode.NodeName); girError(geDebug, 'Unknown Node Type for Reposiotory: '+ node.NodeName);
end; end;
ANode := ANode.NextSibling; Node := Node.NextSibling;
end; end;

View File

@ -34,7 +34,9 @@ type
TgirNamespace = class(IgirParser) TgirNamespace = class(IgirParser)
private private
FCIncludeName: String;
FConstants: TList; FConstants: TList;
FCPackageName: String;
FFunctions: TList; FFunctions: TList;
FNameSpace: String; FNameSpace: String;
FOnlyImplied: Boolean; FOnlyImplied: Boolean;
@ -75,9 +77,11 @@ type
procedure ParseNode(ANode: TDomNode); procedure ParseNode(ANode: TDomNode);
procedure ParseSubNode(ANode: TDomNode); // generally do not use outside of TgirNameSpace procedure ParseSubNode(ANode: TDomNode); // generally do not use outside of TgirNameSpace
constructor Create(AOwner:TObject; AImpliedNamespace: String); constructor Create(AOwner:TObject; AImpliedNamespace: String);
constructor CreateFromNamespaceNode(AOwner:TObject; ANode: TDOMNode; AIncludes: TList); constructor CreateFromRepositoryNode(AOwner:TObject; ANode: TDOMNode; AIncludes: TList);
destructor Destroy; override; destructor Destroy; override;
property NameSpace: String read FNameSpace; property NameSpace: String read FNameSpace;
property CIncludeName: String read FCIncludeName;
property CPackageName: String read FCPackageName;
property RequiredNameSpaces: TList Read FRequiredNameSpaces; property RequiredNameSpaces: TList Read FRequiredNameSpaces;
property SharedLibrary: String read FSharedLibrary; property SharedLibrary: String read FSharedLibrary;
property Version: String read FVersion; property Version: String read FVersion;
@ -499,19 +503,39 @@ begin
girError(geDebug, 'Creating Stub for namespace: '+ AImpliedNamespace); girError(geDebug, 'Creating Stub for namespace: '+ AImpliedNamespace);
end; end;
constructor TgirNamespace.CreateFromNamespaceNode(AOwner:TObject; ANode: TDOMNode; AIncludes: TList); constructor TgirNamespace.CreateFromRepositoryNode(AOwner:TObject; ANode: TDOMNode; AIncludes: TList);
procedure SetCInclude;
var
Child: TDomElement;
begin
Child := TDOMElement(ANode.FindNode('c:include name'));
if (Child <> nil) and Child.InheritsFrom(TDOMElement) then
FCIncludeName:= Child.GetAttribute('name');
end;
procedure SetPackage;
var
Child: TDOMElement;
begin
Child := TDOMElement(ANode.FindNode('package'));
if (Child <> nil) and Child.InheritsFrom(TDOMElement) then
FCPackageName:=Child.GetAttribute('name');
end;
var var
Node: TDOMElement absolute ANode; Node: TDOMElement;
begin begin
FOwner := AOwner; FOwner := AOwner;
if ANode = nil then if ANode = nil then
girError(geError, 'expected namespace got nil'); girError(geError, 'expected namespace got nil');
if ANode.NodeName <> 'namespace' then if ANode.NodeName <> 'repository' then
girError(geError, 'expected namespace got '+ANode.NodeName); girError(geError, 'expected "repository" got '+ANode.NodeName);
Node := TDOMElement( ANode.FindNode('namespace') );
FNameSpace:=Node.GetAttribute('name'); FNameSpace:=Node.GetAttribute('name');
FRequiredNameSpaces := AIncludes; FRequiredNameSpaces := AIncludes;
FSharedLibrary:=Node.GetAttribute('shared-library'); FSharedLibrary:=Node.GetAttribute('shared-library');
FVersion:=Node.GetAttribute('version'); FVersion:=Node.GetAttribute('version');
SetCInclude;
SetPackage;
girError(geDebug, Format('Creating namespace=%s Version=%s LibName=%s',[FNameSpace, FVersion, FSharedLibrary])); girError(geDebug, Format('Creating namespace=%s Version=%s LibName=%s',[FNameSpace, FVersion, FSharedLibrary]));
FConstants := TList.Create; FConstants := TList.Create;

View File

@ -43,6 +43,7 @@ type
FCType: String; FCType: String;
FDoc: String; FDoc: String;
FForwardDefinitionWritten: Boolean; FForwardDefinitionWritten: Boolean;
FHasFields: Boolean;
FImpliedPointerLevel: Integer; FImpliedPointerLevel: Integer;
FName: String; FName: String;
FObjectType: TGirObjectType; FObjectType: TGirObjectType;
@ -265,9 +266,11 @@ type
{ TgirFieldsList } { TgirFieldsList }
TgirFieldsList = class(TFPList) TgirFieldsList = class(TList)
private private
FHasFields: Boolean;
function GetField(AIndex: Integer): TGirBaseType; function GetField(AIndex: Integer): TGirBaseType;
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
public public
property Field[AIndex: Integer]: TGirBaseType read GetField; property Field[AIndex: Integer]: TGirBaseType read GetField;
end; end;
@ -277,6 +280,7 @@ type
TgirRecord = class(TGirBaseType) TgirRecord = class(TGirBaseType)
private private
FFields: TgirFieldsList; FFields: TgirFieldsList;
function GetHasFields: Boolean;
protected protected
procedure HandleUnion(ANode: TDomNode); procedure HandleUnion(ANode: TDomNode);
procedure HandleField(ANode: TDomNode); procedure HandleField(ANode: TDomNode);
@ -285,6 +289,7 @@ type
constructor Create(AOwner: TObject; ANode: TDomNode); override; constructor Create(AOwner: TObject; ANode: TDomNode); override;
destructor Destroy; override; destructor Destroy; override;
property Fields: TgirFieldsList read FFields; property Fields: TgirFieldsList read FFields;
property HasFields: Boolean read GetHasFields;
end; end;
{ TgirUnion } { TgirUnion }
@ -413,6 +418,7 @@ constructor TgirBitField.Create(AOwner: TObject; ANode: TDomNode);
begin begin
inherited Create(AOwner, ANode); inherited Create(AOwner, ANode);
FObjectType:=otBitfield; FObjectType:=otBitfield;
FHasFields:=True;
end; end;
{ TgirFieldsList } { TgirFieldsList }
@ -422,6 +428,15 @@ begin
Result := TGirBaseType(Items[AIndex]); Result := TGirBaseType(Items[AIndex]);
end; end;
procedure TgirFieldsList.Notify(Ptr: Pointer; Action: TListNotification);
var
gir: TGirBaseType absolute Ptr;
begin
if FHasFields then
Exit;
FHasFields:= gir.ObjectType in [otTypeParam, otCallback, otArray];
end;
{ TgirParamList } { TgirParamList }
function TgirParamList.GetParam(AIndex: Integer): TGirFunctionParam; function TgirParamList.GetParam(AIndex: Integer): TGirFunctionParam;
@ -625,6 +640,10 @@ end;
function TgirRecord.GetHasFields: Boolean;
begin
Result := Fields.FHasFields;
end;
procedure TgirRecord.HandleUnion(ANode: TDomNode); procedure TgirRecord.HandleUnion(ANode: TDomNode);
var var

View File

@ -26,19 +26,22 @@ uses
Classes, SysUtils, girNameSpaces, girObjects, girTokens, contnrs; Classes, SysUtils, girNameSpaces, girObjects, girTokens, contnrs;
type type
TUnitWriteEvent = procedure (Sender: TObject; AUnitName: AnsiString; AStream: TStringStream) of object; TgirWriteEvent = procedure (Sender: TObject; AUnitName: AnsiString; AStream: TStringStream) of object;
{ TgirPascalWriter } { TgirPascalWriter }
TgirPascalWriter = class TgirPascalWriter = class
private private
FOnUnitWriteEvent: TUnitWriteEvent; FDefaultUnitExtension: String;
FOnUnitWriteEvent: TgirWriteEvent;
FNameSpaces: TgirNamespaces; FNameSpaces: TgirNamespaces;
FUnits: TList; FUnits: TList;
FWantTest: Boolean;
public public
constructor Create(ANameSpaces: TgirNamespaces); constructor Create(ANameSpaces: TgirNamespaces; AWantTest: Boolean);
procedure GenerateUnits; procedure GenerateUnits;
property OnUnitWriteEvent: TUnitWriteEvent read FOnUnitWriteEvent write FOnUnitWriteEvent; property OnUnitWriteEvent: TgirWriteEvent read FOnUnitWriteEvent write FOnUnitWriteEvent;
property DefaultUnitExtension: String read FDefaultUnitExtension write FDefaultUnitExtension; // is .pas by default
end; end;
@ -180,7 +183,11 @@ type
FInterfaceSection: TPInterface; FInterfaceSection: TPInterface;
FLibName: String; FLibName: String;
FNameSpace: TgirNamespace; FNameSpace: TgirNamespace;
FWantTest: Boolean;
ProcessLevel: Integer; //used to know if to write forward definitions ProcessLevel: Integer; //used to know if to write forward definitions
FTestCFile: TStringStream;
FTestPascalFile: TStringStream;
FTestPascalBody: TStringList;
function GetUnitName: String; function GetUnitName: String;
// functions to ensure the type is being written in the correct declaration // functions to ensure the type is being written in the correct declaration
@ -230,13 +237,16 @@ type
procedure ProcessType(AType: TGirBaseType; AForceWrite: Boolean = False); procedure ProcessType(AType: TGirBaseType; AForceWrite: Boolean = False);
procedure ResolveFuzzyTypes; procedure ResolveFuzzyTypes;
procedure AddTestType(APascalName: String; ACName: String);
public public
constructor Create(ANameSpace: TgirNamespace; ALinkDynamic: Boolean); constructor Create(ANameSpace: TgirNamespace; ALinkDynamic: Boolean; AWantTest: Boolean);
destructor Destroy; override;
procedure ProcessConsts(AList:TList); // of TgirBaseType descandants procedure ProcessConsts(AList:TList); // of TgirBaseType descandants
procedure ProcessTypes(AList:TFPHashObjectList); // of TgirBaseType descandants procedure ProcessTypes(AList:TFPHashObjectList); // of TgirBaseType descandants
procedure ProcessFunctions(AList:TList);// of TgirFunction procedure ProcessFunctions(AList:TList);// of TgirFunction
procedure GenerateUnit; procedure GenerateUnit;
function AsStream: TStringStream; function AsStream: TStringStream;
procedure Finish;
property InterfaceSection: TPInterface read FInterfaceSection; property InterfaceSection: TPInterface read FInterfaceSection;
property ImplementationSection: TPImplementation read FImplementationSection; property ImplementationSection: TPImplementation read FImplementationSection;
@ -614,6 +624,8 @@ begin
WriteLn('Unknown Type: ', AType.ClassName); WriteLn('Unknown Type: ', AType.ClassName);
Halt; Halt;
end; // case end; // case
if (AType.InheritsFrom(TgirRecord)) and (TgirRecord(AType).HasFields) then
AddTestType(AType.TranslatedName, AType.CType);
AType.Writing:=msWritten; AType.Writing:=msWritten;
Dec(ProcessLevel); Dec(ProcessLevel);
@ -643,6 +655,43 @@ begin
end; end;
end; end;
procedure TPascalUnit.AddTestType(APascalName: String; ACName: String);
const
CFunction = 'int GetSizeOf_%s(void)'+
'{ return sizeof(%s); };'+LineEnding;
PImport = 'function GetSizeOf_%s: LongInt; cdecl; external;'+LineEnding;
PTest = 'procedure Test_%s;' +LineEnding+
'var' +LineEnding+
' PSize: Integer;' +LineEnding+
' CSize: Integer;' +LineEnding+
'begin' +LineEnding+
' PSize := SizeOf(%s);' +LineEnding+
' CSize := GetSizeOf_%s;' +LineEnding+
' if CSize = PSize then' +LineEnding+
' WriteLn(''%s Matches C Size: '',CSize)' +LineEnding+
' else' +LineEnding+
' WriteLn(''%s size ('',PSize,'') does NOT match %s size ('',CSize,'')'');' +LineEnding+
'end;' +LineEnding;
var
CF: String;
PI: String;
PT: String;
begin
if not FWantTest then
Exit;
if (ACName = '') or (ACName[1] = '_') then // we skip private types
Exit;
CF := Format(CFunction,[ACName, ACName]);
PI := Format(PImport, [ACName]);
PT := Format(PTest, [ACName, APascalName, ACName, APascalName, APascalName, ACName]);
FTestCFile.WriteString(CF); // c sizeof wrapper
FTestPascalFile.WriteString(PI); // c import
FTestPascalFile.WriteString(PT); // pascal testproc
FTestPascalBody.Add(Format('Test_%s;',[ACName])); //call pascal testproc
end;
function TPascalUnit.WantTypeSection: TPDeclarationType; function TPascalUnit.WantTypeSection: TPDeclarationType;
begin begin
if (InterfaceSection.Declarations.Count = 0) if (InterfaceSection.Declarations.Count = 0)
@ -961,6 +1010,7 @@ var
TypeFuncs: TStrings; TypeFuncs: TStrings;
ParentType: String =''; ParentType: String ='';
UsedNames: TStringList; UsedNames: TStringList;
WrittenFields: Integer;
function GetTypeForProperty(AProperty: TgirProperty; out SetFound: Boolean): String; function GetTypeForProperty(AProperty: TgirProperty; out SetFound: Boolean): String;
var var
@ -1040,10 +1090,12 @@ var
Param: String; Param: String;
begin begin
ResolveTypeTranslation(AParam.VarType); ResolveTypeTranslation(AParam.VarType);
if (ParentType <> '') and (ParenParams(AParam.VarType.TranslatedName) = ParentType) then Inc(WrittenFields);
if (WrittenFields = 1) and (AObjectType = gtClass) and (TgirClass(AItem).ParentClass <> nil) then
begin begin
Exit; Exit;
end; end;
Param := WriteParamAsString(AParam,i, nil, UsedNames); Param := WriteParamAsString(AParam,i, nil, UsedNames);
//if Pos('destroy_:', Param) > 0 then //if Pos('destroy_:', Param) > 0 then
// Param := StringReplace(Param, 'destroy_', 'destroy_f', [rfReplaceAll]); // Param := StringReplace(Param, 'destroy_', 'destroy_f', [rfReplaceAll]);
@ -1063,7 +1115,7 @@ var
otCallback, otCallback,
otArray, otArray,
otTypeParam, otTypeParam,
otUnion: ; // these will be done on the second pass. this is to make the field names different if they are the same as some function or property. giving the function priority of the original name otUnion: Exit; // these will be done on the second pass. this is to avoid duplicate names if they are the same as some function or property. giving the function priority of the original name
otGlibSignal : if AObjectType <> gtClass then TypeDecl.Add(IndentText(WriteCallBack(TgirCallback(Field),True, UsedNames),4,0)); // classes do not have signals They are in the class *struct* otGlibSignal : if AObjectType <> gtClass then TypeDecl.Add(IndentText(WriteCallBack(TgirCallback(Field),True, UsedNames),4,0)); // classes do not have signals They are in the class *struct*
@ -1166,11 +1218,17 @@ begin
AddGetTypeProc(TgirGType(AItem)); AddGetTypeProc(TgirGType(AItem));
end; end;
TypeDecl.Add(IndentText(AItem.TranslatedName +' = object'+ParentType,2,0)); TypeDecl.Add(IndentText(AItem.TranslatedName +' = object'+ParentType,2,0));
// two passes to process the fields last for naming reasons
// two passes to process the fields last for naming reasons first for methods/properties second for fields
for i := 0 to Aitem.Fields.Count-1 do for i := 0 to Aitem.Fields.Count-1 do
HandleFieldType(AItem.Fields.Field[i], True); HandleFieldType(AItem.Fields.Field[i], True);
for i := 0 to Aitem.Fields.Count-1 do if AItem.CType <> 'GInitiallyUnowned' then // empty type GInitiallyUnowned is empty and aliased to GObject which causes object introspection to add the types again since it's empty...how many places does that happen...
HandleFieldType(AItem.Fields.Field[i], False); begin
WrittenFields:=0;
for i := 0 to Aitem.Fields.Count-1 do
HandleFieldType(AItem.Fields.Field[i], False);
end;
if TypeFuncs.Count > 0 then if TypeFuncs.Count > 0 then
@ -1595,19 +1653,50 @@ begin
ABaseType.TranslatedName:=MakePascalTypeFromCType(ABaseType.CType, 0); ABaseType.TranslatedName:=MakePascalTypeFromCType(ABaseType.CType, 0);
end; end;
constructor TPascalUnit.Create(ANameSpace: TgirNamespace; ALinkDynamic: Boolean); constructor TPascalUnit.Create(ANameSpace: TgirNamespace; ALinkDynamic: Boolean; AWantTest: Boolean);
const
CBasic = '#include <%s>'+LineEnding;
PBasic = 'program %s_test;'+LineEnding+
'{$LINK %s_c_test}'+LineEnding+
'uses %s;'+LineEnding;
begin begin
ProcessLevel:=0; ProcessLevel:=0;
FWantTest:=AWantTest;
FLinkDynamic := ALinkDynamic; FLinkDynamic := ALinkDynamic;
FFinalizeSection := TPFinialization.Create(Self); FFinalizeSection := TPFinialization.Create(Self);
FImplementationSection := TPImplementation.Create(Self); FImplementationSection := TPImplementation.Create(Self);
FInitializeSection := TPInitialize.Create(Self); FInitializeSection := TPInitialize.Create(Self);
FInterfaceSection := TPInterface.Create(Self, TPUses.Create); FInterfaceSection := TPInterface.Create(Self, TPUses.Create);
FNameSpace := ANameSpace; FNameSpace := ANameSpace;
if FWantTest then
begin
FTestCFile := TStringStream.Create('');
FTestCFile.WriteString(Format(CBasic, [FNameSpace.CIncludeName]));
FTestPascalFile := TStringStream.Create('');
FTestPascalFile.WriteString(Format(PBasic,[UnitName, UnitName, UnitName]));
FTestPascalBody := TStringList.Create;
FTestPascalBody.Add('begin');
end;
ResolveFuzzyTypes; ResolveFuzzyTypes;
GenerateUnit; GenerateUnit;
end; end;
destructor TPascalUnit.Destroy;
begin
if FWantTest then
begin
FTestPascalFile.Free;
FTestCFile.Free;
FTestPascalBody.Free;
end;
FFinalizeSection.Free;
FImplementationSection.Free;
FInitializeSection.Free;
FInterfaceSection.Free;
inherited Destroy;
end;
procedure TPascalUnit.ProcessConsts(AList: TList); procedure TPascalUnit.ProcessConsts(AList: TList);
function WriteConst(AConst: TgirConstant; Suffix: String = ''): String; function WriteConst(AConst: TgirConstant; Suffix: String = ''): String;
begin begin
@ -1744,6 +1833,17 @@ begin
Result.Position:=0; Result.Position:=0;
end; end;
procedure TPascalUnit.Finish;
begin
if FWantTest then
begin
FTestPascalFile.WriteString(FTestPascalBody.Text);
FTestPascalFile.WriteString('end.');
FTestCFile.Position:=0;
FTestPascalFile.Position:=0;
end;
end;
{ TPDeclarationList } { TPDeclarationList }
function TPDeclarationList.GetDeclarations(AIndex: Integer): TPDeclaration; function TPDeclarationList.GetDeclarations(AIndex: Integer): TPDeclaration;
@ -1763,10 +1863,12 @@ end;
{ TgirPascalWriter } { TgirPascalWriter }
constructor TgirPascalWriter.Create(ANameSpaces: TgirNamespaces); constructor TgirPascalWriter.Create(ANameSpaces: TgirNamespaces; AWantTest: Boolean);
begin begin
FNameSpaces := ANameSpaces; FNameSpaces := ANameSpaces;
FUnits := TList.Create; FUnits := TList.Create;
FDefaultUnitExtension:='.pas';
FWantTest:=AWantTest;
end; end;
procedure TgirPascalWriter.GenerateUnits; procedure TgirPascalWriter.GenerateUnits;
@ -1774,16 +1876,23 @@ var
i: Integer; i: Integer;
FUnit: TPascalUnit; FUnit: TPascalUnit;
begin begin
for i := 0 to FNameSpaces.Count-1 do for i := 0 to FNameSpaces.Count-1 do
begin begin
WriteLn(Format('Converting %s', [FNameSpaces.NameSpace[i].NameSpace])); WriteLn(Format('Converting %s', [FNameSpaces.NameSpace[i].NameSpace]));
FUnit := TPascalUnit.Create(FNameSpaces.NameSpace[i], False); FUnit := TPascalUnit.Create(FNameSpaces.NameSpace[i], False, FWantTest);
FUnit.ProcessConsts(FNameSpaces.NameSpace[i].Constants); FUnit.ProcessConsts(FNameSpaces.NameSpace[i].Constants);
FUnit.ProcessTypes(FNameSpaces.NameSpace[i].Types); FUnit.ProcessTypes(FNameSpaces.NameSpace[i].Types);
FUnit.ProcessFunctions(FNameSpaces.NameSpace[i].Functions); FUnit.ProcessFunctions(FNameSpaces.NameSpace[i].Functions);
FUnit.Finish;
FUnits.Add(FUnit); FUnits.Add(FUnit);
FOnUnitWriteEvent(Self, FUnit.UnitName, FUnit.AsStream); FOnUnitWriteEvent(Self, FUnit.UnitName+FDefaultUnitExtension, FUnit.AsStream);
if FWantTest then
begin
FOnUnitWriteEvent(Self, FUnit.UnitName+'_test'+FDefaultUnitExtension, FUnit.FTestPascalFile);
FOnUnitWriteEvent(Self, FUnit.UnitName+'_c_test.c', FUnit.FTestCFile);
end;
end; end;
end; end;