1*84d9c625SLionel Sambuc /* $NetBSD: infocmp.c,v 1.8 2013/10/01 09:01:49 roy Exp $ */
25139afeeSAntoine Leca
35139afeeSAntoine Leca /*
45139afeeSAntoine Leca * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
55139afeeSAntoine Leca *
65139afeeSAntoine Leca * This code is derived from software contributed to The NetBSD Foundation
75139afeeSAntoine Leca * by Roy Marples.
85139afeeSAntoine Leca *
95139afeeSAntoine Leca * Redistribution and use in source and binary forms, with or without
105139afeeSAntoine Leca * modification, are permitted provided that the following conditions
115139afeeSAntoine Leca * are met:
125139afeeSAntoine Leca * 1. Redistributions of source code must retain the above copyright
135139afeeSAntoine Leca * notice, this list of conditions and the following disclaimer.
145139afeeSAntoine Leca * 2. Redistributions in binary form must reproduce the above copyright
155139afeeSAntoine Leca * notice, this list of conditions and the following disclaimer in the
165139afeeSAntoine Leca * documentation and/or other materials provided with the distribution.
175139afeeSAntoine Leca *
185139afeeSAntoine Leca * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
195139afeeSAntoine Leca * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
205139afeeSAntoine Leca * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
215139afeeSAntoine Leca * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
225139afeeSAntoine Leca * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
235139afeeSAntoine Leca * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
245139afeeSAntoine Leca * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
255139afeeSAntoine Leca * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
265139afeeSAntoine Leca * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
275139afeeSAntoine Leca * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285139afeeSAntoine Leca */
295139afeeSAntoine Leca
305139afeeSAntoine Leca #include <sys/cdefs.h>
31*84d9c625SLionel Sambuc __RCSID("$NetBSD: infocmp.c,v 1.8 2013/10/01 09:01:49 roy Exp $");
325139afeeSAntoine Leca
335139afeeSAntoine Leca #include <sys/ioctl.h>
345139afeeSAntoine Leca
355139afeeSAntoine Leca #include <ctype.h>
365139afeeSAntoine Leca #include <err.h>
375139afeeSAntoine Leca #include <stdio.h>
385139afeeSAntoine Leca #include <stdlib.h>
395139afeeSAntoine Leca #include <string.h>
405139afeeSAntoine Leca #include <term_private.h>
415139afeeSAntoine Leca #include <term.h>
425139afeeSAntoine Leca #include <unistd.h>
435139afeeSAntoine Leca
445139afeeSAntoine Leca #define SW 8
455139afeeSAntoine Leca
465139afeeSAntoine Leca typedef struct tient {
475139afeeSAntoine Leca char type;
485139afeeSAntoine Leca const char *id;
495139afeeSAntoine Leca signed char flag;
505139afeeSAntoine Leca short num;
515139afeeSAntoine Leca const char *str;
525139afeeSAntoine Leca } TIENT;
535139afeeSAntoine Leca
545139afeeSAntoine Leca static size_t cols;
555139afeeSAntoine Leca static int aflag, cflag, nflag, qflag, xflag;
565139afeeSAntoine Leca
575139afeeSAntoine Leca static size_t
outstr(FILE * f,const char * str)585139afeeSAntoine Leca outstr(FILE *f, const char *str)
595139afeeSAntoine Leca {
605139afeeSAntoine Leca unsigned char ch;
615139afeeSAntoine Leca size_t r, l;
625139afeeSAntoine Leca
635139afeeSAntoine Leca r = 0;
645139afeeSAntoine Leca l = strlen(str);
655139afeeSAntoine Leca while ((ch = (unsigned char)(*str++)) != '\0') {
665139afeeSAntoine Leca switch (ch) {
675139afeeSAntoine Leca case 128:
685139afeeSAntoine Leca ch = '0';
695139afeeSAntoine Leca break;
705139afeeSAntoine Leca case '\033':
715139afeeSAntoine Leca ch = 'E';
725139afeeSAntoine Leca break;
735139afeeSAntoine Leca case '\014':
745139afeeSAntoine Leca ch = 'f';
755139afeeSAntoine Leca break;
765139afeeSAntoine Leca case '^': /* FALLTHROUGH */
775139afeeSAntoine Leca case ',': /* escape these */
785139afeeSAntoine Leca break;
795139afeeSAntoine Leca case ' ':
805139afeeSAntoine Leca ch = 's';
815139afeeSAntoine Leca break;
825139afeeSAntoine Leca default:
835139afeeSAntoine Leca if (ch == '\177') {
845139afeeSAntoine Leca if (f != NULL)
855139afeeSAntoine Leca fputc('^', f);
865139afeeSAntoine Leca ch = '?';
875139afeeSAntoine Leca r++;
885139afeeSAntoine Leca } else if (iscntrl(ch) &&
895139afeeSAntoine Leca ch < 128 &&
905139afeeSAntoine Leca ch != '\\' &&
915139afeeSAntoine Leca (l < 4 || isdigit((unsigned char)*str)))
925139afeeSAntoine Leca {
935139afeeSAntoine Leca if (f != NULL)
945139afeeSAntoine Leca fputc('^', f);
955139afeeSAntoine Leca ch += '@';
965139afeeSAntoine Leca r++;
975139afeeSAntoine Leca } else if (!isprint(ch)) {
985139afeeSAntoine Leca if (f != NULL)
995139afeeSAntoine Leca fprintf(f, "\\%03o", ch);
1005139afeeSAntoine Leca r += 4;
1015139afeeSAntoine Leca continue;
1025139afeeSAntoine Leca }
1035139afeeSAntoine Leca goto prnt;
1045139afeeSAntoine Leca }
1055139afeeSAntoine Leca
1065139afeeSAntoine Leca if (f != NULL)
1075139afeeSAntoine Leca fputc('\\', f);
1085139afeeSAntoine Leca r++;
1095139afeeSAntoine Leca prnt:
1105139afeeSAntoine Leca if (f != NULL)
1115139afeeSAntoine Leca fputc(ch, f);
1125139afeeSAntoine Leca r++;
1135139afeeSAntoine Leca }
1145139afeeSAntoine Leca return r;
1155139afeeSAntoine Leca }
1165139afeeSAntoine Leca
1175139afeeSAntoine Leca static int
ent_compare(const void * a,const void * b)1185139afeeSAntoine Leca ent_compare(const void *a, const void *b)
1195139afeeSAntoine Leca {
1205139afeeSAntoine Leca const TIENT *ta, *tb;
1215139afeeSAntoine Leca
1225139afeeSAntoine Leca ta = (const TIENT *)a;
1235139afeeSAntoine Leca tb = (const TIENT *)b;
1245139afeeSAntoine Leca return strcmp(ta->id, tb->id);
1255139afeeSAntoine Leca }
1265139afeeSAntoine Leca
1275139afeeSAntoine Leca static void
setdb(char * db)1285139afeeSAntoine Leca setdb(char *db)
1295139afeeSAntoine Leca {
1305139afeeSAntoine Leca size_t len;
1315139afeeSAntoine Leca
1325139afeeSAntoine Leca len = strlen(db);
1335139afeeSAntoine Leca if (len > 3 &&
1345139afeeSAntoine Leca db[len - 3] == '.' &&
1355139afeeSAntoine Leca db[len - 2] == 'd' &&
1365139afeeSAntoine Leca db[len - 1] == 'b')
1375139afeeSAntoine Leca db[len - 3] = '\0';
1385139afeeSAntoine Leca setenv("TERMINFO", db, 1);
1395139afeeSAntoine Leca }
1405139afeeSAntoine Leca
1415139afeeSAntoine Leca static void
print_ent(const TIENT * ents,size_t nents)1425139afeeSAntoine Leca print_ent(const TIENT *ents, size_t nents)
1435139afeeSAntoine Leca {
1445139afeeSAntoine Leca size_t col, i, l;
1455139afeeSAntoine Leca char nbuf[64];
1465139afeeSAntoine Leca
1475139afeeSAntoine Leca if (nents == 0)
1485139afeeSAntoine Leca return;
1495139afeeSAntoine Leca
1505139afeeSAntoine Leca col = SW;
1515139afeeSAntoine Leca printf("\t");
1525139afeeSAntoine Leca for (i = 0; i < nents; i++) {
1535139afeeSAntoine Leca if (*ents[i].id == '.' && aflag == 0)
1545139afeeSAntoine Leca continue;
1555139afeeSAntoine Leca switch (ents[i].type) {
1565139afeeSAntoine Leca case 'f':
1575139afeeSAntoine Leca if (ents[i].flag == ABSENT_BOOLEAN)
1585139afeeSAntoine Leca continue;
1595139afeeSAntoine Leca l = strlen(ents[i].id) + 2;
1605139afeeSAntoine Leca if (ents[i].flag == CANCELLED_BOOLEAN)
1615139afeeSAntoine Leca l++;
1625139afeeSAntoine Leca break;
1635139afeeSAntoine Leca case 'n':
1645139afeeSAntoine Leca if (ents[i].num == ABSENT_NUMERIC)
1655139afeeSAntoine Leca continue;
1665139afeeSAntoine Leca if (VALID_NUMERIC(ents[i].num))
1675139afeeSAntoine Leca l = snprintf(nbuf, sizeof(nbuf), "%s#%d,",
1685139afeeSAntoine Leca ents[i].id, ents[i].num);
1695139afeeSAntoine Leca else
1705139afeeSAntoine Leca l = snprintf(nbuf, sizeof(nbuf), "%s@,",
1715139afeeSAntoine Leca ents[i].id);
1725139afeeSAntoine Leca break;
1735139afeeSAntoine Leca case 's':
1745139afeeSAntoine Leca if (ents[i].str == ABSENT_STRING)
1755139afeeSAntoine Leca continue;
1765139afeeSAntoine Leca if (VALID_STRING(ents[i].str))
1775139afeeSAntoine Leca l = strlen(ents[i].id) +
1785139afeeSAntoine Leca outstr(NULL, ents[i].str) + 7;
1795139afeeSAntoine Leca else
1805139afeeSAntoine Leca l = strlen(ents[i].id) + 3;
1815139afeeSAntoine Leca break;
1825139afeeSAntoine Leca default:
1835139afeeSAntoine Leca errx(1, "invalid type");
1845139afeeSAntoine Leca }
1855139afeeSAntoine Leca if (col != SW) {
1865139afeeSAntoine Leca if (col + l > cols) {
1875139afeeSAntoine Leca printf("\n\t");
1885139afeeSAntoine Leca col = SW;
1895139afeeSAntoine Leca } else
1905139afeeSAntoine Leca col += printf(" ");
1915139afeeSAntoine Leca }
1925139afeeSAntoine Leca switch (ents[i].type) {
1935139afeeSAntoine Leca case 'f':
1945139afeeSAntoine Leca col += printf("%s", ents[i].id);
1955139afeeSAntoine Leca if (ents[i].flag == ABSENT_BOOLEAN ||
1965139afeeSAntoine Leca ents[i].flag == CANCELLED_BOOLEAN)
1975139afeeSAntoine Leca col += printf("@");
1985139afeeSAntoine Leca col += printf(",");
1995139afeeSAntoine Leca break;
2005139afeeSAntoine Leca case 'n':
2015139afeeSAntoine Leca col += printf("%s", nbuf);
2025139afeeSAntoine Leca break;
2035139afeeSAntoine Leca case 's':
2045139afeeSAntoine Leca col += printf("%s", ents[i].id);
2055139afeeSAntoine Leca if (VALID_STRING(ents[i].str)) {
2065139afeeSAntoine Leca col += printf("=");
2075139afeeSAntoine Leca col += outstr(stdout, ents[i].str);
2085139afeeSAntoine Leca } else
2095139afeeSAntoine Leca col += printf("@");
2105139afeeSAntoine Leca col += printf(",");
2115139afeeSAntoine Leca break;
2125139afeeSAntoine Leca }
2135139afeeSAntoine Leca }
2145139afeeSAntoine Leca printf("\n");
2155139afeeSAntoine Leca }
2165139afeeSAntoine Leca
2175139afeeSAntoine Leca static size_t
load_ents(TIENT * ents,TERMINAL * t,char type)2185139afeeSAntoine Leca load_ents(TIENT *ents, TERMINAL *t, char type)
2195139afeeSAntoine Leca {
2205139afeeSAntoine Leca size_t i, n, max;
2215139afeeSAntoine Leca TERMUSERDEF *ud;
2225139afeeSAntoine Leca
2235139afeeSAntoine Leca switch (type) {
2245139afeeSAntoine Leca case 'f':
2255139afeeSAntoine Leca max = TIFLAGMAX;
2265139afeeSAntoine Leca break;
2275139afeeSAntoine Leca case 'n':
2285139afeeSAntoine Leca max = TINUMMAX;
2295139afeeSAntoine Leca break;
2305139afeeSAntoine Leca default:
2315139afeeSAntoine Leca max = TISTRMAX;
2325139afeeSAntoine Leca }
2335139afeeSAntoine Leca
2345139afeeSAntoine Leca n = 0;
2355139afeeSAntoine Leca for (i = 0; i <= max; i++) {
2365139afeeSAntoine Leca switch (type) {
2375139afeeSAntoine Leca case 'f':
2385139afeeSAntoine Leca if (t->flags[i] == 1 ||
2395139afeeSAntoine Leca (aflag && t->flags[i] == CANCELLED_BOOLEAN))
2405139afeeSAntoine Leca {
2415139afeeSAntoine Leca ents[n].id = _ti_flagid(i);
2425139afeeSAntoine Leca ents[n].type = 'f';
2435139afeeSAntoine Leca ents[n++].flag = t->flags[i];
2445139afeeSAntoine Leca }
2455139afeeSAntoine Leca break;
2465139afeeSAntoine Leca case 'n':
2475139afeeSAntoine Leca if (VALID_NUMERIC(t->nums[i]) ||
2485139afeeSAntoine Leca (aflag && t->nums[i] == CANCELLED_NUMERIC))
2495139afeeSAntoine Leca {
2505139afeeSAntoine Leca ents[n].id = _ti_numid(i);
2515139afeeSAntoine Leca ents[n].type = 'n';
2525139afeeSAntoine Leca ents[n++].num = t->nums[i];
2535139afeeSAntoine Leca }
2545139afeeSAntoine Leca break;
2555139afeeSAntoine Leca default:
2565139afeeSAntoine Leca if (VALID_STRING(t->strs[i]) ||
2575139afeeSAntoine Leca (aflag && t->strs[i] == CANCELLED_STRING))
2585139afeeSAntoine Leca {
2595139afeeSAntoine Leca ents[n].id = _ti_strid(i);
2605139afeeSAntoine Leca ents[n].type = 's';
2615139afeeSAntoine Leca ents[n++].str = t->strs[i];
2625139afeeSAntoine Leca }
2635139afeeSAntoine Leca break;
2645139afeeSAntoine Leca }
2655139afeeSAntoine Leca }
2665139afeeSAntoine Leca
2675139afeeSAntoine Leca if (xflag != 0 && t->_nuserdefs != 0) {
2685139afeeSAntoine Leca for (i = 0; i < t->_nuserdefs; i++) {
2695139afeeSAntoine Leca ud = &t->_userdefs[i];
2705139afeeSAntoine Leca if (ud->type == type) {
2715139afeeSAntoine Leca switch (type) {
2725139afeeSAntoine Leca case 'f':
2735139afeeSAntoine Leca if (!aflag &&
2745139afeeSAntoine Leca !VALID_BOOLEAN(ud->flag))
2755139afeeSAntoine Leca continue;
2765139afeeSAntoine Leca break;
2775139afeeSAntoine Leca case 'n':
2785139afeeSAntoine Leca if (!aflag &&
2795139afeeSAntoine Leca !VALID_NUMERIC(ud->num))
2805139afeeSAntoine Leca continue;
2815139afeeSAntoine Leca break;
2825139afeeSAntoine Leca case 's':
2835139afeeSAntoine Leca if (!aflag &&
2845139afeeSAntoine Leca !VALID_STRING(ud->str))
2855139afeeSAntoine Leca continue;
2865139afeeSAntoine Leca break;
2875139afeeSAntoine Leca }
2885139afeeSAntoine Leca ents[n].id = ud->id;
2895139afeeSAntoine Leca ents[n].type = ud->type;
2905139afeeSAntoine Leca ents[n].flag = ud->flag;
2915139afeeSAntoine Leca ents[n].num = ud->num;
2925139afeeSAntoine Leca ents[n++].str = ud->str;
2935139afeeSAntoine Leca }
2945139afeeSAntoine Leca }
2955139afeeSAntoine Leca }
2965139afeeSAntoine Leca
2975139afeeSAntoine Leca qsort(ents, n, sizeof(TIENT), ent_compare);
2985139afeeSAntoine Leca return n;
2995139afeeSAntoine Leca }
3005139afeeSAntoine Leca
3015139afeeSAntoine Leca static void
cprint_ent(TIENT * ent)3025139afeeSAntoine Leca cprint_ent(TIENT *ent)
3035139afeeSAntoine Leca {
3045139afeeSAntoine Leca
3055139afeeSAntoine Leca if (ent == NULL) {
3065139afeeSAntoine Leca if (qflag == 0)
3075139afeeSAntoine Leca printf("NULL");
3085139afeeSAntoine Leca else
3095139afeeSAntoine Leca printf("-");
3105139afeeSAntoine Leca }
3115139afeeSAntoine Leca
3125139afeeSAntoine Leca switch (ent->type) {
3135139afeeSAntoine Leca case 'f':
3145139afeeSAntoine Leca if (VALID_BOOLEAN(ent->flag))
3155139afeeSAntoine Leca printf(ent->flag == 1 ? "T" : "F");
3165139afeeSAntoine Leca else if (qflag == 0)
3175139afeeSAntoine Leca printf("F");
3185139afeeSAntoine Leca else if (ent->flag == CANCELLED_BOOLEAN)
3195139afeeSAntoine Leca printf("@");
3205139afeeSAntoine Leca else
3215139afeeSAntoine Leca printf("-");
3225139afeeSAntoine Leca break;
3235139afeeSAntoine Leca case 'n':
3245139afeeSAntoine Leca if (VALID_NUMERIC(ent->num))
3255139afeeSAntoine Leca printf("%d", ent->num);
3265139afeeSAntoine Leca else if (qflag == 0)
3275139afeeSAntoine Leca printf("NULL");
3285139afeeSAntoine Leca else if (ent->num == CANCELLED_NUMERIC)
3295139afeeSAntoine Leca printf("@");
3305139afeeSAntoine Leca else
3315139afeeSAntoine Leca printf("-");
3325139afeeSAntoine Leca break;
3335139afeeSAntoine Leca case 's':
3345139afeeSAntoine Leca if (VALID_STRING(ent->str)) {
3355139afeeSAntoine Leca printf("'");
3365139afeeSAntoine Leca outstr(stdout, ent->str);
3375139afeeSAntoine Leca printf("'");
3385139afeeSAntoine Leca } else if (qflag == 0)
3395139afeeSAntoine Leca printf("NULL");
3405139afeeSAntoine Leca else if (ent->str == CANCELLED_STRING)
3415139afeeSAntoine Leca printf("@");
3425139afeeSAntoine Leca else
3435139afeeSAntoine Leca printf("-");
3445139afeeSAntoine Leca break;
3455139afeeSAntoine Leca }
3465139afeeSAntoine Leca }
3475139afeeSAntoine Leca
3485139afeeSAntoine Leca static void
compare_ents(TIENT * ents1,size_t n1,TIENT * ents2,size_t n2)3495139afeeSAntoine Leca compare_ents(TIENT *ents1, size_t n1, TIENT *ents2, size_t n2)
3505139afeeSAntoine Leca {
3515139afeeSAntoine Leca size_t i1, i2;
3525139afeeSAntoine Leca TIENT *e1, *e2, ee;
3535139afeeSAntoine Leca int c;
3545139afeeSAntoine Leca
3555139afeeSAntoine Leca i1 = i2 = 0;
3565139afeeSAntoine Leca ee.type = 'f';
3575139afeeSAntoine Leca ee.flag = ABSENT_BOOLEAN;
3585139afeeSAntoine Leca ee.num = ABSENT_NUMERIC;
3595139afeeSAntoine Leca ee.str = ABSENT_STRING;
3605139afeeSAntoine Leca while (i1 != n1 || i2 != n2) {
3615139afeeSAntoine Leca if (i1 == n1)
3625139afeeSAntoine Leca c = 1;
3635139afeeSAntoine Leca else if (i2 == n2)
3645139afeeSAntoine Leca c = -1;
3655139afeeSAntoine Leca else
3665139afeeSAntoine Leca c = strcmp(ents1[i1].id, ents2[i2].id);
3675139afeeSAntoine Leca if (c == 0) {
3685139afeeSAntoine Leca e1 = &ents1[i1++];
3695139afeeSAntoine Leca e2 = &ents2[i2++];
3705139afeeSAntoine Leca } else if (c < 0) {
3715139afeeSAntoine Leca e1 = &ents1[i1++];
3725139afeeSAntoine Leca e2 = ⅇ
3735139afeeSAntoine Leca ee.id = e1->id;
3745139afeeSAntoine Leca ee.type = e1->type;
3755139afeeSAntoine Leca } else {
3765139afeeSAntoine Leca e1 = ⅇ
3775139afeeSAntoine Leca e2 = &ents2[i2++];
3785139afeeSAntoine Leca ee.id = e2->id;
3795139afeeSAntoine Leca ee.type = e2->type;
3805139afeeSAntoine Leca }
3815139afeeSAntoine Leca switch (e1->type) {
3825139afeeSAntoine Leca case 'f':
3835139afeeSAntoine Leca if (cflag != 0) {
3845139afeeSAntoine Leca if (e1->flag == e2->flag)
3855139afeeSAntoine Leca printf("\t%s\n", ents1[i1].id);
3865139afeeSAntoine Leca continue;
3875139afeeSAntoine Leca }
3885139afeeSAntoine Leca if (e1->flag == e2->flag)
3895139afeeSAntoine Leca continue;
3905139afeeSAntoine Leca break;
3915139afeeSAntoine Leca case 'n':
3925139afeeSAntoine Leca if (cflag != 0) {
3935139afeeSAntoine Leca if (e1->num == e2->num)
3945139afeeSAntoine Leca printf("\t%s#%d\n",
3955139afeeSAntoine Leca ents1[i1].id, ents1[i1].num);
3965139afeeSAntoine Leca continue;
3975139afeeSAntoine Leca }
3985139afeeSAntoine Leca if (e1->num == e2->num)
3995139afeeSAntoine Leca continue;
4005139afeeSAntoine Leca break;
4015139afeeSAntoine Leca case 's':
4025139afeeSAntoine Leca if (cflag != 0) {
4035139afeeSAntoine Leca if (VALID_STRING(e1->str) &&
4045139afeeSAntoine Leca VALID_STRING(e2->str) &&
4055139afeeSAntoine Leca strcmp(e1->str, e2->str) == 0) {
4065139afeeSAntoine Leca printf("\t%s=", ents1[i1].id);
4075139afeeSAntoine Leca outstr(stdout, ents1[i1].str);
4085139afeeSAntoine Leca printf("\n");
4095139afeeSAntoine Leca }
4105139afeeSAntoine Leca continue;
4115139afeeSAntoine Leca }
4125139afeeSAntoine Leca if (VALID_STRING(e1->str) &&
4135139afeeSAntoine Leca VALID_STRING(e2->str) &&
4145139afeeSAntoine Leca strcmp(e1->str, e2->str) == 0)
4155139afeeSAntoine Leca continue;
4165139afeeSAntoine Leca break;
4175139afeeSAntoine Leca }
4185139afeeSAntoine Leca printf("\t%s: ", e1->id);
4195139afeeSAntoine Leca cprint_ent(e1);
4205139afeeSAntoine Leca if (e1->type == 'f')
4215139afeeSAntoine Leca printf(":");
4225139afeeSAntoine Leca else
4235139afeeSAntoine Leca printf(", ");
4245139afeeSAntoine Leca cprint_ent(e2);
4255139afeeSAntoine Leca printf(".\n");
4265139afeeSAntoine Leca }
4275139afeeSAntoine Leca }
4285139afeeSAntoine Leca
4295139afeeSAntoine Leca static TERMINAL *
load_term(const char * name)4305139afeeSAntoine Leca load_term(const char *name)
4315139afeeSAntoine Leca {
4325139afeeSAntoine Leca TERMINAL *t;
4335139afeeSAntoine Leca
4345139afeeSAntoine Leca t = calloc(1, sizeof(*t));
4355139afeeSAntoine Leca if (t == NULL)
4365139afeeSAntoine Leca err(1, "calloc");
4375139afeeSAntoine Leca if (name == NULL)
4385139afeeSAntoine Leca name = getenv("TERM");
4395139afeeSAntoine Leca if (name == NULL)
4405139afeeSAntoine Leca name = "dumb";
4415139afeeSAntoine Leca if (_ti_getterm(t, name, 1) == 1)
4425139afeeSAntoine Leca return t;
4435139afeeSAntoine Leca
4445139afeeSAntoine Leca if (_ti_database == NULL)
4455139afeeSAntoine Leca errx(1, "no terminal definition found in internal database");
4465139afeeSAntoine Leca else
4475139afeeSAntoine Leca errx(1, "no terminal definition found in %s.db", _ti_database);
4485139afeeSAntoine Leca }
4495139afeeSAntoine Leca
4505139afeeSAntoine Leca static void
show_missing(TERMINAL * t1,TERMINAL * t2,char type)4515139afeeSAntoine Leca show_missing(TERMINAL *t1, TERMINAL *t2, char type)
4525139afeeSAntoine Leca {
4535139afeeSAntoine Leca ssize_t i, max;
4545139afeeSAntoine Leca const char *id;
4555139afeeSAntoine Leca
4565139afeeSAntoine Leca switch (type) {
4575139afeeSAntoine Leca case 'f':
4585139afeeSAntoine Leca max = TIFLAGMAX;
4595139afeeSAntoine Leca break;
4605139afeeSAntoine Leca case 'n':
4615139afeeSAntoine Leca max = TINUMMAX;
4625139afeeSAntoine Leca break;
4635139afeeSAntoine Leca default:
4645139afeeSAntoine Leca max = TISTRMAX;
4655139afeeSAntoine Leca }
4665139afeeSAntoine Leca
4675139afeeSAntoine Leca for (i = 0; i <= max; i++) {
4685139afeeSAntoine Leca switch (type) {
4695139afeeSAntoine Leca case 'f':
4705139afeeSAntoine Leca if (t1->flags[i] != ABSENT_BOOLEAN ||
4715139afeeSAntoine Leca t2->flags[i] != ABSENT_BOOLEAN)
4725139afeeSAntoine Leca continue;
4735139afeeSAntoine Leca id = _ti_flagid(i);
4745139afeeSAntoine Leca break;
4755139afeeSAntoine Leca case 'n':
4765139afeeSAntoine Leca if (t1->nums[i] != ABSENT_NUMERIC ||
4775139afeeSAntoine Leca t2->nums[i] != ABSENT_NUMERIC)
4785139afeeSAntoine Leca continue;
4795139afeeSAntoine Leca id = _ti_numid(i);
4805139afeeSAntoine Leca break;
4815139afeeSAntoine Leca default:
4825139afeeSAntoine Leca if (t1->strs[i] != ABSENT_STRING ||
4835139afeeSAntoine Leca t2->strs[i] != ABSENT_STRING)
4845139afeeSAntoine Leca continue;
4855139afeeSAntoine Leca id = _ti_strid(i);
4865139afeeSAntoine Leca break;
4875139afeeSAntoine Leca }
4885139afeeSAntoine Leca printf("\t!%s.\n", id);
4895139afeeSAntoine Leca }
4905139afeeSAntoine Leca }
4915139afeeSAntoine Leca
4925139afeeSAntoine Leca static TERMUSERDEF *
find_userdef(TERMINAL * term,const char * id)4935139afeeSAntoine Leca find_userdef(TERMINAL *term, const char *id)
4945139afeeSAntoine Leca {
4955139afeeSAntoine Leca size_t i;
4965139afeeSAntoine Leca
4975139afeeSAntoine Leca for (i = 0; i < term->_nuserdefs; i++)
4985139afeeSAntoine Leca if (strcmp(term->_userdefs[i].id, id) == 0)
4995139afeeSAntoine Leca return &term->_userdefs[i];
5005139afeeSAntoine Leca return NULL;
5015139afeeSAntoine Leca }
5025139afeeSAntoine Leca
5035139afeeSAntoine Leca static void
use_terms(TERMINAL * term,size_t nuse,char ** uterms)5045139afeeSAntoine Leca use_terms(TERMINAL *term, size_t nuse, char **uterms)
5055139afeeSAntoine Leca {
5065139afeeSAntoine Leca TERMINAL **terms;
5075139afeeSAntoine Leca TERMUSERDEF *ud, *tud;
5085139afeeSAntoine Leca size_t i, j, agree, absent, data;
5095139afeeSAntoine Leca
5105139afeeSAntoine Leca terms = malloc(sizeof(**terms) * nuse);
5115139afeeSAntoine Leca if (terms == NULL)
5125139afeeSAntoine Leca err(1, "malloc");
5135139afeeSAntoine Leca for (i = 0; i < nuse; i++) {
5145139afeeSAntoine Leca if (strcmp(term->name, *uterms) == 0)
5155139afeeSAntoine Leca errx(1, "cannot use same terminal");
5165139afeeSAntoine Leca for (j = 0; j < i; j++)
5175139afeeSAntoine Leca if (strcmp(terms[j]->name, *uterms) == 0)
5185139afeeSAntoine Leca errx(1, "cannot use same terminal");
5195139afeeSAntoine Leca terms[i] = load_term(*uterms++);
5205139afeeSAntoine Leca }
5215139afeeSAntoine Leca
5225139afeeSAntoine Leca for (i = 0; i < TIFLAGMAX + 1; i++) {
5235139afeeSAntoine Leca agree = absent = data = 0;
5245139afeeSAntoine Leca for (j = 0; j < nuse; j++) {
5255139afeeSAntoine Leca if (terms[j]->flags[i] == ABSENT_BOOLEAN ||
5265139afeeSAntoine Leca terms[j]->flags[i] == CANCELLED_BOOLEAN)
5275139afeeSAntoine Leca absent++;
5285139afeeSAntoine Leca else {
5295139afeeSAntoine Leca data++;
5305139afeeSAntoine Leca if (term->flags[i] == terms[j]->flags[i])
5315139afeeSAntoine Leca agree++;
5325139afeeSAntoine Leca }
5335139afeeSAntoine Leca }
5345139afeeSAntoine Leca if (data == 0)
5355139afeeSAntoine Leca continue;
5365139afeeSAntoine Leca if (agree > 0 && agree + absent == nuse)
5375139afeeSAntoine Leca term->flags[i] = ABSENT_BOOLEAN;
5385139afeeSAntoine Leca else if (term->flags[i] == ABSENT_BOOLEAN)
5395139afeeSAntoine Leca term->flags[i] = CANCELLED_BOOLEAN;
5405139afeeSAntoine Leca }
5415139afeeSAntoine Leca
5425139afeeSAntoine Leca for (i = 0; i < TINUMMAX + 1; i++) {
5435139afeeSAntoine Leca agree = absent = data = 0;
5445139afeeSAntoine Leca for (j = 0; j < nuse; j++) {
5455139afeeSAntoine Leca if (terms[j]->nums[i] == ABSENT_NUMERIC ||
5465139afeeSAntoine Leca terms[j]->nums[i] == CANCELLED_NUMERIC)
5475139afeeSAntoine Leca absent++;
5485139afeeSAntoine Leca else {
5495139afeeSAntoine Leca data++;
5505139afeeSAntoine Leca if (term->nums[i] == terms[j]->nums[i])
5515139afeeSAntoine Leca agree++;
5525139afeeSAntoine Leca }
5535139afeeSAntoine Leca }
5545139afeeSAntoine Leca if (data == 0)
5555139afeeSAntoine Leca continue;
5565139afeeSAntoine Leca if (agree > 0 && agree + absent == nuse)
5575139afeeSAntoine Leca term->nums[i] = ABSENT_NUMERIC;
5585139afeeSAntoine Leca else if (term->nums[i] == ABSENT_NUMERIC)
5595139afeeSAntoine Leca term->nums[i] = CANCELLED_NUMERIC;
5605139afeeSAntoine Leca }
5615139afeeSAntoine Leca
5625139afeeSAntoine Leca for (i = 0; i < TISTRMAX + 1; i++) {
5635139afeeSAntoine Leca agree = absent = data = 0;
5645139afeeSAntoine Leca for (j = 0; j < nuse; j++) {
5655139afeeSAntoine Leca if (terms[j]->strs[i] == ABSENT_STRING ||
5665139afeeSAntoine Leca terms[j]->strs[i] == CANCELLED_STRING)
5675139afeeSAntoine Leca absent++;
5685139afeeSAntoine Leca else {
5695139afeeSAntoine Leca data++;
5705139afeeSAntoine Leca if (VALID_STRING(term->strs[i]) &&
5715139afeeSAntoine Leca strcmp(term->strs[i],
5725139afeeSAntoine Leca terms[j]->strs[i]) == 0)
5735139afeeSAntoine Leca agree++;
5745139afeeSAntoine Leca }
5755139afeeSAntoine Leca }
5765139afeeSAntoine Leca if (data == 0)
5775139afeeSAntoine Leca continue;
5785139afeeSAntoine Leca if (agree > 0 && agree + absent == nuse)
5795139afeeSAntoine Leca term->strs[i] = ABSENT_STRING;
5805139afeeSAntoine Leca else if (term->strs[i] == ABSENT_STRING)
5815139afeeSAntoine Leca term->strs[i] = CANCELLED_STRING;
5825139afeeSAntoine Leca }
5835139afeeSAntoine Leca
5845139afeeSAntoine Leca /* User defined caps are more tricky.
5855139afeeSAntoine Leca First we set any to absent that agree. */
5865139afeeSAntoine Leca for (i = 0; i < term->_nuserdefs; i++) {
5875139afeeSAntoine Leca agree = absent = data = 0;
5885139afeeSAntoine Leca ud = &term->_userdefs[i];
5895139afeeSAntoine Leca for (j = 0; j < nuse; j++) {
5905139afeeSAntoine Leca tud = find_userdef(terms[j], ud->id);
5915139afeeSAntoine Leca if (tud == NULL)
5925139afeeSAntoine Leca absent++;
5935139afeeSAntoine Leca else {
5945139afeeSAntoine Leca data++;
5955139afeeSAntoine Leca switch (ud->type) {
5965139afeeSAntoine Leca case 'f':
5975139afeeSAntoine Leca if (tud->type == 'f' &&
5985139afeeSAntoine Leca tud->flag == ud->flag)
5995139afeeSAntoine Leca agree++;
6005139afeeSAntoine Leca break;
6015139afeeSAntoine Leca case 'n':
6025139afeeSAntoine Leca if (tud->type == 'n' &&
6035139afeeSAntoine Leca tud->num == ud->num)
6045139afeeSAntoine Leca agree++;
6055139afeeSAntoine Leca break;
6065139afeeSAntoine Leca case 's':
6075139afeeSAntoine Leca if (tud->type == 's' &&
6085139afeeSAntoine Leca VALID_STRING(tud->str) &&
6095139afeeSAntoine Leca VALID_STRING(ud->str) &&
6105139afeeSAntoine Leca strcmp(ud->str, tud->str) == 0)
6115139afeeSAntoine Leca agree++;
6125139afeeSAntoine Leca break;
6135139afeeSAntoine Leca }
6145139afeeSAntoine Leca }
6155139afeeSAntoine Leca }
6165139afeeSAntoine Leca if (data == 0)
6175139afeeSAntoine Leca continue;
6185139afeeSAntoine Leca if (agree > 0 && agree + absent == nuse) {
6195139afeeSAntoine Leca ud->flag = ABSENT_BOOLEAN;
6205139afeeSAntoine Leca ud->num = ABSENT_NUMERIC;
6215139afeeSAntoine Leca ud->str = ABSENT_STRING;
6225139afeeSAntoine Leca }
6235139afeeSAntoine Leca }
6245139afeeSAntoine Leca
6255139afeeSAntoine Leca /* Now add any that we don't have as cancelled */
6265139afeeSAntoine Leca for (i = 0; i < nuse; i++) {
6275139afeeSAntoine Leca for (j = 0; j < terms[i]->_nuserdefs; j++) {
6285139afeeSAntoine Leca ud = find_userdef(term, terms[i]->_userdefs[j].id);
6295139afeeSAntoine Leca if (ud != NULL)
6305139afeeSAntoine Leca continue; /* We have handled this */
6315139afeeSAntoine Leca term->_userdefs = realloc(term->_userdefs,
6325139afeeSAntoine Leca sizeof(*term->_userdefs) * (term->_nuserdefs + 1));
6335139afeeSAntoine Leca if (term->_userdefs == NULL)
6345139afeeSAntoine Leca err(1, "malloc");
6355139afeeSAntoine Leca tud = &term->_userdefs[term->_nuserdefs++];
6365139afeeSAntoine Leca tud->id = terms[i]->_userdefs[j].id;
6375139afeeSAntoine Leca tud->type = terms[i]->_userdefs[j].flag;
6385139afeeSAntoine Leca tud->flag = CANCELLED_BOOLEAN;
6395139afeeSAntoine Leca tud->num = CANCELLED_NUMERIC;
6405139afeeSAntoine Leca tud->str = CANCELLED_STRING;
6415139afeeSAntoine Leca }
6425139afeeSAntoine Leca }
6435139afeeSAntoine Leca }
6445139afeeSAntoine Leca
6455139afeeSAntoine Leca int
main(int argc,char ** argv)6465139afeeSAntoine Leca main(int argc, char **argv)
6475139afeeSAntoine Leca {
6485139afeeSAntoine Leca char *term, *Barg;
6495139afeeSAntoine Leca int ch, uflag;
6505139afeeSAntoine Leca TERMINAL *t, *t2;
6515139afeeSAntoine Leca size_t n, n2;
6525139afeeSAntoine Leca struct winsize ws;
6535139afeeSAntoine Leca TIENT ents[TISTRMAX + 1], ents2[TISTRMAX + 1];
6545139afeeSAntoine Leca
6555139afeeSAntoine Leca cols = 80; /* default */
6565139afeeSAntoine Leca term = getenv("COLUMNS");
6575139afeeSAntoine Leca if (term != NULL)
6585139afeeSAntoine Leca cols = strtoul(term, NULL, 10);
6595139afeeSAntoine Leca else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0)
6605139afeeSAntoine Leca cols = ws.ws_col;
6615139afeeSAntoine Leca
6625139afeeSAntoine Leca uflag = xflag = 0;
6635139afeeSAntoine Leca Barg = NULL;
6645139afeeSAntoine Leca while ((ch = getopt(argc, argv, "1A:B:acnquw:x")) != -1)
6655139afeeSAntoine Leca switch (ch) {
6665139afeeSAntoine Leca case '1':
6675139afeeSAntoine Leca cols = 1;
6685139afeeSAntoine Leca break;
6695139afeeSAntoine Leca case 'A':
6705139afeeSAntoine Leca setdb(optarg);
6715139afeeSAntoine Leca break;
6725139afeeSAntoine Leca case 'B':
6735139afeeSAntoine Leca Barg = optarg;
6745139afeeSAntoine Leca break;
6755139afeeSAntoine Leca case 'a':
6765139afeeSAntoine Leca aflag = 1;
6775139afeeSAntoine Leca break;
6785139afeeSAntoine Leca case 'c':
6795139afeeSAntoine Leca cflag = 1;
6805139afeeSAntoine Leca break;
6815139afeeSAntoine Leca case 'n':
6825139afeeSAntoine Leca nflag = 1;
6835139afeeSAntoine Leca break;
6845139afeeSAntoine Leca case 'q':
6855139afeeSAntoine Leca qflag = 1;
6865139afeeSAntoine Leca break;
6875139afeeSAntoine Leca case 'u':
6885139afeeSAntoine Leca uflag = 1;
6895139afeeSAntoine Leca aflag = 1;
6905139afeeSAntoine Leca break;
6915139afeeSAntoine Leca case 'w':
6925139afeeSAntoine Leca cols = strtoul(optarg, NULL, 10);
6935139afeeSAntoine Leca break;
6945139afeeSAntoine Leca case 'x':
6955139afeeSAntoine Leca xflag = 1;
6965139afeeSAntoine Leca break;
6975139afeeSAntoine Leca case '?':
6985139afeeSAntoine Leca default:
6995139afeeSAntoine Leca fprintf(stderr,
7005139afeeSAntoine Leca "usage: %s [-1acnqux] [-A database] [-B database] "
7015139afeeSAntoine Leca "[-w cols] [term]\n",
7025139afeeSAntoine Leca getprogname());
7035139afeeSAntoine Leca return EXIT_FAILURE;
7045139afeeSAntoine Leca }
7055139afeeSAntoine Leca cols--;
7065139afeeSAntoine Leca
7075139afeeSAntoine Leca if (optind + 1 < argc)
7085139afeeSAntoine Leca aflag = 1;
7095139afeeSAntoine Leca
7105139afeeSAntoine Leca if (optind < argc)
7115139afeeSAntoine Leca term = argv[optind++];
7125139afeeSAntoine Leca else
7135139afeeSAntoine Leca term = NULL;
7145139afeeSAntoine Leca t = load_term(term);
7155139afeeSAntoine Leca
7165139afeeSAntoine Leca if (uflag != 0)
7175139afeeSAntoine Leca use_terms(t, argc - optind, argv + optind);
7185139afeeSAntoine Leca
7195139afeeSAntoine Leca if ((optind + 1 != argc && nflag == 0) || uflag != 0) {
7205139afeeSAntoine Leca if (uflag == 0) {
7215139afeeSAntoine Leca printf("# Reconstructed from ");
7225139afeeSAntoine Leca if (_ti_database == NULL)
7235139afeeSAntoine Leca printf("internal database\n");
7245139afeeSAntoine Leca else
7255139afeeSAntoine Leca printf("%s%s\n", _ti_database,
726*84d9c625SLionel Sambuc *_ti_database == '/' ? ".cdb" : "");
7275139afeeSAntoine Leca }
7285139afeeSAntoine Leca printf("%s", t->name);
7295139afeeSAntoine Leca if (t->_alias != NULL && *t->_alias != '\0')
7305139afeeSAntoine Leca printf("|%s", t->_alias);
7315139afeeSAntoine Leca if (t->desc != NULL && *t->desc != '\0')
7325139afeeSAntoine Leca printf("|%s", t->desc);
7335139afeeSAntoine Leca printf(",\n");
7345139afeeSAntoine Leca
7355139afeeSAntoine Leca n = load_ents(ents, t, 'f');
7365139afeeSAntoine Leca print_ent(ents, n);
7375139afeeSAntoine Leca n = load_ents(ents, t, 'n');
7385139afeeSAntoine Leca print_ent(ents, n);
7395139afeeSAntoine Leca n = load_ents(ents, t, 's');
7405139afeeSAntoine Leca print_ent(ents, n);
7415139afeeSAntoine Leca
7425139afeeSAntoine Leca if (uflag != 0) {
7435139afeeSAntoine Leca printf("\t");
7445139afeeSAntoine Leca n = SW;
7455139afeeSAntoine Leca for (; optind < argc; optind++) {
7465139afeeSAntoine Leca n2 = 5 + strlen(argv[optind]);
7475139afeeSAntoine Leca if (n != SW) {
7485139afeeSAntoine Leca if (n + n2 > cols) {
7495139afeeSAntoine Leca printf("\n\t");
7505139afeeSAntoine Leca n = SW;
7515139afeeSAntoine Leca } else
7525139afeeSAntoine Leca n += printf(" ");
7535139afeeSAntoine Leca }
7545139afeeSAntoine Leca n += printf("use=%s,", argv[optind]);
7555139afeeSAntoine Leca }
7565139afeeSAntoine Leca printf("\n");
7575139afeeSAntoine Leca }
7585139afeeSAntoine Leca return EXIT_SUCCESS;
7595139afeeSAntoine Leca }
7605139afeeSAntoine Leca
7615139afeeSAntoine Leca if (Barg == NULL)
7625139afeeSAntoine Leca unsetenv("TERMINFO");
7635139afeeSAntoine Leca else
7645139afeeSAntoine Leca setdb(Barg);
7655139afeeSAntoine Leca t2 = load_term(argv[optind++]);
7665139afeeSAntoine Leca printf("comparing %s to %s.\n", t->name, t2->name);
7675139afeeSAntoine Leca if (qflag == 0)
7685139afeeSAntoine Leca printf(" comparing booleans.\n");
7695139afeeSAntoine Leca if (nflag == 0) {
7705139afeeSAntoine Leca n = load_ents(ents, t, 'f');
7715139afeeSAntoine Leca n2 = load_ents(ents2, t2, 'f');
7725139afeeSAntoine Leca compare_ents(ents, n, ents2, n2);
7735139afeeSAntoine Leca } else
7745139afeeSAntoine Leca show_missing(t, t2, 'f');
7755139afeeSAntoine Leca if (qflag == 0)
7765139afeeSAntoine Leca printf(" comparing numbers.\n");
7775139afeeSAntoine Leca if (nflag == 0) {
7785139afeeSAntoine Leca n = load_ents(ents, t, 'n');
7795139afeeSAntoine Leca n2 = load_ents(ents2, t2, 'n');
7805139afeeSAntoine Leca compare_ents(ents, n, ents2, n2);
7815139afeeSAntoine Leca } else
7825139afeeSAntoine Leca show_missing(t, t2, 'n');
7835139afeeSAntoine Leca if (qflag == 0)
7845139afeeSAntoine Leca printf(" comparing strings.\n");
7855139afeeSAntoine Leca if (nflag == 0) {
7865139afeeSAntoine Leca n = load_ents(ents, t, 's');
7875139afeeSAntoine Leca n2 = load_ents(ents2, t2, 's');
7885139afeeSAntoine Leca compare_ents(ents, n, ents2, n2);
7895139afeeSAntoine Leca } else
7905139afeeSAntoine Leca show_missing(t, t2, 's');
7915139afeeSAntoine Leca return EXIT_SUCCESS;
7925139afeeSAntoine Leca }
793