From: crigler@cs.ucf.edu (James Crigler)
Subject: Re: Can this data be represented in Ada?
Organization: University of Central Florida
Date: Sun, 3 Jan 1993 05:06:00 GMT

psm@nosc.mil (Scot Mcintosh) writes:

>I'm implementing a data communications protocol that has some data
>structural features that don't look possible to implement in Ada.
>Perhaps someone more experienced can suggest a way to accomplish
>what I'm trying to do (changing the protocol is not an option).

>A Transmission Unit looks like:

[Picture deleted]


>Each Packet looks like:

[Picture deleted]

>For a given transmission, the Packet Length is fixed, but can be
>different in the next transmission. The Data Length within each
>Packet can be different for each Packet. I've tried to figure out how
>to define Ada types for the Transmission Unit and Packet that
>allow for the variability of the field sizes and haven't succeeded.
>Any ideas? Thanks in advance.

I've done this kind of thing before, and it's not easy to map this kind
of structure at compile time:  Ada just won't let you do it.  However,
it may be possible to create your structure at run time by use of blocks
contained in procedures.  Below is a little idea.  I've filled in some
stuff by assumption.

procedure CREATE_TRANSMISSION (PACKET_SIZE : in POSITIVE,
			       [other parms as required]) is

  subtype PACKET_LENGTH is POSITIVE range 1 .. 255; -- or whatever
  subtype DATUM         is NATURAL  range 0 .. 255; -- or whatever
  type PACKET_DATA is array (1 .. PACKET_SIZE - 1) of DATUM;
  type PACKET is record
    DATA_SIZE : POSITIVE;
    DATA      : PACKET_DATA;
  end record;

  TRANSIMISSION_UNIT_SIZE : constant := 1024;

  PACKET_COUNT : constant := TRANSMISSION_UNIT_SIZE / PACKET_SIZE;
  -- But if it can be an even multiple, subtract 1.

  type TRANSMISSION_UNIT is record
    PACKET_SIZE : PACKET_LENGTH;
    PACKET      : array (1 .. PACKET_COUNT) of PACKET;
  end record;

  -- Put necessary procedures to fill in data here, followed by
  -- main body of procedure.


At the receiving end, use a system like this:

with SYSTEM;

package body FRED is

subtype PACKET_LENGTH is POSITIVE range 1 .. 255; -- or whatever
subtype DATUM         is NATURAL  range 0 .. 255; -- or whatever
TRANSIMISSION_UNIT_SIZE : constant := 1024;

type RECEPTION_UNIT is record
  PACKET_SIZE : PACKET_LENGTH;
  DATA        : ARRAY (1 .. TRANMISSION_UNIT_SIZE - 1) of DATUM;
end record;

procedure DECODE_DATA (DATA : in RECEPTION_UNIT) is

  type PACKET_DATA is array (1 .. DATA.PACKET_SIZE - 1) of DATUM;
  type PACKET_REC is record
    DATA_SIZE : PACKET_LENGTH;
    DATA      : PACKET_DATA;
  end record;

  PACKET_COUNT : constant := TRANSMISSION_UNIT_SIZE / DATA.PACKET_SIZE;
  -- But if it can be an even multiple, subtract 1.

  type PACKET_ARRAY is array (1 .. PACKET_COUNT) of PACKET_REC;
  PACKET : PACKET_ARRAY; for PACKET use at DATA.DATA'ADDRESS;
  [other declarations and procedure body]



I haven't used anything like this in a long time but I think it should
work.  The trick here is that the in mode parameter PACKET_SIZE is
a constant at run time from the procedure's point of view.  There are
two problems:

    1.  A hit in run time if there is a lot of range checking to do.
        Remember that the language is required to do a lot of "safety"
	checking behind your back, so you may have to program to
	defend yourself against the language.

    2.  You don't get a global "type" that you can put in a package
	spec for the world to see.

Hope this sheds a little lux et veritas.

Jim Crigler
------------------------------------------------------
!PC
Newsgroups: comp.lang.ada