Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Dec 2008 20:46:30 GMT
From:      Ed Schouten <ed@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 154017 for review
Message-ID:  <200812032046.mB3KkUBx016516@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=154017

Change 154017 by ed@ed_dull on 2008/12/03 20:45:59

	Submit the latest version of libteken again.
	
	libteken now passes a lot of (basic) tests from the vttest
	suite. I've also tested various applications. It also handles
	the telnet/SSH interface of my HP2626 switch correctly. Let's
	see if we can hook this beauty up to syscons(4).
	
	I'm not entirely happy with modifying kern.post.mk to generate
	teken_state.h. Maybe we should regenerate by hand...

Affected files ...

.. //depot/projects/mpsafetty/sys/conf/files#29 edit
.. //depot/projects/mpsafetty/sys/conf/kern.post.mk#2 edit
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/gensequences#1 add
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/sequences#1 add
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken.c#2 edit
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken.h#2 edit
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken_internal.h#2 delete
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken_state.c#2 delete
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken_subr.c#2 delete
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken_subr.h#1 add
.. //depot/projects/mpsafetty/sys/dev/syscons/teken/teken_subr_cons25.h#1 add

Differences ...

==== //depot/projects/mpsafetty/sys/conf/files#29 (text+ko) ====

@@ -1432,8 +1432,6 @@
 dev/syscons/syscons.c		optional sc
 dev/syscons/sysmouse.c		optional sc
 dev/syscons/teken/teken.c	optional sc
-dev/syscons/teken/teken_state.c	optional sc
-dev/syscons/teken/teken_subr.c	optional sc
 dev/syscons/warp/warp_saver.c	optional warp_saver
 dev/tdfx/tdfx_linux.c		optional tdfx_linux tdfx compat_linux
 dev/tdfx/tdfx_pci.c		optional tdfx pci

==== //depot/projects/mpsafetty/sys/conf/kern.post.mk#2 (text+ko) ====

@@ -98,7 +98,8 @@
 .endif
 
 .if !exists(${.OBJDIR}/.depend)
-${SYSTEM_OBJS}: assym.s vnode_if.h ${BEFORE_DEPEND:M*.h} ${MFILES:T:S/.m$/.h/}
+${SYSTEM_OBJS}: assym.s vnode_if.h teken_state.h ${BEFORE_DEPEND:M*.h}\
+	    ${MFILES:T:S/.m$/.h/}
 .endif
 
 LNFILES=	${CFILES:T:S/.c$/.ln/}
@@ -117,7 +118,7 @@
 	    ${FULLKERNEL} ${KERNEL_KO} ${KERNEL_KO}.symbols \
 	    linterrs makelinks tags vers.c \
 	    vnode_if.c vnode_if.h vnode_if_newproto.h vnode_if_typedef.h \
-	    ${MFILES:T:S/.m$/.c/} ${MFILES:T:S/.m$/.h/} \
+	    teken_state.h ${MFILES:T:S/.m$/.c/} ${MFILES:T:S/.m$/.h/} \
 	    ${CLEAN}
 
 lint: ${LNFILES}
@@ -147,7 +148,7 @@
 kernel-depend: .depend
 # The argument list can be very long, so use make -V and xargs to
 # pass it to mkdep.
-SRCS=	assym.s vnode_if.h ${BEFORE_DEPEND} ${CFILES} \
+SRCS=	assym.s vnode_if.h teken_state.h ${BEFORE_DEPEND} ${CFILES} \
 	${SYSTEM_CFILES} ${GEN_CFILES} ${SFILES} \
 	${MFILES:T:S/.m$/.h/}
 .depend: .PRECIOUS ${SRCS}
@@ -258,6 +259,10 @@
 vnode_if_typedef.h:
 	${AWK} -f $S/tools/vnode_if.awk $S/kern/vnode_if.src -q
 
+teken_state.h: $S/dev/syscons/teken/gensequences $S/dev/syscons/teken/sequences
+	${AWK} -f $S/dev/syscons/teken/gensequences \
+	    < $S/dev/syscons/teken/sequences > teken_state.h
+
 # XXX strictly, everything depends on Makefile because changes to ${PROF}
 # only appear there, but we don't handle that.
 

