@@ -163,7 +163,8 @@ implementation
163
163
uses
164
164
Winapi.Windows,
165
165
System.Types,
166
- System.IOUtils;
166
+ System.IOUtils,
167
+ System.Masks;
167
168
168
169
{ THeaderTranslator }
169
170
@@ -353,7 +354,7 @@ procedure THeaderTranslator.CreateCombinedHeaderFile;
353
354
var
354
355
Option: TSearchOption;
355
356
Writer: TStreamWriter;
356
- HeaderFiles: TStringDynArray;
357
+ HeaderFiles,IgnoredFiles : TStringDynArray;
357
358
HeaderPath, HeaderFile: String;
358
359
I: Integer;
359
360
begin
@@ -363,7 +364,26 @@ procedure THeaderTranslator.CreateCombinedHeaderFile;
363
364
Option := TSearchOption.soTopDirectoryOnly;
364
365
365
366
HeaderPath := IncludeTrailingPathDelimiter(FProject.HeaderFileDirectory);
366
- HeaderFiles := TDirectory.GetFiles(HeaderPath, ' *.h' , Option);
367
+ IgnoredFiles := FProject.IgnoredFiles.Split([' ,' ],' "' ,' "' ,TStringSplitOptions.ExcludeEmpty);
368
+
369
+ if Length(IgnoredFiles) = 0 then
370
+ HeaderFiles := TDirectory.GetFiles(HeaderPath, ' *.h' , Option)
371
+ else
372
+ HeaderFiles := TDirectory.GetFiles(HeaderPath, ' *.h' , Option,
373
+ function(const Path: string; const SearchRec: TSearchRec): Boolean
374
+ var
375
+ mask: string;
376
+ begin
377
+ for mask in IgnoredFiles do
378
+ begin
379
+ if MatchesMask(SearchRec.Name , mask) then
380
+ Exit(False);
381
+ end ;
382
+
383
+ Result := True;
384
+ end
385
+ );
386
+
367
387
if (Length(HeaderFiles) = 0 ) then
368
388
raise EHeaderTranslatorError.CreateFmt(' No C header files found in directory "%s".' , [FProject.HeaderFileDirectory]);
369
389
@@ -1067,6 +1087,10 @@ procedure THeaderTranslator.SetupTokenMap;
1067
1087
end ;
1068
1088
1069
1089
procedure THeaderTranslator.SetupTypeMap ;
1090
+ var
1091
+ customTypePair: TPair<string,string>;
1092
+ customTypes: TArray<string>;
1093
+ i,n: Integer;
1070
1094
begin
1071
1095
FTypeMap.Add(' size_t' , ' NativeUInt' );
1072
1096
FTypeMap.Add(' intptr_t' , ' IntPtr' );
@@ -1115,12 +1139,24 @@ procedure THeaderTranslator.SetupTypeMap;
1115
1139
// Type FILE the cannot be used in Delphi, so we convert to a Pointer.
1116
1140
FTypeMap.Add(' FILE' , ' Pointer' );
1117
1141
1118
- // WinNT.h
1119
- FTypeMap.Add(' WORD' , ' UInt16' );
1120
- FTypeMap.Add(' DWORD' , ' UInt32' );
1121
- FTypeMap.Add(' LONG' , ' Int32' );
1122
- FTypeMap.Add(' ULONG' , ' UInt32' );
1123
- FTypeMap.Add(' BYTE' , ' Byte' );
1142
+ // attempt to add user-defined types, if any.
1143
+ customTypes := FProject.CustomCTypesMap.Split([' ,' ],' "' ,' "' ,TStringSplitOptions.ExcludeEmpty);
1144
+ for i := 0 to High(customTypes) do
1145
+ begin
1146
+ customTypes[i] := customTypes[i].Replace(' ;' ,' ' ,[rfReplaceAll]).Trim.DeQuotedString(' "' );
1147
+ n := customTypes[i].IndexOf(' =' );
1148
+ if n < 0 then Continue;
1149
+
1150
+ customTypePair.Key := customTypes[i].Substring(0 ,n).DeQuotedString(' "' ).Trim;
1151
+ customTypePair.Value := customTypes[i].Substring(1 +n).DeQuotedString(' "' ).Trim;
1152
+
1153
+ if customTypePair.Key.IsEmpty or
1154
+ customTypePair.Value .IsEmpty or
1155
+ FTypeMap.ContainsKey(customTypePair.Key) then
1156
+ Continue;
1157
+
1158
+ FTypeMap.TryAdd(customTypePair.Key,customTypePair.Value );
1159
+ end ;
1124
1160
end ;
1125
1161
1126
1162
function THeaderTranslator.Spelling (const AType: TType): String;
@@ -2283,9 +2319,10 @@ procedure THeaderTranslator.WriteProceduralType(const ACursor: TCursor;
2283
2319
procedure THeaderTranslator.WriteStructType (const ACursor: TCursor; const AIsUnion: Boolean);
2284
2320
var
2285
2321
T: TType;
2286
- FieldIndex, BitFieldCount: Integer;
2287
- StructName, FieldName, BitDataDelphiTypeName : String;
2322
+ FieldIndex, BitFieldOffsetFromStructStart, BitFieldDataFieldCount, BitFieldCount: Integer;
2323
+ StructName, FieldName: String;
2288
2324
IsAnonymousStruct, IsFieldInited: Boolean;
2325
+ BitFieldValueFieldName: string;
2289
2326
begin
2290
2327
T := ACursor.CursorType;
2291
2328
if (not FWriter.IsAtSectionStart) then
@@ -2308,13 +2345,15 @@ FWriter.WriteLn('%s = record', [StructName]);
2308
2345
2309
2346
FieldIndex := 0 ;
2310
2347
BitFieldCount := 0 ;
2348
+ BitFieldOffsetFromStructStart := 0 ;
2311
2349
IsFieldInited := True;
2312
- BitDataDelphiTypeName := ' ' ;
2350
+ BitFieldDataFieldCount := 0 ;
2351
+
2313
2352
T.VisitFields(
2314
2353
function(const ACursor: TCursor): TVisitorResult
2315
2354
var
2316
2355
CursorType, PointeeType: TType;
2317
- OffsetOfField, BitWidth, BitIndex: Integer;
2356
+ BitWidth, FieldOfset , BitIndex: Integer;
2318
2357
DelphiTypeName: string;
2319
2358
begin
2320
2359
FCommentWriter.WriteComment(ACursor);
@@ -2327,25 +2366,63 @@ FWriter.WriteLn('%s = record', [StructName]);
2327
2366
2328
2367
if ACursor.IsBitField then
2329
2368
begin
2330
- if FieldIndex = 0 then
2369
+ // https://en.cppreference.com/w/cpp/language/bit_field
2370
+ // http://www.rvelthuis.de/articles/articles-convert.html#bitfields
2371
+ // https://stackoverflow.com/questions/282019/how-to-simulate-bit-fields-in-delphi-records#282385
2372
+ BitWidth := ACursor.FieldDeclBitWidth;
2373
+ FieldOfset := BitFieldOffsetFromStructStart;
2374
+ if BitFieldDataFieldCount > 0 then
2375
+ Dec(FieldOfset, 32 * BitFieldDataFieldCount);
2376
+ BitIndex := (FieldOfset shl 8 ) + BitWidth;
2377
+
2378
+ if (BitFieldCount = 0 ) or (BitFieldDataFieldCount > 0 ) then
2331
2379
begin
2332
- BitDataDelphiTypeName := DelphiTypeName;
2380
+ BitFieldValueFieldName := ' Data' + BitFieldDataFieldCount.ToString;
2381
+
2333
2382
FWriter.WriteLn(' private' );
2334
2383
FWriter.Indent;
2335
- FWriter.WriteLn(' FData : ' +DelphiTypeName+' ;' );
2336
- FWriter.WriteLn(' function GetBits (const aIndex: Integer): ' +BitDataDelphiTypeName +' ;' );
2337
- FWriter.WriteLn(' procedure SetBits (const aIndex: Integer; const aValue: ' +BitDataDelphiTypeName +' );' );
2384
+ FWriter.WriteLn(BitFieldValueFieldName+ ' : ' +DelphiTypeName+' ;' );
2385
+ FWriter.WriteLn(' function Get ' +BitFieldValueFieldName+ ' Value (const aIndex: Integer): ' +DelphiTypeName +' ;' );
2386
+ FWriter.WriteLn(' procedure Set ' +BitFieldValueFieldName+ ' Value (const aIndex: Integer; const aValue: ' +DelphiTypeName +' );' );
2338
2387
FWriter.Outdent;
2339
2388
FWriter.WriteLn(' public' );
2389
+
2390
+ if FImplementation = nil then
2391
+ FImplementation := TStringList.Create;
2392
+ // todo: compatibility with "ancient" delphi versions?
2393
+ FImplementation.Add(' {' +StructName +' }' );
2394
+ FImplementation.Add(' function ' +StructName+' .Get' +BitFieldValueFieldName+' Value(const aIndex: Integer): ' +DelphiTypeName+' ;' );
2395
+ FImplementation.Add(' var' );
2396
+ FImplementation.Add(' BitCount, Offset, Mask: Integer;' );
2397
+ FImplementation.Add(' begin' );
2398
+ FImplementation.Add(' // {$UNDEF Q_temp}{$IFOPT Q+}{$DEFINE Q_temp}{$ENDIF}{$Q-} // disable OverFlowChecks' );
2399
+ FImplementation.Add(' BitCount := aIndex and $FF;' );
2400
+ FImplementation.Add(' Offset := aIndex shr 8;' );
2401
+ FImplementation.Add(' Mask := ((1 shl BitCount) - 1);' );
2402
+ FImplementation.Add(' Result := (' +BitFieldValueFieldName+' shr Offset) and Mask;' );
2403
+ FImplementation.Add(' // {$IFDEF Q_temp}{$Q-}{$ENDIF}' );
2404
+ FImplementation.Add(' end;' + sLineBreak);
2405
+
2406
+ FImplementation.Add(' procedure ' +StructName+' .Set' +BitFieldValueFieldName+' Value(const aIndex: Integer; const aValue: ' +DelphiTypeName+' );' );
2407
+ FImplementation.Add(' var' );
2408
+ FImplementation.Add(' BitCount, Offset, Mask: Integer;' );
2409
+ FImplementation.Add(' begin' );
2410
+ FImplementation.Add(' // {$UNDEF Q_temp}{$IFOPT Q+}{$DEFINE Q_temp}{$ENDIF}{$Q-} // disable OverFlowChecks' );
2411
+ FImplementation.Add(' BitCount := aIndex and $FF;' );
2412
+ FImplementation.Add(' Offset := aIndex shr 8;' );
2413
+ FImplementation.Add(' Mask := ((1 shl BitCount) - 1);' );
2414
+ FImplementation.Add(' ' +BitFieldValueFieldName+' := (' +BitFieldValueFieldName+' and (not (Mask shl Offset))) or (aValue shl Offset);' );
2415
+ FImplementation.Add(' // {$IFDEF Q_temp}{$Q-}{$ENDIF}' );
2416
+ FImplementation.Add(' end;' +sLineBreak);
2340
2417
end ;
2341
2418
2342
- OffsetOfField := ACursor.OffsetOfField;
2343
- BitWidth := ACursor.FieldDeclBitWidth;
2344
- BitIndex := (OffsetOfField shl 8 ) + BitWidth;
2345
2419
FWriter.Indent;
2346
- FWriter.WriteLn(' property ' +FieldName+' : ' +DelphiTypeName+' index $' +BitIndex.ToHexString(CursorType.Sizeof)+' read GetBits write SetBits ; // ' +BitWidth.ToString+' bits at offset ' +OffsetOfField .ToString);
2420
+ FWriter.WriteLn(' property ' +FieldName+' : ' +DelphiTypeName+' index $' +BitIndex.ToHexString(CursorType.Sizeof)+' read Get ' +BitFieldValueFieldName+ ' Value write Set ' +BitFieldValueFieldName+ ' Value ; // ' +BitWidth.ToString+' bits at offset ' +FieldOfset .ToString + ' in ' + BitFieldValueFieldName );
2347
2421
FWriter.Outdent;
2348
2422
Inc(BitFieldCount);
2423
+ Inc(BitFieldOffsetFromStructStart, BitWidth);
2424
+ if BitFieldOffsetFromStructStart > 31 then
2425
+ Inc(BitFieldDataFieldCount);
2349
2426
IsFieldInited := False;
2350
2427
end
2351
2428
else
@@ -2383,41 +2460,6 @@ FWriter.WriteLn('%s = record', [StructName]);
2383
2460
FWriter.Outdent;
2384
2461
FWriter.WriteLn(' end;' );
2385
2462
2386
- if (BitFieldCount > 0 ) and (BitDataDelphiTypeName <> ' ' ) then
2387
- begin
2388
- if FImplementation = nil then
2389
- FImplementation := TStringList.Create;
2390
-
2391
- FImplementation.Add(' {$region '' ' +StructName + ' fields read/write'' }' );
2392
- // FImplementation.Add('(*');
2393
- FImplementation.Add(' function ' +StructName+' .GetBits(const aIndex: Integer): ' +BitDataDelphiTypeName+' ;' );
2394
- FImplementation.Add(' var' );
2395
- FImplementation.Add(' Offset, NrBits, Mask: Integer;' );
2396
- FImplementation.Add(' begin' );
2397
- FImplementation.Add(' {$UNDEF Q_temp}{$IFOPT Q+}{$DEFINE Q_temp}{$ENDIF}{$Q-} // disable OverFlowChecks' );
2398
- FImplementation.Add(' NrBits := aIndex and $FF;' );
2399
- FImplementation.Add(' Offset := aIndex shr 8;' );
2400
- FImplementation.Add(' Mask := ((1 shl NrBits) - 1);' );
2401
- FImplementation.Add(' Result := (FData shr Offset) and Mask;' );
2402
- FImplementation.Add(' {$IFDEF Q_temp}{$Q-}{$ENDIF}' );
2403
- FImplementation.Add(' end;' + sLineBreak);
2404
-
2405
- FImplementation.Add(' procedure ' +StructName+' .SetBits(const aIndex: Integer; const aValue: ' +BitDataDelphiTypeName+' );' );
2406
- FImplementation.Add(' var' );
2407
- FImplementation.Add(' Offset, NrBits, Mask: Integer;' );
2408
- FImplementation.Add(' begin' );
2409
- FImplementation.Add(' {$UNDEF Q_temp}{$IFOPT Q+}{$DEFINE Q_temp}{$ENDIF}{$Q-} // disable OverFlowChecks' );
2410
- FImplementation.Add(' NrBits := aIndex and $FF;' );
2411
- FImplementation.Add(' Offset := aIndex shr 8;' );
2412
- FImplementation.Add(' Mask := ((1 shl NrBits) - 1);' );
2413
- FImplementation.Add(' Assert(aValue <= Mask);' );
2414
- FImplementation.Add(' FData := (FData and (not (Mask shl Offset))) or (aValue shl Offset);' );
2415
- FImplementation.Add(' {$IFDEF Q_temp}{$Q-}{$ENDIF}' );
2416
- FImplementation.Add(' end;' );
2417
- FImplementation.Add(' {$endregion '' ' +StructName + ' fields read/write'' }' +sLineBreak);
2418
- // FImplementation.Add('*)');
2419
- end ;
2420
-
2421
2463
FWriter.WriteLn;
2422
2464
end ;
2423
2465
0 commit comments