comp.lang.ada
 help / color / mirror / Atom feed
* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 ` Dale Stanbrough
@ 1998-10-22  0:00   ` Hans Marqvardsen
  1998-10-23  0:00     ` John McCabe
  1998-10-22  0:00   ` Hans Marqvardsen
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 24+ messages in thread
From: Hans Marqvardsen @ 1998-10-22  0:00 UTC (permalink / raw)


Dale Stanbrough wrote:
> 
> --------------------------------------------------------
> with System;                  use System;
> with System.Storage_Elements; use System.Storage_Elements;
> with System.Address_To_Access_Conversions;
> with text_io;                 use text_IO;
> 
> procedure PB is
> 
>    package Char_Address is new System.Address_To_Access_Conversions (Character);
>    use Char_Address;
> 
>    procedure Print_Bytes (Buffer : System.Address; Length : Integer)
>    is
>       Temp : System.Address;
>    begin
>       Temp := Buffer;
>       for i in 1..Length loop
>          Text_IO.Put (To_Pointer (Temp).all);
>          Temp := Temp + 1;
>       end loop;
>    end Print_Bytes;
> 
>    X : String := "Hello There";
> begin
> 
>    Print_Bytes (X'Address, X'Length);
> 
> end;
> --------------------------------------------------------
> (compiled and works using Gnat3.10, Sparc Solaris).

> Dale

Strangely, using OA 7.1.1 it wont compile.
Error message:
          Temp := Temp + 1;
 Line 20 col 23: the expression is ambiguous.




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 ` Dale Stanbrough
  1998-10-22  0:00   ` Hans Marqvardsen
@ 1998-10-22  0:00   ` Hans Marqvardsen
  1998-10-23  0:00   ` David C. Hoos, Sr.
  1998-10-23  0:00   ` David C. Hoos, Sr.
  3 siblings, 0 replies; 24+ messages in thread
From: Hans Marqvardsen @ 1998-10-22  0:00 UTC (permalink / raw)


Hello Craig!
Since you say, you're new to Ada,
here is 2 further hints regarding Dales program:

	The 'Size attribute is defined for any data-element
	giving its size in bits.  Use 'Size instead of 'Length.
	(remember to divide by Storage_Unit)

	Probably the number 1 should be casted as type 
	Storage_offset before it is added to a System.address. 
	(At least the OA compiler says so)  

With these inclusions, Dales program will truly do the job, 
not only for strings, but for any data-type passed, 
for example integers, floats or records.
(Compiles and works on OA 7.1.1, Windows NT)

Hans.

Sorry for not including Dales original program.
My Netscape wont allow more included text than new text.




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00     ` John McCabe
  1998-10-23  0:00       ` Ed Falis
@ 1998-10-23  0:00       ` dennison
  1 sibling, 0 replies; 24+ messages in thread
From: dennison @ 1998-10-23  0:00 UTC (permalink / raw)


In article <70pfpm$qe5@gcsin3.geccs.gecm.com>,
  John McCabe <john@assen.demon.co.uk> wrote:

> In the OA package System, what is type Address declared as?

    type Address is access Integer;
    Null_Address          : constant Address := null;


--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 simple question - how to emulate void * ? Craig Allen
  1998-10-23  0:00 ` Tom Moran
  1998-10-23  0:00 ` Dale Stanbrough
@ 1998-10-23  0:00 ` Jeff Carter
  1998-10-24  0:00   ` Dale Stanbrough
  1998-11-05  0:00 ` Craig Allen
  3 siblings, 1 reply; 24+ messages in thread
From: Jeff Carter @ 1998-10-23  0:00 UTC (permalink / raw)
  To: Craig Allen

Craig Allen wrote:
> 
> Well, yes, I'm new to ada, and coming from C.
> 
> Now, I have some simple functionality that I'd like to see, and can't
> figure out how to do it in Ada.
> 
> in C, it goes like this:
> 
> /* libfile.c */
> 
> void print_bytes(void *buf, int len)
> {
>         int i;
>         char *c = buf;
>         for (i=0; i<len; ++i) {
>                 putchar(c[i]);
>         }
> 
>         return;
> }
> 
> /* app.c */
>         ...
>         struct any_struct data;
>         print_bytes(&data, sizeof (struct data));
>         ...
> 
> The lib can access byte for byte the data passed in regardless of the
> app's struct type.  Now, Ada being such a strongly typed language, I
> have tried different things but just can't seem to figure out how to
> get this lib routine to work on my buffer, regardless of its type.
> I've come close with some generic functions, but can't seem to get the
> syntax acceptable for the compiler.
> Can someone point me in the right direction?
> 
> Specifically, this library function will be shipping things out a
> serial port, one byte at a time, that is why i'd like to address it as
> an array of bytes.
> 
> Thanks.
> -Craig

Well, some of the responses showed how to implement this exact
capability (print anything as an array of characters) and something
along the lines of what is really desired (print anything as an array of
bytes), but the real answer should be, "You should not try to emulate
'void *' in Ada.". No one has addressed how to solve this problem
properly using Ada. Basically, the question is how to access an object
of any type as an array of bytes and apply an arbitrary operation to
that array of bytes, such as shipping the bytes out a serial port.

For shipping the bytes out a serial port, streams seem to be the best
way. Define the 'Write operation for the type(s) to write the object(s)
byte by byte.

In general, though, assume we want to apply an arbitrary operation on an
array of bytes to any type. I would specifiy this as something like

package Byte_By_Byte is
   Byte_Size : constant := 8;
   type Byte is mod 2 ** Byte_Size;
   for Byte'Size use Byte_Size;

   type Byte_List is array (Positive range <>) of Byte;
   for Byte_List'Component_Size use Byte_Size;
   pragma Pack (Byte_List);

   generic -- Apply_Operation
      type Anything (<>) is limited private;

      with procedure Operation (List : in Byte_List);
   procedure Apply_Operation (Thing : in Anything);
end Byte_By_Byte;

The user of this would then define the operation on a list of bytes:

with Ada.Text_Io;
with Byte_By_Byte;
...
   procedure Write_As_Characters (List : in Byte_By_Byte.Byte_List) is
   begin -- Write_As_Characters
      All_Bytes : for I in List'range loop
         Ada.Text_Io.Put (Item => Character'Val (List (I) ) );
      end loop All_Bytes;
   end Write_As_Characters;

(or any other operation the user chooses, such as sending the bytes to a
serial port), define the type(s):

   type Ugly is record
      X : Integer  := Integer'First;
      Y : Float    := 0.0;
      Z : Duration := Duration'Last;
   end record;

instantiate the generic:

   procedure Write_Bytes is new Byte_By_Byte.Apply_Operation
      (Anything => Ugly, Operation => Write_As_Characters);

and use it:

   U : Ugly := (X => Integer'Last, Y => 0.0, Z => Duration'First);
begin
   Write_Bytes (Thing => U);

Then Allen's question would be, how should he implement the body of
Byte_By_Byte. The responses I've seen should give him a clue. I'd
suggest something like

package body Byte_By_Byte is
   procedure Apply_Operation (Thing : in Anything) is
      List : Byte_List (1 .. (Thing'Size + Byte_Size - 1) / Byte_Size);
      for List'Address use Thing'Address;
   begin -- Apply_Operation
      Operation (List => List);
   end Apply_Operation;
end Byte_By_Byte;

I have not compiled any of this code, and apologize in advance for the
errors I have made. (I take it as given that I have made errors; that's
why I have inspections of anything I do related to SW development.
However, here I have not even let a compiler find the most blatant of my
errors, so my certainty that I've made errors is stronger.)

I think this is a better answer because it shows how Ada features are
intended to be used, within limits and dealing with something of
interest to the questioner. The short answers will likely result Allen
going away and solving this problem, but by writing Ada-C.

-- 
Jeff Carter  PGP:1024/440FBE21
"We burst our pimples at you."
Monty Python & the Holy Grail




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00       ` Ed Falis
@ 1998-10-23  0:00         ` dennison
  1998-10-24  0:00           ` Joe Wisniewski
  1998-10-25  0:00           ` dewar
  1998-10-24  0:00         ` Dale Stanbrough
  1 sibling, 2 replies; 24+ messages in thread