==== //depot/projects/mpsafetty/sys/dev/syscons/teken/teken.c#2 (text+ko) ====

@@ -24,17 +24,141 @@
  * SUCH DAMAGE.
  */
 
-#include "teken_internal.h"
+#if defined(__FreeBSD__) && defined(_KERNEL)
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/systm.h>
+#define	teken_assert(x)		MPASS(x)
+#define	teken_printf(x,...)
+#else /* !(__FreeBSD__ && _KERNEL) */
+#include <sys/types.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#define	teken_assert(x)		assert(x)
+#define	teken_printf(x,...)	do { \
+	if (df != NULL) \
+		fprintf(df, x, ## __VA_ARGS__); \
+} while (0)
+/* debug messages */
+static FILE *df;
+#endif /* __FreeBSD__ && _KERNEL */
+
+#include "teken.h"
+
+#define	teken_clamp(x,low,high)	(((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
+
+/* Private flags for teken_format_t. */
+#define	TF_REVERSE	0x08
+
+/* Private flags for t_stateflags. */
+#define	TS_FIRSTDIGIT	0x01	/* First numeric digit in escape sequence. */
+#define	TS_INSERT	0x02	/* Insert mode. */
+#define	TS_AUTOWRAP	0x04	/* Autowrap. */
+#define	TS_ORIGIN	0x08	/* Origin mode. */
+
+static teken_state_t	teken_state_init;
 
-const teken_attr_t teken_defattr = {
+static const teken_attr_t teken_defattr = {
 	.ta_format = 0,
 	.ta_fgcolor = TC_WHITE,
 	.ta_bgcolor = TC_BLACK,
 };
 
-#if !(defined(__FreeBSD__) && defined(_KERNEL))
-FILE *df = NULL;
-#endif /* !(__FreeBSD__ && _KERNEL) */
+/*
+ * Wrappers for hooks.
+ */
+
+static inline void
+teken_funcs_bell(teken_t *t)
+{
+
+	t->t_funcs->tf_bell(t->t_softc);
+}
+
+static inline void
+teken_funcs_cursor(teken_t *t)
+{
+
+	teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
+	teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
+
+	t->t_funcs->tf_cursor(t->t_softc, &t->t_cursor);
+}
+
+static inline void
+teken_funcs_putchar(teken_t *t, const teken_pos_t *p, teken_char_t c,
+    const teken_attr_t *a)
+{
+	teken_attr_t ta;
+
+	teken_assert(p->tp_row < t->t_winsize.tp_row);
+	teken_assert(p->tp_col < t->t_winsize.tp_col);
+
+	/* Apply inversion. */
+	if (a->ta_format & TF_REVERSE) {
+		ta.ta_format = a->ta_format;
+		ta.ta_fgcolor = a->ta_bgcolor;
+		ta.ta_bgcolor = a->ta_fgcolor;
+		a = &ta;
+	}
+
+	t->t_funcs->tf_putchar(t->t_softc, p, c, a);
+}
+
+static inline void
+teken_funcs_fill(teken_t *t, const teken_rect_t *r,
+    const teken_char_t c, const teken_attr_t *a)
+{
+	teken_attr_t ta;
+
+	teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
+	teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
+	teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
+	teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
+
+	/* Apply inversion. */
+	if (a->ta_format & TF_REVERSE) {
+		ta.ta_format = a->ta_format;
+		ta.ta_fgcolor = a->ta_bgcolor;
+		ta.ta_bgcolor = a->ta_fgcolor;
+		a = &ta;
+	}
+
+	t->t_funcs->tf_fill(t->t_softc, r, c, a);
+}
+
+static inline void
+teken_funcs_copy(teken_t *t, const teken_rect_t *r, const teken_pos_t *p)
+{
+
+	teken_assert(r->tr_end.tp_row > r->tr_begin.tp_row);
+	teken_assert(r->tr_end.tp_row <= t->t_winsize.tp_row);
+	teken_assert(r->tr_end.tp_col > r->tr_begin.tp_col);
+	teken_assert(r->tr_end.tp_col <= t->t_winsize.tp_col);
+	teken_assert(p->tp_row + (r->tr_end.tp_row - r->tr_begin.tp_row) <= t->t_winsize.tp_row);
+	teken_assert(p->tp_col + (r->tr_end.tp_col - r->tr_begin.tp_col) <= t->t_winsize.tp_col);
+
+	t->t_funcs->tf_copy(t->t_softc, r, p);
+}
+
+static inline void
+teken_funcs_param(teken_t *t, int cmd, int value)
+{
+
+	t->t_funcs->tf_param(t->t_softc, cmd, value);
+}
+
+static inline void
+teken_funcs_respond(teken_t *t, const void *buf, size_t len)
+{
+
+	t->t_funcs->tf_respond(t->t_softc, buf, len);
+}
+
+#include "teken_subr.h"
+#include "teken_subr_cons25.h"
 
 /*
  * Programming interface.
@@ -45,38 +169,113 @@
 {
 	teken_pos_t tp = { .tp_row = 24, .tp_col = 80 };
 
+#if !(defined(__FreeBSD__) && defined(_KERNEL))
+	df = fopen("debuglog", "w");
+	if (df != NULL)
+		setvbuf(df, NULL, _IOLBF, BUFSIZ);
+#endif /* !(__FreeBSD__ && _KERNEL) */
+
 	t->t_funcs = tf;
 	t->t_softc = softc;
 
 	t->t_nextstate = teken_state_init;
 	t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
-	t->t_savepos = t->t_cursor;
-	t->t_stateflags = 0;
+	t->t_saved_cursor = t->t_nextchar = t->t_cursor;
+	t->t_stateflags = TS_AUTOWRAP;
+
+	t->t_curattr = t->t_saved_curattr = teken_defattr;
+
+	teken_tab_default(t);
 
-	t->t_curattr = teken_defattr;
+#ifdef TEKEN_UTF8
+	t->t_utf8_left = 0;
+#endif /* TEKEN_UTF8 */
 
 	teken_winsize(t, &tp);
+}
 
