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:
Abou Al Montacir 2023-05-18 10:07:33 +02:00
parent 1a9142c9e2
commit d1f64050ea
2 changed files with 80 additions and 18 deletions

View File

@ -45,6 +45,7 @@ type
FUnitPrefix: String; FUnitPrefix: String;
FOverWriteFiles: Boolean; FOverWriteFiles: Boolean;
FOptions: TgirOptions; FOptions: TgirOptions;
FEnumImpl: TgirEnumImpl;
procedure AddDefaultPaths; procedure AddDefaultPaths;
procedure AddPaths(APaths: String); procedure AddPaths(APaths: String);
procedure VerifyOptions; procedure VerifyOptions;
@ -256,6 +257,7 @@ begin
AddOption(['P', 'unit-prefix'], True, 'Set a prefix to be added to each unitname.'); 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(['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(['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; end;
FCmdOptions.ReadOptions; FCmdOptions.ReadOptions;
if FCmdOptions.OptionsMalformed then if FCmdOptions.OptionsMalformed then
@ -263,6 +265,9 @@ begin
end; end;
procedure TGirConsoleConverter.DoRun; procedure TGirConsoleConverter.DoRun;
var
EnumImpl: TgirEnumImpl;
ErrorCode: Word;
begin begin
// quick check parameters // quick check parameters
CheckOptions;//('hnp:o:i:wtDCsO',['help','no-default','paths','output-directory', 'input', 'overwrite-files', 'test', 'dynamic', 'classes', 'seperate-units', 'objects']); 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 else
FUnitPrefix:=''; 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; VerifyOptions;
// does all the heavy lifting // does all the heavy lifting

View File

@ -8,9 +8,12 @@ uses
Classes, SysUtils, girNameSpaces, girObjects, girTokens, contnrs, StrUtils; Classes, SysUtils, girNameSpaces, girObjects, girTokens, contnrs, StrUtils;
type 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; TgirOptions = set of TgirOption;
TgirWriteEvent = procedure (Sender: TObject; AUnitName: AnsiString; AStream: TStringStream) of object; TgirWriteEvent = procedure (Sender: TObject; AUnitName: AnsiString; AStream: TStringStream) of object;
TgirEnumImpl = goEnumAsIntConst..goEnumAsSet;
TPDeclaration = class TPDeclaration = class
function AsString: String; virtual; abstract; function AsString: String; virtual; abstract;
@ -200,7 +203,7 @@ type
procedure HandleNativeType(AItem: TgirNativeTypeDef); procedure HandleNativeType(AItem: TgirNativeTypeDef);
procedure HandleAlias(AItem: TgirAlias); procedure HandleAlias(AItem: TgirAlias);
procedure HandleCallback(AItem: TgirCallback); procedure HandleCallback(AItem: TgirCallback);
procedure HandleEnum(AItem: TgirEnumeration; ADeclareType: Boolean = True); procedure HandleEnum(AItem: TgirEnumeration);
procedure HandleBitfield(AItem: TgirBitField); procedure HandleBitfield(AItem: TgirBitField);
procedure HandleRecord(AItem: TgirRecord); procedure HandleRecord(AItem: TgirRecord);
procedure HandleOpaqueType(AItem: TgirFuzzyType); procedure HandleOpaqueType(AItem: TgirFuzzyType);
@ -906,7 +909,6 @@ end;
procedure TPascalUnit.HandleAlias(AItem: TgirAlias); procedure TPascalUnit.HandleAlias(AItem: TgirAlias);
var var
ResolvedForName: String; ResolvedForName: String;
CType: TGirBaseType = nil;
ProperUnit: TPascalUnit; ProperUnit: TPascalUnit;
TargetType: TGirBaseType = nil; TargetType: TGirBaseType = nil;
begin begin
@ -970,55 +972,101 @@ begin
TypeSect.Lines.Add(IndentText(CB,2,0)) TypeSect.Lines.Add(IndentText(CB,2,0))
end; 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 var
ConstSection: TPDeclarationConst; ConstSection: TPDeclarationConst;
Section: TPDeclarationWithLines;
Entry: String; Entry: String;
i: Integer; i: Integer;
CName: String; CName: String;
TypeName: String; TypeName: String;
ProperUnit: TPascalUnit; ProperUnit: TPascalUnit;
IntType: String; IntType: String;
Value: String;
begin begin
ProperUnit := FGroup.GetUnitForType(utTypes); ProperUnit := FGroup.GetUnitForType(utTypes);
if ProperUnit <> Self then begin if ProperUnit <> Self then begin
ProperUnit.HandleEnum(AItem, ADeclareType); ProperUnit.HandleEnum(AItem);
Exit; Exit;
end; end;
ResolveTypeTranslation(AItem); ResolveTypeTranslation(AItem);
ConstSection := WantConstSection; ConstSection := WantConstSection;
ConstSection.Lines.Add(''); if goEnumAsSet in FOptions then begin
//ATK_HYPERLINK_IS_INLINE_ raise Exception.Create('Not yet supported!');
if ADeclareType then end else if goEnumAsEnum in FOptions then begin
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 // forces forward declarations to be written
ProcessType(AItem); ProcessType(AItem);
TypeName := ': '+AItem.TranslatedName; TypeName := AItem.TranslatedName;
if AItem.NeedsSignedType then if AItem.NeedsSignedType then
IntType := 'Integer' IntType := 'Integer'
else else
IntType := 'DWord'; IntType := 'DWord';
// yes we cheat a little here using the const section to write type info // yes we cheat a little here using the const section to write type info
ConstSection.Lines.Add('');
ConstSection.Lines.Add('type'); ConstSection.Lines.Add('type');
ConstSection.Lines.Add(IndentText(AItem.TranslatedName+' = '+IntType+';', 2,0)); ConstSection.Lines.Add(IndentText(AItem.TranslatedName+' = '+IntType+';', 2,0));
ConstSection.Lines.Add('const'); ConstSection.Lines.Add('const');
end ConstSection.Lines.Add(IndentText('{ '+ AItem.CType + ' }', 2, 0));
else Section := ConstSection;
end else begin
TypeName:=''; 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 for i := 0 to AItem.Members.Count-1 do
begin begin
CName := AItem.Members.Member[i]^.CIdentifier; CName := AItem.Members.Member[i]^.CIdentifier;
if CName = 'ATK_HYPERLINK_IS_INLINE' then if CName = 'ATK_HYPERLINK_IS_INLINE' then
CName :='ATK_HYPERLINK_IS_INLINE_'; CName :='ATK_HYPERLINK_IS_INLINE_';
Entry := CName + TypeName+ ' = ' + AItem.Members.Member[i]^.Value+';'; Value := AItem.Members.Member[i]^.Value;
ConstSection.Lines.Add(IndentText(Entry,2,0)); 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; 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; AItem.Writing:=msWritten;
end; end;
@ -1039,7 +1087,7 @@ var
VarType: String; VarType: String;
} }
begin begin
HandleEnum(AItem, True); HandleEnum(AItem);
(* (*
Intf := WantTypeSection; Intf := WantTypeSection;
CodeText := TPCodeText.Create; CodeText := TPCodeText.Create;
@ -1059,7 +1107,7 @@ begin
Halt; Halt;
end; end;
} }
HandleEnum(AItem, False); HandleEnum(AItem);
VarType:='DWord'; VarType:='DWord';