PERFORCE change 154017 for review
Ed Schouten
ed at FreeBSD.org
Wed Dec 3 12:46:31 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=154017
Change 154017 by ed at 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 *);
More information about the p4-projects
mailing list