-#if !(defined(__FreeBSD__) && defined(_KERNEL))
-	df = fopen("debuglog", "w");
-	if (df != NULL)
-		setvbuf(df, NULL, _IOLBF, BUFSIZ);
-#endif /* !(__FreeBSD__ && _KERNEL) */
+static void
+teken_input_char(teken_t *t, teken_char_t c)
+{
+
+	switch (c) {
+	case '\0':
+		teken_subr_null_character(t);
+		break;
+	case '\a':
+		teken_subr_bell(t);
+		break;
+	case '\b':
+		teken_subr_backspace(t);
+		break;
+	case '\n':
+		teken_subr_newline(t);
+		break;
+	case '\r':
+		teken_subr_carriage_return(t);
+		break;
+	case '\t':
+		teken_subr_horizontal_tab(t);
+		break;
+	case '\x0B':
+		teken_subr_vertical_tab(t);
+		break;
+	default:
+		t->t_nextstate(t, c);
+		break;
+	}
+
+	/* Post-processing assertions. */
+	teken_assert(t->t_cursor.tp_row >= t->t_originreg.ts_begin);
+	teken_assert(t->t_cursor.tp_row < t->t_originreg.ts_end);
+	teken_assert(t->t_cursor.tp_row < t->t_winsize.tp_row);
+	teken_assert(t->t_cursor.tp_col < t->t_winsize.tp_col);
+	teken_assert(t->t_saved_cursor.tp_row < t->t_winsize.tp_row);
+	teken_assert(t->t_saved_cursor.tp_col < t->t_winsize.tp_col);
+	teken_assert(t->t_nextchar.tp_row <= t->t_winsize.tp_row);
+	teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
+	teken_assert(t->t_scrollreg.ts_begin < t->t_scrollreg.ts_end);
+	teken_assert(t->t_originreg.ts_end <= t->t_winsize.tp_row);
+	teken_assert(t->t_originreg.ts_begin < t->t_originreg.ts_end);
 }
 
 static void
