mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-09 03:48:08 +02:00
gir2pascal: Generate C enums based pascal type selected by CLO, issue #39988.
Added a new command line option (CLO) `-e/--declare-enums-as` that selects the way how to define C enums and bit fields. Added support for 4 options and a 5th to be implemented later. 1. `IntConst`: No type, just use integer non typed constants. This was already implemented, but not easily selected at CLI. 2. `TypedIntConst`: Use non strict type aliases and typed constants. This was already implemented, selected by default in the code. 3. `IntAliasConst`: Use strict type aliases and non typed constants. This was newly added. 4. `Enum`: Use Pascal enumeration type for both C enums and bit fields. This was newly added. 5. `Set`: Use Pascal enumeration type for both C enums and Pascal sets for bit fields. This is not yet added.
This commit is contained in:
parent
1a9142c9e2
commit
d1f64050ea
@ -45,6 +45,7 @@ type
|
||||
FUnitPrefix: String;
|
||||
FOverWriteFiles: Boolean;
|
||||
FOptions: TgirOptions;
|
||||
FEnumImpl: TgirEnumImpl;
|
||||
procedure AddDefaultPaths;
|
||||
procedure AddPaths(APaths: String);
|
||||
procedure VerifyOptions;
|
||||
@ -256,6 +257,7 @@ begin
|
||||
AddOption(['P', 'unit-prefix'], True, 'Set a prefix to be added to each unitname.');
|
||||
AddOption(['M', 'max-version'], True, 'Do not include symbols introduced after <max-version>. Can be used multiple times. i.e "-M gtk-3.12 -M glib-2.23"');
|
||||
AddOption(['k', 'keep-deprecated-version'], True, 'Include deprecated symbols that are >= to $version. Uses the same format as --max-version. Has no effect if --deprecated is defined');
|
||||
AddOption(['e', 'declare-enums-as'], True, 'Declare C enums as either IntConst, TypedIntConst, IntAliasConst, Enum or Set');
|
||||
end;
|
||||
FCmdOptions.ReadOptions;
|
||||
if FCmdOptions.OptionsMalformed then
|
||||
@ -263,6 +265,9 @@ begin
|
||||
end;
|
||||
|
||||
procedure TGirConsoleConverter.DoRun;
|
||||
var
|
||||
EnumImpl: TgirEnumImpl;
|
||||
ErrorCode: Word;
|
||||
begin
|
||||
// quick check parameters
|
||||
CheckOptions;//('hnp:o:i:wtDCsO',['help','no-default','paths','output-directory', 'input', 'overwrite-files', 'test', 'dynamic', 'classes', 'seperate-units', 'objects']);
|
||||
@ -341,6 +346,15 @@ begin
|
||||
else
|
||||
FUnitPrefix:='';
|
||||
|
||||
if FCmdOptions.HasOption('declare-enums-as') then begin
|
||||
Val('goEnumAs' + FCmdOptions.OptionValue('declare-enums-as'), EnumImpl, ErrorCode);
|
||||
if ErrorCode > 0 then begin
|
||||
WriteLn('Invalid enum declaration type: "', FCmdOptions.OptionValue('declare-enums-as'), '"');
|
||||
Terminate;
|
||||
end;
|
||||
Include(FOptions, EnumImpl);
|
||||
end;
|
||||
|
||||
VerifyOptions;
|
||||
|
||||
// does all the heavy lifting
|
||||
|
@ -8,9 +8,12 @@ uses
|
||||
Classes, SysUtils, girNameSpaces, girObjects, girTokens, contnrs, StrUtils;
|
||||
|
||||
type
|
||||
TgirOption = (goWantTest, goLinkDynamic, goSeperateConsts, goClasses, goObjects, goIncludeDeprecated, goNoWrappers);
|
||||
TgirOption = (goWantTest, goLinkDynamic, goSeperateConsts, goClasses, goObjects, goIncludeDeprecated, goNoWrappers,
|
||||
goEnumAsIntConst, goEnumAsTypedIntConst, goEnumAsIntAliasConst, goEnumAsEnum, goEnumAsSet
|
||||
);
|
||||
TgirOptions = set of TgirOption;
|
||||
TgirWriteEvent = procedure (Sender: TObject; AUnitName: AnsiString; AStream: TStringStream) of object;
|
||||
TgirEnumImpl = goEnumAsIntConst..goEnumAsSet;
|
||||
|
||||
TPDeclaration = class
|
||||
function AsString: String; virtual; abstract;
|
||||
@ -200,7 +203,7 @@ type
|
||||
procedure HandleNativeType(AItem: TgirNativeTypeDef);
|
||||
procedure HandleAlias(AItem: TgirAlias);
|
||||
procedure HandleCallback(AItem: TgirCallback);
|
||||
procedure HandleEnum(AItem: TgirEnumeration; ADeclareType: Boolean = True);
|
||||
procedure HandleEnum(AItem: TgirEnumeration);
|
||||
procedure HandleBitfield(AItem: TgirBitField);
|
||||
procedure HandleRecord(AItem: TgirRecord);
|
||||
procedure HandleOpaqueType(AItem: TgirFuzzyType);
|
||||
@ -906,7 +909,6 @@ end;
|
||||
procedure TPascalUnit.HandleAlias(AItem: TgirAlias);
|
||||
var
|
||||
ResolvedForName: String;
|
||||
CType: TGirBaseType = nil;
|
||||
ProperUnit: TPascalUnit;
|
||||
TargetType: TGirBaseType = nil;
|
||||
begin
|
||||
@ -970,55 +972,101 @@ begin
|
||||
TypeSect.Lines.Add(IndentText(CB,2,0))
|
||||
end;
|
||||
|
||||
procedure TPascalUnit.HandleEnum(AItem: TgirEnumeration; ADeclareType: Boolean = True);
|
||||
function CompareEnumValues(v1, v2: Pointer): Integer;
|
||||
begin
|
||||
Result := StrToInt(PgirEnumMember(v1)^.Value) - StrToInt(PgirEnumMember(v2)^.Value);
|
||||
end;
|
||||
|
||||
procedure TPascalUnit.HandleEnum(AItem: TgirEnumeration);
|
||||
var
|
||||
ConstSection: TPDeclarationConst;
|
||||
Section: TPDeclarationWithLines;
|
||||
Entry: String;
|
||||
i: Integer;
|
||||
CName: String;
|
||||
TypeName: String;
|
||||
ProperUnit: TPascalUnit;
|
||||
IntType: String;
|
||||
Value: String;
|
||||
begin
|
||||
ProperUnit := FGroup.GetUnitForType(utTypes);
|
||||
if ProperUnit <> Self then begin
|
||||
ProperUnit.HandleEnum(AItem, ADeclareType);
|
||||
ProperUnit.HandleEnum(AItem);
|
||||
Exit;
|
||||
end;
|
||||
ResolveTypeTranslation(AItem);
|
||||
|
||||
ConstSection := WantConstSection;
|
||||
ConstSection.Lines.Add('');
|
||||
//ATK_HYPERLINK_IS_INLINE_
|
||||
if ADeclareType then
|
||||
begin
|
||||
if goEnumAsSet in FOptions then begin
|
||||
raise Exception.Create('Not yet supported!');
|
||||
end else if goEnumAsEnum in FOptions then begin
|
||||
// forces forward declarations to be written
|
||||
ProcessType(AItem);
|
||||
TypeName := AItem.TranslatedName;
|
||||
Section := WantTypeSection;
|
||||
Section.Lines.Add(IndentText(TypeName + ' = (', 2, 0));
|
||||
Section.Lines.Add(IndentText(TypeName + 'MinValue = -$7FFFFFFF,', 4, 0));
|
||||
AItem.Members.Sort(@CompareEnumValues)
|
||||
end else if goEnumAsIntAliasConst in FOptions then begin
|
||||
// forces forward declarations to be written
|
||||
ProcessType(AItem);
|
||||
TypeName := AItem.TranslatedName;
|
||||
Section := WantConstSection;
|
||||
Section.Lines.Add('');
|
||||
Section.Lines.Add('type');
|
||||
if AItem.NeedsSignedType then
|
||||
IntType := 'Integer'
|
||||
else
|
||||
IntType := 'DWord';
|
||||
// yes we cheat a little here using the const section to write type info
|
||||
Section.Lines.Add(IndentText(TypeName + ' = type ' + IntType + ';', 2, 0));
|
||||
Section.Lines.Add('const');
|
||||
Section.Lines.Add(IndentText('{ '+ AItem.CType + ' }', 2, 0));
|
||||
end else if goEnumAsTypedIntConst in FOptions then begin
|
||||
// forces forward declarations to be written
|
||||
ProcessType(AItem);
|
||||
|
||||
TypeName := ': '+AItem.TranslatedName;
|
||||
|
||||
TypeName := AItem.TranslatedName;
|
||||
if AItem.NeedsSignedType then
|
||||
IntType := 'Integer'
|
||||
else
|
||||
IntType := 'DWord';
|
||||
|
||||
// yes we cheat a little here using the const section to write type info
|
||||
ConstSection.Lines.Add('');
|
||||
ConstSection.Lines.Add('type');
|
||||
ConstSection.Lines.Add(IndentText(AItem.TranslatedName+' = '+IntType+';', 2,0));
|
||||
ConstSection.Lines.Add('const');
|
||||
end
|
||||
else
|
||||
ConstSection.Lines.Add(IndentText('{ '+ AItem.CType + ' }', 2, 0));
|
||||
Section := ConstSection;
|
||||
end else begin
|
||||
TypeName:='';
|
||||
ConstSection.Lines.Add(IndentText('{ '+ AItem.CType + ' }',2,0));
|
||||
ConstSection.Lines.Add(IndentText('{ '+ AItem.CType + ' }', 2, 0));
|
||||
Section := ConstSection;
|
||||
end;
|
||||
|
||||
for i := 0 to AItem.Members.Count-1 do
|
||||
begin
|
||||
CName := AItem.Members.Member[i]^.CIdentifier;
|
||||
if CName = 'ATK_HYPERLINK_IS_INLINE' then
|
||||
CName :='ATK_HYPERLINK_IS_INLINE_';
|
||||
Entry := CName + TypeName+ ' = ' + AItem.Members.Member[i]^.Value+';';
|
||||
ConstSection.Lines.Add(IndentText(Entry,2,0));
|
||||
Value := AItem.Members.Member[i]^.Value;
|
||||
if goEnumAsSet in FOptions then begin
|
||||
end else if goEnumAsEnum in FOptions then begin
|
||||
Entry := IndentText(CName + ' = ' + Value + ',', 4, 0);
|
||||
end else if goEnumAsIntAliasConst in FOptions then begin
|
||||
Entry := IndentText(CName + ' = ' + TypeName + '(' + Value + ');', 2, 0);
|
||||
end else if goEnumAsTypedIntConst in FOptions then begin
|
||||
Entry := IndentText(CName + ': ' + TypeName + ' = ' + Value + ';', 2, 0);
|
||||
end else begin
|
||||
Entry := IndentText(CName + ' = ' + Value + ';', 2, 0);
|
||||
end;
|
||||
Section.Lines.Add(Entry);
|
||||
end;
|
||||
if goEnumAsEnum in FOptions then begin
|
||||
Section.Lines.Add(IndentText(TypeName + 'MaxValue = $7FFFFFFF', 4, 0));
|
||||
Section.Lines.Add(IndentText(');', 2, 0));
|
||||
end;
|
||||
AItem.Writing:=msWritten;
|
||||
end;
|
||||
|
||||
@ -1039,7 +1087,7 @@ var
|
||||
VarType: String;
|
||||
}
|
||||
begin
|
||||
HandleEnum(AItem, True);
|
||||
HandleEnum(AItem);
|
||||
(*
|
||||
Intf := WantTypeSection;
|
||||
CodeText := TPCodeText.Create;
|
||||
@ -1059,7 +1107,7 @@ begin
|
||||
Halt;
|
||||
end;
|
||||
}
|
||||
HandleEnum(AItem, False);
|
||||
HandleEnum(AItem);
|
||||
|
||||
VarType:='DWord';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user