Module Name: src Committed By: roy Date: Fri Feb 26 00:09:00 UTC 2010
Modified Files: src/lib/libterminfo: term.c term.h termcap.c terminfo.5.in Log Message: Implement captoinfo so that we can convert $TERMCAP into $TERMINFO. We don't currently map %> %B %D. That means no conversion for regent100, hz1500, act4, act5, mime terms. To generate a diff of this commit: cvs rdiff -u -r1.10 -r1.11 src/lib/libterminfo/term.c cvs rdiff -u -r1.4 -r1.5 src/lib/libterminfo/term.h cvs rdiff -u -r1.2 -r1.3 src/lib/libterminfo/termcap.c cvs rdiff -u -r1.12 -r1.13 src/lib/libterminfo/terminfo.5.in Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libterminfo/term.c diff -u src/lib/libterminfo/term.c:1.10 src/lib/libterminfo/term.c:1.11 --- src/lib/libterminfo/term.c:1.10 Mon Feb 22 23:05:39 2010 +++ src/lib/libterminfo/term.c Fri Feb 26 00:09:00 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: term.c,v 1.10 2010/02/22 23:05:39 roy Exp $ */ +/* $NetBSD: term.c,v 1.11 2010/02/26 00:09:00 roy Exp $ */ /* * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: term.c,v 1.10 2010/02/22 23:05:39 roy Exp $"); +__RCSID("$NetBSD: term.c,v 1.11 2010/02/26 00:09:00 roy Exp $"); #include <sys/stat.h> @@ -283,6 +283,34 @@ } static int +ticcmp(const TIC *tic, const char *name) +{ + char *alias, *s; + size_t len, l; + + if (strcmp(tic->name, name) == 0) + return 0; + if (tic->alias == NULL) + return -1; + + len = strlen(name); + alias = tic->alias; + while (*alias != '\0') { + s = strchr(alias, '|'); + if (s == NULL) + l = strlen(alias); + else + l = s - alias; + if (len == l && strncmp(alias, name, l) == 0) + return 0; + if (s == NULL) + break; + alias = s + 1; + } + return 1; +} + +static int _ti_findterm(TERMINAL *term, const char *name, int flags) { int r; @@ -298,13 +326,32 @@ _ti_database = NULL; r = 0; - if ((e = getenv("TERMINFO")) != NULL && *e != '\0') { + if ((e = getenv("TERMINFO")) != NULL && *e != '\0') if (e[0] == '/') return _ti_dbgetterm(term, e, name, flags); - c = strdup(e); /* So we don't destroy env */ - tic = _ti_compile(c, TIC_WARNING | TIC_EXTRA); - free(c); - if (tic != NULL && strcmp(tic->name, name) == 0) { + + c = NULL; + if (e == NULL && (c = getenv("TERMCAP")) != NULL) { + if (*c != '\0' && *c != '/') { + c = strdup(c); + if (c != NULL) { + e = captoinfo(c); + free(c); + } + } + } + + if (e != NULL) { + if (c == NULL) + e = strdup(e); /* So we don't destroy env */ + if (e == NULL) + tic = NULL; + else + tic = _ti_compile(e, TIC_WARNING | + TIC_ALIAS | TIC_DESCRIPTION | TIC_EXTRA); + if (c == NULL && e != NULL) + free(e); + if (tic != NULL && ticcmp(tic, name) == 0) { len = _ti_flatten(&f, tic); if (len != -1) { r = _ti_readterm(term, (char *)f, len, flags); @@ -313,7 +360,10 @@ } _ti_freetic(tic); if (r == 1) { - _ti_database = "$TERMINFO"; + if (c == NULL) + _ti_database = "$TERMINFO"; + else + _ti_database = "$TERMCAP"; return r; } } Index: src/lib/libterminfo/term.h diff -u src/lib/libterminfo/term.h:1.4 src/lib/libterminfo/term.h:1.5 --- src/lib/libterminfo/term.h:1.4 Thu Feb 11 00:27:09 2010 +++ src/lib/libterminfo/term.h Fri Feb 26 00:09:00 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: term.h,v 1.4 2010/02/11 00:27:09 roy Exp $ */ +/* $NetBSD: term.h,v 1.5 2010/02/26 00:09:00 roy Exp $ */ /* * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. @@ -1512,5 +1512,9 @@ # define t_parm t_vtparm #endif +/* Convert a termcap string into a terminfo string. + * The passed string is destroyed and the return string needs to be freed. */ +char * captoinfo(char *); + __END_DECLS #endif Index: src/lib/libterminfo/termcap.c diff -u src/lib/libterminfo/termcap.c:1.2 src/lib/libterminfo/termcap.c:1.3 --- src/lib/libterminfo/termcap.c:1.2 Thu Feb 4 09:46:26 2010 +++ src/lib/libterminfo/termcap.c Fri Feb 26 00:09:00 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: termcap.c,v 1.2 2010/02/04 09:46:26 roy Exp $ */ +/* $NetBSD: termcap.c,v 1.3 2010/02/26 00:09:00 roy Exp $ */ /* * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -28,9 +28,11 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: termcap.c,v 1.2 2010/02/04 09:46:26 roy Exp $"); +__RCSID("$NetBSD: termcap.c,v 1.3 2010/02/26 00:09:00 roy Exp $"); #include <assert.h> +#include <ctype.h> +#include <errno.h> #include <stdint.h> #include <string.h> #include <term_private.h> @@ -180,3 +182,176 @@ _DIAGASSERT(cm != NULL); return vtparm(cm, destline, destcol); } + +static const char * +flagname(const char *key) +{ + uint32_t idx; + + idx = _t_flaghash((const unsigned char *)key, strlen(key)); + if (idx <= __arraycount(_ti_cap_flagids) && + strcmp(key, _ti_cap_flagids[idx].id) == 0) + return _ti_flagid(_ti_cap_flagids[idx].ti); + return key; +} + +static const char * +numname(const char *key) +{ + uint32_t idx; + + idx = _t_numhash((const unsigned char *)key, strlen(key)); + if (idx <= __arraycount(_ti_cap_numids) && + strcmp(key, _ti_cap_numids[idx].id) == 0) + return _ti_numid(_ti_cap_numids[idx].ti); + return key; +} + +static const char * +strname(const char *key) +{ + uint32_t idx; + + idx = _t_strhash((const unsigned char *)key, strlen(key)); + if (idx <= __arraycount(_ti_cap_strids) && + strcmp(key, _ti_cap_strids[idx].id) == 0) + return _ti_strid(_ti_cap_strids[idx].ti); + + if (strcmp(key, "tc") == 0) + return "use"; + + return key; +} + +/* We don't currently map %> %B %D + * That means no conversion for regent100, hz1500, act4, act5, mime terms. */ +static char * +strval(const char *val) +{ + char *info, *ip, c; + int p; + size_t len, l, n; + + len = 1024; /* no single string should be bigger */ + info = ip = malloc(len); + if (info == NULL) + return 0; + + l = 0; + p = 1; + for (; *val != '\0'; val++) { + if (l + 2 > len) + goto elen; + if (*val != '%') { + *ip++ = *val; + l++; + continue; + } + switch (c = *(++val)) { + case 'd': + if (l + 6 > len) + goto elen; + *ip++ = '%'; + *ip++ = 'p'; + *ip++ = '0' + p; + *ip++ = '%'; + *ip++ = 'd'; + l += 5; + n += 5; + /* FALLTHROUGH */ + case 'r': + p = 3 - p; + break; + default: + /* Hope it matches a terminfo command. */ + *ip++ = '%'; + *ip++ = c; + l += 2; + break; + } + } + + *ip = '\0'; + return info; + +elen: + free(info); + errno = ENOMEM; + return NULL; +} + +char * +captoinfo(char *cap) +{ + char *info, *ip, *token, *val, *p, tok[3]; + const char *name; + size_t len, lp, nl, vl, rl; + + _DIAGASSERT(cap != NULL); + + len = strlen(cap) * 2; + info = ip = malloc(len); + if (info == NULL) + return NULL; + + lp = 0; + tok[2] = '\0'; + while ((token = strsep(&cap, ":")) != NULL) { + /* Trim whitespace */ + while (isspace((unsigned char)*token)) + token++; + if (token[0] == '\0') + continue; + name = token; + val = NULL; + if (token[1] != '\0') { + tok[0] = token[0]; + tok[1] = token[1]; + if (token[2] == '\0') { + name = flagname(tok); + val = NULL; + } else if (token[2] == '#') { + name = numname(tok); + val = token + 2; + } else if (token[2] == '=') { + name = strname(tok); + val = strval(token + 2); + } + } + nl = strlen(name); + if (val == NULL) + vl = 0; + else + vl = strlen(val); + rl = nl + vl + 3; /* , \0 */ + + if (lp + rl > len) { + if (rl < 256) + len += 256; + else + len += rl; + p = realloc(info, len); + if (p == NULL) + return NULL; + info = p; + } + + if (ip != info) { + *ip++ = ','; + *ip++ = ' '; + } + + strcpy(ip, name); + ip += nl; + if (val != NULL) { + strcpy(ip, val); + ip += vl; + if (token[2] == '=') + free(val); + } + } + + *ip = '\0'; + return info; +} + Index: src/lib/libterminfo/terminfo.5.in diff -u src/lib/libterminfo/terminfo.5.in:1.12 src/lib/libterminfo/terminfo.5.in:1.13 --- src/lib/libterminfo/terminfo.5.in:1.12 Mon Feb 22 23:05:39 2010 +++ src/lib/libterminfo/terminfo.5.in Fri Feb 26 00:09:00 2010 @@ -1,4 +1,4 @@ -.\" $NetBSD: terminfo.5.in,v 1.12 2010/02/22 23:05:39 roy Exp $ +.\" $NetBSD: terminfo.5.in,v 1.13 2010/02/26 00:09:00 roy Exp $ .\" .\" Copyright (c) 2009, 2010 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd February 22, 2010 +.Dd February 26, 2010 .Dt TERMINFO 5 .Os .Sh NAME @@ -209,8 +209,16 @@ then it is used. .Pp If the environment variable +.Ev TERMCAP +is available and does not begin with / then it will be translated into +terminfo and compiled as above. +If its name matches +.Ev TERM +then it is used. +.Pp +If the environment variable .Ev TERMINFO -is available then and begins with / then only this file is searched. +is available and begins with / then only this file is searched. Otherwise .Nm will first look for @@ -248,3 +256,7 @@ .Xr tic 1 . .Sh AUTHORS .An Roy Marples Aq r...@netbsd.org +.Sh BUGS +The +.Ev TERMCAP +capabilities %>, %B and %D are not converted into terminfo capabilities.