-teken_input_byte(teken_t *t, char c)
+teken_input_byte(teken_t *t, unsigned char c)
 {
 
-	/* XXX: UTF-8! */
-#if 1
-	teken_printf("C %3u %3u -> ", t->t_cursor.tp_row, t->t_cursor.tp_col);
-	t->t_nextstate(t, c);
-	teken_printf("%3u %3u B %3hhu (%c)\n", t->t_cursor.tp_row, t->t_cursor.tp_col, (unsigned char)c, c);
-	teken_printf("%u %u %u\n", t->t_curattr.ta_format, t->t_curattr.ta_fgcolor, t->t_curattr.ta_bgcolor);
-#else
-	t->t_nextstate(t, c);
-#endif
+#ifdef TEKEN_UTF8
+	/*
+	 * UTF-8 handling.
+	 */
+	if ((c & 0x80) == 0x00) {
+		/* One-byte sequence. */
+		t->t_utf8_left = 0;
+		teken_input_char(t, c);
+	} else if ((c & 0xe0) == 0xc0) {
+		/* Two-byte sequence. */
+		t->t_utf8_left = 1;
+		t->t_utf8_partial = c & 0x1f;
+	} else if ((c & 0xf0) == 0xe0) {
+		/* Three-byte sequence. */
+		t->t_utf8_left = 2;
+		t->t_utf8_partial = c & 0x0f;
+	} else if ((c & 0xf8) == 0xf0) {
+		/* Four-byte sequence. */
+		t->t_utf8_left = 3;
+		t->t_utf8_partial = c & 0x07;
+	} else if ((c & 0xc0) == 0x80) {
+		if (t->t_utf8_left == 0)
+			return;
+		t->t_utf8_left--;
+		t->t_utf8_partial = (t->t_utf8_partial << 6) | (c & 0x3f);
+		if (t->t_utf8_left == 0) {
+			teken_printf("Got UTF-8 char %u\n", t->t_utf8_partial);
+			teken_input_char(t, t->utf8_partial);
+		}
+	}
+#else /* !TEKEN_UTF8 */
+	teken_input_char(t, c);
+#endif /* TEKEN_UTF8 */
 }
 
 void
@@ -93,10 +292,13 @@
 {
 	teken_rect_t tr;
 
+	teken_assert(p->tp_col <= T_NUMCOL);
+
 	t->t_winsize = *p;
 	/* XXX: discards active scroll region. */
 	t->t_scrollreg.ts_begin = 0;
 	t->t_scrollreg.ts_end = t->t_winsize.tp_row;
+	t->t_originreg = t->t_scrollreg;
 
 	/* Blank screen. */
 	tr.tr_begin.tp_row = 0;
@@ -104,3 +306,64 @@
 	tr.tr_end = t->t_winsize;
 	teken_funcs_fill(t, &tr, ' ', &teken_defattr);
 }
+
+/*
+ * State machine.
+ */
+
+static void
+teken_state_switch(teken_t *t, teken_state_t *s)
+{
+
+	t->t_nextstate = s;
+	t->t_curnum = 0;
+	t->t_stateflags |= TS_FIRSTDIGIT;
+}
+
+static int
+teken_state_numbers(teken_t *t, teken_char_t c)
+{
+
+	teken_assert(t->t_curnum < T_NUMSIZE);
+
+	if (c >= '0' && c <= '9') {
+		/*
+		 * Don't do math with the default value of 1 when a
+		 * custom number is inserted.
+		 */
+		if (t->t_stateflags & TS_FIRSTDIGIT) {
+			t->t_stateflags &= ~TS_FIRSTDIGIT;
+			t->t_nums[t->t_curnum] = 0;
+		} else {
+			t->t_nums[t->t_curnum] *= 10;
+		}
+
+		t->t_nums[t->t_curnum] += c - '0';
+		return (1);
+	} else if (c == ';') {
+		if (t->t_stateflags & TS_FIRSTDIGIT)
+			t->t_nums[t->t_curnum] = 0;
+
+		/* Only allow a limited set of arguments. */
+		if (++t->t_curnum == T_NUMSIZE) {
+			teken_state_switch(t, teken_state_init);
+			return (1);
+		}
+
+		t->t_stateflags |= TS_FIRSTDIGIT;
+		return (1);
+	} else {
+		if (t->t_stateflags & TS_FIRSTDIGIT && t->t_curnum > 0) {
+			/* Finish off the last empty argument. */
+			t->t_nums[t->t_curnum] = 0;
+			t->t_curnum++;
+		} else if ((t->t_stateflags & TS_FIRSTDIGIT) == 0) {
+			/* Also count the last argument. */
+			t->t_curnum++;
+		}
+	}
+
+	return (0);
+}
+
+#include "teken_state.h"

