summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2019-08-12 16:30:43 -0400
committerJune McEnroe <june@causal.agency>2019-08-12 16:30:43 -0400
commitcdb00a05823f69ceb9ed86f510450a5ee5cae7b9 (patch)
tree6c37ae5fe215edc4667c3937d17ff894cfbc2673
parentUse low numbers for states (diff)
downloadstream-cdb00a05823f69ceb9ed86f510450a5ee5cae7b9.tar.gz
stream-cdb00a05823f69ceb9ed86f510450a5ee5cae7b9.zip
Use a big macro switch-case
This lets the compiler inline and generate jump tables however it sees
fit.
-rw-r--r--term.c141
1 files changed, 81 insertions, 60 deletions
diff --git a/term.c b/term.c
index 7bc6282..5ee88ac 100644
--- a/term.c
+++ b/term.c
@@ -358,68 +358,77 @@ static void add(struct Term *t, wchar_t ch) {
 	}
 }
 
-static Action *Actions[][128] = {
-	[Def][0]   = add,
-	[Def][BEL] = nop,
-	[Def][BS]  = bs,
-	[Def][HT]  = ht,
-	[Def][NL]  = nl,
-	[Def][CR]  = cr,
-	[Def][ESC] = esc,
-
-	[Esc][0]   = escUnhandled,
-	[Esc]['('] = g0,
-	[Esc]['7'] = decsc,
-	[Esc]['8'] = decrc,
-	[Esc]['='] = nop,
-	[Esc]['>'] = nop,
-	[Esc]['M'] = ri,
-	[Esc]['['] = csi,
-	[Esc][']'] = osc,
-	
-	[G0][0]    = nop,
-
-	[CSI][0]   = csiParam,
-	[CSI]['@'] = ich,
-	[CSI]['A'] = cuu,
-	[CSI]['B'] = cud,
-	[CSI]['C'] = cuf,
-	[CSI]['D'] = cub,
-	[CSI]['E'] = cnl,
-	[CSI]['F'] = cpl,
-	[CSI]['G'] = cha,
-	[CSI]['H'] = cup,
-	[CSI]['J'] = ed,
-	[CSI]['K'] = el,
-	[CSI]['L'] = il,
-	[CSI]['M'] = dl,
-	[CSI]['P'] = dch,
-	[CSI]['S'] = su,
-	[CSI]['T'] = sd,
-	[CSI]['X'] = ech,
-	[CSI]['d'] = vpa,
-	[CSI]['h'] = mode,
-	[CSI]['l'] = mode,
-	[CSI]['m'] = sgr,
-	[CSI]['r'] = decstbm,
-	[CSI]['t'] = nop,
-	
-	[OSC][0]   = osc,
-	[OSC][BEL] = nop,
-	[OSC][ESC] = oscEsc,
-
-	[OSCEsc][0] = osc,
-	[OSCEsc]['\\'] = nop,
-};
-
+#define S(s) break; case (s): switch (ch)
+#define A(c, a) break; case (c): (a)(term, ch)
+#define D(a) break; default: (a)(term, ch)
 void termUpdate(struct Term *term, wchar_t ch) {
-	assert(term->state < sizeof(Actions) / sizeof(Actions[0]));
-	Action *action = NULL;
-	if (ch < 128) action = Actions[term->state][ch];
-	if (!action) action = Actions[term->state][0];
-	assert(action);
+	uint state = term->state;
 	term->state = Def;
-	action(term, ch);
+	switch (state) {
+		default: abort();
+
+		S(Def) {
+			A(BEL, nop);
+			A(BS,  bs);
+			A(HT,  ht);
+			A(NL,  nl);
+			A(CR,  cr);
+			A(ESC, esc);
+			D(add);
+		}
+
+		S(Esc) {
+			A('(', g0);
+			A('7', decsc);
+			A('8', decrc);
+			A('=', nop);
+			A('>', nop);
+			A('M', ri);
+			A('[', csi);
+			A(']', osc);
+			D(escUnhandled);
+		}
+		S(G0) {
+			D(nop);
+		}
+
+		S(CSI) {
+			A('@', ich);
+			A('A', cuu);
+			A('B', cud);
+			A('C', cuf);
+			A('D', cub);
+			A('E', cnl);
+			A('F', cpl);
+			A('G', cha);
+			A('H', cup);
+			A('J', ed);
+			A('K', el);
+			A('L', il);
+			A('M', dl);
+			A('P', dch);
+			A('S', su);
+			A('T', sd);
+			A('X', ech);
+			A('d', vpa);
+			A('h', mode);
+			A('l', mode);
+			A('m', sgr);
+			A('r', decstbm);
+			A('t', nop);
+			D(csiParam);
+		}
+
+		S(OSC) {
+			A(BEL, nop);
+			A(ESC, oscEsc);
+			D(osc);
+		}
+		S(OSCEsc) {
+			A('\\', nop);
+			D(osc);
+		}
+	}
 }
 
 struct Term *termAlloc(uint rows, uint cols) {
@@ -545,3 +554,15 @@ fail:
 	fclose(file);
 	return -1;
 }
+
+#ifdef TERM_MAIN
+
+int main(void) {
+	struct Term *term = termAlloc(24, 80);
+	wint_t ch;
+	while (WEOF != (ch = getwchar())) {
+		termUpdate(term, ch);
+	}
+}
+
+#endif