Oberon || Library || Module Index || Search Engine || Definition || Module


Ulm's Oberon Library:
SysConversions


NAME

SysConversions - convert Oberon records to/from C structures

SYNOPSIS

TYPE Address = SysTypes.Address;
TYPE Size = Address;
TYPE Event = POINTER TO EventRec;
TYPE EventRec =
   RECORD
      (Events.EventRec)
      format: Events.Message;
   END;
TYPE Format = POINTER TO FormatRec;
TYPE FormatRec =
   RECORD
      (Objects.ObjectRec)
   END;
VAR badformat: Events.EventType;


PROCEDURE ByAddrToC(from, to: Address; format: ARRAY OF CHAR); PROCEDURE ByAddrFromC(from, to: Address; format: ARRAY OF CHAR); PROCEDURE ToC(VAR from, to: ARRAY OF BYTE; format: ARRAY OF CHAR); PROCEDURE FromC(VAR from, to: ARRAY OF BYTE; format: ARRAY OF CHAR); PROCEDURE CSize(format: ARRAY OF CHAR) : Size; PROCEDURE OberonSize(format: ARRAY OF CHAR) : Size; PROCEDURE Compile(VAR fmt: Format; format: ARRAY OF CHAR); PROCEDURE ByFmtAndAddrToC(from, to: Address; format: Format); PROCEDURE ByFmtAndAddrFromC(from, to: Address; format: Format); PROCEDURE ByFmtToC(VAR from, to: ARRAY OF BYTE; format: Format); PROCEDURE ByFmtFromC(VAR from, to: ARRAY OF BYTE; format: Format);

DESCRIPTION

SysConversions supports type conversions of Oberon records to and from C structures. Conversions are necessary for some system calls (e.g. ioctl(2) and stat(2)) and file formats (e.g. a.out(5)).

The relation of an Oberon record to a C structure is described by a format string. It is important to note that the same format string is used for conversions in both directions (i.e. from and to the C structure).

Format strings consists of a slash-separated list of component pairs. Each component pair describes a conversion of a Oberon component type from and to a C member type. Component types are given by a single letter, e.g. "is" converts an Oberon INTEGER component to/from short int. Arrays are specified by a length and a colon preceding the component types, e.g. "2:is" for ARRAY 2 OF INTEGER to/from short int [2]. Factors allow shorter format strings, e.g. "3*is" is equivalent to "is/is/is". Note that "2:is" is not equivalent to "2*is" because of different alignment and padding for arrays. Factors and arrays may be combined, e.g. "2:2*is" converts ARRAY 2 OF RECORD a, b: INTEGER END to/from struct { int a, b; } [2]. The factor takes precedence over the array specification, thus "2:2*is" is equivalent to "2*2:is".

Both data types may be of different size. Conversions to smaller data types cause the higher significant bits to be cut off. Conversions to larger data types depend on the data types involved: signed data types are converted with sign extension, unsigned data types (this includes addresses and sets) are filled up with zeroes. Conversions to BOOLEAN are treated special: any nonzero bit pattern is converted to TRUE, zero is converted to FALSE.

Skip specifications allow to suppress conversions and assignments. E.g. "i-" suppresses the Oberon to C conversion because there is no corresponding member of the C structure and causes the integer component to remain unchanged in case of C to Oberon conversions. This allows multiple conversions into one record.

Conversions may be followed by comments with leading "=". Comments are intended to document the member names of the C structure.

Format strings must conform to the syntax following:

Format = Conversion { "/" Conversion } .
Conversion = [ Factors ] ConvChars [ Comment ] .
Factors = Array | Factor | Array Factor | Factor Array .
Array = Integer ":" .
Factor = Integer "*" .
ConvChars = OberonType CType | Skip CType | OberonType Skip .
OberonType = "a" | "b" | "c" | "h" | "s" | "i" | "l" | "S" .
CType = "a" | "c" | "C" | "s" | "S" | "i" | "I" | "u" | "l" | "L" .
Integer = Digit { Digit } .
Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" .
Skip = "-" .
Comment = "=" { AnyChar } .
AnyChar = (* all characters except "/" *) .
Following data types are supported:
___________________________________________
|___OberonType___|__________CType_________|
|a   Address     |  a   char *            |
|b   BYTE        |  c   /* signed */ char |
|B   BOOLEAN     |  C   unsigned char     |
|c   CHAR        |  s   short int         |
|h   SYSTEM.INT16|  S   unsigned short int|
|s   SHORTINT    |  i   int               |
|i   INTEGER     |  I   unsigned int      |
|l   LONGINT     |  u   unsigned int      |
|S   SET         |  l   long int          |
|                |  L   unsigned long int |
|________________|________________________|

Formats may be given as string or as reference to an internal representation. The internal representation is much faster in case of multiple conversions. Compile converts format into fmt which may be given to the ByFmt procedures as reference to the internal representation.

Oberon records and C structures may be given either by address (ByAddr procedures) or by an array of BYTE.

OberonSize and CSize return the size in bytes of the corresponding data types as defined by format. The result of OberonSize should be equal to the size of the corresponding Oberon record and the size of the byte array containing the C structure should be at least as large as the result of CSize. ToC and FromC compare the length of the byte arrays against OberonSize and CSize of the given format and raise badformat in case of insufficient space. For the other conversion procedures it is in the responsibility of the caller to assert that both parameters are at least as large as described by the format.

EXAMPLE

Conversion from
Rec =
   RECORD
      a, b: INTEGER;
      c: CHAR;
      s: SET;
      f: ARRAY 3 OF INTEGER;
   END;
to
struct rec {
   short a, b;
   char c;
   int xx;      /* to be skipped on conversion */
   int s;
   int f[3];
};
and vice versa works as follows:
CONST
   format = "2*is=a,b/cc=c/-i=xx/Si=s/3:ii=f";
   structlen = 26; (* system dependent *)

TYPE
   StructRec = ARRAY structlen OF CHAR;

VAR
   fmt: SysConversions.Format;

PROCEDURE ConvertToC(from: Rec; VAR to: StructRec);
BEGIN
   SysConversions.ByFmtToC(from, to, fmt);
END ConvertToC;

PROCEDURE ConvertToOberon(from: StructRec; VAR to: Rec);
BEGIN
   SysConversions.ByFmtFromC(from, to, fmt);
END ConvertToOberon;

PROCEDURE Init;
BEGIN
   ASSERT(structlen >= SysConversions.CSize(format));
   ASSERT(SYSTEM.SIZE(Rec) = SysConversions.OberonSize(format));
   SysConversions.Compile(fmt, format);
END Init;

DIAGNOSTICS

badformat is raised in case of syntax errors in formats.

SEE ALSO

Events
event handling

BUGS

Multidimensional arrays are not implemented.

Character arrays with different lengths are not supported.


Edited by: borchert, last change: 2004/04/02, revision: 1.6, converted to HTML: 2004/04/02

Oberon || Library || Module Index || Search Engine || Definition || Module