Recent

Author Topic: FPC feature request/suggestion  (Read 1269 times)

440bx

  • Hero Member
  • *****
  • Posts: 3921
FPC feature request/suggestion
« on: June 29, 2022, 04:36:51 am »
Hello,

In Windows, it's becoming quite common for structures to include a size field which the O/S uses at runtime to determine which fields it can set. 

It would be very nice if FPC supported a variant of "sizeof" where it could take a field name, i.e, sizeof(<record name>, <record field name>) yielding the size of the record up to and _including_ the field.

There is a way of doing it but, it is very unclean because, it requires using the name of the field that _follows_ the field of interest which makes it completely unclear what the last field to be included is.

Succinctly: a sizeof(<record name>, <record field name>)

It's might be worth noting that the compiler already has the necessary information in its symbol tables to implement this compile time facility.

Thank you for reading.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11352
  • FPC developer.
Re: FPC feature request/suggestion
« Reply #1 on: June 29, 2022, 09:41:59 am »
You mean like https://gitlab.com/freepascal.org/fpc/source/-/issues/15416
 ?

Note that ptrint(@pstruct(nil).field) is a workaround.
« Last Edit: June 29, 2022, 01:18:06 pm by marcov »

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: FPC feature request/suggestion
« Reply #2 on: June 29, 2022, 10:34:40 am »
You mean like https://gitlab.com/freepascal.org/fpc/source/-/issues/15416
 ?
That's the basic idea but, the offset of the field is _not_ the size of the record up to and including that field.  To obtain the size of the record, including the field, requires adding the size of the field to its offset.

As the posters in the feature request you linked to mentioned, that nil pointer dereference is not elegant and has a number of shortcomings.  It's, as you stated, a workaround and one that is not really clear nor very desirable.

The compiler has the offset of every record field in its symbol tables, it can easily return the offset of any field and the size of a record up to and including the field, what's missing is a simple and straightforward way of asking the compiler for that information.

OffsetOf(<record>, <field>) _and_ sizeof(<record>, <record field>) would be _very_ nice features to have.  In C, these capabilities are implemented with macros but, they cannot be implemented using FPC's macro facilities.

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

alpine

  • Hero Member
  • *****
  • Posts: 1032
Re: FPC feature request/suggestion
« Reply #3 on: June 29, 2022, 11:31:22 am »
Hello,

In Windows, it's becoming quite common for structures to include a size field which the O/S uses at runtime to determine which fields it can set. 

It would be very nice if FPC supported a variant of "sizeof" where it could take a field name, i.e, sizeof(<record name>, <record field name>) yielding the size of the record up to and _including_ the field.

*snip*
Sure it will be nice, but for what is that needed for? I'm not getting it clearly from your first sentence.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: FPC feature request/suggestion
« Reply #4 on: June 29, 2022, 12:21:07 pm »
Sure it will be nice, but for what is that needed for? I'm not getting it clearly from your first sentence.
There are quite a few cases when it would be extremely convenient to have those features. 

The most common case is when a Windows structure has changed and Windows relies on the size to determine what to return (fill in).  If a program can use sizeof(<record>, <record field>) then fields added later don't affect how the code works.  IOW, the layout of the record can be updated without causing any potentially damaging side effects in existing code that uses that record.

Another case, less common, there are some programs that need to determine offsets and fields sizes at runtime, e.g, debuggers.  Without, OffsetOf and/or sizeof(<record>, <field>) writing the code is very laborious and tedious not to mention that maintaining the code becomes difficult.

Another case is when translating C headers.  In C, using the macros that are already in the headers, it is straightforward to create (even generate) a program that lists all the records along with their fields, including the field offset and size.  Doing that in Delphi/FPC is laborious and tedious, thereby making the verification that the translation is correct also tedious and time consuming.

OffsetOf(<record>, <field>) and sizeof(<record>, <field>) would _really_ make life _much_ simpler in a number of important cases.


