text: #include <string.h>
  #include <malloc.h>
  #include <stdint.h>
  #include <unistd.h>
  #include "defs.h"
  
  #include "vt100.h"
  typedef uint32_t u32;
  typedef  uint8_t u8;
  typedef uint16_t u16;
  typedef     char s8;
  typedef    short s16;
  
  #define arraycountof(x) (sizeof(x)/sizeof((x)[0]))
  
  
  static const u16 translate[] = {
    0x0002, 0x0202, 0x0202, 0x0219, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0205, 0x0202, 0x0202,
    0x1a1b, 0x021c, 0x0202, 0x0202, 0x0202, 0x021d, 0x021e, 0x1f20,
    0x0e0f, 0x1112, 0x1314, 0x1516, 0x1718, 0x2110, 0x0202, 0x0202,
    0x2208, 0x0609, 0x0a26, 0x2728, 0x292a, 0x2b0b, 0x2c07, 0x2d2e,
    0x0c2f, 0x3031, 0x3233, 0x3435, 0x3637, 0x3803, 0x0204, 0x2324,
    0x0239, 0x3a3b, 0x3c3d, 0x3e3f, 0x4041, 0x4243, 0x440d, 0x4546,
    0x4748, 0x494a, 0x4b4c, 0x4d4e, 0x4f50, 0x5102, 0x0202, 0x2502,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
    0x0102
  };
  
  static const u16 r[] = {
    0x0000, 0x5202, 0x5302, 0x5302, 0x5303, 0x5402, 0x5402, 0x5402,
    0x5402, 0x5402, 0x5402, 0x5402, 0x5500, 0x5501, 0x5601, 0x5601,
    0x5602, 0x5602, 0x5602, 0x5603, 0x5603, 0x5604, 0x5701, 0x5701,
    0x5801, 0x5802, 0x5901, 0x5901, 0x5901, 0x5901, 0x5901, 0x5a01,
    0x5a01, 0x5a01, 0x5a01, 0x5b01, 0x5b01, 0x5b01, 0x5b01, 0x5c01,
    0x5d01, 0x5d01, 0x5e01, 0x5e01, 0x5f01, 0x5f01, 0x5f01, 0x6001,
    0x6001, 0x6104, 0x6201, 0x6202, 0x6301, 0x6301, 0x6301, 0x6301,
    0x6301, 0x6301, 0x6301, 0x6301, 0x6301, 0x6301, 0x6301, 0x6301,
    0x6301, 0x6301, 0x6301, 0x6301, 0x6401, 0x6401, 0x6401, 0x6401,
    0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401,
    0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401,
    0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6401, 0x6501, 0x6501,
    0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501,
    0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501,
    0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501, 0x6501
  };
  
  static const u16 defact[] = {
    0x000c, 0x0000, 0x0016, 0x2829, 0x2a2b, 0x2c2d, 0x2e2f, 0x3002,
    0x0000, 0x0d17, 0x181f, 0x2021, 0x2227, 0x2800, 0x1a1b, 0x1c1d,
    0x1e03, 0x0001, 0x0605, 0x0708, 0x090a, 0x0b11, 0x1200, 0x1910,
    0x2324, 0x2526, 0x0004, 0x1314, 0x0045, 0x5044, 0x4647, 0x4e53,
    0x6a3d, 0x3435, 0x3637, 0x3839, 0x3a3c, 0x3e40, 0x4143, 0x4849,
    0x4a4b, 0x4c4d, 0x4f51, 0x5254, 0x5556, 0x5758, 0x595a, 0x5b5c,
    0x5d5e, 0x5f60, 0x6162, 0x6364, 0x6566, 0x6768, 0x696b, 0x6c6d,
    0x6e6f, 0x7071, 0x7273, 0x7475, 0x7677, 0x3b00, 0x323f, 0x4215,
    0x3133
  };
  
  static const u16 defgoto[] = {
    0x0005, 0x1011, 0x1213, 0x147b, 0x1530, 0x1d1e, 0x1f20, 0x2122,
    0x7c7d, 0x7e7f
  };
  
  static const u16 pact[] = {
    0xe396, 0xaa60, 0xa3a2, 0xb800, 0x0000, 0x0000, 0x0000, 0x0000,
    0xd3c5, 0x00aa, 0x0000, 0xbb00, 0x0000, 0x00b3, 0x0000, 0x0000,
    0x0000, 0xac00, 0x0000, 0x0000, 0x0000, 0x0000, 0x00d2, 0x0000,
    0x0000, 0x0000, 0x4d00, 0x0000, 0xbb00, 0x0000, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
    0x0000
  };
  
  static const u16 pgoto[] = {
    0x0000, 0x0000, 0x0000, 0x00a4, 0x0082, 0x8c9f, 0x9ea0, 0xd900,
    0x0067, 0x0000
  };
  
  static const u16 tabchk[] = {
    0x4807, 0x4908, 0x4a09, 0x4b0a, 0x4c0b, 0x4d0c, 0x4e0d, 0x4f0e,
    0x280f, 0x2910, 0x5011, 0x1612, 0x1713, 0x1814, 0x1915, 0x1a16,
    0x1b17, 0x1c18, 0x1d19, 0x8f1a, 0x511b, 0x521c, 0x531d, 0x541e,
    0x551f, 0x5620, 0x5721, 0x5822, 0x5923, 0x5a24, 0x5b25, 0x5c26,
    0x5d27, 0x5e28, 0x5f29, 0x602a, 0x612b, 0x622c, 0x632d, 0x642e,
    0x652f, 0x6630, 0x6731, 0x6832, 0x6933, 0x6a34, 0x6b35, 0x6c36,
    0x6d37, 0x6e38, 0x6f39, 0x703a, 0x713b, 0x723c, 0x733d, 0x743e,
    0x753f, 0x7640, 0x7741, 0x7842, 0x7943, 0x7a44, 0x7b45, 0x7c46,
    0x7d47, 0x7e48, 0x7f49, 0x804a, 0x814b, 0x824c, 0x834d, 0x844e,
    0x854f, 0x8650, 0x8751, 0x8852, 0x4807, 0x4908, 0x4a09, 0x4b0a,
    0x4c0b, 0x4d0c, 0x4e0d, 0x4f0e, 0x280f, 0x2910, 0x5011, 0x1612,
    0x1713, 0x1814, 0x1915, 0x1a16, 0x1b17, 0x1c18, 0x1d19, 0x3107,
    0x511b, 0x521c, 0x531d, 0x541e, 0x551f, 0x5620, 0x5721, 0x5822,
    0x5923, 0x5a24, 0x5b25, 0x5c26, 0x5d27, 0x5e28, 0x5f29, 0x602a,
    0x612b, 0x622c, 0x632d, 0x642e, 0x652f, 0x6630, 0x6731, 0x6832,
    0x6933, 0x6a34, 0x6b35, 0x6c36, 0x6d37, 0x6e38, 0x6f39, 0x703a,
    0x713b, 0x723c, 0x733d, 0x743e, 0x753f, 0x7640, 0x7741, 0x7842,
    0x7943, 0x7a44, 0x7b45, 0x7c46, 0x7d47, 0x7e48, 0x7f49, 0x804a,
    0x814b, 0x824c, 0x834d, 0x844e, 0x854f, 0x8650, 0x8751, 0x8852,
    0x2502, 0x2402, 0x2602, 0x3f17, 0x3201, 0x140f, 0x1510, 0x2a03,
    0x1612, 0x1713, 0x1814, 0x1915, 0x1a16, 0x1b17, 0x1c18, 0x1d19,
    0x010e, 0x010f, 0x0110, 0x0111, 0x4408, 0x4117, 0x4017, 0x4217,
    0x3d14, 0x280f, 0x2910, 0x8e39, 0x1612, 0x1713, 0x1814, 0x1915,
    0x1a16, 0x1b17, 0x1c18, 0x1d19, 0x4311, 0x3f39, 0x000e, 0x000f,
    0x0010, 0x0011, 0x280f, 0x2910, 0x472e, 0x1612, 0x1713, 0x1814,
    0x1915, 0x1a16, 0x1b17, 0x390e, 0x3a0f, 0x3b10, 0x3c11, 0x4139,
    0x4039, 0x4239, 0x3307, 0x2702, 0x3409, 0x350a, 0x360b, 0x370c,
    0x380d, 0x450f, 0x4610, 0x907c, 0x0f00, 0x1713, 0x1814, 0x1004,
    0x1105, 0x1206
  };
  
  struct esc_seq_stack {
  	int state;
  	u16 value;
  };
  struct esc_seq_state {
  	u16 cb;
  	int result;
  	int state;
  	char *cstr;
  	size_t cb_cstr;
  	size_t i_stack;
  	size_t nums_count;
  	u16 nums[1];
  };
  void esc_seq_parse_free (void *state_)
  {
  struct esc_seq_state *m_;
  	m_ = (struct esc_seq_state *)state_;
  	if (m_->cstr) {
  		free (m_->cstr);
  		m_->cstr = NULL;
  		m_->cb_cstr = 0;
  	}
  }
  #define stack_bottom(m_) ((struct esc_seq_stack *)((u8 *)(m_) + (m_)->cb) -1)
  #define UNDEF_VALUE 0
  bool esc_seq_parse_init (void *state_, size_t size)
  {
  	if (size < sizeof(struct esc_seq_state) || 0xffff < size)
  		return false;
  	memset (state_, 0, sizeof(struct esc_seq_state));
  struct esc_seq_state *m_;
  	m_ = (struct esc_seq_state *)state_;
  	m_->cb = (u16)size;
  	if ((void *)stack_bottom(m_) < (void *)m_->nums)
  		return false;
  	stack_bottom(m_)->value = UNDEF_VALUE;
  	return true;
  }
  
  #define U16AS8(a,i) (0xff & (a)[(i) / 2] >> ((i) % 2 ? 0 : 8))
  #define HI8(u16) (0xff & (u16) >> 8)
  #define LO8(u16) (0xff & (u16))
  #define translate_(c) U16AS8(translate, (c))
  #define r1_(n) HI8(r[n])
  #define r2_(n) LO8(r[n])
  #define defact_(state) U16AS8(defact, (state))
  #define defgoto_(n) U16AS8(defgoto, (n)) -1
  #define pact_(state) U16AS8(pact, (state)) -7
  #define pgoto_(n) U16AS8(pgoto, (n)) -7
  #define table_(n_or_state) HI8(tabchk[n_or_state]) -15
  #define check_(n_or_state) LO8(tabchk[n_or_state]) -1
  size_t esc_seq_parse (void *state_, const void *buf_, size_t len, IVt100Action *iface, void *param)
  {
  const char *buf;
  	buf = (const char *)buf_;
  struct esc_seq_state *m_;
  	m_ = (struct esc_seq_state *)state_;
  size_t used;
  	if (4 == m_->result) {
  		if ((used = iface->on_bmp (param, buf, len)) < len)
  			m_->result = 1;
  		return used;
  	}
  const char *begin, *end;
  	begin = buf, end = buf +len;
  int c;
  	c = -2;
  struct esc_seq_stack *stack;
  	stack = stack_bottom(m_) - m_->i_stack;
  int state, result;
  	state = m_->state;
  	result = m_->result;
  	while (0 == result) {
  		stack->state = state;
  		if ((void *)(stack -1) < (void *)(m_->nums + m_->nums_count)) {
  			result = 3; // not enough memory (stack overflow)
  			continue;
  		}
  bool do_defact;
  		do_defact = true;
  int n;
  		if (! (-7 == (n = pact_(state)))) {
  			if (-2 == c) {
  				if (!(buf < end) || '\0' == *buf) // null cannot parse now, always treat end of input.
  					break;
  				c = *buf++;
  			}
  			n += translate_(c);
  			if (0 <= n && n < arraycountof(tabchk) && check_(n) == translate_(c)) {
  				if (0 == (n = table_(n)) || -15 == n +1) {
  					result = 2; // syntax error
  					continue;
  				}
  				else if (35 == n) {
  					result = 1; // accept.
  					continue;
  				}
  				else if (0 < n) {
  					c = -2;
  					(--stack)->value = UNDEF_VALUE;
  					state = n;
  					continue;
  				}
  				n = -n;
  				do_defact = false;
  			}
  		}
  		if (do_defact && 0 == (n = defact_(state))) {
  			result = 2; // syntax error
  			continue;
  		}
  int reduce_len;
  		reduce_len = r2_(n);
  u16 value, num;
  		value = (stack + reduce_len -1)->value;
  u32 u;
  int i;
  		switch (n) {
  		case 4:
  			result = 4;
  			iface->on_bmp (param, NULL, 0);
  			used = 0;
  			if (buf < end && (used = iface->on_bmp (param, buf, end - buf)) < end - buf)
  				result = 1;
  			buf += used;
  			continue;
  		case 2: case 3:
  			result = 1;
  			continue;
  		case 6: case 8:
  			num = (0 < m_->nums_count) ? m_->nums[0] : 1;
  			//iface->on_cuX (param, num);
  			break;
  		case 5:
  			num = (0 < m_->nums_count) ? m_->nums[0] : 1;
  			iface->on_cuu (param, num);
  			break;
  		case 7:
  			num = (0 < m_->nums_count) ? m_->nums[0] : 1;
  			iface->on_cuf (param, num);
  			break;
  		case 9:
  			num = (0 < m_->nums_count) ? m_->nums[0] : 0;
  			iface->on_el (param, num);
  			break;
  		case 10:
  			num = (0 < m_->nums_count) ? m_->nums[0] : 1;
  			//iface->on_dch (param, num);
  			break;
  		case 11:
  			//foreach(NN-list) SGR(n)
  			for (i = 0; i < m_->nums_count; ++i) {
  				switch (num = m_->nums[i]) {
  				case 0:
  					iface->on_none_sgr (param);
  					break;
  				case 1:
  					iface->on_bold_sgr (param);
  					break;
  				case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37:
  					iface->on_fgcl_sgr (param, num - 30);
  					break;
  				}
  			}
  			break;
  		case 12:
  			break;
  		case 13:
  			if ((void *)stack < (void *)(m_->nums + m_->nums_count +1)) {
  				result = 3; // not enough memory ([<n>] store overflow)
  				continue;
  			}
  			m_->nums[m_->nums_count++] = stack->value;
  			break;
  		case 14: case 19: case 17:
  		case 15: case 20: case 18:
  			if ((void *)stack < (void *)(m_->nums + m_->nums_count +1)) {
  				result = 3; // not enough memory (<n>[[;:]<n>...] store overflow)
  				continue;
  			}
  			m_->nums[m_->nums_count++] = stack->value;
  			break;
  		case 16: case 21:
  			if ((void *)stack < (void *)(m_->nums + m_->nums_count +1)) {
  				result = 3; // not enough memory (<n>[[;:]<n>...] store overflow)
  				continue;
  			}
  			m_->nums[m_->nums_count++] = stack->value + 10 * stack[1].value;
  			break;
  		case 24:
  			value = stack->value;
  			break;
  		case 25:
  			if (0xffff < (u = (stack->value + 10 * stack[1].value))) {
  				result = 2;
  				break;
  			}
  			value = (u16)u;
  			break;
  		case 26: case 35:
  		case 27: case 31: case 36:
  		case 28: case 32: case 37:
  		case 29: case 33: case 38:
  		case 30: case 34:
  			value = stack->value;
  			break;
  		case 39: case 40: case 41: case 42:
  		case 43: case 44: case 45: case 46:
  		case 47: case 48: case 22:
  			value = buf[-1] - '0';
  			break;
  		case 50: case 51:
  			if (NULL == m_->cstr) {
  				if (NULL == (m_->cstr = (char *)malloc (m_->cb_cstr = 128))) {
  					result = 3; // not enough memory (Pt malloc)
  					continue;
  				}
  				*m_->cstr = '\0';
  			}
  size_t len;
  			if (m_->cb_cstr < (len = strlen (m_->cstr)) +1 +1)
  				if (NULL == (m_->cstr = (char *)realloc (m_->cstr, m_->cb_cstr = 2 * m_->cb_cstr))) {
  					result = 3; // not enough memory (Pt malloc)
  					continue;
  				}
  			m_->cstr[len] = buf[-1];
  			m_->cstr[++len] = '\0';
  			break;
  		case 49:
  			iface->on_title_chg (param, m_->cstr);
  			free (m_->cstr);
  			m_->cstr = NULL;
  			break;
  		default:
  			break;
  		}
  		stack += reduce_len;
  		(--stack)->value = value;
  		n = r1_(n);
  		state = pgoto_(n -82) + stack[1].state;
  		if (! (0 <= state && state < arraycountof(tabchk) && check_(state) == stack[1].state))
  			state = defgoto_(n -82);
  		else
  			state = table_(state);
  	}
  	m_->i_stack = stack_bottom(m_) - stack;
  	m_->state = state;
  	m_->result = result;
  	return buf - begin;
  }
  
  
  