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>