summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorroy <roy@NetBSD.org>2010-02-22 23:05:39 +0000
committerroy <roy@NetBSD.org>2010-02-22 23:05:39 +0000
commitfde317d2b105ccabb4599840ec51d8a5259a1247 (patch)
treef24f7ab08c38aac083d35014b0f1cb716ae9c360 /lib
parent24e08ad36b31041b7acbbb4affd7cb0fe9e2f521 (diff)
libterminfo can now compile a single terminfo description which allows
$TERMINFO to be a terminfo description as well as a file reference. This enables the user to modify the terminfo description on read-only media.
Diffstat (limited to 'lib')
-rw-r--r--lib/libterminfo/Makefile4
-rw-r--r--lib/libterminfo/compile.c652
-rw-r--r--lib/libterminfo/curterm.c10
-rw-r--r--lib/libterminfo/term.c49
-rw-r--r--lib/libterminfo/term_private.h36
-rw-r--r--lib/libterminfo/terminfo.5.in13
6 files changed, 734 insertions, 30 deletions
diff --git a/lib/libterminfo/Makefile b/lib/libterminfo/Makefile
index 262f1919270..203e76d3b08 100644
--- a/lib/libterminfo/Makefile
+++ b/lib/libterminfo/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.10 2010/02/19 13:53:17 njoly Exp $
+# $NetBSD: Makefile,v 1.11 2010/02/22 23:05:39 roy Exp $
USE_SHLIBDIR= yes
@@ -8,7 +8,7 @@ WARNS= 4
CPPFLAGS+= -I${.CURDIR}
SRCS= term.c ti.c setupterm.c curterm.c tparm.c tputs.c
-SRCS+= hash.c
+SRCS+= compile.c hash.c
INCS= term.h
INCSDIR= /usr/include
diff --git a/lib/libterminfo/compile.c b/lib/libterminfo/compile.c
new file mode 100644
index 00000000000..32c9c56412e
--- /dev/null
+++ b/lib/libterminfo/compile.c
@@ -0,0 +1,652 @@
+/* $NetBSD: compile.c,v 1.1 2010/02/22 23:05:39 roy Exp $ */
+
+/*
+ * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roy Marples.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: compile.c,v 1.1 2010/02/22 23:05:39 roy Exp $");
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <term_private.h>
+#include <term.h>
+
+static void __attribute__((__format__(__printf__, 2, 3)))
+dowarn(int flags, const char *fmt, ...)
+{
+ va_list va;
+
+ errno = EINVAL;
+ if (flags & TIC_WARNING) {
+ va_start(va, fmt);
+ vwarnx(fmt, va);
+ va_end(va);
+ }
+}
+
+char *
+_ti_grow_tbuf(TBUF *tbuf, size_t len)
+{
+ char *buf;
+ size_t l;
+
+ _DIAGASSERT(tbuf != NULL);
+
+ l = tbuf->bufpos + len;
+ if (l > tbuf->buflen) {
+ if (tbuf->bufpos == 0)
+ buf = malloc(l);
+ else
+ buf = realloc(tbuf->buf, l);
+ if (buf == NULL)
+ return NULL;
+ tbuf->buf = buf;
+ tbuf->buflen = l;
+ }
+ return tbuf->buf;
+}
+
+char *
+_ti_find_cap(TBUF *tbuf, char type, short ind)
+{
+ size_t n;
+ short num;
+ char *cap;
+
+ _DIAGASSERT(tbuf != NULL);
+
+ cap = tbuf->buf;
+ for (n = tbuf->entries; n > 0; n--) {
+ num = le16dec(cap);
+ cap += sizeof(uint16_t);
+ if (num == ind)
+ return cap;
+ switch (type) {
+ case 'f':
+ cap++;
+ break;
+ case 'n':
+ cap += sizeof(uint16_t);
+ break;
+ case 's':
+ num = le16dec(cap);
+ cap += sizeof(uint16_t);
+ cap += num;
+ break;
+ }
+ }
+
+ errno = ESRCH;
+ return NULL;
+}
+
+char *
+_ti_find_extra(TBUF *tbuf, const char *code)
+{
+ size_t n;
+ short num;
+ char *cap;
+
+ _DIAGASSERT(tbuf != NULL);
+ _DIAGASSERT(code != NULL);
+
+ cap = tbuf->buf;
+ for (n = tbuf->entries; n > 0; n--) {
+ num = le16dec(cap);
+ cap += sizeof(uint16_t);
+ if (strcmp(cap, code) == 0)
+ return cap + num;
+ cap += num;
+ switch (*cap++) {
+ case 'f':
+ cap++;
+ break;
+ case 'n':
+ cap += sizeof(uint16_t);
+ break;
+ case 's':
+ num = le16dec(cap);
+ cap += sizeof(uint16_t);
+ cap += num;
+ break;
+ }
+ }
+
+ errno = ESRCH;
+ return NULL;
+}
+
+size_t
+_ti_store_extra(TIC *tic, int wrn, char *id, char type, char flag, short num,
+ char *str, size_t strl, int flags)
+{
+ size_t l;
+
+ _DIAGASSERT(tic != NULL);
+
+ if (strcmp(id, "use") != 0) {
+ if (_ti_find_extra(&tic->extras, id) != NULL)
+ return 0;
+ if (!(flags & TIC_EXTRA)) {
+ if (wrn != 0)
+ dowarn(flags, "%s: %s: unknown capability",
+ tic->name, id);
+ return 0;
+ }
+ }
+
+ l = strlen(id) + 1;
+ if (l > UINT16_T_MAX) {
+ dowarn(flags, "%s: %s: cap name is too long", tic->name, id);
+ return 0;
+ }
+
+ if (!_ti_grow_tbuf(&tic->extras,
+ l + strl + (sizeof(uint16_t) * 2) + 1))
+ return 0;
+ le16enc(tic->extras.buf + tic->extras.bufpos, l);
+ tic->extras.bufpos += sizeof(uint16_t);
+ memcpy(tic->extras.buf + tic->extras.bufpos, id, l);
+ tic->extras.bufpos += l;
+ tic->extras.buf[tic->extras.bufpos++] = type;
+ switch (type) {
+ case 'f':
+ tic->extras.buf[tic->extras.bufpos++] = flag;
+ break;
+ case 'n':
+ le16enc(tic->extras.buf + tic->extras.bufpos, num);
+ tic->extras.bufpos += sizeof(uint16_t);
+ break;
+ case 's':
+ le16enc(tic->extras.buf + tic->extras.bufpos, strl);
+ tic->extras.bufpos += sizeof(uint16_t);
+ memcpy(tic->extras.buf + tic->extras.bufpos, str, strl);
+ tic->extras.bufpos += strl;
+ break;
+ }
+ tic->extras.entries++;
+ return 1;
+}
+
+ssize_t
+_ti_flatten(uint8_t **buf, const TIC *tic)
+{
+ size_t buflen, len, alen, dlen;
+ uint8_t *cap;
+
+ _DIAGASSERT(buf != NULL);
+ _DIAGASSERT(tic != NULL);
+
+ len = strlen(tic->name) + 1;
+ if (tic->alias == NULL)
+ alen = 0;
+ else
+ alen = strlen(tic->alias) + 1;
+ if (tic->desc == NULL)
+ dlen = 0;
+ else
+ dlen = strlen(tic->desc) + 1;
+ buflen = sizeof(char) +
+ sizeof(uint16_t) + len +
+ sizeof(uint16_t) + alen +
+ sizeof(uint16_t) + dlen +
+ (sizeof(uint16_t) * 2) + tic->flags.bufpos +
+ (sizeof(uint16_t) * 2) + tic->nums.bufpos +
+ (sizeof(uint16_t) * 2) + tic->strs.bufpos +
+ (sizeof(uint16_t) * 2) + tic->extras.bufpos;
+ *buf = malloc(buflen);
+ if (*buf == NULL)
+ return -1;
+
+ cap = *buf;
+ *cap++ = 2; /* version */
+ le16enc(cap, len);
+ cap += sizeof(uint16_t);
+ memcpy(cap, tic->name, len);
+ cap += len;
+
+ le16enc(cap, alen);
+ cap += sizeof(uint16_t);
+ if (tic->alias != NULL) {
+ memcpy(cap, tic->alias, alen);
+ cap += alen;
+ }
+ le16enc(cap, dlen);
+ cap += sizeof(uint16_t);
+ if (tic->desc != NULL) {
+ memcpy(cap, tic->desc, dlen);
+ cap += dlen;
+ }
+
+ if (tic->flags.entries == 0) {
+ le16enc(cap, 0);
+ cap += sizeof(uint16_t);
+ } else {
+ le16enc(cap, (tic->flags.bufpos + sizeof(uint16_t)));
+ cap += sizeof(uint16_t);
+ le16enc(cap, tic->flags.entries);
+ cap += sizeof(uint16_t);
+ memcpy(cap, tic->flags.buf, tic->flags.bufpos);
+ cap += tic->flags.bufpos;
+ }
+
+ if (tic->nums.entries == 0) {
+ le16enc(cap, 0);
+ cap += sizeof(uint16_t);
+ } else {
+ le16enc(cap, (tic->nums.bufpos + sizeof(uint16_t)));
+ cap += sizeof(uint16_t);
+ le16enc(cap, tic->nums.entries);
+ cap += sizeof(uint16_t);
+ memcpy(cap, tic->nums.buf, tic->nums.bufpos);
+ cap += tic->nums.bufpos;
+ }
+
+ if (tic->strs.entries == 0) {
+ le16enc(cap, 0);
+ cap += sizeof(uint16_t);
+ } else {
+ le16enc(cap, (tic->strs.bufpos + sizeof(uint16_t)));
+ cap += sizeof(uint16_t);
+ le16enc(cap, tic->strs.entries);
+ cap += sizeof(uint16_t);
+ memcpy(cap, tic->strs.buf, tic->strs.bufpos);
+ cap += tic->strs.bufpos;
+ }
+
+ if (tic->extras.entries == 0) {
+ le16enc(cap, 0);
+ cap += sizeof(uint16_t);
+ } else {
+ le16enc(cap, (tic->extras.bufpos + sizeof(uint16_t)));
+ cap += sizeof(uint16_t);
+ le16enc(cap, tic->extras.entries);
+ cap += sizeof(uint16_t);
+ memcpy(cap, tic->extras.buf, tic->extras.bufpos);
+ cap += tic->extras.bufpos;
+ }
+
+ return cap - *buf;
+}
+
+static int
+encode_string(const char *term, const char *cap, TBUF *tbuf, const char *str,
+ int flags)
+{
+ int slash, i, num;
+ char ch, *p, *s, last;
+
+ if (_ti_grow_tbuf(tbuf, strlen(str) + 1) == NULL)
+ return -1;
+ p = s = tbuf->buf + tbuf->bufpos;
+ slash = 0;
+ last = '\0';
+ /* Convert escape codes */
+ while ((ch = *str++) != '\0') {
+ if (slash == 0 && ch == '\\') {
+ slash = 1;
+ continue;
+ }
+ if (slash == 0) {
+ if (last != '%' && ch == '^') {
+ ch = *str++;
+ if (((unsigned char)ch) >= 128)
+ dowarn(flags,
+ "%s: %s: illegal ^ character",
+ term, cap);
+ if (ch == '\0')
+ break;
+ if (ch == '?')
+ ch = '\177';
+ else if ((ch &= 037) == 0)
+ ch = 128;
+ }
+ *p++ = ch;
+ last = ch;
+ continue;
+ }
+ slash = 0;
+ if (ch >= '0' && ch <= '7') {
+ num = ch - '0';
+ for (i = 0; i < 2; i++) {
+ if (*str < '0' || *str > '7') {
+ if (isdigit((unsigned char)*str))
+ dowarn(flags,
+ "%s: %s: non octal"
+ " digit", term, cap);
+ else
+ break;
+ }
+ num = num * 8 + *str++ - '0';
+ }
+ if (num == 0)
+ num = 0200;
+ *p++ = (char)num;
+ continue;
+ }
+ switch (ch) {
+ case 'a':
+ *p++ = '\a';
+ break;
+ case 'b':
+ *p++ = '\b';
+ break;
+ case 'e': /* FALLTHROUGH */
+ case 'E':
+ *p++ = '\033';
+ break;
+ case 'f':
+ *p++ = '\014';
+ break;
+ case 'l': /* FALLTHROUGH */
+ case 'n':
+ *p++ = '\n';
+ break;
+ case 'r':
+ *p++ = '\r';
+ break;
+ case 's':
+ *p++ = ' ';
+ break;
+ case 't':
+ *p++ = '\t';
+ break;
+ default:
+
+ /* We should warn here */
+ case '^':
+ case ',':
+ case ':':
+ case '|':
+ *p++ = ch;
+ break;
+ }
+ last = ch;
+ }
+ *p++ = '\0';
+ tbuf->bufpos += p - s;
+ return 0;
+}
+
+static char *
+get_token(char **cap)
+{
+ char *token;
+ int esc;
+
+ while (isspace((unsigned char)**cap))
+ (*cap)++;
+ if (**cap == '\0')
+ return NULL;
+
+ /* We can't use stresep(3) as ^ we need two escape chars */
+ esc = 0;
+ for (token = *cap;
+ **cap != '\0' && (esc == 1 || **cap != ',');
+ (*cap)++)
+ {
+ if (esc == 0) {
+ if (**cap == '\\' || **cap == '^')
+ esc = 1;
+ } else
+ esc = 0;
+ }
+
+ if (**cap != '\0')
+ *(*cap)++ = '\0';
+
+ return token;
+}
+
+TIC *
+_ti_compile(char *cap, int flags)
+{
+ char *token, *p, *e, *name, *desc, *alias;
+ signed char flag;
+ long num;
+ ssize_t ind;
+ size_t len;
+ TBUF buf;
+ TIC *tic;
+
+ _DIAGASSERT(cap != NULL);
+
+ name = get_token(&cap);
+ if (name == NULL) {
+ dowarn(flags, "no seperator found: %s", cap);
+ return NULL;
+ }
+ desc = strrchr(name, '|');
+ if (desc != NULL)
+ *desc++ = '\0';
+ alias = strchr(name, '|');
+ if (alias != NULL)
+ *alias++ = '\0';
+
+ tic = calloc(sizeof(*tic), 1);
+ if (tic == NULL)
+ return NULL;
+
+ buf.buf = NULL;
+ buf.buflen = 0;
+
+ tic->name = strdup(name);
+ if (tic->name == NULL)
+ goto error;
+ if (alias != NULL && flags & TIC_ALIAS) {
+ tic->alias = strdup(alias);
+ if (tic->alias == NULL)
+ goto error;
+ }
+ if (desc != NULL && flags & TIC_DESCRIPTION) {
+ tic->desc = strdup(desc);
+ if (tic->desc == NULL)
+ goto error;
+ }
+
+ for (token = get_token(&cap);
+ token != NULL && *token != '\0';
+ token = get_token(&cap))
+ {
+ /* Skip commented caps */
+ if (!(flags & TIC_COMMENT) && token[0] == '.')
+ continue;
+
+ /* Obsolete entries */
+ if (token[0] == 'O' && token[1] == 'T') {
+ if (!(flags & TIC_EXTRA))
+ continue;
+ token += 2;
+ }
+
+ /* str cap */
+ p = strchr(token, '=');
+ if (p != NULL) {
+ *p++ = '\0';
+ /* Don't use the string if we already have it */
+ ind = _ti_strindex(token);
+ if (ind != -1 &&
+ _ti_find_cap(&tic->strs, 's', ind) != NULL)
+ continue;
+
+ /* Encode the string to our scratch buffer */
+ buf.bufpos = 0;
+ if (encode_string(tic->name, token,
+ &buf, p, flags) == -1)
+ goto error;
+ if (buf.bufpos > UINT16_T_MAX) {
+ dowarn(flags, "%s: %s: string is too long",
+ tic->name, token);
+ continue;
+ }
+ if (!VALID_STRING(buf.buf)) {
+ dowarn(flags, "%s: %s: invalid string",
+ tic->name, token);
+ continue;
+ }
+
+ if (ind == -1)
+ _ti_store_extra(tic, 1, token, 's', -1, -2,
+ buf.buf, buf.bufpos, flags);
+ else {
+ if (!_ti_grow_tbuf(&tic->strs,
+ (sizeof(uint16_t) * 2) + buf.bufpos))
+ goto error;
+ le16enc(tic->strs.buf + tic->strs.bufpos, ind);
+ tic->strs.bufpos += sizeof(uint16_t);
+ le16enc(tic->strs.buf + tic->strs.bufpos,
+ buf.bufpos);
+ tic->strs.bufpos += sizeof(uint16_t);
+ memcpy(tic->strs.buf + tic->strs.bufpos,
+ buf.buf, buf.bufpos);
+ tic->strs.bufpos += buf.bufpos;
+ tic->strs.entries++;
+ }
+ continue;
+ }
+
+ /* num cap */
+ p = strchr(token, '#');
+ if (p != NULL) {
+ *p++ = '\0';
+ /* Don't use the number if we already have it */
+ ind = _ti_numindex(token);
+ if (ind != -1 &&
+ _ti_find_cap(&tic->nums, 'n', ind) != NULL)
+ continue;
+
+ num = strtol(p, &e, 0);
+ if (*e != '\0') {
+ dowarn(flags, "%s: %s: not a number",
+ tic->name, token);
+ continue;
+ }
+ if (!VALID_NUMERIC(num)) {
+ dowarn(flags, "%s: %s: number out of range",
+ tic->name, token);
+ continue;
+ }
+ if (ind == -1)
+ _ti_store_extra(tic, 1, token, 'n', -1,
+ num, NULL, 0, flags);
+ else {
+ if (_ti_grow_tbuf(&tic->nums,
+ sizeof(uint16_t) * 2) == NULL)
+ goto error;
+ le16enc(tic->nums.buf + tic->nums.bufpos, ind);
+ tic->nums.bufpos += sizeof(uint16_t);
+ le16enc(tic->nums.buf + tic->nums.bufpos, num);
+ tic->nums.bufpos += sizeof(uint16_t);
+ tic->nums.entries++;
+ }
+ continue;
+ }
+
+ flag = 1;
+ len = strlen(token) - 1;
+ if (token[len] == '@') {
+ flag = CANCELLED_BOOLEAN;
+ token[len] = '\0';
+ }
+ ind = _ti_flagindex(token);
+ if (ind == -1 && flag == CANCELLED_BOOLEAN) {
+ if ((ind = _ti_numindex(token)) != -1) {
+ if (_ti_find_cap(&tic->nums, 'n', ind) != NULL)
+ continue;
+ if (_ti_grow_tbuf(&tic->nums,
+ sizeof(uint16_t) * 2) == NULL)
+ goto error;
+ le16enc(tic->nums.buf + tic->nums.bufpos, ind);
+ tic->nums.bufpos += sizeof(uint16_t);
+ le16enc(tic->nums.buf + tic->nums.bufpos,
+ CANCELLED_NUMERIC);
+ tic->nums.bufpos += sizeof(uint16_t);
+ tic->nums.entries++;
+ continue;
+ } else if ((ind = _ti_strindex(token)) != -1) {
+ if (_ti_find_cap(&tic->strs, 's', ind) != NULL)
+ continue;
+ if (_ti_grow_tbuf(&tic->strs,
+ (sizeof(uint16_t) * 2) + 1) == NULL)
+ goto error;
+ le16enc(tic->strs.buf + tic->strs.bufpos, ind);
+ tic->strs.bufpos += sizeof(uint16_t);
+ le16enc(tic->strs.buf + tic->strs.bufpos, 0);
+ tic->strs.bufpos += sizeof(uint16_t);
+ tic->strs.entries++;
+ continue;
+ }
+ }
+ if (ind == -1)
+ _ti_store_extra(tic, 1, token, 'f', flag, 0, NULL, 0,
+ flags);
+ else if (_ti_find_cap(&tic->flags, 'f', ind) == NULL) {
+ if (_ti_grow_tbuf(&tic->flags, sizeof(uint16_t) + 1)
+ == NULL)
+ goto error;
+ le16enc(tic->flags.buf + tic->flags.bufpos, ind);
+ tic->flags.bufpos += sizeof(uint16_t);
+ tic->flags.buf[tic->flags.bufpos++] = flag;
+ tic->flags.entries++;
+ }
+ }
+
+ free(buf.buf);
+ return tic;
+
+error:
+ free(buf.buf);
+ _ti_freetic(tic);
+ return NULL;
+}
+
+void
+_ti_freetic(TIC *tic)
+{
+
+ if (tic != NULL) {
+ free(tic->name);
+ free(tic->alias);
+ free(tic->desc);
+ free(tic->flags.buf);
+ free(tic->nums.buf);
+ free(tic->strs.buf);
+ free(tic);
+ }
+}
diff --git a/lib/libterminfo/curterm.c b/lib/libterminfo/curterm.c
index 033d38a614c..53efb6c8208 100644
--- a/lib/libterminfo/curterm.c
+++ b/lib/libterminfo/curterm.c
@@ -1,4 +1,4 @@
-/* $NetBSD: curterm.c,v 1.3 2010/02/11 09:34:12 roy Exp $ */
+/* $NetBSD: curterm.c,v 1.4 2010/02/22 23:05:39 roy Exp $ */
/*
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: curterm.c,v 1.3 2010/02/11 09:34:12 roy Exp $");
+__RCSID("$NetBSD: curterm.c,v 1.4 2010/02/22 23:05:39 roy Exp $");
#include <assert.h>
#include <stdlib.h>
@@ -89,9 +89,7 @@ set_curterm(TERMINAL *nterm)
int
del_curterm(TERMINAL *oterm)
{
- if (oterm != NULL) {
- _ti_freeterm(oterm);
- free(oterm);
- }
+
+ _ti_freeterm(oterm);
return 0;
}
diff --git a/lib/libterminfo/term.c b/lib/libterminfo/term.c
index f8dd06583c1..f75121579b0 100644
--- a/lib/libterminfo/term.c
+++ b/lib/libterminfo/term.c
@@ -1,4 +1,4 @@
-/* $NetBSD: term.c,v 1.9 2010/02/12 12:18:33 roy Exp $ */
+/* $NetBSD: term.c,v 1.10 2010/02/22 23:05:39 roy Exp $ */
/*
* Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: term.c,v 1.9 2010/02/12 12:18:33 roy Exp $");
+__RCSID("$NetBSD: term.c,v 1.10 2010/02/22 23:05:39 roy Exp $");
#include <sys/stat.h>
@@ -286,23 +286,41 @@ static int
_ti_findterm(TERMINAL *term, const char *name, int flags)
{
int r;
- char *e, h[PATH_MAX];
+ char *c, *e, h[PATH_MAX];
+ TIC *tic;
+ uint8_t *f;
+ ssize_t len;
_DIAGASSERT(term != NULL);
_DIAGASSERT(name != NULL);
database[0] = '\0';
_ti_database = NULL;
+ r = 0;
- if ((e = getenv("TERMINFO")) != NULL) {
+ 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) {
+ len = _ti_flatten(&f, tic);
+ if (len != -1) {
+ r = _ti_readterm(term, (char *)f, len, flags);
+ free(f);
+ }
+ }
+ _ti_freetic(tic);
+ if (r == 1) {
+ _ti_database = "$TERMINFO";
+ return r;
+ }
}
if ((e = getenv("TERMINFO_DIRS")) != NULL)
return _ti_dbgettermp(term, e, name, flags);
- r = 0;
if ((e = getenv("HOME")) != NULL) {
snprintf(h, sizeof(h), "%s/.terminfo", e);
r = _ti_dbgetterm(term, h, name, flags);
@@ -323,7 +341,7 @@ _ti_getterm(TERMINAL *term, const char *name, int flags)
r = _ti_findterm(term, name, flags);
if (r == 1)
- return 1;
+ return r;
for (i = 0; i < __arraycount(compiled_terms); i++) {
t = &compiled_terms[i];
@@ -340,16 +358,11 @@ void
_ti_freeterm(TERMINAL *term)
{
- _DIAGASSERT(term != NULL);
-
- free(term->_area);
- term->_area = NULL;
- free(term->strs);
- term->strs = NULL;
- free(term->nums);
- term->nums = NULL;
- free(term->flags);
- term->flags = NULL;
- free(term->_userdefs);
- term->_userdefs = NULL;
+ if (term != NULL) {
+ free(term->_area);
+ free(term->strs);
+ free(term->nums);
+ free(term->flags);
+ free(term->_userdefs);
+ }
}
diff --git a/lib/libterminfo/term_private.h b/lib/libterminfo/term_private.h
index af3a37bf5e4..bd5277a9b59 100644
--- a/lib/libterminfo/term_private.h
+++ b/lib/libterminfo/term_private.h
@@ -1,4 +1,4 @@
-/* $NetBSD: term_private.h,v 1.5 2010/02/11 00:27:09 roy Exp $ */
+/* $NetBSD: term_private.h,v 1.6 2010/02/22 23:05:39 roy Exp $ */
/*
* Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -116,4 +116,38 @@ int _ti_getterm(TERMINAL *, const char *, int);
void _ti_setospeed(TERMINAL *);
void _ti_freeterm(TERMINAL *);
+/* libterminfo can compile terminfo strings too */
+#define TIC_WARNING (1 << 0)
+#define TIC_DESCRIPTION (1 << 1)
+#define TIC_ALIAS (1 << 2)
+#define TIC_COMMENT (1 << 3)
+#define TIC_EXTRA (1 << 4)
+
+#define UINT16_T_MAX 0xffff
+
+typedef struct tbuf {
+ char *buf;
+ size_t buflen;
+ size_t bufpos;
+ size_t entries;
+} TBUF;
+
+typedef struct tic {
+ char *name;
+ char *alias;
+ char *desc;
+ TBUF flags;
+ TBUF nums;
+ TBUF strs;
+ TBUF extras;
+} TIC;
+
+char *_ti_grow_tbuf(TBUF *, size_t);
+char *_ti_find_cap(TBUF *, char, short);
+char *_ti_find_extra(TBUF *, const char *);
+size_t _ti_store_extra(TIC *, int, char *, char, char, short,
+ char *, size_t, int);
+TIC *_ti_compile(char *, int);
+ssize_t _ti_flatten(uint8_t **, const TIC *);
+void _ti_freetic(TIC *);
#endif
diff --git a/lib/libterminfo/terminfo.5.in b/lib/libterminfo/terminfo.5.in
index c9bee44518e..cffa51e0222 100644
--- a/lib/libterminfo/terminfo.5.in
+++ b/lib/libterminfo/terminfo.5.in
@@ -1,4 +1,4 @@
-.\" $NetBSD: terminfo.5.in,v 1.11 2010/02/12 10:18:56 roy Exp $
+.\" $NetBSD: terminfo.5.in,v 1.12 2010/02/22 23:05:39 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 12, 2010
+.Dd February 22, 2010
.Dt TERMINFO 5
.Os
.Sh NAME
@@ -203,7 +203,14 @@ is appended to each file checked.
.Pp
If the environment variable
.Ev TERMINFO
-is available then only this file is searched.
+is available, does not begin with /, can be compiled with the above rules and
+whose 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.
Otherwise
.Nm
will first look for