From: dennison @ 1998-10-23  0:00 UTC (permalink / raw)


In article <1104_909142646@DZOG-CHEN>,
  falis@ma.aonix.com (Ed Falis) wrote:
> In OA, both System and System.Storage_Units declare "+" operators with Address
and Integer or Storage_Offset respectively.  Since there are use clauses
> for both units, the compiler doesn't know how to interpret the numeric literal
"1" on the right hand side of the expression.
>
> So, eliminate one of the use clauses, or qualify the literal, e.g. Integer'(1)
or Storage_Offset'(1), and the code will compile and execute.
>

One more poor soul burned by the evil "use" clause...

--
T.E.D.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 24+ messages in thread

* simple question - how to emulate void * ?
@ 1998-10-23  0:00 Craig Allen
  1998-10-23  0:00 ` Tom Moran
                   ` (3 more replies)
  0 siblings, 4 replies; 24+ messages in thread
From: Craig Allen @ 1998-10-23  0:00 UTC (permalink / raw)


Well, yes, I'm new to ada, and coming from C.

Now, I have some simple functionality that I'd like to see, and can't 
figure out how to do it in Ada.

in C, it goes like this:

/* libfile.c */

void print_bytes(void *buf, int len)
{
	int i;
	char *c = buf;
	for (i=0; i<len; ++i) {
		putchar(c[i]);
	}

	return;
}

/* app.c */
	...
	struct any_struct data;
	print_bytes(&data, sizeof (struct data));
	...

The lib can access byte for byte the data passed in regardless of the 
app's struct type.  Now, Ada being such a strongly typed language, I 
have tried different things but just can't seem to figure out how to 
get this lib routine to work on my buffer, regardless of its type.  
I've come close with some generic functions, but can't seem to get the
syntax acceptable for the compiler.
Can someone point me in the right direction?

Specifically, this library function will be shipping things out a 
serial port, one byte at a time, that is why i'd like to address it as
an array of bytes.

Thanks.
-Craig




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 simple question - how to emulate void * ? Craig Allen
@ 1998-10-23  0:00 ` Tom Moran
  1998-10-23  0:00 ` Dale Stanbrough
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 24+ messages in thread
From: Tom Moran @ 1998-10-23  0:00 UTC (permalink / raw)


You might look into Ada.Streams.  Alternatively, if you really want to
send the bytes comprising the data (which would make little sense if
they were pointers, say), you can either create an array of bytes,
located at the same address as the data, or simply do an unchecked
conversion from the data to an array of bytes of the appropriate size.
 type bytes is mod 256;
  for bytes'size use 8;