==== //depot/projects/mpsafetty/sys/dev/syscons/teken/teken.h#2 (text+ko) ====

@@ -34,17 +34,16 @@
  * commands. It implements commands similar to xterm-color.
  */
 
-#if 0
-/* XXX: UTF-8 */
+#ifdef TEKEN_UTF8
 typedef uint32_t teken_char_t;
-#endif
+#else /* !TEKEN_UTF8 */
 typedef unsigned char teken_char_t;
+#endif /* TEKEN_UTF8 */
 typedef unsigned int teken_unit_t;
 typedef char teken_format_t;
 #define	TF_BOLD		0x01
 #define	TF_UNDERLINE	0x02
 #define	TF_BLINK	0x04
-#define	TF_REVERSE	0x08
 typedef char teken_color_t;
 #define	TC_BLACK	0
 #define	TC_RED		1
@@ -89,9 +88,10 @@
     const teken_attr_t *);
 typedef void tf_copy_t(void *, const teken_rect_t *, const teken_pos_t *);
 typedef void tf_param_t(void *, int, int);
-#define	TP_SHOWCURSOR	0x00
-#define	TP_CURSORKEYS	0x01
-#define	TP_KEYPADAPP	0x02
+#define	TP_SHOWCURSOR	0
+#define	TP_CURSORKEYS	1
+#define	TP_KEYPADAPP	2
+typedef void tf_respond_t(void *, const void *, size_t);
 
 typedef struct {
 	tf_bell_t	*tf_bell;
@@ -100,6 +100,7 @@
 	tf_fill_t	*tf_fill;
 	tf_copy_t	*tf_copy;
 	tf_param_t	*tf_param;
+	tf_respond_t	*tf_respond;
 } teken_funcs_t;
 
 /*
@@ -111,19 +112,31 @@
 
 	teken_state_t	*t_nextstate;
 	unsigned int	 t_stateflags;
-#define	TS_FIRSTDIGIT	0x01	/* First numeric digit in escape sequence. */
-#define	TS_INSERT	0x02	/* Insert mode. */
 
-#define T_NUMSIZE	4
+#define T_NUMSIZE	8
 	unsigned int	 t_nums[T_NUMSIZE];
 	unsigned int	 t_curnum;
 
 	teken_pos_t	 t_cursor;
-	teken_pos_t	 t_savepos;
+	teken_attr_t	 t_curattr;
+	teken_pos_t	 t_saved_cursor;
+	teken_attr_t	 t_saved_curattr;
+
+	teken_pos_t	 t_nextchar;
 	teken_pos_t	 t_winsize;
+
+	/* For DECSTBM. */
 	teken_span_t	 t_scrollreg;
+	/* For DECOM. */
+	teken_span_t	 t_originreg;
 
-	teken_attr_t	 t_curattr;
+#define	T_NUMCOL	160
+	unsigned int	t_tabstops[T_NUMCOL / (sizeof(unsigned int) * 8)];
+
+#ifdef TEKEN_UTF8
+	unsigned int	t_utf8_left;
+	teken_char_t	t_utf8_partial;
+#endif /* TEKEN_UTF8 */
 };
 
 void	teken_init(teken_t *, const teken_funcs_t *, void *);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812032046.mB3KkUBx016516>