Import infocmp from NetBSD

Convert the content of the terminfo database into human-readable
form, the same as used by the tic(1) command already present.
This commit is contained in:
Antoine Leca 2013-01-25 11:19:17 +00:00 committed by Lionel Sambuc
parent 1999c518b6
commit 5139afee6b
6 changed files with 940 additions and 1 deletions

View file

@ -253,6 +253,7 @@
./usr/bin/ifconfig minix-sys
./usr/bin/ifdef minix-sys
./usr/bin/indent minix-sys
./usr/bin/infocmp minix-sys
./usr/bin/in.fingerd minix-sys
./usr/bin/in.rshd minix-sys
./usr/bin/install minix-sys
@ -1222,6 +1223,7 @@
./usr/man/man1/if.1 minix-sys
./usr/man/man1/ifdef.1 minix-sys
./usr/man/man1/indent.1 minix-sys
./usr/man/man1/infocmp.1 minix-sys
./usr/man/man1/install.1 minix-sys
./usr/man/man1/isodir.1 minix-sys
./usr/man/man1/isoinfo.1 minix-sys

View file

@ -121,6 +121,7 @@
2012/10/17 12:00:00,usr.bin/genassym
2012/10/17 12:00:00,usr.bin/gzip
2012/10/17 12:00:00,usr.bin/indent
2012/10/17 12:00:00,usr.bin/infocmp
2012/10/17 12:00:00,usr.bin/join
2011/01/17 18:11:10,usr.bin/ldd
2012/02/10 16:16:12,usr.bin/login

View file

@ -12,7 +12,7 @@ SUBDIR= \
\
\
genassym \
indent join \
indent infocmp join \
ldd \
login lorder m4 \
make man \

10
usr.bin/infocmp/Makefile Normal file
View file

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.1 2010/02/03 15:16:33 roy Exp $
PROG= infocmp
WARNS= 4
CPPFLAGS+= -I${.CURDIR}/../../lib/libterminfo
LDADD+= -lterminfo
DPADD+= ${LIBTERMINFO}
.include <bsd.prog.mk>

131
usr.bin/infocmp/infocmp.1 Normal file
View file

@ -0,0 +1,131 @@
.\" $NetBSD: infocmp.1,v 1.5 2011/01/14 14:21:36 wiz Exp $
.\"
.\" Copyright (c) 2009 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``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 FOUNDATION OR CONTRIBUTORS
.\" 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.
.\"
.Dd February 5, 2010
.Dt INFOCMP 1
.Os
.Sh NAME
.Nm infocmp
.Nd compare or print compiled terminfo descriptions
.Sh SYNOPSIS
.Nm infocmp
.Op Fl 1acnqux
.Op Fl A Ar database
.Op Fl B Ar database
.Op Fl w Ar cols
.Op Ar term ...
.Sh DESCRIPTION
The
.Nm
reconstructs the first available
.Xr terminfo 5
definition found for
.Ar term
and prints the result in a
.Xr terminfo 5
format.
Capability types are grouped together and new types start new lines,
first flags, then numbers, then strings.
Capabilities are sorted by their name.
If a second
.Ar term
is given then the capabilities are compared against each other.
.Pp
The following options are available:
.Bl -tag -width Ev
.It Fl 1
Print one capability per line.
.It Fl A Ar database
Use this database to load the first terminal definition.
.It Fl B Ar database
Use this database to load subsequent terminal definitions.
.It Fl a
Include commented out capabilities.
This only works if the database was compiled with the
.Fl a
flag passed to
.Xr tic 1 .
This also sets the
.Fl x
flag as
.Nm
retains commented out capabilities as non standard.
.It Fl c
Print capabilities common to each definition.
.It Fl n
Print capabilities that do not exist in either definition.
.It Fl q
Make the comparison listing shorter by omitting subheadings and using
- for absent capabilities, @ for canceled capabilities rather than
.Dv NULL .
.It Fl u
Build a new terminal description for the first terminal description,
using subsequent terminal descriptions.
This also sets the
.Fl a
flag.
.It Fl w Ar cols
Limit the width to
.Ar cols .
.It Fl x
Include non-standard capabilities.
More
.Fl x
only handles non-standard capabilities.
This only works if the database was compiled with the
.Fl x
flag passed to
.Xr tic 1 .
.El
.Sh ENVIRONMENT
.Bl -tag -width Ev
.It Ev COLUMNS
Override columns returned by the output terminal.
.Fl w
.Ar cols
supersedes this.
.It Ev TERM
.Nm
uses the contents of the
.Ev TERM
environment variable if no terminal name is given on the command line.
.El
.Sh EXIT STATUS
.Ex -std infocmp
.Sh SEE ALSO
.Xr tic 1 ,
.Xr terminfo 5
.Sh STANDARDS
The
.Nm
utility outputs information that conforms to the
.St -xcurses4.2
standard.
.Sh AUTHORS
.An Roy Marples Aq roy@NetBSD.org