type byte_array_type is array(natural range <>) of bytes;
procedure send_bytes(b : in byte_array_type) is .....
procedure send(x : in some_record_type) is
  subtype x_byte_array_type is byte_array_type(1 .. x'size/8);
  for x_byte_array_type'size use x'size;
  function bytes_of is new
Ada.Unchecked_Conversion(source=>some_record_type;
     target=>x_byte_array_type);
begin
    send_bytes(bytes_of(x));
end send;
  (Typed in on the fly, but should give the general idea)




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-22  0:00   ` Hans Marqvardsen
@ 1998-10-23  0:00     ` John McCabe
  1998-10-23  0:00       ` Ed Falis
  1998-10-23  0:00       ` dennison
  0 siblings, 2 replies; 24+ messages in thread
From: John McCabe @ 1998-10-23  0:00 UTC (permalink / raw)


Hans Marqvardsen <hm@ddre.dk> wrote:

Works on Irix 6.4, GNAT 3.07 (?)

<..snip..>

>>          Temp := Temp + 1;

>Strangely, using OA 7.1.1 it wont compile.
>Error message:
>          Temp := Temp + 1;
> Line 20 col 23: the expression is ambiguous.

In the OA package System, what is type Address declared as?

-- 
Best Regards
John McCabe
---------------------------------------------------------------------
Marconi Electronic Systems
Simulation & Training Division
=====================================================================
Not necessarily my company or service providers opinions.
=====================================================================






^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00     ` John McCabe
@ 1998-10-23  0:00       ` Ed Falis
  1998-10-23  0:00         ` dennison
  1998-10-24  0:00         ` Dale Stanbrough
  1998-10-23  0:00       ` dennison
  1 sibling, 2 replies; 24+ messages in thread
From: Ed Falis @ 1998-10-23  0:00 UTC (permalink / raw)


> Hans Marqvardsen <hm@ddre.dk> wrote:
> 
> Works on Irix 6.4, GNAT 3.07 (?)
> 
> <..snip..>
> 
> >>          Temp := Temp + 1;
> 
> >Strangely, using OA 7.1.1 it wont compile.
> >Error message:
> >          Temp := Temp + 1;
> > Line 20 col 23: the expression is ambiguous.
> 

In OA, both System and System.Storage_Units declare "+" operators with Address and Integer or Storage_Offset respectively.  Since there are use clauses 
for both units, the compiler doesn't know how to interpret the numeric literal  "1" on the right hand side of the expression.

So, eliminate one of the use clauses, or qualify the literal, e.g. Integer'(1) or Storage_Offset'(1), and the code will compile and execute.

My guess is that the address arithmetic in OA System was left in for compatibility with the Alsys Ada 83 compilers it replaced.

- Ed Falis
Aonix




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 ` Dale Stanbrough
  1998-10-22  0:00   ` Hans Marqvardsen
  1998-10-22  0:00   ` Hans Marqvardsen
@ 1998-10-23  0:00   ` David C. Hoos, Sr.
  1998-10-23  0:00   ` David C. Hoos, Sr.
  3 siblings, 0 replies; 24+ messages in thread
From: David C. Hoos, Sr. @ 1998-10-23  0:00 UTC (permalink / raw)


The trouble with Dale's solution is that it doesn't meet Craig's requirement
that the data be able to be of any type.
Further, Dale's liberal use uf use clauses obscures the fact that To_Pointer
is really Char_Addr.To_Pointer, thus rendering the procedure Print_Bytes
suitable only for arrays of characters -- i.e. strings.

The solution at the end of this post does meet Craig's requirement.  Because
my Print_Bytes procedure is type-independent, I print each byte's
hexadecimal value.

David C. Hoos, Sr.

Dale Stanbrough wrote in message ...
>Craig Allen wrote:
>
> Well, yes, I'm new to ada, and coming from C.
>
> Now, I have some simple functionality that I'd like to see, and can't
> figure out how to do it in Ada.
>
> in C, it goes like this:
>
> /* libfile.c */
>
> void print_bytes(void *buf, int len)
> {
>         int i;
>         char *c = buf;
>         for (i=0; i<len; ++i) {
>                 putchar(c[i]);
>         }
>
>         return;
> }
>
> /* app.c */
>         ...
>         struct any_struct data;
>         print_bytes(&data, sizeof (struct data));
>         ...
>
> The lib can access byte for byte the data passed in regardless of the
> app's struct type.  Now, Ada being such a strongly typed language, I
> have tried different things but just can't seem to figure out how to
> get this lib routine to work on my buffer, regardless of its type.
> I've come close with some generic functions, but can't seem to get the
> syntax acceptable for the compiler.
> Can someone point me in the right direction?"
>
>
>Try using the object's address...
>
>--------------------------------------------------------
>with System;                  use System;
>with System.Storage_Elements; use System.Storage_Elements;
>with System.Address_To_Access_Conversions;
>with text_io;                 use text_IO;
>
>
>procedure PB is
>
>   package Char_Address is new System.Address_To_Access_Conversions
(Character);
>   use Char_Address;
>
>
>   procedure Print_Bytes (Buffer : System.Address; Length : Integer)
>   is
>      Temp : System.Address;
>   begin
>      Temp := Buffer;
>      for i in 1..Length loop
>         Text_IO.Put (To_Pointer (Temp).all);
>         Temp := Temp + 1;
>      end loop;
>   end Print_Bytes;
>
>
>
>   X : String := "Hello There";
>begin
>
>   Print_Bytes (X'Address, X'Length);
>
>end;
>--------------------------------------------------------
>(compiled and works using Gnat3.10, Sparc Solaris).
>
>Also the function "To_Pointer" is an intrinsic function, so it won't
>incur any overhead (that i can see) for being called. All the package
>Address_To_Access_Conversion does is explicity enforces what C does
>implicity, and at the same cost (someone please correct me if i am
>wrong)).
>
>Note that X'Length will give you the number of _Components_ in an
>array, not the length (in bytes) of the array.
>
>You could also use streams, which (IMHO) is a much more versatile
>tool.
>
>Dale

--- begin file print_bytes.adb -------------------------
with Ada.Text_Io;
with System.Storage_Elements;
procedure Print_Bytes
      (At_The_Address : System.Address;
      Storage_Element_Count : Natural) is
   Elements_Per_Line : constant System.Storage_Elements.Storage_Count := 8;
   use type System.Storage_Elements.Storage_Offset;
   package Storage_Element_Io is new
      Ada.Text_Io.Modular_Io (System.Storage_Elements.Storage_Element);
   The_Data : System.Storage_Elements.Storage_Array
      (1 .. System.Storage_Elements.Storage_Count (Storage_Element_Count));
   for The_Data'Address use At_The_Address;
begin

   for E in The_Data'range loop
      if (E mod Elements_Per_Line) = 1 then
         Ada.Text_Io.New_Line;
      end if;
      Storage_Element_Io.Put
         (Item => The_Data (E),
         Width => 8,
         Base => 16);
   end loop;
