仅在ISO标准Ada中,Record Representation Clause +任何其他语言功能如何可以移植到little-endian和big-endian处理器?

问题描述 投票:2回答:1

在最近的GNAT版本中没有使用非标准的Scalar_Storage_Order clause,可以说,如何通过记录表示条款和任何其他语言特性的任意组合来便携地表示IPv4标头,以便“相同”代码可以工作在IETF调用网络字节顺序(这是IETF对big-endian的奇特名称)中,可以通过线路(例如,通过以太网帧的有效负载)发送小端和大端处理器。在C语言中,“相同”代码可以利用预处理器宏在little-endian处理器上执行字节交换,但在big-endian处理器上是无操作,但标准Ada没有预处理器。在C ++中,“相同”代码可以利用元模板编程(MTP)在小端处理器上执行字节交换,但在大端处理器上是无操作,但标准的Ada缺少MTP。

(顺便说一句,当大端处理器与小端外设IC的存储器映射寄存器接口时,设备驱动程序会出现同样的问题,反之亦然:小端处理器与大端IC的存储器映射寄存器接口。)

    BytesPerWord : constant := 4;
    BitsPerByte : constant := 8;
    PowerOf2Highest : constant := BytesPerWord*BitsPerByte - 1; -- part #1 of byte-swap
    type Header_IPv4 is record
          Version   : integer range 0 ..    F#16;
          IHL       : integer range 0 ..    F#16;
          TOS       : integer range 0 ..   FF#16;
          Length    : integer range 0 ..   FF#16;
          Ident     : integer range 0 .. FFFF#16;
          Flags     : integer range 0 ..    7#16;
          Frag_Offs : integer range 0 .. 1FFF#16;
    end record;
    type Header_IPv4_Homogenous is new Header_IPv4;
    for Header_IPv4_Homogenous use record  -- Good-to-go for big-endian processors
          Version   at 0*BytesPerWord range  0 ..  3;
          IHL       at 0*BytesPerWord range  4 ..  7;
          TOS       at 0*BytesPerWord range  8 .. 15;
          Length    at 0*BytesPerWord range 16 .. 31;
          Ident     at 1*BytesPerWord range  0 .. 15;
          Flags     at 1*BytesPerWord range 16 .. 18;
          Frag_Offs at 1*BytesPerWord range 19 .. 31;
    end record;
    for Header_IPv4_Homogenous'Alignment use 4;
    for Header_IPv4_Homogenous'Bit_Order use High_Order_First;
    type Header_IPv4_Heterogenous is new Header_IPv4;
    for Header_IPv4_Heterogenous use record  -- Good-to-go??? for little-endian processors?
          Version   at 0*BytesPerWord range PowerOf2Highest-  3 .. PowerOf2Highest-  0; -- p
          IHL       at 0*BytesPerWord range PowerOf2Highest-  7 .. PowerOf2Highest-  4; -- a
          TOS       at 0*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  8; -- r
          Length    at 0*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 16; -- t
          Ident     at 1*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  0; --
          Flags     at 1*BytesPerWord range PowerOf2Highest- 18 .. PowerOf2Highest- 16; -- #
          Frag_Offs at 1*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 19; -- 2
    end record;
    for Header_IPv4_Heterogenous'Alignment use 4;
    for Header_IPv4_Heterogenous'Bit_Order use Low_Order_First; -- part #3 of byte-swap

注意如何将字节交换的第2部分中的“PowerOf2Highest减去”和“反转”来自(从,到)顺序到[视觉上,非算术真实](从,到)顺序的大端字节ID粗略等同于VHDL的衰退,这是VHDL如何解决这种异构端点问题的关键部分。 (VHDL是Ada83的堂兄语言。)

但是现在,如何混淆集合中的哪个成员{Header_IPv4_Homogenous,Header_IPv4_Heterogenous}已被选为app-domain-code中的类型名称Header_IPv4_Portable?使用儿童套餐?

‡Scalar_Storage_Order has been proposed作为Ada下一版ISO标准的潜在特征,但到目前为止还没有官方赞助商在ISO标准化委员会中支持该提案,因此标准化提案可能会在葡萄藤上死亡。另外,我将使用非GNAT Ada编译器,因此我无法使用GNAT特定功能。

standards ada iso gnat ada2012
1个回答
1
投票

上面解决方案的部分是由Norman Cohen在大约20年前在ada-auth.org/ai-files/grab_bag/bitorder.pdf中预先设定的,但是在这里和他的文档中缺少的是交换正确的方法。记录表示条款,例如,通过各种Ada编译器中的不同子包。如何在所有Ada编译器中执行子包装条件链接是我现在正在寻找的。

传统的方法是通过多个文件和项目管理器提供正确的编译完成。

也许我们可以使用另一种方法;我认为以下应该可以工作,我编译它但没有测试它:

