TERRA Datentechnik					27-Mar-92
=================================================================

Subject: M2 V4.00 / Different treatment of odd-sized records
------------------------------------------------------------

MODULE TSIZET;
(* Demonstrates imcompatiblities between Mscope m2 v4.00 and m2c 3.4 
   regarding the allocation of arrays of odd-sized records:
   
   v3.4 ensured that arrays elements > 1 where always padded to even size.
     pro: it made no problems using this elements for "x: ARRAY OF WORD" -VAR- 
          parameters. x[HIGH(x)] addressedthe last byte of the
          structure and the padding byte.
          According to the language definition every kind of variable can 
          be used for an ARRAY OF WORD parameter.
          
     contra: Mapping externally defined Structures containing 
          BYTE-packed ARRAYs of ODD-sized RECORDs
          to a normal M2-RECORD-TYPE was not possible with that scheme. 
          
          On ALLOCATion of memory for dynamic ARRAYs one must compute the 
          total ARRAY-SIZE accordingly - usually:
          dynArr = POINTER TO ARRAY [0..9999(*Dummy*)] OF ElemRec;
          RealSize := (NoOfElemsNeeded)*(TSIZE(ElemRec)+TSIZE(ElemRec) MOD 2).
          
           
   v4 beta allows odd sized Array Elements and Records.
      This doesn't depend on alignement which seems not to affect array
      addressing.
     pro: the above size computation  is not neccessary.
     
     contra: modifying x[HIGH(x)] in a PROCEDURE with
       "VAR x: ARRAY OF WORD"-parameter could inadvertently change the byte 
       following x in memory!

@WR 16.1.92       
*)
FROM SYSTEM IMPORT TSIZE,ADDRESS,ADR,BYTE,WORD,SIZE;
FROM Storage IMPORT ALLOCATE,DEALLOCATE;

TYPE OddSizedRec= RECORD
      a: LONGINT;
      b: CHAR;
      c: CARDINAL;
      d: BOOLEAN;
      e: LONGREAL;
      x: BYTE;
     END;
     
VAR tosrSize,
    osrSize,
    osrESize,
    osrTSize: CARDINAL;
    
    osrTabPt: POINTER TO ARRAY [0..2] OF OddSizedRec;
    
PROCEDURE FillWords (VAR v: ARRAY OF WORD; pattern: WORD);
VAR i: CARDINAL;
BEGIN
  FOR i := 0 TO HIGH(v) DO 
    v[i] := pattern;
  END;
END FillWords;

PROCEDURE FillBytes (VAR v: ARRAY OF BYTE; pattern: BYTE);
VAR i: CARDINAL;
BEGIN
  FOR i := 0 TO HIGH(v) DO 
    v[i] := pattern;
  END;
END FillBytes;

PROCEDURE ZeroItem (VAR v: ARRAY OF BYTE);
BEGIN
  FillBytes (v,BYTE(0));
  FillWords (v,WORD(0)); (* should be possible too; but code
                            generated by m2v4 would ignore the
                            last byte of an oddsized parameter
                         *)
END ZeroItem;

PROCEDURE TestItem (VAR v: ARRAY OF BYTE; allBytesAre: BYTE): BOOLEAN;
VAR i: CARDINAL;
BEGIN
  FOR i := 0 TO HIGH(v) DO 
    IF v[i] # allBytesAre THEN RETURN FALSE END;
  END;
  RETURN TRUE;
END TestItem;

    
BEGIN (*  *)
    NEW (osrTabPt);
    ALLOCATE (osrTabPt,(HIGH(osrTabPt^)+1)*TSIZE(OddSizedRec)); (*same code?*)
    ZeroItem (osrTabPt^);
    FillBytes (osrTabPt^[1],BYTE(055h));
    IF NOT TestItem (osrTabPt^[0],BYTE(0)) THEN HALT(1) END;
    IF NOT TestItem (osrTabPt^[1],BYTE(055H)) THEN HALT(1) END;
    IF NOT TestItem (osrTabPt^[2],BYTE(0)) THEN HALT(1) END;
    FillWords (osrTabPt^[1],0ffffh); (* using [2] would have corrupted the heap!*)
    IF NOT TestItem (osrTabPt^[0],BYTE(0)) THEN HALT(1) END;
    IF NOT TestItem (osrTabPt^[1],BYTE(0FFH)) THEN HALT(1) END;
    IF NOT TestItem (osrTabPt^[2],BYTE(0)) THEN HALT(1) END;
    osrSize := SIZE (osrTabPt^[0]);
    osrTSize := TSIZE(OddSizedRec); (* should be the same *)
    tosrSize := SIZE (osrTabPt^); (* 3 * osrSize or 3 * osrSize+1 ??*)
    osrESize := ADR(osrTabPt^[2])-ADR( osrTabPt^[1]);
    (* element size used with index expression *)
END TSIZET.