end Print_Bytes;
--- end file print_bytes.adb -------------------------


--- begin file app.adb -------------------------
with print_bytes;
with System.Storage_Elements;
procedure App is
   subtype Storage_Element is System.Storage_Elements.Storage_Element;

   The_Data : constant array (Positive range <>) of Long_Float :=
      (1.0, 2.0, 3.0, 4.0);
begin
   Print_Bytes
      (At_The_Address => The_Data (The_Data'First)'Address,
      Storage_Element_Count => The_Data'Size / Storage_Element'Size);
end App;
--- end file app.adb -------------------------








^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 ` Dale Stanbrough
                     ` (2 preceding siblings ...)
  1998-10-23  0:00   ` David C. Hoos, Sr.
@ 1998-10-23  0:00   ` David C. Hoos, Sr.
  3 siblings, 0 replies; 24+ messages in thread
From: David C. Hoos, Sr. @ 1998-10-23  0:00 UTC (permalink / raw)


The trouble with Dale's solution is that it doesn't meet Craig's requirement
that the data be able to be of any type.
Further, Dale's liberal use of use clauses obscures the fact that To_Pointer
is really Char_Addr.To_Pointer, thus rendering the procedure Print_Bytes
suitable only for arrays of characters -- i.e. strings.

The solution at the end of this post does meet Craig's requirement.  Because
my Print_Bytes procedure is type-independent, I print each byte's
hexadecimal value.

David C. Hoos, Sr.

Dale Stanbrough wrote in message ...
>Craig Allen wrote:
>
> Well, yes, I'm new to ada, and coming from C.
>
> Now, I have some simple functionality that I'd like to see, and can't
> figure out how to do it in Ada.
>
> in C, it goes like this:
>
> /* libfile.c */
>
> void print_bytes(void *buf, int len)
> {
>         int i;
>         char *c = buf;
>         for (i=0; i<len; ++i) {
>                 putchar(c[i]);
>         }
>
>         return;
> }
>
> /* app.c */
>         ...
>         struct any_struct data;
>         print_bytes(&data, sizeof (struct data));
>         ...
>
> The lib can access byte for byte the data passed in regardless of the
> app's struct type.  Now, Ada being such a strongly typed language, I
> have tried different things but just can't seem to figure out how to
> get this lib routine to work on my buffer, regardless of its type.
> I've come close with some generic functions, but can't seem to get the
> syntax acceptable for the compiler.
> Can someone point me in the right direction?"
>
>
>Try using the object's address...
>
>--------------------------------------------------------
>with System;                  use System;
>with System.Storage_Elements; use System.Storage_Elements;
>with System.Address_To_Access_Conversions;
>with text_io;                 use text_IO;
>
>
>procedure PB is
>
>   package Char_Address is new System.Address_To_Access_Conversions
(Character);
>   use Char_Address;
>
>
>   procedure Print_Bytes (Buffer : System.Address; Length : Integer)
>   is
>      Temp : System.Address;
>   begin
>      Temp := Buffer;
>      for i in 1..Length loop
>         Text_IO.Put (To_Pointer (Temp).all);
>         Temp := Temp + 1;
>      end loop;
>   end Print_Bytes;
>
>
>
>   X : String := "Hello There";
>begin
>
>   Print_Bytes (X'Address, X'Length);
>
>end;
>--------------------------------------------------------
>(compiled and works using Gnat3.10, Sparc Solaris).
>
>Also the function "To_Pointer" is an intrinsic function, so it won't
>incur any overhead (that i can see) for being called. All the package
>Address_To_Access_Conversion does is explicity enforces what C does
>implicity, and at the same cost (someone please correct me if i am
>wrong)).
>
>Note that X'Length will give you the number of _Components_ in an
>array, not the length (in bytes) of the array.
>
>You could also use streams, which (IMHO) is a much more versatile
>tool.
>
>Dale

--- begin file print_bytes.adb -------------------------
with Ada.Text_Io;
with System.Storage_Elements;
procedure Print_Bytes
      (At_The_Address : System.Address;
      Storage_Element_Count : Natural) is
   Elements_Per_Line : constant System.Storage_Elements.Storage_Count := 8;
   use type System.Storage_Elements.Storage_Offset;
   package Storage_Element_Io is new
      Ada.Text_Io.Modular_Io (System.Storage_Elements.Storage_Element);
   The_Data : System.Storage_Elements.Storage_Array
      (1 .. System.Storage_Elements.Storage_Count (Storage_Element_Count));
   for The_Data'Address use At_The_Address;
begin

   for E in The_Data'range loop
      if (E mod Elements_Per_Line) = 1 then
         Ada.Text_Io.New_Line;
      end if;
      Storage_Element_Io.Put
         (Item => The_Data (E),
         Width => 8,
         Base => 16);
   end loop;
end Print_Bytes;
--- end file print_bytes.adb -------------------------


--- begin file app.adb -------------------------
with print_bytes;
with System.Storage_Elements;
procedure App is
   subtype Storage_Element is System.Storage_Elements.Storage_Element;

   The_Data : constant array (Positive range <>) of Long_Float :=
      (1.0, 2.0, 3.0, 4.0);