Package IPv4 is
  Type Header_IPv4 is private;
  Function Version      ( Object : Header_IPv4 ) return Integer;
  Function IHL          ( Object : Header_IPv4 ) return Integer;
  Function TOS          ( Object : Header_IPv4 ) return Integer;
  Function Length       ( Object : Header_IPv4 ) return Integer;
  Function Ident        ( Object : Header_IPv4 ) return Integer;
  Function Flags        ( Object : Header_IPv4 ) return Integer;
  Function Frag_Offs    ( Object : Header_IPv4 ) return Integer;
  -- If you need to write fields, use:
  --   Procedure Field  ( Object : in out Header_IPv4; Value : Integer );

Private
  Header_Size : Constant := 7 * (4*8); -- 7 Integers of 4-bytes.
  type Base_IPv4 is record
     Version   : integer range 0 ..    16#F#;
     IHL       : integer range 0 ..    16#F#;
     TOS       : integer range 0 ..   16#FF#;
     Length    : integer range 0 ..   16#FF#;
     Ident     : integer range 0 .. 16#FFFF#;
     Flags     : integer range 0 ..    16#7#;
     Frag_Offs : integer range 0 .. 16#1FFF#;
  end record
  with Size => Header_Size, Object_Size => Header_Size;

  type Header_IPv4 is null record
  with Size => Header_Size, Object_Size => Header_Size;
End IPv4;


Package Body IPv4 is
  Package Internal is
     Use System;

     BytesPerWord    : constant := 4;
     BitsPerByte     : constant := 8;
     PowerOf2Highest : constant := BytesPerWord*BitsPerByte - 1; -- part #1 of byte-swap

     type Header_IPv4_Homogenous is new Base_IPv4;
     for Header_IPv4_Homogenous use record  -- Good-to-go for big-endian processors
        Version   at 0*BytesPerWord range  0 ..  3;
        IHL       at 0*BytesPerWord range  4 ..  7;
        TOS       at 0*BytesPerWord range  8 .. 15;
        Length    at 0*BytesPerWord range 16 .. 31;
        Ident     at 1*BytesPerWord range  0 .. 15;
        Flags     at 1*BytesPerWord range 16 .. 18;
        Frag_Offs at 1*BytesPerWord range 19 .. 31;
     end record;
     for Header_IPv4_Homogenous'Alignment use 4;
     for Header_IPv4_Homogenous'Bit_Order use High_Order_First;
     type Header_IPv4_Heterogenous is new Base_IPv4;
     for Header_IPv4_Heterogenous use record  -- Good-to-go??? for little-endian processors?
        Version   at 0*BytesPerWord range PowerOf2Highest-  3 .. PowerOf2Highest-  0; -- p
        IHL       at 0*BytesPerWord range PowerOf2Highest-  7 .. PowerOf2Highest-  4; -- a
        TOS       at 0*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  8; -- r
        Length    at 0*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 16; -- t
        Ident     at 1*BytesPerWord range PowerOf2Highest- 15 .. PowerOf2Highest-  0; --
        Flags     at 1*BytesPerWord range PowerOf2Highest- 18 .. PowerOf2Highest- 16; -- #
        Frag_Offs at 1*BytesPerWord range PowerOf2Highest- 31 .. PowerOf2Highest- 19; -- 2
     end record;
     for Header_IPv4_Heterogenous'Alignment use 4;
     for Header_IPv4_Heterogenous'Bit_Order use Low_Order_First; -- part #3 of byte-swap

     Function Convert_Heterogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4,
        Target => Header_IPv4_Heterogenous
       );
     Function Convert_Homogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4,
        Target => Header_IPv4_Homogenous
       );
     Function Convert_Heterogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4_Heterogenous,
        Target => Header_IPv4
       );
     Function Convert_Homogenous is new Ada.Unchecked_Conversion(
        Source => Header_IPv4_Homogenous,
        Target => Header_IPv4
       );

  End Internal;

  Function Convert( Object : Header_IPv4 ) return Base_IPv4 is
     use Internal, System;
  Begin
     if Default_Bit_Order = High_Order_First then
        Return Base_IPv4( Convert_Homogenous(Object) );
     else
        Return Base_IPv4( Convert_Heterogenous(Object) );
     end if;
  End Convert;


  Function Version      ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Version);
  Function IHL      ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).IHL);
  Function TOS      ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).TOS);
  Function Length       ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Length);
  Function Ident        ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Ident);
  Function Flags        ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Flags);
  Function Frag_Offs    ( Object : Header_IPv4 ) return Integer is
     (Convert(Object).Frag_Offs);

End IPv4;

通过使用read / write属性可以获得另一种替代方法,尽管这种形式不允许对IPv4类型变量进行内存映射并正确读取它,它应该足以进行基于流的处理,并且比这里的更简单。

© www.soinside.com 2019 - 2024. All rights reserved.