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.
This commit is contained in:
roy 2010-02-26 00:09:00 +00:00
parent 51d6f75dc3
commit 007ba6f7e2
4 changed files with 255 additions and 14 deletions

View File

@ -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>
@ -282,6 +282,34 @@ _ti_dbgettermp(TERMINAL *term, const char *path, const char *name, int flags)
return e;
}
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)
{
@ -298,13 +326,32 @@ _ti_findterm(TERMINAL *term, const char *name, int flags)
_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_findterm(TERMINAL *term, const char *name, int flags)
}
_ti_freetic(tic);
if (r == 1) {
_ti_database = "$TERMINFO";
if (c == NULL)
_ti_database = "$TERMINFO";
else
_ti_database = "$TERMCAP";
return r;
}
}

View File

@ -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 @@ char * t_vparm(TERMINAL *, const char *, ...);
# 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

View File

@ -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 @@ tgoto(const char *cm, int destcol, int destline)
_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;
}

View File

@ -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 @@ whose name matches
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 @@ Extensions to the standard are noted in
.Xr tic 1 .
.Sh AUTHORS
.An Roy Marples Aq roy@NetBSD.org
.Sh BUGS
The
.Ev TERMCAP
capabilities %>, %B and %D are not converted into terminfo capabilities.