begin
   Print_Bytes
      (At_The_Address => The_Data (The_Data'First)'Address,
      Storage_Element_Count => The_Data'Size / Storage_Element'Size);
end App;
--- end file app.adb -------------------------










^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 simple question - how to emulate void * ? Craig Allen
  1998-10-23  0:00 ` Tom Moran
@ 1998-10-23  0:00 ` Dale Stanbrough
  1998-10-22  0:00   ` Hans Marqvardsen
                     ` (3 more replies)
  1998-10-23  0:00 ` Jeff Carter
  1998-11-05  0:00 ` Craig Allen
  3 siblings, 4 replies; 24+ messages in thread
From: Dale Stanbrough @ 1998-10-23  0:00 UTC (permalink / raw)


Craig Allen wrote:

 Well, yes, I'm new to ada, and coming from C.
 
 Now, I have some simple functionality that I'd like to see, and can't 
 figure out how to do it in Ada.
 
 in C, it goes like this:
 
 /* libfile.c */
 
 void print_bytes(void *buf, int len)
 {
         int i;
         char *c = buf;
         for (i=0; i<len; ++i) {
                 putchar(c[i]);
         }
 
         return;
 }
 
 /* app.c */
         ...
         struct any_struct data;
         print_bytes(&data, sizeof (struct data));
         ...
 
 The lib can access byte for byte the data passed in regardless of the 
 app's struct type.  Now, Ada being such a strongly typed language, I 
 have tried different things but just can't seem to figure out how to 
 get this lib routine to work on my buffer, regardless of its type.  
 I've come close with some generic functions, but can't seem to get the
 syntax acceptable for the compiler.
 Can someone point me in the right direction?"


Try using the object's address...

--------------------------------------------------------
with System;                  use System;
with System.Storage_Elements; use System.Storage_Elements;
with System.Address_To_Access_Conversions;
with text_io;                 use text_IO;


procedure PB is

   package Char_Address is new System.Address_To_Access_Conversions (Character);
   use Char_Address;


   procedure Print_Bytes (Buffer : System.Address; Length : Integer)
   is
      Temp : System.Address;
   begin
      Temp := Buffer;
      for i in 1..Length loop
         Text_IO.Put (To_Pointer (Temp).all);
         Temp := Temp + 1;
      end loop;
   end Print_Bytes;



   X : String := "Hello There";
begin

   Print_Bytes (X'Address, X'Length);

end;
--------------------------------------------------------
(compiled and works using Gnat3.10, Sparc Solaris).

Also the function "To_Pointer" is an intrinsic function, so it won't
incur any overhead (that i can see) for being called. All the package
Address_To_Access_Conversion does is explicity enforces what C does
implicity, and at the same cost (someone please correct me if i am 
wrong)).

Note that X'Length will give you the number of _Components_ in an
array, not the length (in bytes) of the array.

You could also use streams, which (IMHO) is a much more versatile 
tool.

Dale




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-24  0:00         ` Dale Stanbrough
@ 1998-10-24  0:00           ` Robert A Duff
  1998-10-24  0:00           ` Tucker Taft
  1 sibling, 0 replies; 24+ messages in thread
From: Robert A Duff @ 1998-10-24  0:00 UTC (permalink / raw)


dale@cs.rmit.edu.au (Dale Stanbrough) writes:

> This is then a problem with Ada, ...

True.

>... Perhaps we need to understand the rationale of
> having
> 
>    type Address is <impl. defined>
> 
> vs.
> 
>    type Address is private;

Making type Address private, with a portable set of operators, is
clearly preferable.  The Ada 95 RM has Implementation Advice that
encourages that.  However, we couldn't *require* it, because in Ada 83,
an implementation could put anything they liked into package System, and
we wanted allow those implementations to have an upward-compatible
System.

A good rule of thumb is to never say "use System;", because you never
know what junk might be in System, and might conflict with other use
clauses.  That was good advice in Ada 83, too, since one might be using
different versions of System from different compilers.

At least this sort of error is found at compile time.  The use-clause
rules prevent Beujolais effects -- that is, if there's a conflict
between, say, System."+" and System.Storage_Elements."+", then neither
one silently wins, but you get a compile-time error.

> I certainly haven't hit this particular problem before, ...

Perhaps because you never said "use System", but instead always
"System.Whatever".

- Bob
-- 
Change robert to bob to get my real email address.  Sorry.




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00         ` dennison
@ 1998-10-24  0:00           ` Joe Wisniewski
  1998-10-25  0:00           ` dewar
  1 sibling, 0 replies; 24+ messages in thread
From: Joe Wisniewski @ 1998-10-24  0:00 UTC (permalink / raw)


There is an analogous situation to this "use" problem with
named notation for a subprogram that is overloaded. I can't
quite remember the situation exactly. Ugh, I can't quite remember
the situation. If someone;s run into this recently, it would be interesting
to look at.

Joe

dennison@telepath.com wrote in message <70q89d$io1$1@nnrp1.dejanews.com>...
>In article <1104_909142646@DZOG-CHEN>,
>  falis@ma.aonix.com (Ed Falis) wrote:
>> In OA, both System and System.Storage_Units declare "+" operators with
Address
>and Integer or Storage_Offset respectively.  Since there are use clauses
>> for both units, the compiler doesn't know how to interpret the numeric
literal
>"1" on the right hand side of the expression.
>>
>> So, eliminate one of the use clauses, or qualify the literal, e.g.
Integer'(1)
>or Storage_Offset'(1), and the code will compile and execute.
>>
>
>One more poor soul burned by the evil "use" clause...
>
>--
>T.E.D.
>
>-----------== Posted via Deja News, The Discussion Network ==----------
>http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own






^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-24  0:00         ` Dale Stanbrough
  1998-10-24  0:00           ` Robert A Duff
