/* Describes a C language type for C structures.
  See CTYPES.ACT for some sample C Type definitions. */!!

inherit(Object, #CType,
#(name      /* symbolic name */
length    /* size of type in bytes */
atBlock   /* output convertor */
putBlock  /* input convertor */), 2, nil)!!

setClassVars(CType,
#($CTypes,    /* dictionary of standard C types */
$UserTypes  /* dictionary of user defined types which are composed of C types or other user defined types */))!!

now(class(CType))!!

/* Add a new C type. */
Def addNewCType(self, name, size, fetchBlock, putBlock)
{ ^add($CTypes, name, init(new(self), name, size,
     fetchBlock, putBlock));
}!!

/* Return a type object by looking up its
  name in global dictionaries. */
Def findType(self, tName)
{ ^errorIfNil($CTypes[tName] cor $UserTypes[tName], #badTypeError);
}!!

/* Return a type object by looking up its name in
  global dictionaries.  Same as findType except
  does no error checking. */
Def getType(self, tName)
{ ^$CTypes[tName] cor $UserTypes[tName];
}!!

now(CType)!!

/* Execute a fetch operation for a field of this
  C type. */
Def fetch(self, struct, offs)
{ ^eval(atBlock, struct, offs);
}!!

/* Initialize a CType object with the given values. */
Def init(self, nam, len, atBlk, putBlk)
{ name := nam;
  length := len;
  atBlock := atBlk;
  putBlock := putBlk;
}!!

/* Return the length of the C data denoted by this
  type. */
Def length(self)
{ ^length;
}!!

/* Print receiver to the specified stream. */
Def printOn(self, aStream)
{ if name
  then printOn(name, aStream);
  else printOn("undefined", aStream);
  endif;
}!!

/* Execute a store operation for a field of this
  C type. */
Def store(self, struct, val, offs)
{ ^eval(putBlock, struct, val, offs);
}!!

/* Return the type symbol for this CType. */
Def type(self)
{ ^name;
}!!

/* CType class initialization. */
$CTypes := new(IdentityDictionary, 16);
$UserTypes := new(IdentityDictionary, 2);!!
