<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;">Hi Jay:<br>Pretty much is good question that you are asking. I believe mostly the guys in SPIN did pretty much what you suggest, using the Multiflow C compiler for dynamic event dispatching optimization:<br>http://oldwww.cs.pitt.edu/~mock/papers/wcsss96.pdf<br><br>and AVOCA x-kernel subsystem using C but with Modula-3 keywords (so there was an abstract specification, e.g INTERFACE) and its implementation in C with Modula-3 idiom, p.77 with a Graph Description Language:<br>http://arizona.openrepository.com/arizona/bitstream/10150/185158/1/azu_td_9103022_sip1_m.pdf<br><br>Hope it helps. Thanks in advance.<br><br><br>--- El <b>jue, 26/1/12, Jay K <i><jay.krell@cornell.edu></i></b> escribió:<br><blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"><br>De: Jay K <jay.krell@cornell.edu><br>Asunto: Re: [M3devel]
 packing problem… how exactly does modula-3 pack data into records?? … "solved"<br>Para: dragisha@m3w.org<br>CC: "m3devel" <m3devel@elegosoft.com><br>Fecha: jueves, 26 de enero, 2012 00:46<br><br><div id="yiv1649151197">

<style><!--
#yiv1649151197 .yiv1649151197hmmessage P
{
margin:0px;padding:0px;}
#yiv1649151197 body.yiv1649151197hmmessage
{
font-size:10pt;font-family:Tahoma;}
--></style><div><div dir="ltr">
Let's say we have something defined by hardware, I'm making this up,<br>and we have a C header already for it:<br><br><br>  typedef struct x86_pte /* fictional page table entry */  <br>  {  <br>    unsigned valid : 1;  <br>    unsigned execute : 1;  <br>    unsigned writable : 1;  <br>    unsigned physical_page : 29;  <br>  } x86_pte;  <br>  <br>  <br>  and I want to interface with this hardware from Modula-3.  <br><br>  What do I do?  <br><br>  ?Find the documenation, let's say it goes like:  <br>  ?<br>     x86_pte_valid 0x80000000    <br>    x86_pte_executable 0x40000000  <br>    x86_pte_writable 0x20000000  <br><br>  ?Translate that into Modula-3.  <br>  Do I write:  <br><br>  x86_pte = BITS 32 FOR
 RECORD  <br>    valid: BITS 1 FOR BOOLEAN;  <br>    executable: BITS 1 FOR BOOLEAN;  <br>    writable: BITS 1 FOR BOOLEAN;  <br>    physical_page: BITS 29 FOR [0...16_1FFFFFFF];  <br>  END;<br><br>or do I write:<br>  x86_pte = BITS 32 FOR RECORD    <br>    physical_page: BITS 29 FOR [0...16_1FFFFFFF];  <br>    writable: BITS 1 FOR BOOLEAN;  <br>    executable: BITS 1 FOR BOOLEAN;  <br>    valid: BITS 1 FOR BOOLEAN;  <br>  END;  <br><br>?or do I write something else (maybe physical_page isn't unpacked properly) <br><br><br> ?or do I write something unambiguous but possibly slow:  <br><br>  x86_pte_opaque = RECORD:  <br>    opaque: BITS 32 FOR ARRAY OF BITS 8 FOR [0..255];<br>  END;<br><br><br>  PROCEDURE
 Valid(pte: x86_pte):  BOOLEAN =  <br>  BEGIN  <br>    RETURN Word.And(pte.opaque[0], 16_80) # 0;  <br>  END Valid;  <br><br>  PROCEDURE Writable(pte: x86_pte):  BOOLEAN =  <br>  BEGIN  <br>    RETURN Word.And(pte.opaque[0], 16_40) # 0;  <br>  END Writable;  <br><br>  PROCEDURE Executable(pte: x86_pte):  BOOLEAN =  <br>  BEGIN  <br>    RETURN Word.And(pte.opaque[0], 16_20) # 0;  <br>  END Executable;  <br><br> PROCEDURE PhysicalPage(pte: x86_pte):  CARDINAL =  <br>  BEGIN  <br>    RETURN Word.Or(Word.Or(Word.Or(Word.LeftShift(Word.And(pte.opaque[0], 16_1F), 24), Word.LeftShift(pte.opaque[1], 16)), Word.LeftShift(pte.opaque[2], 8),     pte.opaque[3]); (* approx *)   <br>  END PhysicalPage;  <br><br>Or
 maybe:<br><br>RECORD UnpackedPTE = RECORD<br>  Valid, Executable, Writable: BOOLEAN;<br>  Page: CARDINAL;<br>END;<br><br>filled in by the above functions and then accessed directly?<br><br><br><br>  But I also want to write some sort of simulator -- i.e. I'm not necessarily running on a little endian system.  <br><br><br>I believe the original authors desired a "straight" translation from C headers -- the first Modula-3 version above.<br>This allows for easier transliteration of /usr/include into m3core/unix.<br><br><br>  However it does not allow for the "simulator scenario" -- where the host's C compiler is<br>  different than the one that interprets the C struct I showed. <br>  Nor does it allow well for what you want to do -- portability across machines.  <br><br><br>C programmers face the same dilemna.<br>Know that their compiler is somehow sane and predictable and use nice/convenient bitfields,<br>or take no
 dependency on the unspecified bitfield behavior and unpack bits/bytes manually.<br><br><br>Where C programmers depend on bitfields, and where Modula-3 transliterates C headers,<br>it is profitable for Modula-3 to try to emulate the platform's C compiler's behavior.<br>I have gone and removed m3core's dependency on this.<br><br><br>Again, I believe that was the original authors' intent.<br><br><br>Clearly there are pluses and minuses to the various approaches.<br><br><br>If you look at the GNU binutils, I think they do stuff like:<br><br>struct packed_foo<br>{<br>  unsigned char foo[2];<br>  unsigned char bar[4];<br>  unsigned char abc[8];<br>|;<br><br>struct unpacked_foo<br>
{<br>
  unsigned short foo;<br>
  unsigned long bar;<br>
  unsigned long long abc;<br>
};<br><br>void unpack_foo(packed_foo* packed, unpacked_foo* unpacked)<br>{<br>  unpack_little_endian(packed->foo, sizeof(packed->foo), &unpacked->foo, sizeof(&unpacked->foo));<br>}<br><br>void unpack_little_endian(unsigned char* packed, size_t packed_size, void* unpacked, size_t unpacked_size)<br>{<br>  unsigned long long value = { 0 };  <br>  size_t i = { 0 };  <br>  assert(unpacked_size >= packed_size);   <br>  for (i = 0; < packed_size)  <br>    value = (value << 8) | packed[i];  <br>  if (unpacked_size == 1)  <br>     *(unsigned char*)unpacked = (unsigned char)value;    <br>  else if (unpacked_size == sizeof(unsigned short))   <br>     *(unsigned short*)unpacked = (unsigned short)value;    <br>  else if (unpacked_size == sizeof(unsigned long))   
 <br>     *(unsigned long*)unpacked = (unsigned long)value;    <br>  else if (unpacked_size == sizeof(unsigned long long))    <br>     *(unsigned long long*)unpacked = (unsigned long  long)value;    <br>  else<br>    assert(false);  <br>}<br><br><br>This has the cost/tedium of copying, but it is very portable, while still letting the<br>compiler do a little of the layout for you.<br><br>
  <br>If you are defining your own protocol, I think the opaque/unpacking strategy is safest,<br>albeit slowest and most tedious.<br><br><br>You could also be wasteful and not use bitfields in your protocol.<br><br><br> - Jay<br><br><br><br><br><br><div><div id="yiv1649151197SkyDrivePlaceholder"></div><hr id="yiv1649151197stopSpelling">From: dragisha@m3w.org<br>Date: Fri, 20 Jan 2012 22:59:34 +0100<br>To: jay.krell@cornell.edu<br>CC: m3devel@elegosoft.com<br>Subject: Re: [M3devel] packing problem… how exactly does modula-3 pack data into records?? … "solved"<br><br>
 
 Ok, it is your standpoint. I don't share it. <div><br></div><div>Right now my problem is solved. If I encounter its variation again, I'l fix it for myself.</div><div><br></div><div>Excuse "C does it too" does not ring too Modulee for me :).</div><div><br></div><div>dd</div><div><br><div><div>On Jan 20, 2012, at 7:11 PM, Jay wrote:</div><br class="yiv1649151197ecxApple-interchange-newline"><blockquote><span class="yiv1649151197ecxApple-style-span" style="border-collapse: separate; font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;">As in C, if you need portability and predictability, just don't use bitfields. Use integer types of size 8, 16, 32, or possibly 64 bits, and do the appropriate shifting and masking, possibly
 endian-dependent.<br><br><br>Actually, to avoid endian and packing/alignment concerns, use only 8 bit integers and optionally pack/unpack into more convenient types.<br><br><br>- Jay (phone)</span></blockquote></div><br></div></div>                                         </div></div>
</div></blockquote></td></tr></table>