@ 1998-10-24  0:00           ` Tucker Taft
  1 sibling, 0 replies; 24+ messages in thread
From: Tucker Taft @ 1998-10-24  0:00 UTC (permalink / raw)


Dale Stanbrough (dale@cs.rmit.edu.au) wrote:

: ...
: This is then a problem with Ada, that the legality of calling a routine in
: a child package can be affected by the exact definition of a type defined
: as "implementation defined".

: ...

: Perhaps it would have been better if the LRM specifically excluded these
: operations from package System.Address, given the presence of
: System.Storage_Elements. Perhaps we need to understand the rationale of
: having

:    type Address is <impl. defined>

: vs.

:    type Address is private;

: I certainly haven't hit this particular problem before, and it _is_
: an annoying "feature". Can anyone clarify this point for me?

In RM95 we tried to balance the requirements for upward compatibility
against the requirements for portability.  In Ada 83, package System
became a dumping ground for all kinds of non-portable stuff.  In Ada 95,
we tried to encourage vendors to put the non-portable stuff into
implementation-defined children of System.  In particular, RM95 13.7(36)
and 13.7(37) permit implementation-defined additions to System, but
encourage the use of children instead, and encourage declaring Address as 
a private type.

However, vendors with a large installed Ada 83 base had to make certain 
choices based on their customer preferences.  The adding operators
on type Address involve such a choice.  

The net effect is that users who want to write portable code 
have to reckon with the possibility that package System 
might have extra stuff in it.  Hence, minimize the use of 
"use" on package System.  A "use" on package System.Storage_Elements
(or a "use type" on System.Storage_Elements.Storage_Offset) should be 
safe and portable, since no implementation-defined additions
are permitted to that package.

: Dale

--
-Tucker Taft   stt@inmet.com   http://www.inmet.com/~stt/
Intermetrics, Inc.  Burlington, MA  USA
An AverStar Company




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00       ` Ed Falis
  1998-10-23  0:00         ` dennison
@ 1998-10-24  0:00         ` Dale Stanbrough
  1998-10-24  0:00           ` Robert A Duff
  1998-10-24  0:00           ` Tucker Taft
  1 sibling, 2 replies; 24+ messages in thread
From: Dale Stanbrough @ 1998-10-24  0:00 UTC (permalink / raw)


Ed Falis wrote:

"In OA, both System and System.Storage_Units declare "+" operators with Address
 and Integer or Storage_Offset respectively.  Since there are use clauses 
 for both units, the compiler doesn't know how to interpret the numeric literal 
 "1" on the right hand side of the expression.
 
 So, eliminate one of the use clauses, or qualify the literal, e.g. Integer'(1)
 or Storage_Offset'(1), and the code will compile and execute.
 
 My guess is that the address arithmetic in OA System was left in for
 compatibility with the Alsys Ada 83 compilers it replaced.
 
 - Ed Falis
 Aonix"



This is then a problem with Ada, that the legality of calling a routine in
a child package can be affected by the exact definition of a type defined
as "implementation defined".

package System has...

   type Address is <implementation defined>;


package System.Storage_Elements is...

   address manipulation routines such as +, - and mod.


If Address is defined as an integer type, then it automatically gets all
of the numeric operations inherited.

If Address is an access type, then it gets not much.

Perhaps it would have been better if the LRM specifically excluded these
operations from package System.Address, given the presence of
System.Storage_Elements. Perhaps we need to understand the rationale of
having

   type Address is <impl. defined>

vs.

   type Address is private;

I certainly haven't hit this particular problem before, and it _is_
an annoying "feature". Can anyone clarify this point for me?


Dale




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 ` Jeff Carter
@ 1998-10-24  0:00   ` Dale Stanbrough
  1998-10-25  0:00     ` dewar
  0 siblings, 1 reply; 24+ messages in thread
From: Dale Stanbrough @ 1998-10-24  0:00 UTC (permalink / raw)


Jeff Carter wrote:

"Well, some of the responses showed how to implement this exact
 capability (print anything as an array of characters) and something
 along the lines of what is really desired (print anything as an array of
 bytes), but the real answer should be, "You should not try to emulate
 'void *' in Ada."."


You should also be careful of scaring people away. Many people want to
know if they can do a task in a particular way, i replied that they 
could (I often get asked "can Ada call "system"?" - there is a hell of
a lot of ignorance out there (well, amongst students at least, but I 
would imagine that exactly the same happens elsewhere). Showing people
that yes, Ada can do it in exactly this way _is_ a useful thing to show.

People can then walk away and say 

   "ok, so i can do all of those things that C can. Maybe it's not 
    so bad...".

rather than...

   "i asked them how to do this, and all they did was say i was 
    wrong and to stop doing it that way."

Technically you may be correct, but that's no use if the person goes
away with a feeling in the back of their mind that says C still has it
over Ada in some areas.

Note i did also say that streams were probably a better way of doing it.


Dale




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00         ` dennison
  1998-10-24  0:00           ` Joe Wisniewski
@ 1998-10-25  0:00           ` dewar
  1 sibling, 0 replies; 24+ messages in thread
From: dewar @ 1998-10-25  0:00 UTC (permalink / raw)


In article <70q89d$io1$1@nnrp1.dejanews.com>,
  dennison@telepath.com wrote:
> In article <1104_909142646@DZOG-CHEN>,
>   falis@ma.aonix.com (Ed Falis) wrote:
> > In OA, both System and System.Storage_Units declare "+" operators with
Address
> and Integer or Storage_Offset respectively.  Since there are use clauses
> > for both units, the compiler doesn't know how to interpret the numeric
literal
> "1" on the right hand side of the expression.
> >
> > So, eliminate one of the use clauses, or qualify the literal, e.g.
Integer'(1)
> or Storage_Offset'(1), and the code will compile and execute.
> >
>
> One more poor soul burned by the evil "use" clause...


That does not seem exactly fair in this case. It is a mistake in an Ada 95
compiler to provide address arithmetic in System. Yes, some compilers do
this for compatibility with implementation dependent additions to their
System packages for Ada 83, but it is a huge pain for Ada 95 programmers.

We ran across this with the DEC version of System which also supplies address
arithmetic (and lots of other stuff) in their System, and it definitely
inteferes with many existing programs. The danger here is not in using a
USE clause per se, but in the assumption that "use System" only gets you
the stuff you see in the RM. Unfortunately, that is not necessarily the
case, since implementors are allowed to add anything they like to System.

In GNAT, the standard version of System that you get without doing anything
special is the one in the RM. If you need an extended version of System with
non-standard extensions, then you can use the GNAT pragma Extend_System,
naming a package that provides the extensions. We distribute a standard
package System.Aux_DEC that provides the DEC Ada 83 extensions, but
additional extensions can be provided.