795
usr.bin/infocmp/infocmp.c Normal file
View file

@ -0,0 +1,795 @@
/* $NetBSD: infocmp.c,v 1.7 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.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: infocmp.c,v 1.7 2010/02/22 23:05:39 roy Exp $");
#include <sys/ioctl.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <term_private.h>
#include <term.h>
#include <unistd.h>
/* Specifically needed on MINIX, as struct winsize in not defined elsewhere */
#include <minix/termios.h>
#define SW 8
typedef struct tient {
char type;
const char *id;
signed char flag;
short num;
const char *str;
} TIENT;
static size_t cols;
static int aflag, cflag, nflag, qflag, xflag;
static size_t
outstr(FILE *f, const char *str)
{
unsigned char ch;
size_t r, l;
r = 0;
l = strlen(str);
while ((ch = (unsigned char)(*str++)) != '\0') {
switch (ch) {
case 128:
ch = '0';
break;
case '\033':
ch = 'E';
break;
case '\014':
ch = 'f';
break;
case '^': /* FALLTHROUGH */
case ',': /* escape these */
break;
case ' ':
ch = 's';
break;
default:
if (ch == '\177') {
if (f != NULL)
fputc('^', f);
ch = '?';
r++;
} else if (iscntrl(ch) &&
ch < 128 &&
ch != '\\' &&
(l < 4 || isdigit((unsigned char)*str)))
{
if (f != NULL)
fputc('^', f);
ch += '@';
r++;
} else if (!isprint(ch)) {
if (f != NULL)
fprintf(f, "\\%03o", ch);
r += 4;
continue;
}
goto prnt;
}
if (f != NULL)
fputc('\\', f);
r++;
prnt:
if (f != NULL)
fputc(ch, f);
r++;
}
return r;
}
static int
ent_compare(const void *a, const void *b)
{
const TIENT *ta, *tb;
ta = (const TIENT *)a;
tb = (const TIENT *)b;
return strcmp(ta->id, tb->id);
}
static void
setdb(char *db)
{
size_t len;
len = strlen(db);
if (len > 3 &&
db[len - 3] == '.' &&
db[len - 2] == 'd' &&
db[len - 1] == 'b')
db[len - 3] = '\0';
setenv("TERMINFO", db, 1);
}
static void
print_ent(const TIENT *ents, size_t nents)
{
size_t col, i, l;
char nbuf[64];
if (nents == 0)
return;
col = SW;
printf("\t");
for (i = 0; i < nents; i++) {
if (*ents[i].id == '.' && aflag == 0)
continue;
switch (ents[i].type) {
case 'f':
if (ents[i].flag == ABSENT_BOOLEAN)
continue;
l = strlen(ents[i].id) + 2;
if (ents[i].flag == CANCELLED_BOOLEAN)
l++;
break;
case 'n':
if (ents[i].num == ABSENT_NUMERIC)
continue;
if (VALID_NUMERIC(ents[i].num))
l = snprintf(nbuf, sizeof(nbuf), "%s#%d,",
ents[i].id, ents[i].num);
else
l = snprintf(nbuf, sizeof(nbuf), "%s@,",
ents[i].id);
break;
case 's':
if (ents[i].str == ABSENT_STRING)
continue;
if (VALID_STRING(ents[i].str))
l = strlen(ents[i].id) +
outstr(NULL, ents[i].str) + 7;
else
l = strlen(ents[i].id) + 3;
break;
default:
errx(1, "invalid type");
}
if (col != SW) {
if (col + l > cols) {
printf("\n\t");
col = SW;
} else
col += printf(" ");
}
switch (ents[i].type) {
case 'f':
col += printf("%s", ents[i].id);
if (ents[i].flag == ABSENT_BOOLEAN ||
ents[i].flag == CANCELLED_BOOLEAN)
col += printf("@");
col += printf(",");
break;
case 'n':
col += printf("%s", nbuf);
break;
case 's':
col += printf("%s", ents[i].id);
if (VALID_STRING(ents[i].str)) {
col += printf("=");
col += outstr(stdout, ents[i].str);
} else
col += printf("@");
col += printf(",");
break;
}
}
printf("\n");
}
static size_t
load_ents(TIENT *ents, TERMINAL *t, char type)
{
size_t i, n, max;
TERMUSERDEF *ud;
switch (type) {
case 'f':
max = TIFLAGMAX;
break;
case 'n':
max = TINUMMAX;
break;
default:
max = TISTRMAX;
}
n = 0;
for (i = 0; i <= max; i++) {
switch (type) {
case 'f':
if (t->flags[i] == 1 ||
(aflag && t->flags[i] == CANCELLED_BOOLEAN))
{
ents[n].id = _ti_flagid(i);
ents[n].type = 'f';
ents[n++].flag = t->flags[i];
}
break;
case 'n':
if (VALID_NUMERIC(t->nums[i]) ||
(aflag && t->nums[i] == CANCELLED_NUMERIC))
{
ents[n].id = _ti_numid(i);
ents[n].type = 'n';
ents[n++].num = t->nums[i];
}
break;
default:
if (VALID_STRING(t->strs[i]) ||
(aflag && t->strs[i] == CANCELLED_STRING))
{
ents[n].id = _ti_strid(i);
ents[n].type = 's';
ents[n++].str = t->strs[i];
}
break;
}
}
if (xflag != 0 && t->_nuserdefs != 0) {
for (i = 0; i < t->_nuserdefs; i++) {
ud = &t->_userdefs[i];
if (ud->type == type) {
switch (type) {
case 'f':
if (!aflag &&
!VALID_BOOLEAN(ud->flag))
continue;
break;
case 'n':
if (!aflag &&
!VALID_NUMERIC(ud->num))
continue;
break;
case 's':
if (!aflag &&
!VALID_STRING(ud->str))
continue;
break;
}
ents[n].id = ud->id;
ents[n].type = ud->type;
ents[n].flag = ud->flag;
ents[n].num = ud->num;
ents[n++].str = ud->str;
}
}
}
qsort(ents, n, sizeof(TIENT), ent_compare);
return n;
}
static void
cprint_ent(TIENT *ent)
{
if (ent == NULL) {
if (qflag == 0)
printf("NULL");
else
printf("-");
}
switch (ent->type) {
case 'f':
if (VALID_BOOLEAN(ent->flag))
printf(ent->flag == 1 ? "T" : "F");
else if (qflag == 0)
printf("F");
else if (ent->flag == CANCELLED_BOOLEAN)
printf("@");
else
printf("-");
break;
case 'n':
if (VALID_NUMERIC(ent->num))
printf("%d", ent->num);
else if (qflag == 0)
printf("NULL");
else if (ent->num == CANCELLED_NUMERIC)
printf("@");
else
printf("-");
break;
case 's':
if (VALID_STRING(ent->str)) {
printf("'");
outstr(stdout, ent->str);
printf("'");
} else if (qflag == 0)
printf("NULL");
else if (ent->str == CANCELLED_STRING)
printf("@");
else
printf("-");
break;
}
}
static void
compare_ents(TIENT *ents1, size_t n1, TIENT *ents2, size_t n2)
{
size_t i1, i2;
TIENT *e1, *e2, ee;
int c;
i1 = i2 = 0;
ee.type = 'f';
ee.flag = ABSENT_BOOLEAN;
ee.num = ABSENT_NUMERIC;
ee.str = ABSENT_STRING;
while (i1 != n1 || i2 != n2) {
if (i1 == n1)
c = 1;
else if (i2 == n2)
c = -1;
else
c = strcmp(ents1[i1].id, ents2[i2].id);
if (c == 0) {
e1 = &ents1[i1++];
e2 = &ents2[i2++];
} else if (c < 0) {
e1 = &ents1[i1++];
e2 = &ee;
ee.id = e1->id;
ee.type = e1->type;
} else {
e1 = &ee;
e2 = &ents2[i2++];
ee.id = e2->id;
ee.type = e2->type;
}
switch (e1->type) {
case 'f':
if (cflag != 0) {
if (e1->flag == e2->flag)
printf("\t%s\n", ents1[i1].id);
continue;
}
if (e1->flag == e2->flag)
continue;
break;
case 'n':
if (cflag != 0) {
if (e1->num == e2->num)
printf("\t%s#%d\n",
ents1[i1].id, ents1[i1].num);
continue;
}
if (e1->num == e2->num)
continue;
break;
case 's':
if (cflag != 0) {
if (VALID_STRING(e1->str) &&
VALID_STRING(e2->str) &&
strcmp(e1->str, e2->str) == 0) {
printf("\t%s=", ents1[i1].id);
outstr(stdout, ents1[i1].str);
printf("\n");
}
continue;
}
if (VALID_STRING(e1->str) &&
VALID_STRING(e2->str) &&
strcmp(e1->str, e2->str) == 0)
continue;
break;
}
printf("\t%s: ", e1->id);
cprint_ent(e1);
if (e1->type == 'f')
printf(":");
else
printf(", ");
cprint_ent(e2);
printf(".\n");
}
}
static TERMINAL *
load_term(const char *name)
{
TERMINAL *t;
t = calloc(1, sizeof(*t));
if (t == NULL)
err(1, "calloc");
if (name == NULL)
name = getenv("TERM");
if (name == NULL)
name = "dumb";
if (_ti_getterm(t, name, 1) == 1)
return t;
if (_ti_database == NULL)
errx(1, "no terminal definition found in internal database");
else
errx(1, "no terminal definition found in %s.db", _ti_database);
}
static void
show_missing(TERMINAL *t1, TERMINAL *t2, char type)
{
ssize_t i, max;
const char *id;
switch (type) {
case 'f':
max = TIFLAGMAX;
break;
case 'n':
max = TINUMMAX;
break;
default:
max = TISTRMAX;
}
for (i = 0; i <= max; i++) {
switch (type) {
case 'f':
if (t1->flags[i] != ABSENT_BOOLEAN ||
t2->flags[i] != ABSENT_BOOLEAN)
continue;
id = _ti_flagid(i);
break;
case 'n':
if (t1->nums[i] != ABSENT_NUMERIC ||
t2->nums[i] != ABSENT_NUMERIC)
continue;
id = _ti_numid(i);
break;
default:
if (t1->strs[i] != ABSENT_STRING ||
t2->strs[i] != ABSENT_STRING)
continue;
id = _ti_strid(i);
break;
}
printf("\t!%s.\n", id);
}
}
static TERMUSERDEF *
find_userdef(TERMINAL *term, const char *id)
{
size_t i;
for (i = 0; i < term->_nuserdefs; i++)
if (strcmp(term->_userdefs[i].id, id) == 0)
return &term->_userdefs[i];
return NULL;
}
static void
use_terms(TERMINAL *term, size_t nuse, char **uterms)
{
TERMINAL **terms;
TERMUSERDEF *ud, *tud;
size_t i, j, agree, absent, data;
terms = malloc(sizeof(**terms) * nuse);
if (terms == NULL)
err(1, "malloc");
for (i = 0; i < nuse; i++) {
if (strcmp(term->name, *uterms) == 0)
errx(1, "cannot use same terminal");
for (j = 0; j < i; j++)
if (strcmp(terms[j]->name, *uterms) == 0)
errx(1, "cannot use same terminal");
terms[i] = load_term(*uterms++);
}
for (i = 0; i < TIFLAGMAX + 1; i++) {
agree = absent = data = 0;
for (j = 0; j < nuse; j++) {
if (terms[j]->flags[i] == ABSENT_BOOLEAN ||
terms[j]->flags[i] == CANCELLED_BOOLEAN)
absent++;
else {
data++;
if (term->flags[i] == terms[j]->flags[i])
agree++;
}
}
if (data == 0)
continue;
if (agree > 0 && agree + absent == nuse)
term->flags[i] = ABSENT_BOOLEAN;
else if (term->flags[i] == ABSENT_BOOLEAN)
term->flags[i] = CANCELLED_BOOLEAN;
}
for (i = 0; i < TINUMMAX + 1; i++) {
agree = absent = data = 0;
for (j = 0; j < nuse; j++) {
if (terms[j]->nums[i] == ABSENT_NUMERIC ||
terms[j]->nums[i] == CANCELLED_NUMERIC)
absent++;
else {
data++;
if (term->nums[i] == terms[j]->nums[i])
agree++;
}
}
if (data == 0)
continue;
if (agree > 0 && agree + absent == nuse)
term->nums[i] = ABSENT_NUMERIC;
else if (term->nums[i] == ABSENT_NUMERIC)
term->nums[i] = CANCELLED_NUMERIC;
}
for (i = 0; i < TISTRMAX + 1; i++) {
agree = absent = data = 0;
for (j = 0; j < nuse; j++) {
if (terms[j]->strs[i] == ABSENT_STRING ||
terms[j]->strs[i] == CANCELLED_STRING)
absent++;
else {
data++;
if (VALID_STRING(term->strs[i]) &&
strcmp(term->strs[i],
terms[j]->strs[i]) == 0)
agree++;
}
}
if (data == 0)
continue;
if (agree > 0 && agree + absent == nuse)
term->strs[i] = ABSENT_STRING;
else if (term->strs[i] == ABSENT_STRING)
term->strs[i] = CANCELLED_STRING;
}
/* User defined caps are more tricky.
First we set any to absent that agree. */
for (i = 0; i < term->_nuserdefs; i++) {
agree = absent = data = 0;
ud = &term->_userdefs[i];
for (j = 0; j < nuse; j++) {
tud = find_userdef(terms[j], ud->id);
if (tud == NULL)
absent++;
else {
data++;
switch (ud->type) {
case 'f':
if (tud->type == 'f' &&
tud->flag == ud->flag)
agree++;
break;
case 'n':
if (tud->type == 'n' &&
tud->num == ud->num)
agree++;
break;
case 's':
if (tud->type == 's' &&
VALID_STRING(tud->str) &&
VALID_STRING(ud->str) &&
strcmp(ud->str, tud->str) == 0)
agree++;
break;
}
}
}
if (data == 0)
continue;
if (agree > 0 && agree + absent == nuse) {
ud->flag = ABSENT_BOOLEAN;
ud->num = ABSENT_NUMERIC;
ud->str = ABSENT_STRING;
}
}
/* Now add any that we don't have as cancelled */
for (i = 0; i < nuse; i++) {
for (j = 0; j < terms[i]->_nuserdefs; j++) {
ud = find_userdef(term, terms[i]->_userdefs[j].id);
if (ud != NULL)
continue; /* We have handled this */
term->_userdefs = realloc(term->_userdefs,
sizeof(*term->_userdefs) * (term->_nuserdefs + 1));
if (term->_userdefs == NULL)
err(1, "malloc");
tud = &term->_userdefs[term->_nuserdefs++];
tud->id = terms[i]->_userdefs[j].id;
tud->type = terms[i]->_userdefs[j].flag;
tud->flag = CANCELLED_BOOLEAN;
tud->num = CANCELLED_NUMERIC;
tud->str = CANCELLED_STRING;
}
}
}
int
main(int argc, char **argv)
{
char *term, *Barg;
int ch, uflag;
TERMINAL *t, *t2;
size_t n, n2;
struct winsize ws;
TIENT ents[TISTRMAX + 1], ents2[TISTRMAX + 1];
cols = 80; /* default */
term = getenv("COLUMNS");
if (term != NULL)
cols = strtoul(term, NULL, 10);
else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0)
cols = ws.ws_col;
uflag = xflag = 0;
Barg = NULL;
while ((ch = getopt(argc, argv, "1A:B:acnquw:x")) != -1)
switch (ch) {
case '1':
cols = 1;
break;
case 'A':
setdb(optarg);
break;
case 'B':
Barg = optarg;
break;
case 'a':
aflag = 1;
break;
case 'c':
cflag = 1;
break;
case 'n':
nflag = 1;
break;
case 'q':
qflag = 1;
break;
case 'u':
uflag = 1;
aflag = 1;
break;
case 'w':
cols = strtoul(optarg, NULL, 10);
break;
case 'x':
xflag = 1;
break;
case '?':
default:
fprintf(stderr,
"usage: %s [-1acnqux] [-A database] [-B database] "
"[-w cols] [term]\n",
getprogname());
return EXIT_FAILURE;
}
cols--;
if (optind + 1 < argc)
aflag = 1;
if (optind < argc)
term = argv[optind++];
else
term = NULL;
t = load_term(term);
if (uflag != 0)
use_terms(t, argc - optind, argv + optind);
if ((optind + 1 != argc && nflag == 0) || uflag != 0) {
if (uflag == 0) {
printf("# Reconstructed from ");
if (_ti_database == NULL)
printf("internal database\n");
else
printf("%s%s\n", _ti_database,
*_ti_database == '/' ? ".db" : "");
}
printf("%s", t->name);
if (t->_alias != NULL && *t->_alias != '\0')
printf("|%s", t->_alias);
if (t->desc != NULL && *t->desc != '\0')
printf("|%s", t->desc);
printf(",\n");
n = load_ents(ents, t, 'f');
print_ent(ents, n);
n = load_ents(ents, t, 'n');
print_ent(ents, n);
n = load_ents(ents, t, 's');
print_ent(ents, n);
if (uflag != 0) {
printf("\t");
n = SW;
for (; optind < argc; optind++) {
n2 = 5 + strlen(argv[optind]);
if (n != SW) {
if (n + n2 > cols) {
printf("\n\t");
n = SW;
} else
n += printf(" ");
}
n += printf("use=%s,", argv[optind]);
}
printf("\n");
}
return EXIT_SUCCESS;
}
if (Barg == NULL)
unsetenv("TERMINFO");
else
setdb(Barg);
t2 = load_term(argv[optind++]);
printf("comparing %s to %s.\n", t->name, t2->name);
if (qflag == 0)
printf(" comparing booleans.\n");
if (nflag == 0) {
n = load_ents(ents, t, 'f');
n2 = load_ents(ents2, t2, 'f');
compare_ents(ents, n, ents2, n2);
} else
show_missing(t, t2, 'f');
if (qflag == 0)
printf(" comparing numbers.\n");
if (nflag == 0) {
n = load_ents(ents, t, 'n');
n2 = load_ents(ents2, t2, 'n');
compare_ents(ents, n, ents2, n2);
} else
show_missing(t, t2, 'n');
if (qflag == 0)
printf(" comparing strings.\n");
if (nflag == 0) {
n = load_ents(ents, t, 's');
n2 = load_ents(ents2, t2, 's');
compare_ents(ents, n, ents2, n2);
} else
show_missing(t, t2, 's');
return EXIT_SUCCESS;
}