#ifndef __IMPTYPES_H__
#define __IMPTYPES_H__ 1

#include <stdint.h>
#include <string.h>

// NOTE: All of the macros below are unsafe:
//       The current implementation of Imp strings does *not* guarantee a terminating
//       '\0' at the end of the Imp string.

#define _imp_c2istr(str) ({_imp_string tmp; strcpy(tmp.cstr.s, str); tmp.length=strlen(tmp.cstr.s);/*_imp_zeropad(&tmp);*/tmp;})

#define _imp_i2cstr(str) ({(*str).cstr.s[(*str).length] = '\0'; (*str).cstr.s;})

// experimental code to see if we can be sure to avoid use of strlen at runtime:
#define _imp_str_literal(lit) (_imp_string){.cstr = {(sizeof(lit))-1, lit} }

#define _imp_assign_str_literal(s,lit) _imp_strcpy(s, _imp_str_literal(lit))

typedef uintptr_t _imp_address; // This is to handle systems with 64-bit addresses


// NAME   - Generic %name type is implemented by a struct.  i2c will construct the
//          struct on the fly when anything other than another generic %name variable is
//          passed as a %name parameter.

typedef struct {
  void *address;
  int sizeinfo;
  int typeinfo;
} _imp_Name;


// STRINGS

#define define_imp_c_string(N) typedef struct cstring_##N { unsigned char ignored; char s[N]; } cstring_##N
#define define_imp_string(N) typedef struct { union { unsigned char length; unsigned char charno[256]; cstring_##N cstr; }; } _imp_string##N
#define define_string(N) define_imp_c_string(N); define_imp_string(N)

define_string(255); define_string(254); define_string(253); define_string(252); 
define_string(251); define_string(250); define_string(249); define_string(248); 
define_string(247); define_string(246); define_string(245); define_string(244); 
define_string(243); define_string(242); define_string(241); define_string(240); 
define_string(239); define_string(238); define_string(237); define_string(236); 
define_string(235); define_string(234); define_string(233); define_string(232); 
define_string(231); define_string(230); define_string(229); define_string(228); 
define_string(227); define_string(226); define_string(225); define_string(224); 
define_string(223); define_string(222); define_string(221); define_string(220); 
define_string(219); define_string(218); define_string(217); define_string(216); 
define_string(215); define_string(214); define_string(213); define_string(212); 
define_string(211); define_string(210); define_string(209); define_string(208); 
define_string(207); define_string(206); define_string(205); define_string(204); 
define_string(203); define_string(202); define_string(201); define_string(200); 
define_string(199); define_string(198); define_string(197); define_string(196); 
define_string(195); define_string(194); define_string(193); define_string(192); 
define_string(191); define_string(190); define_string(189); define_string(188); 
define_string(187); define_string(186); define_string(185); define_string(184); 
define_string(183); define_string(182); define_string(181); define_string(180); 
define_string(179); define_string(178); define_string(177); define_string(176); 
define_string(175); define_string(174); define_string(173); define_string(172); 
define_string(171); define_string(170); define_string(169); define_string(168); 
define_string(167); define_string(166); define_string(165); define_string(164); 
define_string(163); define_string(162); define_string(161); define_string(160); 
define_string(159); define_string(158); define_string(157); define_string(156); 
define_string(155); define_string(154); define_string(153); define_string(152); 
define_string(151); define_string(150); define_string(149); define_string(148); 
define_string(147); define_string(146); define_string(145); define_string(144); 
define_string(143); define_string(142); define_string(141); define_string(140); 
define_string(139); define_string(138); define_string(137); define_string(136); 
define_string(135); define_string(134); define_string(133); define_string(132); 
define_string(131); define_string(130); define_string(129); define_string(128); 
define_string(127); define_string(126); define_string(125); define_string(124); 
define_string(123); define_string(122); define_string(121); define_string(120); 
define_string(119); define_string(118); define_string(117); define_string(116); 
define_string(115); define_string(114); define_string(113); define_string(112); 
define_string(111); define_string(110); define_string(109); define_string(108); 
define_string(107); define_string(106); define_string(105); define_string(104); 
define_string(103); define_string(102); define_string(101); define_string(100); 
define_string(99); define_string(98); define_string(97); define_string(96); 
define_string(95); define_string(94); define_string(93); define_string(92); 
define_string(91); define_string(90); define_string(89); define_string(88); 
define_string(87); define_string(86); define_string(85); define_string(84); 
define_string(83); define_string(82); define_string(81); define_string(80); 
define_string(79); define_string(78); define_string(77); define_string(76); 
define_string(75); define_string(74); define_string(73); define_string(72); 
define_string(71); define_string(70); define_string(69); define_string(68); 
define_string(67); define_string(66); define_string(65); define_string(64); 
define_string(63); define_string(62); define_string(61); define_string(60); 
define_string(59); define_string(58); define_string(57); define_string(56); 
define_string(55); define_string(54); define_string(53); define_string(52); 
define_string(51); define_string(50); define_string(49); define_string(48); 
define_string(47); define_string(46); define_string(45); define_string(44); 
define_string(43); define_string(42); define_string(41); define_string(40); 
define_string(39); define_string(38); define_string(37); define_string(36); 
define_string(35); define_string(34); define_string(33); define_string(32); 
define_string(31); define_string(30); define_string(29); define_string(28); 
define_string(27); define_string(26); define_string(25); define_string(24); 
define_string(23); define_string(22); define_string(21); define_string(20); 
define_string(19); define_string(18); define_string(17); define_string(16); 
define_string(15); define_string(14); define_string(13); define_string(12); 
define_string(11); define_string(10); define_string(9); define_string(8); 
define_string(7); define_string(6); define_string(5); define_string(4); 
define_string(3); define_string(2); define_string(1); define_string(0);
                                                   /* ^ Only for the empty string! And consistency. */
typedef _imp_string255 _imp_string; // default %string(*) is %string(255) ...

#undef define_imp_c_string
#undef define_imp_string
#undef define_string

#endif // defined __IMPTYPES_H__