(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6647
Re: FPC feature request/suggestion
« Reply #5 on: June 29, 2022, 12:42:45 pm »
The most common case is when a Windows structure has changed and Windows relies on the size to determine what to return (fill in).  If a program can use sizeof(<record>, <record field>) then fields added later don't affect how the code works.  IOW, the layout of the record can be updated without causing any potentially damaging side effects in existing code that uses that record.

I think that I'd argue is that you should use a case statement, and only support fixed-size data structures (i.e. preceded by an API-version-specific length) where the particular API version has been tested.

Otherwise, where the data structure is not fixed length (i.e. is preceded by a varying length field like a Pascal string) I don't see the problem.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

440bx

  • Hero Member
  • *****
  • Posts: 3921
Re: FPC feature request/suggestion
« Reply #6 on: June 29, 2022, 01:21:41 pm »
I think that I'd argue is that you should use a case statement, and only support fixed-size data structures
It's not that simple.  Consider you have a library of API definitions, MS adds a few fields to some structure, you add them to your definitions to keep up to date.  Now the problem is this, if the code is using "sizeof(<the record>)" then it will be using the new larger record size and the existing code may or may not work correctly with a larger structure, that's why limiting to a specific field is important.  Otherwise, those additional fields would force the programmer to review _every_ program that uses that record to ensure it is not affected by the new size.

By making the record size specific to one field then older code can be updated as needed or when convenient instead of, at least in some cases, breaking.

Also, when translating headers, the two things that really matter are the offsets of each field (particularly when some of them have specific alignment requirements) and the record size up to and including a particular field.  If memory serves, the MS common controls library is full of "variations" based on record sizes.  It's really inconvenient not having a simple, clear and straightforward way of determining field offsets and record sizes up to and including a field.

Those missing features in FPC'/Delphi also make verifying that structures are translated correctly from C to Pascal very tedious and laborious.



(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6647
Re: FPC feature request/suggestion
« Reply #7 on: June 29, 2022, 01:30:16 pm »
additional fields would force the programmer to review _every_ program that uses that record to ensure it is not affected by the new size.

That's right.

What you should be asking for is some form of annotation, possibly related to Lazarus's TODO, which can be applied to anything declared to mimic a non-Pascal API or data structure.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

alpine

  • Hero Member
  • *****
  • Posts: 1032
Re: FPC feature request/suggestion
« Reply #8 on: June 29, 2022, 01:39:20 pm »
Sure it will be nice, but for what is that needed for? I'm not getting it clearly from your first sentence.
There are quite a few cases when it would be extremely convenient to have those features. 

The most common case is when a Windows structure has changed and Windows relies on the size to determine what to return (fill in).  If a program can use sizeof(<record>, <record field>) then fields added later don't affect how the code works.  IOW, the layout of the record can be updated without causing any potentially damaging side effects in existing code that uses that record.
Do you mean something like:
Code: C  [Select][+][-]
  1. typedef struct {
  2.   int field;
  3.   int field2; // added in v2 of the api
  4.   int field3; // added in v3 of the api
  5. } apistruct, *papistruct;
  6.  
  7. void APIfunc( papistruct arg, size_t arglen ) // latest api
  8. {
  9.   arg->field = 1;
  10.   if( arglen > offsetof( apistruct, field2 ) )  // v2 of the api?
  11.     arg->field2 = 2;
  12.   if( arglen > offsetof( apistruct, field3 ) )  // v3 of the api?
  13.     arg->field3 = 3;
  14. }
  15.  
  16. // ... and in the api calling application:
  17. // (presumably built when api was < v3 and apistruct was shorter)
  18.  
  19. apistruct s;
  20.  
  21.   APIfunc( &s, sizeof( apistruct ) ); // call the recent APIfunc() with older version of apistruct
  22.  
Or you mean something different?
Because I'm not using the proposed sizeof( apistruct, field3 ) above.

Another case, less common, there are some programs that need to determine offsets and fields sizes at runtime, e.g, debuggers.  Without, OffsetOf and/or sizeof(<record>, <field>) writing the code is very laborious and tedious not to mention that maintaining the code becomes difficult.
That will be impossible at runtime without some sort of introspection or linker/debugger symbol table. IMO that is not what you're asking for, i.e. compile-time sizeof(<record name>, <record field name>).

Another case is when translating C headers.  In C, using the macros that are already in the headers, it is straightforward to create (even generate) a program that lists all the records along with their fields, including the field offset and size.  Doing that in Delphi/FPC is laborious and tedious, thereby making the verification that the translation is correct also tedious and time consuming.

OffsetOf(<record>, <field>) and sizeof(<record>, <field>) would _really_ make life _much_ simpler in a number of important cases.
I still don't get it. Why showing offsets and sizes of structs defined in C headers from FPC? Patching something? BTW one of the few cases I used offsetof() in C was when I wrote patching of configuration structures in a micro-controller NV memory where it can be written by single words but only erased in bulk.

And what's wrong with offsetof(a, b) + sizeof(b) compared to sizeof(a, b)?
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

 

TinyPortal © 2005-2018