It would for example be possible to provide a package that added the OA
extensions, and this is probably easy to do. We just haven't done it because
there hasn't been any demand for this (our customers are typically writing
new Ada 95 programs, or porting legacy code from other than Alsys systems,
or porting standard Ada code that does not use these extensions) so the
issue has not arisen. Note that it is definitely good Ada practice NOT
to use System dependent extensions in Ada programs.

For those not allergic to use clauses, it is a bit of a pity not to allow
yourself to "use system", but with compilers around that add
implementation dependent stuff to System, it may cause difficulties.

Note that Ada is carefully designed so that the "evil" effects of using USE
in a case like this are limited to the introduction of ambiguities that are
(a) clearly diagnosed by any decent compiler and (b) easily fixed, so that's
not exactly so evil if you know what you are doing!

Note of course that address arithmetic is something that should in any case
ONLY be used by Ada programmers who know what they are doing (in practice of
course, as one can tell from the somewhat distasteful subject line of this
thread, distasteful because void * is in some ways a crystallization of
what is wrong with C, people often try to use address arithmetic in
inappropriate cases!)

Robert Dewar
Ada Core Technologies


-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-24  0:00   ` Dale Stanbrough
@ 1998-10-25  0:00     ` dewar
  0 siblings, 0 replies; 24+ messages in thread
From: dewar @ 1998-10-25  0:00 UTC (permalink / raw)


In article <dale-2410982221230001@dale.ppp.cs.rmit.edu.au>,
  dale@cs.rmit.edu.au (Dale Stanbrough) wrote:

