* Importing C Structures @ 1995-03-23 6:34 Chris O'Regan 1995-03-23 7:55 ` Vladimir Vukicevic 1995-03-24 15:32 ` Robert Dewar 0 siblings, 2 replies; 20+ messages in thread From: Chris O'Regan @ 1995-03-23 6:34 UTC (permalink / raw) For my Real-Time Systems project, my partner and I are writing a program to control a train set. We will be working on an Indy using GNAT 2.03, and as little C code as possible. We need to interface the Indy's serial port. We have some documention which explains how to do this in standard C, but we would prefer to do this in Ada. We figure that we will need to import the functions and types from the standard C library. Importing a function isn't a problem, but what about data types? Rationale and the Reference Manual claim that it is possible, but without an sample code snippet, we don't know where to begin. Could someone shed some light on the subject? Or should we give in and write our serial port routines in C? Chris O'Regan Computer Engineering, Concordia University, Montreal, Canada. -- ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 6:34 Importing C Structures Chris O'Regan @ 1995-03-23 7:55 ` Vladimir Vukicevic 1995-03-23 18:55 ` Robert S. White 1995-03-24 17:30 ` Robert Dewar 1995-03-24 15:32 ` Robert Dewar 1 sibling, 2 replies; 20+ messages in thread From: Vladimir Vukicevic @ 1995-03-23 7:55 UTC (permalink / raw) In article <3kr4q3$jd9@newsflash.concordia.ca> ct_oreg@vega.concordia.ca (Chris O'Regan) writes: > > For my Real-Time Systems project, my partner and I are writing a program > to control a train set. We will be working on an Indy using GNAT 2.03, and > as little C code as possible. > > We need to interface the Indy's serial port. We have some documention > which explains how to do this in standard C, but we would prefer to do this > in Ada. We figure that we will need to import the functions and types from > the standard C library. > > Importing a function isn't a problem, but what about data types? > Rationale and the Reference Manual claim that it is possible, but without an > sample code snippet, we don't know where to begin. > > Could someone shed some light on the subject? Or should we give in and > write our serial port routines in C? No. Write them in Ada. :-) First, decide which functions you'll need. I'm assuming open (), read(), write(), ioctl() and the like. open () returns an int, so that's no problem. read/write would use Interfaces.C.Strings. ioctl () would use System.Address and others. If you need to pass around pointers, and don't care what they point to, treat them as System.Addresses. If there is some some struct that you need to map to Ada, it should be farily straightforward. i.e. typedef struct { int foo; char bar[10]; long *q; } A_Struct; becomes with Interfaces.C; package IC renames Interfaces.C; type A_Struct is record foo : IC.int; bar : IC.char_array (1 .. 10); q : access IC.long; end record; - Vladimir ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 7:55 ` Vladimir Vukicevic @ 1995-03-23 18:55 ` Robert S. White 1995-03-24 8:51 ` Vladimir Vukicevic ` (3 more replies) 1995-03-24 17:30 ` Robert Dewar 1 sibling, 4 replies; 20+ messages in thread From: Robert S. White @ 1995-03-23 18:55 UTC (permalink / raw) In article <VLADIMIR.95Mar22235527@speedy.intrepid.com>, vladimir@speedy.intrepid.com says... > >If there is some some struct that you need to map to Ada, it should be >farily straightforward. i.e. > - Vladimir Do you have a clean way to handle hardware registers that have one meaning when you read them and another when you write to them with nice seperate names for each type of usage? I know "use at" for Ada 83 can overide this but it seems to be not in the spirit of the 83 LRM; 13.5 "Address clauses should not be used to achieve overlays of objects...Any program using address clauses to achieve such effects is erroneous." A work around is to have a dual meaning name for the register and use one procedure, appropriately named, to write to it and a function, again with a suitable name, for reading it. This is a case where C programmers use the union structure. I confess that I have not ferreted out in the Ada 95 RM or Rational the right (and very concise) way to do this now. Recommendations? Robert S. White 76166.1137@compuserve.com -- speaking for myself only ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 18:55 ` Robert S. White @ 1995-03-24 8:51 ` Vladimir Vukicevic 1995-03-25 9:57 ` Keith Thompson 1995-03-27 16:00 ` Norman H. Cohen 1995-03-24 16:08 ` Robert I. Eachus ` (2 subsequent siblings) 3 siblings, 2 replies; 20+ messages in thread From: Vladimir Vukicevic @ 1995-03-24 8:51 UTC (permalink / raw) In article <3ksg66$h1c@newssvr.cacd.rockwell.com> rswhite@cacd.rockwell.com (Robert S. White) writes: > Do you have a clean way to handle hardware registers that have one > meaning when you read them and another when you write to them with > nice seperate names for each type of usage? I know "use at" for > Ada 83 can overide this but it seems to be not in the spirit of > the 83 LRM; > 13.5 "Address clauses should not be used to achieve overlays of > objects...Any program using address clauses to achieve > such effects is erroneous." > A work around is to have a dual meaning name for the register and > use one procedure, appropriately named, to write to it and a function, > again with a suitable name, for reading it. There is no such clause in the Ada 95 LRM... the "Erroneous Execution" section for using a X'Address representation clause (13.3 (13)) states: If an Address is specified, it is the programmer's responsibility to ensure that the address is valid; otherwise, program execution is erroneous. So, it is perfectly valid to use the same 'Address for two objects, as long as the Address you specify is valid :-) > This is a case where C programmers use the union structure. I > confess that I have not ferreted out in the Ada 95 RM or Rational > the right (and very concise) way to do this now. > > Recommendations? Something like this (in Ada 95): Input_Register : Integer; for Input_Register'Address use System.Storage_Elements.To_Address (16#0020); Output_Register : Integer; for Output_Register'Address use System.Storage_Elements.To_Address (16#0020); This is perfectly valid and within the spirit of the 95 LRM. - Vladimir ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-24 8:51 ` Vladimir Vukicevic @ 1995-03-25 9:57 ` Keith Thompson 1995-03-26 13:16 ` Larry Kilgallen, LJK Software 1995-03-27 16:00 ` Norman H. Cohen 1 sibling, 1 reply; 20+ messages in thread From: Keith Thompson @ 1995-03-25 9:57 UTC (permalink / raw) In <VLADIMIR.95Mar24005132@speedy.intrepid.com> vladimir@speedy.intrepid.com (Vladimir Vukicevic) writes: > There is no such clause in the Ada 95 LRM... the "Erroneous Execution" > section for using a X'Address representation clause (13.3 (13)) states: > > If an Address is specified, it is the programmer's responsibility > to ensure that the address is valid; otherwise, program execution > is erroneous. > > So, it is perfectly valid to use the same 'Address for two objects, as > long as the Address you specify is valid :-) Here's an example of an erroneous use of address clauses in Ada 83: X : Integer; ... Y : Integer; for Y use at X'Address; The reason this is erroneous is that the compiler may not be aware that X and Y are really the same object (X may be declared in a different compilation unit, or the overlaid object might be something more complex than a simple object, say a dynamically indexed array element). The compiler is free to keep the value of X in a register, optimize out dead assignments, etc., so the apparent values of X and Y won't track each other as the user might naively expect. The AARM, if I'm reading it correctly, still gives implementations considerable freedom to treat such constructs as erroneous. Paragraph 13.3(13) says If an Address is specified, it is the programmer's responsibility to ensure that the address is valid; otherwise, program execution is erroneous. What does "valid" mean in this context? See paragraph 12.b in the same subsection: The validity of a given address depends on the run-time model; thus, in order to use Address clauses correctly, one needs intimate knowledge of the run-time model. Caveat hacker. A minor digression: Initialization of objects with address clauses has caused a lot of problems in Ada 83; the language doesn't give permission not to initialize such objects, but if you're trying to map an access or System.Address object to a hardware register you probably don't want it initialized to null. Paragraph 12.c of the AARM says: If the Address of an object is specified, any explicit or implicit initialization takes place as usual, unless a pragma Import is also specified for the object (in which case any necessary initialization is presumably done in the foreign language). (The language specified in the pragma Import can be Ada.) -- Keith Thompson (The_Other_Keith) kst@thomsoft.com (kst@alsys.com still works) TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products 10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2718 That's Keith Thompson *with* a 'p', Thomson Software Products *without* a 'p'. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-25 9:57 ` Keith Thompson @ 1995-03-26 13:16 ` Larry Kilgallen, LJK Software 1995-03-27 0:00 ` Kevin F. Quinn ` (2 more replies) 0 siblings, 3 replies; 20+ messages in thread From: Larry Kilgallen, LJK Software @ 1995-03-26 13:16 UTC (permalink / raw) In article <D5zqB9.5F8@thomsoft.com>, kst@thomsoft.com (Keith Thompson) writes: > Here's an example of an erroneous use of address clauses in Ada 83: > > X : Integer; > ... > Y : Integer; > for Y use at X'Address; > > The reason this is erroneous is that the compiler may not be aware that > X and Y are really the same object (X may be declared in a different > compilation unit, or the overlaid object might be something more > complex than a simple object, say a dynamically indexed array element). > The compiler is free to keep the value of X in a register, optimize out > dead assignments, etc., so the apparent values of X and Y won't track For an address representation clause, which might be used to access hardware, optimizing out dead assignments seems quite inappropriate. Is there no Ada83 method of avoiding such an optimization for such objects? ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-26 13:16 ` Larry Kilgallen, LJK Software @ 1995-03-27 0:00 ` Kevin F. Quinn 1995-04-07 0:00 ` Larry Kilgallen 1995-03-27 15:35 ` Theodore Dennison 1995-03-27 23:39 ` Importing C Structures Keith Thompson 2 siblings, 1 reply; 20+ messages in thread From: Kevin F. Quinn @ 1995-03-27 0:00 UTC (permalink / raw) In article <1995Mar26.081652.9489@eisner>, kilgallen@eisner.decus.org (Larry Kilgallen, LJK Software) wrote: > In article <D5zqB9.5F8@thomsoft.com>, kst@thomsoft.com (Keith Thompson) writes: > > > Here's an example of an erroneous use of address clauses in Ada 83: > > > > X : Integer; > > ... > > Y : Integer; > > for Y use at X'Address; > > > > The reason this is erroneous is that the compiler may not be aware that > > X and Y are really the same object (X may be declared in a different > > compilation unit, or the overlaid object might be something more > > complex than a simple object, say a dynamically indexed array element). > > The compiler is free to keep the value of X in a register, optimize out > > dead assignments, etc., so the apparent values of X and Y won't track You're correct (of course :) ) but I would expect the situation with more complex objects, especially ones involving dynamically chosen elements to be very rare indeed. Especially justifiable situations... > > For an address representation clause, which might be used to access hardware, > optimizing out dead assignments seems quite inappropriate. Is there no > Ada83 method of avoiding such an optimization for such objects? The problem occurs with 'X', which the compiler is free to handle purely in a register for a while if that is appropriate; it doesn't know that an interrupt handler which uses Y can come in expecting Y to be the same as X at all times, for example. Possibly a bit of a contrived situation, but if it can be done, it probably will be done by someone somewhere :) Dead assignments for Y should never be optimised away, for the reasons you mention, Larry. Not that I'd trust a compiler in this; I'd always take a glance at the assembly listing to be sure... Most compilers I've used have a "pragma Volatile" or similar, which marks a variable so that the optimiser leaves it in memory. If your compiler doesn't have a suitable pragma (and it doesn't have to), you can try: private_XY : Integer; X : Integer; for X use at private_Z'address; Y : Integer; for Y use at private_Z'address; Then you can use X and Y with impunity - if the compiler is worth anything then both X and Y will always be accessed over the bus. Leave it to coding standards to ensure that private_XY is never used. This can be done in all situations, including ones where data is declared in a new block (hence is declared dynamically, probably on a stack or heap). I'm not sure if you can put private_XY in a package body, vis: package MyData is X : Integer; Y : Integer; end MyData; package body MyData is private_XY : Integer; for X use at private_XY'address; for Y use at private_XY'address; end Mydata; It might work though (don't have a compiler here to check...), in which case you will have enforced the non-use of private_XY by packaging. If you're relying on this kind of thing, it is always best to check your object code just to be sure, anyway. I may be stating the obvious, but then again... Especially since you'll need to give VERY good reasons why you're doing it in the first place :) -- Kevin F. Quinn * "No-one ever made any money out of good kevq@banana.demon.co.uk * looks and charm." kevq@cix.compulink.co.uk * "You obviously haven't met Lady Hamilton..." Compu$erve: 100025,1525 * Blackadder III ... I'll have what the guy on the floor is having... ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-27 0:00 ` Kevin F. Quinn @ 1995-04-07 0:00 ` Larry Kilgallen 0 siblings, 0 replies; 20+ messages in thread From: Larry Kilgallen @ 1995-04-07 0:00 UTC (permalink / raw) In article <19950327.180750.74@banana.demon.co.uk>, kevq@banana.demon.co.uk (Kevin F. Quinn) writes: > In article <1995Mar26.081652.9489@eisner>, > kilgallen@eisner.decus.org (Larry Kilgallen, LJK Software) wrote: > > > For an address representation clause, which might be used to access hardware, > > optimizing out dead assignments seems quite inappropriate. Is there no > > Ada83 method of avoiding such an optimization for such objects? > Most compilers I've used have a "pragma Volatile" or similar, which > marks a variable so that the optimiser leaves it in memory. If your Oh, the compiler I use has lots of that stuff, but it is printed in blue ink (non-standard) and this seems such a basic concept (for a language that provides Address clauses at all) that I was hoping for a standard method. Since one is looking at machine addresses, the code is by definition non-portable, but recent experience in another language has made me hyper-sensitive to vendor-specific enhancements. If someday there were a second compiler vendor for the platform, standard syntax might be useful. Larry Kilgallen ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-26 13:16 ` Larry Kilgallen, LJK Software 1995-03-27 0:00 ` Kevin F. Quinn @ 1995-03-27 15:35 ` Theodore Dennison 1995-03-28 0:00 ` Robert Dewar 1995-03-28 11:44 ` Keith Thompson 1995-03-27 23:39 ` Importing C Structures Keith Thompson 2 siblings, 2 replies; 20+ messages in thread From: Theodore Dennison @ 1995-03-27 15:35 UTC (permalink / raw) Keith Thompson <kilgallen@eisner.decus.org> wrote: > In article <D5zqB9.5F8@thomsoft.com>, kst@thomsoft.com (Keith Thompson) writes: > > For an address representation clause, which might be used to access hardware, > optimizing out dead assignments seems quite inappropriate. Is there no > Ada83 method of avoiding such an optimization for such objects? There is no PORTABLE way. Most compiler vendors however will tell you what you can do to avoid this. The DEC Ada compiler, if memory serves, treated any variable associated with an address clause as "volatile" for the scope of the address clause. "Volatile" addresses are not optimized into registers. Again, this is DEC Ada only. Check your vendor docs. T.E.D. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-27 15:35 ` Theodore Dennison @ 1995-03-28 0:00 ` Robert Dewar 1995-03-28 11:44 ` Keith Thompson 1 sibling, 0 replies; 20+ messages in thread From: Robert Dewar @ 1995-03-28 0:00 UTC (permalink / raw) T.E.D says "volatile is in Dec Ada only". And in Ada 95, where it is one of the predefined pragmas (and is currently implemented in GNAT). One thing to be concerned with is that if you map to hardware memory addressed locations, you are making non-portable, target dependent assumptions about the exact sequence of instructions that will be generated. For example, if you map to a byte, normally the code generator could use a load word/extract byte sequence or a load byte instruction. Normally the choice would make no difference, but it could make a BIG DIFFERENCE in the memory mapped case. In a way, I would prefer to see the use of a machine instrinsic instruction (coming soon in GNAT!) for this purpose, to make it absolutely CLEAR what is going on without hidden assumptions. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-27 15:35 ` Theodore Dennison 1995-03-28 0:00 ` Robert Dewar @ 1995-03-28 11:44 ` Keith Thompson 1995-03-29 0:00 ` misattrubation (was: Re: Importing C Structures) Theodore Dennison 1 sibling, 1 reply; 20+ messages in thread From: Keith Thompson @ 1995-03-28 11:44 UTC (permalink / raw) In <3l6m0b$pj9@theopolis.orl.mmc.com> Theodore Dennison <dennison@escmail.orl.mmc.com> writes: > Keith Thompson <kilgallen@eisner.decus.org> wrote: ^^^^^^^^^^^^^^ > > In article <D5zqB9.5F8@thomsoft.com>, kst@thomsoft.com (Keith Thompson) writes: > > > > For an address representation clause, which might be used to access hardware, > > optimizing out dead assignments seems quite inappropriate. Is there no > > Ada83 method of avoiding such an optimization for such objects? Just to set things straight, "kilgallen@eisner.decus.org" is Larry Kilgallen of LJK Software; he wrote the quoted paragraph in response to something I posted. Though my name appears in Theodore Dennison's article, he didn't quote anything that I wrote. No biggie; I'm sure it was just a simple mistake. -- Keith Thompson (The_Other_Keith) kst@thomsoft.com (kst@alsys.com still works) TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products 10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2718 That's Keith Thompson *with* a 'p', Thomson Software Products *without* a 'p'. ^ permalink raw reply [flat|nested] 20+ messages in thread
* misattrubation (was: Re: Importing C Structures) 1995-03-28 11:44 ` Keith Thompson @ 1995-03-29 0:00 ` Theodore Dennison 1995-03-31 0:00 ` Theodore Dennison 0 siblings, 1 reply; 20+ messages in thread From: Theodore Dennison @ 1995-03-29 0:00 UTC (permalink / raw) To: kst Keith Thompson <kst@thomsoft.com> wrote: > Just to set things straight, "kilgallen@eisner.decus.org" is Larry > Kilgallen of LJK Software; he wrote the quoted paragraph in response > to something I posted. Though my name appears in Theodore Dennison's > article, he didn't quote anything that I wrote. > > No biggie; I'm sure it was just a simple mistake. > Sorry about that. Lame excuse: I'm using the new Beta version of Netscape to read my news. In this version they removed the feature that automaticly puts the author's name at the top of a follow-up post, so now I have to do it manually. As a human, I'm apt to screw this up once in a while (as T.E.D., I'm apt to screw this up quite often). One of the things I'm best at is making mistakes, which is why I like Ada so much. It also now automaticly e-mails a copy of the posting to the previous author, unless you tell it not to. So if you are suddenly seeing a lot of misattrubations and email identical to postings (particularly from me) now you know why. Thanks for letting me know it happened. I'll try to be a bit more careful. T.E.D. (structured programming bigot) ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: misattrubation (was: Re: Importing C Structures) 1995-03-29 0:00 ` misattrubation (was: Re: Importing C Structures) Theodore Dennison @ 1995-03-31 0:00 ` Theodore Dennison 0 siblings, 0 replies; 20+ messages in thread From: Theodore Dennison @ 1995-03-31 0:00 UTC (permalink / raw) Theodore Dennison <dennison@escmail.orl.mmc.com> wrote: >Lame excuse: > I'm using the new Beta version of Netscape to read my news. In >this version they removed the feature that automaticly puts the >author's name at the top of a follow-up post, so now I have to do it >manually. As a human, I'm apt to screw this up once in a while (as Sorry to reply to my own post, but for those of you using Netscape, there is now a new version that fixes the aforementioned problem. It is version 1.1b2, and is available through the netscape home page. So hopefully, this was the one and only instance of me making this mistake. Note that it still e-mails each post unless you stop it. T.E.D. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-26 13:16 ` Larry Kilgallen, LJK Software 1995-03-27 0:00 ` Kevin F. Quinn 1995-03-27 15:35 ` Theodore Dennison @ 1995-03-27 23:39 ` Keith Thompson 2 siblings, 0 replies; 20+ messages in thread From: Keith Thompson @ 1995-03-27 23:39 UTC (permalink / raw) In <1995Mar26.081652.9489@eisner> kilgallen@eisner.decus.org (Larry Kilgallen, LJK Software) writes: > In article <D5zqB9.5F8@thomsoft.com>, kst@thomsoft.com (Keith Thompson) writes: > > Here's an example of an erroneous use of address clauses in Ada 83: > > > > X : Integer; > > ... > > Y : Integer; > > for Y use at X'Address; [...] > For an address representation clause, which might be used to access hardware, > optimizing out dead assignments seems quite inappropriate. Is there no > Ada83 method of avoiding such an optimization for such objects? I certainly agree that optimizing out dead assignments for an object to which an address clause applies is inappropriate. I suspect most or all Ada 83 compilers treat such objects specially (but consult your compiler documentation to be sure). In the example, accesses to Y are probably safe from such optimizations. The problem is that access to X may not be safe. If you write a value to X (which *doesn't* have an address clause) and then try to read it through Y, you may not get the results you expect, since the generated code might not bother to store the value at X's address. This is an example of a general problem with aliasing; I think you can run into the same kind of problems with subprogram parameters passed by reference. It is possible for a compiler to do the analysis needed to mark any *potentially* aliased objects as volatile, avoiding this problem, but I don't know how many actual compilers do so. Any variable visible to other compilation units can be aliased in this way. (There presumably won't be very many such objects in well-designed code.) To summarize, if you alias two declared objects by using an address clause, it's likely that they'll behave as you'd expect, but it's usually far better to use other methods. If you want to alias an object with the same type, use a renames declaration; if you need a different type, use Unchecked_Conversion (which explicitly accesses the aliased object). -- Keith Thompson (The_Other_Keith) kst@thomsoft.com (kst@alsys.com still works) TeleSoft^H^H^H^H^H^H^H^H Alsys^H^H^H^H^H Thomson Software Products 10251 Vista Sorrento Parkway, Suite 300, San Diego, CA, USA, 92121-2718 That's Keith Thompson *with* a 'p', Thomson Software Products *without* a 'p'. ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-24 8:51 ` Vladimir Vukicevic 1995-03-25 9:57 ` Keith Thompson @ 1995-03-27 16:00 ` Norman H. Cohen 1 sibling, 0 replies; 20+ messages in thread From: Norman H. Cohen @ 1995-03-27 16:00 UTC (permalink / raw) In article <VLADIMIR.95Mar24005132@speedy.intrepid.com>, vladimir@speedy.intrepid.com (Vladimir Vukicevic) writes: |> In article <3ksg66$h1c@newssvr.cacd.rockwell.com> rswhite@cacd.rockwell.com (Robert S. White) writes: |> |> > Do you have a clean way to handle hardware registers that have one |> > meaning when you read them and another when you write to them with |> > nice seperate names for each type of usage? ... |> > Recommendations? |> |> Something like this (in Ada 95): |> |> Input_Register : Integer; |> for Input_Register'Address use |> System.Storage_Elements.To_Address (16#0020); |> |> Output_Register : Integer; |> for Output_Register'Address use |> System.Storage_Elements.To_Address (16#0020); |> |> This is perfectly valid and within the spirit of the 95 LRM. Yes, it is. Personally, I think memory-mapped I/O is a pernicious abstraction. Just because the hardware lies and claims that we are reading from or writing to a storage location when we are reading from or writing to a device, I see no need to perpetuate this lie in the source program and make it appear as though we are reading from or writing to a variable. Therefore, I would prefer a procedural interface: with System; package Low_Level_IO is -- Loosely inspired by RM83 14.6 type Device_Address is new System.Address; type Word is mod 2**32; -- or whatever procedure Send_Control (Device: in Device_Address; Data: in Word); procedure Receive_Control (Device: in Device_Address; Data: out Word); end Low_Level_IO; with System.Address_To_Access_Conversions; package body Low_Level_IO is use System; package Word_Pointers is new Address_To_Access_Conversions (Word); procedure Send_Control (Device: in Device_Address; Data: in Word) is begin Word_Pointers.To_Pointer(Address(Device)).all := Data; end Send_Control; procedure Receive_Control (Device: in Device_Address; Data: out Word) is begin Data := Word_Pointers.To_Pointer(Address(Device)).all; end Receive_Control; end Low_Level_IO; Code procedures would provide even less of a suggestion that some variable is being updated or referenced. -- Norman H. Cohen ncohen@watson.ibm.com ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 18:55 ` Robert S. White 1995-03-24 8:51 ` Vladimir Vukicevic @ 1995-03-24 16:08 ` Robert I. Eachus 1995-03-24 20:20 ` Bob Gilbert 1995-03-25 18:07 ` Robert Dewar 3 siblings, 0 replies; 20+ messages in thread From: Robert I. Eachus @ 1995-03-24 16:08 UTC (permalink / raw) In article <3ksg66$h1c@newssvr.cacd.rockwell.com> rswhite@cacd.rockwell.com (Robert S. White) writes: > I know "use at" for Ada 83 can overide this but it seems to be > not in the spirit of the 83 LRM; > 13.5 "Address clauses should not be used to achieve overlays of > objects...Any program using address clauses to achieve > such effects is erroneous." This is a common misunderstanding. When the Ada 83 RM says that "misusing this freedom is erroneous," the intent was to lay the onus for proper use on the programmer not the compiler. Since the stated use does not violate the first sentence--the objects are overlayed by the hardware, not the users program--the effect is not erroneous, but it sure is implementation dependent. The wording in the 95 RM is much clearer about this, but the intent has always been the same. There are certain areas where compilers cannot do sanity checks, and in those areas the responsibility for correctness and testing falls on the user. > A work around is to have a dual meaning name for the register and > use one procedure, appropriately named, to write to it and a function, > again with a suitable name, for reading it. > This is a case where C programmers use the union structure. I > confess that I have not ferreted out in the Ada 95 RM or Rational > the right (and very concise) way to do this now. > Recommendations? If the right C analog is a union with a field in the struct which can be used to determine which choice is correct, write it in Ada as a discriminated record. If the necessary information is stored separately or not at all, do the Ada equivalent with Unchecked_Conversion between variants, and recognize that coding errors are the responsibility of the programmer. (Or fix the record so you can let the compiler do the checking, even if it means fixing the bug in the C code as well.) -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 18:55 ` Robert S. White 1995-03-24 8:51 ` Vladimir Vukicevic 1995-03-24 16:08 ` Robert I. Eachus @ 1995-03-24 20:20 ` Bob Gilbert 1995-03-25 18:07 ` Robert Dewar 3 siblings, 0 replies; 20+ messages in thread From: Bob Gilbert @ 1995-03-24 20:20 UTC (permalink / raw) In article h1c@newssvr.cacd.rockwell.com, rswhite@cacd.rockwell.com (Robert S. White) writes: -> ->Do you have a clean way to handle hardware registers that have one ->meaning when you read them and another when you write to them with ->nice seperate names for each type of usage? I know "use at" for ->Ada 83 can overide this but it seems to be not in the spirit of ->the 83 LRM; -> 13.5 "Address clauses should not be used to achieve overlays of -> objects...Any program using address clauses to achieve -> such effects is erroneous." ->A work around is to have a dual meaning name for the register and ->use one procedure, appropriately named, to write to it and a function, ->again with a suitable name, for reading it. -> ->This is a case where C programmers use the union structure. I ->confess that I have not ferreted out in the Ada 95 RM or Rational ->the right (and very concise) way to do this now. -> ->Recommendations? Well, using Ada 83 there are a couple of ways. You are correct about avoiding the address clause to "overlay" two or more objects to the same memory location. If the location has different meaning when read from that when written to, I would use Unchecked_Conversion and do something like the following: package Whatever_Interface is type READ_WHATEVER is record ..... end record; type WRITE_WHATEVER is record .... end record; procedure Write(Val : in WRITE_WHATEVER); function Read return READ_WHATEVER; end Whatever_Interface; with System; with Unchecked_Conversion; package body Whatever_Interface is Whatever : WRITE_WHATEVER; for Whatever use at {put address here}; procedure Write(Val : in WRITE_WHATEVER) is begin Whatever := Val; end Write; function Read return READ_WHATEVER is function To_Read_Type is new Unchecked_Conversion(WRITE_WHATEVER, READ_WHATEVER); begin return To_Read_Type(Whatever); end Read; end Whatever_Interface; The advantage of using the packaging and procedure/function to access the location is that it allows protection of the object. You can only write a valid type to it as well as returning the proper type when using the function to read the object. You can use pragma Inline if there are concerns about the overhead in making these simple calls. Most reasonable compilers will optimize the code generated such that it will appear to give direct access to the memory location. Of course if you really want to "overlay" two seperate objects to the same location, you can probably make the assumption that access types are implemented as addresses, and you could then do the following: with System; with Unchecked_Conversion; package Whatever_Interface is Location : constant System.ADDRESS := {put address here}; type READ_WHATEVER is record ..... end record; type WRITE_WHATEVER is record .... end record; type READ_WHATEVER_PTR is access READ_WHATEVER; type WRITE_WHATEVER_PTR is access WRITE_WHATEVER; function To_Ptr is new Unchecked_Conversion(System.ADDRESS, READ_WHATEVER_PTR); function To_Ptr is new Unchecked_Conversion(System.ADDRESS, WRITE_WHATEVER_PTR); Read_Val : constant READ_WHATEVER_PTR := To_Ptr(Location); Write_Val : constant WRITE_WHATEVER_PTR := To_Ptr(Location); end Whatever_Interface; Of course you have to remember to use the ".all" notation to make sure you are referencing the value "pointed" to by the access value(s). This is probably considered bastardized Ada code. It is dangerous since you can write a read type value (Read_Val := xxx) and the compiler will offer no protection. It also relies on the knowlege that access types are implemented as an address (not required by the LRM, but usually true). Note that at least I made the access (pointer) values constants so that they are protected from accidental modification (also stating that something you intend to be constant with the key word "constant" frequently allows the compiler to make advantageous assumptions during optimization). Now with Ada 83 the first example may have a problem using the address clause. Many compilers will perform a write to the location during elaboration (I guess to insure that any initialization that might have been specified is performed). This is the reason I used the WRITE_WHATEVER type to define the object. If this should be a problem, you can use the access type to map the object in the same style as done in the second example. As for Ada 95, I'll quote Tucker Taft from a previous post: -------------------------------------------------------------- In Ada 95, you can specify "pragma Import(Ada, <object-name>);" which indicates that *no* default initialization is to be performed by the compiler-generated code. This is generally desirable when using an address clause to associate a name with a machine register of some sort. Also, in Ada 95 there are language-defined functions for converting integers to addresses. Finally, the preferred syntax for specifying the address of an object uses "for ...'Address use ...", such as: for Console_Status_Register'Address use System.Storage_Elements.To_Address(16#FFC0#); The "for ... use at ..." syntax is still retained for upward compatibility reasons. -------------------------------------------------------------- -Bob ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 18:55 ` Robert S. White ` (2 preceding siblings ...) 1995-03-24 20:20 ` Bob Gilbert @ 1995-03-25 18:07 ` Robert Dewar 3 siblings, 0 replies; 20+ messages in thread From: Robert Dewar @ 1995-03-25 18:07 UTC (permalink / raw) Another way to deal with giving different names for reading and writing the same memory location would simply be to rename it with appropriate names, and then by convention use the appropriate name. This wouldn't enforce the right name use, but would permit it, and that may be perfectly good enough. One doesn't always need enforce mechanisms for ensuring that one's own code is not incompetently written :-) ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 7:55 ` Vladimir Vukicevic 1995-03-23 18:55 ` Robert S. White @ 1995-03-24 17:30 ` Robert Dewar 1 sibling, 0 replies; 20+ messages in thread From: Robert Dewar @ 1995-03-24 17:30 UTC (permalink / raw) Vladimir writes: type A_Struct is record foo : IC.int; bar : IC.char_array (1 .. 10); q : access IC.long; end record; that's wrong, you can't use anonymous access types like this (It's always a good idea to compile code that you put on CLA, to protect against slipups like this, which can confuse the unwary). If I were doing this in GNAT, I wouldn't bother with Interfaces.C, since obviously you are not trying to write code that can be ported to other Ada 95 compilers. Instead I would just write type A_Struct is record foo : Integer; bar : String (0 .. 9); q : Access_Long_Integer; end record; it is particularly nice to avoid the To_Ada and To_C stuff for converting between GNAT Character/String and C char/char*, since these are always the same in GNAT. Interfaces.C is predicated on the assumption that Ada and C will use different data structures for basic data. THis assumption is wrong for GNAT. Of course if you want to write code that will port to other Ada 95 compilers that might make less convenient choices, then you can use Interfaces.C ^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: Importing C Structures 1995-03-23 6:34 Importing C Structures Chris O'Regan 1995-03-23 7:55 ` Vladimir Vukicevic @ 1995-03-24 15:32 ` Robert Dewar 1 sibling, 0 replies; 20+ messages in thread From: Robert Dewar @ 1995-03-24 15:32 UTC (permalink / raw) First of all, the usual advice, if you have questions on GNAT, be SURE to copy them to gnat-report@cs.nyu.edu which is read by the key people on the GNAT development team, not all of whom read comp.lang.ada. There is a simple correspondence between data in Ada and data in C as follows: int -> integer short -> short_integer signed char -> short_short_integer long -> long integer char -> character any simple records map directly to the corresponding C record. In other words, pragma Convention C is the default for GNAT. This should be enough to get you started. For argument passing, see the RM, except there is ONE place we differ from the RM. We do NOT follow the implementation advice to pass IN parameters that are records by address, instead we pass them the same way that C would pass the record (which seems to us a better choice). This may be by address on some machines, but on some machines, depending on the size of the record, they are passed by value. It seems closer to the ABI to follow exactly the same scheme in Ada. ^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~1995-04-07 0:00 UTC | newest] Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1995-03-23 6:34 Importing C Structures Chris O'Regan 1995-03-23 7:55 ` Vladimir Vukicevic 1995-03-23 18:55 ` Robert S. White 1995-03-24 8:51 ` Vladimir Vukicevic 1995-03-25 9:57 ` Keith Thompson 1995-03-26 13:16 ` Larry Kilgallen, LJK Software 1995-03-27 0:00 ` Kevin F. Quinn 1995-04-07 0:00 ` Larry Kilgallen 1995-03-27 15:35 ` Theodore Dennison 1995-03-28 0:00 ` Robert Dewar 1995-03-28 11:44 ` Keith Thompson 1995-03-29 0:00 ` misattrubation (was: Re: Importing C Structures) Theodore Dennison 1995-03-31 0:00 ` Theodore Dennison 1995-03-27 23:39 ` Importing C Structures Keith Thompson 1995-03-27 16:00 ` Norman H. Cohen 1995-03-24 16:08 ` Robert I. Eachus 1995-03-24 20:20 ` Bob Gilbert 1995-03-25 18:07 ` Robert Dewar 1995-03-24 17:30 ` Robert Dewar 1995-03-24 15:32 ` Robert Dewar
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox