// static inline void READ(_imp_NAME dest);

// i2c can, when allowed, change READ into a call on readitem,
// readstring, or the newly-invented readint and readfloat/readdouble etc!

// Note that this mechanism will not work if READ is passed a %name parameter,
// or if READ itself is passed to another procedure as a procedure parameter...

// Implementations of READ for specific types:
extern void _imp_readbyte(unsigned char *dest);
extern void _imp_readshort(short int *dest);
extern void _imp_readint(int *dest);
extern void _imp_readlong(long long int *dest);
extern void _imp_readfloat(float *dest);
extern void _imp_readdouble(double *dest);
extern void _imp_readitem(_imp_string *dest);

// Generic implementation of READ:
#define _imp_READ(var) do {                                             \
       if (__builtin_types_compatible_p(typeof(var), unsigned char *)) _imp_readbyte  ((unsigned char *) var); \
  else if (__builtin_types_compatible_p(typeof(var), short int *))     _imp_readshort ((short int *)     var); \
  else if (__builtin_types_compatible_p(typeof(var), int *))           _imp_readint   ((int *)           var); \
  else if (__builtin_types_compatible_p(typeof(var), long long int *)) _imp_readlong  ((long long int *) var); \
  else if (__builtin_types_compatible_p(typeof(var), float *))         _imp_readfloat ((float *)         var); \
  else if (__builtin_types_compatible_p(typeof(var), double *))        _imp_readdouble((double *)        var); \
  else if (__builtin_types_compatible_p(typeof(var), _imp_string *))   _imp_readitem  ((_imp_string *)   var); \
  else { fprintf(stderr, "READ failes - cannot determine type of parameter\n"); exit(1); } \
} while(0)

// Version of READ to be called if compiler cannot determine type of parameter:
// (This may change to use an _imp_NAME parameter.)
static inline void _imp_READ_name(void *PTR, int PTR_typeof) {
  fprintf(stderr, "* READ(%%name) not implemented\n"); /*TO DO*/
  exit(1);
}