> You should also be careful of scaring people away. Many people want to
> know if they can do a task in a particular way, i replied that they
> could (I often get asked "can Ada call "system"?" - there is a hell of
> a lot of ignorance out there (well, amongst students at least, but I
> would imagine that exactly the same happens elsewhere). Showing people
> that yes, Ada can do it in exactly this way _is_ a useful thing to show.
>
> People can then walk away and say
>
>    "ok, so i can do all of those things that C can. Maybe it's not
>     so bad...".

Dale certainly has a point. On the other hand, if you end up sending a message
that Ada can do anything you can do in C, and do not emphasize the advantages
of Ada, then a reasonable reaction is "well if Ada can do anything that C can
do [and implicitly vice versa, since I haven't heard anything to the contrary]
I might as well stick with C".

So it is important to emphasize the Ada way of doing things. In general people
tend to ask how to do something in Ada and tell you the solution they already
figured out in some other language, rather than the original problem, which
probably has a better solution.

After all if you really want to write a program full of address arithmetic
and low level C-style mucking (as opposed to using these features only at
critical points where they are justified), then I think you indeed should
stick to C, there is no point in writing C-style code in Ada. Interestingly
the converse is not true, there *is* a point in writing Ada-style code in C.
If you know Ada, and then force yourself to do things in a stylized way in
Ada style, you can get some of the advantages of Ada in C, at least at a
readability level (however, note the use of the word "some" here!)

Tucker Taft claims that the Intermetrics front end, which is written in C,
follows such style rules, but since few people have seen these sources it
is hard for people to judge how well this was achieved.

My own feeling is that even if you do try to write C in a restricted, "nice"
style, and enforce this with tools (the enforcement is very important or long
term maintenance by C programmers not so committed to the stylistic decisions
of the original will ruin things), you still have something that is far short
of satisfactory.

One of the best decisions we made in the GNAT project was to implement the
front end and library entirely in Ada 95. Interestingly this was a decision
forced on us by Chris Anderson, as our project manager at DoD when then GNAT
project was at NYU. She couldn't justify spending their money on writing C
code. We had originally intended to migrate the original Ada-Ed front end
(written in C in the early 80's) to Ada 95, but I think we would never have
succeeded following that path. Indeed the GNAT project itself is one of those
anecdotal cases of C programmers being forced to use Ada, and pretty quickly
being VERY happy with the change :-)

We certainly regard it as an important strength that we write in Ada 95, and
we believe in our own tools for building our tools. It would of course be
nice to rewrite gcc in Ada 95, but as in many other circumstances, one cannot
justify a major rewrite effort of this kind just to change languages. Of
course if one could find the resources for a major reengineering effort for
the GCC backend at the same time, that would be interesting.

However, even though the GCC backend is in C, the strong capabilities for
interfacing Ada 95 and C make it very easy to marry the Ada 95 front end
with the C backend (indeed GNAT itself is a very nice example of the ease
of such mixed language programming with Ada 95!)

Robert Dewar
Ada Core Technologies

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-10-23  0:00 simple question - how to emulate void * ? Craig Allen
                   ` (2 preceding siblings ...)
  1998-10-23  0:00 ` Jeff Carter
@ 1998-11-05  0:00 ` Craig Allen
  1998-11-06  0:00   ` Dale Stanbrough
  1998-11-06  0:00   ` Tom Moran
  3 siblings, 2 replies; 24+ messages in thread
From: Craig Allen @ 1998-11-05  0:00 UTC (permalink / raw)


On Fri, 23 Oct 1998 01:33:52, cpallen@nospam.com (Craig Allen) wrote:

> Well, yes, I'm new to ada, and coming from C.
> 

and the rest of the discussion...

I'd like to thank everyone for their suggestions.  It certainly has 
been a learning experience for me.  I am a little surprised that there
is so much to this problem.  I'm not opposed to doing things 'The 
Right Way', but a simple solution was what I was looking for, that's 
why I was looking for a replacement for (void *).

If anyone is still following this thread, I'd like to ask another 
question:

I've tried the suggestions given here, and failed miserably.  The 
culprit in all cases was the fact that I'm using an Ada83 compiler (no
choice, sorry...).  It doesn't support many of the things that were 
mentioned, like 

with System.(insert anything here)
for var'Address use othervar'Address

for this, I also tried 
for var use at othervar'Address

but my compiler seems to really expect a static address for the 
location.

Anyway, I've learned a lot, but am still stumped.  I'm currently 
giving up and hard coding a lot of 'user-level' information into the 
supposed library routine, thereby making it not reusable.  Exactly the
opposite of what I thought Ada would be better than C for.

I'm really not saying all of this to try to incite responses that 
wouldn't otherwise have been written, but I'm giving my experiences so
far.  If anyone has any ideas about the solution to this problem that 
will work in Ada83, I'm all ears!

Thanks again for the prior help.

-Craig Allen
Ada novice




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-11-06  0:00   ` Dale Stanbrough
@ 1998-11-06  0:00     ` Matthew Heaney
  1998-11-06  0:00       ` dewarr
  0 siblings, 1 reply; 24+ messages in thread
From: Matthew Heaney @ 1998-11-06  0:00 UTC (permalink / raw)


dale@cs.rmit.edu.au (Dale Stanbrough) writes:

>    type My_String is array (1..100_000) of Character;
>             -- any length will do, just ensure it's long enough for
>             -- any problem you have to deal with.
> 
>    type Ptr is access My_String;

And don't forget to also write...

    for Ptr'Storage_Size use 0;
 




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-11-05  0:00 ` Craig Allen
  1998-11-06  0:00   ` Dale Stanbrough
@ 1998-11-06  0:00   ` Tom Moran
  1 sibling, 0 replies; 24+ messages in thread
From: Tom Moran @ 1998-11-06  0:00 UTC (permalink / raw)


>for this, I also tried 
>for var use at othervar'Address

>but my compiler seems to really expect a static address for the 
>location.
Did you try
The_Address : constant System.Address := othervar'address;
var : some_type;
for var use at The_Address;






^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-11-06  0:00     ` Matthew Heaney
@ 1998-11-06  0:00       ` dewarr
  0 siblings, 0 replies; 24+ messages in thread
From: dewarr @ 1998-11-06  0:00 UTC (permalink / raw)


In article <m390hq3tdg.fsf@mheaney.ni.net>,
  Matthew Heaney <matthew_heaney@acm.org> wrote:
> dale@cs.rmit.edu.au (Dale Stanbrough) writes:
>
> >    type My_String is array (1..100_000) of Character;
> >             -- any length will do, just ensure it's
long enough for
> >             -- any problem you have to deal with.
> >
> >    type Ptr is access My_String;
>
>     for Ptr'Storage_Size use 0;


Note that the advice to use the representation clause is
only relevant if the type is declared locally,

By the way, we have found it useful to be a little
systematic with these bogus big array types, we call them
Big_ and define them, e.g.

  type Big_Int_Array is array (Natural) of Integer;

Of course you never want to allocate one of these :-)

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: simple question - how to emulate void * ?
  1998-11-05  0:00 ` Craig Allen
@ 1998-11-06  0:00   ` Dale Stanbrough
  1998-11-06  0:00     ` Matthew Heaney
  1998-11-06  0:00   ` Tom Moran
  1 sibling, 1 reply; 24+ messages in thread
From: Dale Stanbrough @ 1998-11-06  0:00 UTC (permalink / raw)


Craig Allen wrote:

" I've tried the suggestions given here, and failed miserably.  The 
  culprit in all cases was the fact that I'm using an Ada83 compiler"


Ah! This is a problem.

I would then suggest that if you are trying to emulate void *, then 
continue to use System.Address. 

You should also create a mapping from System.Address to the appropriate
pointer type by instantiating the Unchecked_Conversion function (which
may not do it exactly - there is no 100% guarentee that a pointer is
an address).

It is likely that you will have more success if you use a pointer to
a constrained type, as pointers to unconstrained types may well point
at the descriptor, rather than the actual data.

E.g.

   type My_String is array (1..100_000) of Character;
            -- any length will do, just ensure it's long enough for
            -- any problem you have to deal with.

   type Ptr is access My_String;

   function To_Ptr is new Unchecked_Conversion (
                           Source => System.Address,
                           Target => Ptr);


then...

      function Read_Bytes (...) return System.Address is
      begin
         blah blah blah;
         return Data'Address;
      end;

      X : Address := Read_Bytes (...);
      Y : Ptr := To_Ptr (Y);
      i : Positive := 1;
      Sentinel : constant Character := Ascii.nul;

   begin
      loop
         exit when Y (i) = Sentinel or i > My_String'Last;
         -- process item.
         i := i + 1;
      end loop;
   end;



Of course you will have to customise Unchecked_Conversion to deal
with any other pointer type.

Using this will mean you get around any problems of the compiler
expecting a static value for the address clause.

Beware though - you are deliberately subverting the type system. Are
you sure that this is necessary, or is there some aspect of the problem
which would be more elegantly described _within_ the type system offered
by Ada?


Dale




^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~1998-11-06  0:00 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-10-23  0:00 simple question - how to emulate void * ? Craig Allen
1998-10-23  0:00 ` Tom Moran
1998-10-23  0:00 ` Dale Stanbrough
1998-10-22  0:00   ` Hans Marqvardsen
1998-10-23  0:00     ` John McCabe
1998-10-23  0:00       ` Ed Falis
1998-10-23  0:00         ` dennison
1998-10-24  0:00           ` Joe Wisniewski
1998-10-25  0:00           ` dewar
1998-10-24  0:00         ` Dale Stanbrough
1998-10-24  0:00           ` Robert A Duff
1998-10-24  0:00           ` Tucker Taft
1998-10-23  0:00       ` dennison
1998-10-22  0:00   ` Hans Marqvardsen
1998-10-23  0:00   ` David C. Hoos, Sr.
1998-10-23  0:00   ` David C. Hoos, Sr.
1998-10-23  0:00 ` Jeff Carter
1998-10-24  0:00   ` Dale Stanbrough
1998-10-25  0:00     ` dewar
1998-11-05  0:00 ` Craig Allen
1998-11-06  0:00   ` Dale Stanbrough
1998-11-06  0:00     ` Matthew Heaney
1998-11-06  0:00       ` dewarr
1998-11-06  0:00   ` Tom Moran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox