Prof A Olowofoyeku (The African Chief) wrote:
On 10 May 2003 at 3:30, Frank Heckenbach wrote:
Prof A Olowofoyeku (The African Chief) wrote:
This program does not compile. Shouldn't it?
Program attribute_bug;
TYPE Int8 = Integer attribute ( Size = 8 );
WordRec : RECORD Lo, Hi : Cardinal attribute ( Size = 8 ); END;
LongRec = PACKED RECORD Lo, Hi : Cardinal attribute ( Size = 16 ); END;
Begin Writeln ('OK'); End.
Attributes currently don't work in record fields etc. It would be extra effort to recognize them (syntactically). But since one can always declare a type with attributes (such as `Int8') and use this in the record, I'm not conviced whether I should do it ...
Ok. Look at this record (in existing WinAPI import units): TYPE tBits = PACKED RECORD BaseMid : Cardinal ( 8 ); Typ : Cardinal ( 5 ); Dpl : Cardinal ( 2 ); Pres : Cardinal ( 1 ); LimitHi : Cardinal ( 4 ); Sys : Cardinal ( 1 ); Reserved_0 : Cardinal ( 1 ); Default_Big : Cardinal ( 1 ); Granularity : Cardinal ( 1 ); BaseHi : Cardinal ( 8 ) END;
I have to change my code to define at least 4 different types for this. Consider many more structures of this kind. Of course the work can be done, even if tedious - but one would then have a proliferation of types just to be able to create one record. I will do the work, but you might want to reconsider this matter.
I've had a few such cases myself. OTOH, there's probably a limited number of types that occur in such situations at all (like 1 .. 8, 16, 32 and 64 bits, maybe one or two more; and probably all of them unsigned, I think C doesn't even allow signed types there). (And some if not all if the 1-bit types can perhaps be replaced by Boolean, BTW.)
I'm still undecided. Basically, the arguments go like this:
- It's not possible (syntactically) to allow attributes in components of certain structures (arrays, sets, files), so we shouldn't allow them in any.
- C allows `:n' in structs and unions, so we should allow attributes in records.
One reason against it is that it's not possible in arrays, sets and files because then the following would be ambiguous (does the attribute belong to the array of the component type?). So it might be more consistent to not allow it in any structured types.
Perhaps.
I have another problem. This code used to compile:
unit attrbug_2; interface uses GPC; FUNCTION DirectoryExists ( CONST DirName : String ) : Boolean; attribute (name = '_p_DirectoryExists'); external; FUNCTION FileSearch ( CONST FileName, DirList : String ) : TString; attribute (name = '_p_FSearch'); external; implementation end.
Now, it dies with this error: "attributes in forward declared routines are not allowed".
There are two issues here:
First, this isn't allowed anymore:
procedure foo; forward;
procedure foo; attribute (name = 'bar'); begin end;
As you can imagine, this never really worked. GPC would silently produce wrong code (calling asmname `Foo' when the procedure was called between the forward declaration and the implementation). Now it rejects it.
Unit interface declarations are much like `forward'.
The second one is the well-known lack of qualified identifiers, so GPC (wrongly) identifies the function DirectoryExists in the GPC unit and in this unit. So the first problem applies.
But there is a solution, which will work now, and is recommended even when QI will have been implemented because it's cleaner, easier and safer (no problem if the routine interface or asmname in the GPC unit changes). This is explicit module re-export:
- Turn your unit into a module. That's quite simple:
unit Foo;
interface
=>
module Foo;
export Foo = all;
and
implementation
=>
end;
and
begin [...] end.
=>
to begin do begin [...] end;
end.
Then just add anything you want to re-export to the export clause, e.g.:
export attrbug_2 = all (DirectoryExists, FileSearch);
Or if you like to change the name (exactly this code is now in the GPCUtil module where the same issue occurred, BTW):
export GPCUtil = all (DirectoryExists => IsDirectory);
If "external" is removed, then you get an error like "unresolved forward declaration `FileSearch'".
That's clear. Without `external', you claim that you'll implement the function in this unit.
This code is taken from the Sysutils unit, which exports some functions that already exist in the GPC unit. In older times, you just asmnamed them. In the penultimate snapshot, that was changed to the above. Now, it doesn't work. I need this to work (or at least I need to have a way to reexport routines from other units). This is reminiscent of the earlier discussions on unit propagation. I am not sure how that discussion was resolved.
There's no "reexport all" feature, but reexporing selected items works as shown above. (I think that's what you need, you don't want to reexport the whole GPC unit.)
Unfortunately, this problem is not only related to unit propagation. I have just tried to compile the Windows unit (that exports thousands of winapi routines, interfacing to the Mingw winapi libraries), and two of those routines are now rejected with the "attributes in forward declared routines are not allowed" error. There is no reason for those two routines to be singled out, and there is no USES problem here.
Probably these routines are declared `forward' or something like it. Generally, it applies when a routine is declared twice.
Frank