xref: /dflybsd-src/contrib/ncurses/progs/infocmp.c (revision 0cadad7e49c6219b0de0675ef6a6f44683d177d4)
15f4613f2SJohn Marino /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2020 Thomas E. Dickey                                          *
3*32bb5217SDaniel Fojt  * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
45f4613f2SJohn Marino  *                                                                          *
55f4613f2SJohn Marino  * Permission is hereby granted, free of charge, to any person obtaining a  *
65f4613f2SJohn Marino  * copy of this software and associated documentation files (the            *
75f4613f2SJohn Marino  * "Software"), to deal in the Software without restriction, including      *
85f4613f2SJohn Marino  * without limitation the rights to use, copy, modify, merge, publish,      *
95f4613f2SJohn Marino  * distribute, distribute with modifications, sublicense, and/or sell       *
105f4613f2SJohn Marino  * copies of the Software, and to permit persons to whom the Software is    *
115f4613f2SJohn Marino  * furnished to do so, subject to the following conditions:                 *
125f4613f2SJohn Marino  *                                                                          *
135f4613f2SJohn Marino  * The above copyright notice and this permission notice shall be included  *
145f4613f2SJohn Marino  * in all copies or substantial portions of the Software.                   *
155f4613f2SJohn Marino  *                                                                          *
165f4613f2SJohn Marino  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
175f4613f2SJohn Marino  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
185f4613f2SJohn Marino  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
195f4613f2SJohn Marino  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
205f4613f2SJohn Marino  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
215f4613f2SJohn Marino  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
225f4613f2SJohn Marino  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
235f4613f2SJohn Marino  *                                                                          *
245f4613f2SJohn Marino  * Except as contained in this notice, the name(s) of the above copyright   *
255f4613f2SJohn Marino  * holders shall not be used in advertising or otherwise to promote the     *
265f4613f2SJohn Marino  * sale, use or other dealings in this Software without prior written       *
275f4613f2SJohn Marino  * authorization.                                                           *
285f4613f2SJohn Marino  ****************************************************************************/
295f4613f2SJohn Marino 
305f4613f2SJohn Marino /****************************************************************************
315f4613f2SJohn Marino  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
325f4613f2SJohn Marino  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
335f4613f2SJohn Marino  *     and: Thomas E. Dickey                        1996-on                 *
345f4613f2SJohn Marino  ****************************************************************************/
355f4613f2SJohn Marino 
365f4613f2SJohn Marino /*
375f4613f2SJohn Marino  *	infocmp.c -- decompile an entry, or compare two entries
385f4613f2SJohn Marino  *		written by Eric S. Raymond
395f4613f2SJohn Marino  *		and Thomas E Dickey
405f4613f2SJohn Marino  */
415f4613f2SJohn Marino 
425f4613f2SJohn Marino #include <progs.priv.h>
435f4613f2SJohn Marino 
445f4613f2SJohn Marino #include <dump_entry.h>
455f4613f2SJohn Marino 
46*32bb5217SDaniel Fojt MODULE_ID("$Id: infocmp.c,v 1.144 2020/02/02 23:34:34 tom Exp $")
475f4613f2SJohn Marino 
485f4613f2SJohn Marino #define MAX_STRING	1024	/* maximum formatted string */
495f4613f2SJohn Marino 
505f4613f2SJohn Marino const char *_nc_progname = "infocmp";
515f4613f2SJohn Marino 
525f4613f2SJohn Marino typedef char path[PATH_MAX];
535f4613f2SJohn Marino 
545f4613f2SJohn Marino /***************************************************************************
555f4613f2SJohn Marino  *
565f4613f2SJohn Marino  * The following control variables, together with the contents of the
575f4613f2SJohn Marino  * terminfo entries, completely determine the actions of the program.
585f4613f2SJohn Marino  *
595f4613f2SJohn Marino  ***************************************************************************/
605f4613f2SJohn Marino 
615f4613f2SJohn Marino static ENTRY *entries;		/* terminfo entries */
625f4613f2SJohn Marino static int termcount;		/* count of terminal entries */
635f4613f2SJohn Marino 
645f4613f2SJohn Marino static bool limited = TRUE;	/* "-r" option is not set */
655f4613f2SJohn Marino static bool quiet = FALSE;
665f4613f2SJohn Marino static bool literal = FALSE;
675f4613f2SJohn Marino static const char *bool_sep = ":";
685f4613f2SJohn Marino static const char *s_absent = "NULL";
695f4613f2SJohn Marino static const char *s_cancel = "NULL";
705f4613f2SJohn Marino static const char *tversion;	/* terminfo version selected */
713468e90cSJohn Marino static unsigned itrace;		/* trace flag for debugging */
725f4613f2SJohn Marino static int mwidth = 60;
733468e90cSJohn Marino static int mheight = 65535;
745f4613f2SJohn Marino static int numbers = 0;		/* format "%'char'" to/from "%{number}" */
755f4613f2SJohn Marino static int outform = F_TERMINFO;	/* output format */
765f4613f2SJohn Marino static int sortmode;		/* sort_mode */
775f4613f2SJohn Marino 
785f4613f2SJohn Marino /* main comparison mode */
795f4613f2SJohn Marino static int compare;
805f4613f2SJohn Marino #define C_DEFAULT	0	/* don't force comparison mode */
815f4613f2SJohn Marino #define C_DIFFERENCE	1	/* list differences between two terminals */
825f4613f2SJohn Marino #define C_COMMON	2	/* list common capabilities */
835f4613f2SJohn Marino #define C_NAND		3	/* list capabilities in neither terminal */
845f4613f2SJohn Marino #define C_USEALL	4	/* generate relative use-form entry */
855f4613f2SJohn Marino static bool ignorepads;		/* ignore pad prefixes when diffing */
865f4613f2SJohn Marino 
875f4613f2SJohn Marino #if NO_LEAKS
883468e90cSJohn Marino 
893468e90cSJohn Marino typedef struct {
903468e90cSJohn Marino     ENTRY *head;
913468e90cSJohn Marino     ENTRY *tail;
923468e90cSJohn Marino } ENTERED;
933468e90cSJohn Marino 
943468e90cSJohn Marino static ENTERED *entered;
953468e90cSJohn Marino 
965f4613f2SJohn Marino #undef ExitProgram
975f4613f2SJohn Marino static void ExitProgram(int code) GCC_NORETURN;
985f4613f2SJohn Marino /* prototype is to get gcc to accept the noreturn attribute */
995f4613f2SJohn Marino static void
ExitProgram(int code)1005f4613f2SJohn Marino ExitProgram(int code)
1015f4613f2SJohn Marino {
1023468e90cSJohn Marino     int n;
1033468e90cSJohn Marino 
1043468e90cSJohn Marino     for (n = 0; n < termcount; ++n) {
1053468e90cSJohn Marino 	ENTRY *new_head = _nc_head;
1063468e90cSJohn Marino 	ENTRY *new_tail = _nc_tail;
1073468e90cSJohn Marino 	_nc_head = entered[n].head;
1083468e90cSJohn Marino 	_nc_tail = entered[n].tail;
1093468e90cSJohn Marino 	_nc_free_entries(entered[n].head);
1103468e90cSJohn Marino 	_nc_head = new_head;
1113468e90cSJohn Marino 	_nc_tail = new_tail;
1123468e90cSJohn Marino     }
1135f4613f2SJohn Marino     _nc_leaks_dump_entry();
1145f4613f2SJohn Marino     free(entries);
1153468e90cSJohn Marino     free(entered);
1165f4613f2SJohn Marino     _nc_free_tic(code);
1175f4613f2SJohn Marino }
1185f4613f2SJohn Marino #endif
1195f4613f2SJohn Marino 
1203468e90cSJohn Marino static void
failed(const char * s)1213468e90cSJohn Marino failed(const char *s)
1223468e90cSJohn Marino {
1233468e90cSJohn Marino     perror(s);
1243468e90cSJohn Marino     ExitProgram(EXIT_FAILURE);
1253468e90cSJohn Marino }
1263468e90cSJohn Marino 
1275f4613f2SJohn Marino static char *
canonical_name(char * ptr,char * buf)1285f4613f2SJohn Marino canonical_name(char *ptr, char *buf)
1295f4613f2SJohn Marino /* extract the terminal type's primary name */
1305f4613f2SJohn Marino {
1315f4613f2SJohn Marino     char *bp;
1325f4613f2SJohn Marino 
1333468e90cSJohn Marino     _nc_STRCPY(buf, ptr, NAMESIZE);
1345f4613f2SJohn Marino     if ((bp = strchr(buf, '|')) != 0)
1355f4613f2SJohn Marino 	*bp = '\0';
1365f4613f2SJohn Marino 
1375f4613f2SJohn Marino     return (buf);
1385f4613f2SJohn Marino }
1395f4613f2SJohn Marino 
140*32bb5217SDaniel Fojt static bool
no_boolean(int value)141*32bb5217SDaniel Fojt no_boolean(int value)
142*32bb5217SDaniel Fojt {
143*32bb5217SDaniel Fojt     bool result = (value == ABSENT_BOOLEAN);
144*32bb5217SDaniel Fojt     if (!strcmp(s_absent, s_cancel))
145*32bb5217SDaniel Fojt 	result = !VALID_BOOLEAN(value);
146*32bb5217SDaniel Fojt     return result;
147*32bb5217SDaniel Fojt }
148*32bb5217SDaniel Fojt 
149*32bb5217SDaniel Fojt static bool
no_numeric(int value)150*32bb5217SDaniel Fojt no_numeric(int value)
151*32bb5217SDaniel Fojt {
152*32bb5217SDaniel Fojt     bool result = (value == ABSENT_NUMERIC);
153*32bb5217SDaniel Fojt     if (!strcmp(s_absent, s_cancel))
154*32bb5217SDaniel Fojt 	result = !VALID_NUMERIC(value);
155*32bb5217SDaniel Fojt     return result;
156*32bb5217SDaniel Fojt }
157*32bb5217SDaniel Fojt 
158*32bb5217SDaniel Fojt static bool
no_string(char * value)159*32bb5217SDaniel Fojt no_string(char *value)
160*32bb5217SDaniel Fojt {
161*32bb5217SDaniel Fojt     bool result = (value == ABSENT_STRING);
162*32bb5217SDaniel Fojt     if (!strcmp(s_absent, s_cancel))
163*32bb5217SDaniel Fojt 	result = !VALID_STRING(value);
164*32bb5217SDaniel Fojt     return result;
165*32bb5217SDaniel Fojt }
166*32bb5217SDaniel Fojt 
1675f4613f2SJohn Marino /***************************************************************************
1685f4613f2SJohn Marino  *
1695f4613f2SJohn Marino  * Predicates for dump function
1705f4613f2SJohn Marino  *
1715f4613f2SJohn Marino  ***************************************************************************/
1725f4613f2SJohn Marino 
1735f4613f2SJohn Marino static int
capcmp(PredIdx idx,const char * s,const char * t)1745f4613f2SJohn Marino capcmp(PredIdx idx, const char *s, const char *t)
1755f4613f2SJohn Marino /* capability comparison function */
1765f4613f2SJohn Marino {
1775f4613f2SJohn Marino     if (!VALID_STRING(s) && !VALID_STRING(t))
1785f4613f2SJohn Marino 	return (s != t);
1795f4613f2SJohn Marino     else if (!VALID_STRING(s) || !VALID_STRING(t))
1805f4613f2SJohn Marino 	return (1);
1815f4613f2SJohn Marino 
1825f4613f2SJohn Marino     if ((idx == acs_chars_index) || !ignorepads)
1835f4613f2SJohn Marino 	return (strcmp(s, t));
1845f4613f2SJohn Marino     else
1855f4613f2SJohn Marino 	return (_nc_capcmp(s, t));
1865f4613f2SJohn Marino }
1875f4613f2SJohn Marino 
1885f4613f2SJohn Marino static int
use_predicate(unsigned type,PredIdx idx)1895f4613f2SJohn Marino use_predicate(unsigned type, PredIdx idx)
1905f4613f2SJohn Marino /* predicate function to use for use decompilation */
1915f4613f2SJohn Marino {
1925f4613f2SJohn Marino     ENTRY *ep;
1935f4613f2SJohn Marino 
1945f4613f2SJohn Marino     switch (type) {
1955f4613f2SJohn Marino     case BOOLEAN:
1965f4613f2SJohn Marino 	{
1975f4613f2SJohn Marino 	    int is_set = FALSE;
1985f4613f2SJohn Marino 
1995f4613f2SJohn Marino 	    /*
2005f4613f2SJohn Marino 	     * This assumes that multiple use entries are supposed
2015f4613f2SJohn Marino 	     * to contribute the logical or of their boolean capabilities.
2025f4613f2SJohn Marino 	     * This is true if we take the semantics of multiple uses to
2035f4613f2SJohn Marino 	     * be 'each capability gets the first non-default value found
2045f4613f2SJohn Marino 	     * in the sequence of use entries'.
2055f4613f2SJohn Marino 	     *
2065f4613f2SJohn Marino 	     * Note that cancelled or absent booleans are stored as FALSE,
2075f4613f2SJohn Marino 	     * unlike numbers and strings, whose cancelled/absent state is
2085f4613f2SJohn Marino 	     * recorded in the terminfo database.
2095f4613f2SJohn Marino 	     */
2105f4613f2SJohn Marino 	    for (ep = &entries[1]; ep < entries + termcount; ep++)
2115f4613f2SJohn Marino 		if (ep->tterm.Booleans[idx] == TRUE) {
2125f4613f2SJohn Marino 		    is_set = entries[0].tterm.Booleans[idx];
2135f4613f2SJohn Marino 		    break;
2145f4613f2SJohn Marino 		}
2155f4613f2SJohn Marino 	    if (is_set != entries[0].tterm.Booleans[idx])
2165f4613f2SJohn Marino 		return (!is_set);
2175f4613f2SJohn Marino 	    else
2185f4613f2SJohn Marino 		return (FAIL);
2195f4613f2SJohn Marino 	}
2205f4613f2SJohn Marino 
2215f4613f2SJohn Marino     case NUMBER:
2225f4613f2SJohn Marino 	{
2235f4613f2SJohn Marino 	    int value = ABSENT_NUMERIC;
2245f4613f2SJohn Marino 
2255f4613f2SJohn Marino 	    /*
2265f4613f2SJohn Marino 	     * We take the semantics of multiple uses to be 'each
2275f4613f2SJohn Marino 	     * capability gets the first non-default value found
2285f4613f2SJohn Marino 	     * in the sequence of use entries'.
2295f4613f2SJohn Marino 	     */
2305f4613f2SJohn Marino 	    for (ep = &entries[1]; ep < entries + termcount; ep++)
2315f4613f2SJohn Marino 		if (VALID_NUMERIC(ep->tterm.Numbers[idx])) {
2325f4613f2SJohn Marino 		    value = ep->tterm.Numbers[idx];
2335f4613f2SJohn Marino 		    break;
2345f4613f2SJohn Marino 		}
2355f4613f2SJohn Marino 
2365f4613f2SJohn Marino 	    if (value != entries[0].tterm.Numbers[idx])
2375f4613f2SJohn Marino 		return (value != ABSENT_NUMERIC);
2385f4613f2SJohn Marino 	    else
2395f4613f2SJohn Marino 		return (FAIL);
2405f4613f2SJohn Marino 	}
2415f4613f2SJohn Marino 
2425f4613f2SJohn Marino     case STRING:
2435f4613f2SJohn Marino 	{
2445f4613f2SJohn Marino 	    char *termstr, *usestr = ABSENT_STRING;
2455f4613f2SJohn Marino 
2465f4613f2SJohn Marino 	    termstr = entries[0].tterm.Strings[idx];
2475f4613f2SJohn Marino 
2485f4613f2SJohn Marino 	    /*
2495f4613f2SJohn Marino 	     * We take the semantics of multiple uses to be 'each
2505f4613f2SJohn Marino 	     * capability gets the first non-default value found
2515f4613f2SJohn Marino 	     * in the sequence of use entries'.
2525f4613f2SJohn Marino 	     */
2535f4613f2SJohn Marino 	    for (ep = &entries[1]; ep < entries + termcount; ep++)
2545f4613f2SJohn Marino 		if (ep->tterm.Strings[idx]) {
2555f4613f2SJohn Marino 		    usestr = ep->tterm.Strings[idx];
2565f4613f2SJohn Marino 		    break;
2575f4613f2SJohn Marino 		}
2585f4613f2SJohn Marino 
2595f4613f2SJohn Marino 	    if (usestr == ABSENT_STRING && termstr == ABSENT_STRING)
2605f4613f2SJohn Marino 		return (FAIL);
2615f4613f2SJohn Marino 	    else if (!usestr || !termstr || capcmp(idx, usestr, termstr))
2625f4613f2SJohn Marino 		return (TRUE);
2635f4613f2SJohn Marino 	    else
2645f4613f2SJohn Marino 		return (FAIL);
2655f4613f2SJohn Marino 	}
2665f4613f2SJohn Marino     }
2675f4613f2SJohn Marino 
2685f4613f2SJohn Marino     return (FALSE);		/* pacify compiler */
2695f4613f2SJohn Marino }
2705f4613f2SJohn Marino 
2715f4613f2SJohn Marino static bool
useeq(ENTRY * e1,ENTRY * e2)2725f4613f2SJohn Marino useeq(ENTRY * e1, ENTRY * e2)
2735f4613f2SJohn Marino /* are the use references in two entries equivalent? */
2745f4613f2SJohn Marino {
2755f4613f2SJohn Marino     unsigned i, j;
2765f4613f2SJohn Marino 
2775f4613f2SJohn Marino     if (e1->nuses != e2->nuses)
2785f4613f2SJohn Marino 	return (FALSE);
2795f4613f2SJohn Marino 
2805f4613f2SJohn Marino     /* Ugh...this is quadratic again */
2815f4613f2SJohn Marino     for (i = 0; i < e1->nuses; i++) {
2825f4613f2SJohn Marino 	bool foundmatch = FALSE;
2835f4613f2SJohn Marino 
2845f4613f2SJohn Marino 	/* search second entry for given use reference */
2855f4613f2SJohn Marino 	for (j = 0; j < e2->nuses; j++)
2865f4613f2SJohn Marino 	    if (!strcmp(e1->uses[i].name, e2->uses[j].name)) {
2875f4613f2SJohn Marino 		foundmatch = TRUE;
2885f4613f2SJohn Marino 		break;
2895f4613f2SJohn Marino 	    }
2905f4613f2SJohn Marino 
2915f4613f2SJohn Marino 	if (!foundmatch)
2925f4613f2SJohn Marino 	    return (FALSE);
2935f4613f2SJohn Marino     }
2945f4613f2SJohn Marino 
2955f4613f2SJohn Marino     return (TRUE);
2965f4613f2SJohn Marino }
2975f4613f2SJohn Marino 
2985f4613f2SJohn Marino static bool
entryeq(TERMTYPE2 * t1,TERMTYPE2 * t2)299*32bb5217SDaniel Fojt entryeq(TERMTYPE2 *t1, TERMTYPE2 *t2)
3005f4613f2SJohn Marino /* are two entries equivalent? */
3015f4613f2SJohn Marino {
3025f4613f2SJohn Marino     unsigned i;
3035f4613f2SJohn Marino 
3045f4613f2SJohn Marino     for (i = 0; i < NUM_BOOLEANS(t1); i++)
3055f4613f2SJohn Marino 	if (t1->Booleans[i] != t2->Booleans[i])
3065f4613f2SJohn Marino 	    return (FALSE);
3075f4613f2SJohn Marino 
3085f4613f2SJohn Marino     for (i = 0; i < NUM_NUMBERS(t1); i++)
3095f4613f2SJohn Marino 	if (t1->Numbers[i] != t2->Numbers[i])
3105f4613f2SJohn Marino 	    return (FALSE);
3115f4613f2SJohn Marino 
3125f4613f2SJohn Marino     for (i = 0; i < NUM_STRINGS(t1); i++)
3135f4613f2SJohn Marino 	if (capcmp((PredIdx) i, t1->Strings[i], t2->Strings[i]))
3145f4613f2SJohn Marino 	    return (FALSE);
3155f4613f2SJohn Marino 
3165f4613f2SJohn Marino     return (TRUE);
3175f4613f2SJohn Marino }
3185f4613f2SJohn Marino 
3195f4613f2SJohn Marino #define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers)
3205f4613f2SJohn Marino 
3215f4613f2SJohn Marino static void
print_uses(ENTRY * ep,FILE * fp)3225f4613f2SJohn Marino print_uses(ENTRY * ep, FILE *fp)
3235f4613f2SJohn Marino /* print an entry's use references */
3245f4613f2SJohn Marino {
3255f4613f2SJohn Marino     unsigned i;
3265f4613f2SJohn Marino 
3275f4613f2SJohn Marino     if (!ep->nuses)
3285f4613f2SJohn Marino 	fputs("NULL", fp);
3295f4613f2SJohn Marino     else
3305f4613f2SJohn Marino 	for (i = 0; i < ep->nuses; i++) {
3315f4613f2SJohn Marino 	    fputs(ep->uses[i].name, fp);
3325f4613f2SJohn Marino 	    if (i < ep->nuses - 1)
3335f4613f2SJohn Marino 		fputs(" ", fp);
3345f4613f2SJohn Marino 	}
3355f4613f2SJohn Marino }
3365f4613f2SJohn Marino 
3375f4613f2SJohn Marino static const char *
dump_boolean(int val)3385f4613f2SJohn Marino dump_boolean(int val)
3395f4613f2SJohn Marino /* display the value of a boolean capability */
3405f4613f2SJohn Marino {
3415f4613f2SJohn Marino     switch (val) {
3425f4613f2SJohn Marino     case ABSENT_BOOLEAN:
3435f4613f2SJohn Marino 	return (s_absent);
3445f4613f2SJohn Marino     case CANCELLED_BOOLEAN:
3455f4613f2SJohn Marino 	return (s_cancel);
3465f4613f2SJohn Marino     case FALSE:
3475f4613f2SJohn Marino 	return ("F");
3485f4613f2SJohn Marino     case TRUE:
3495f4613f2SJohn Marino 	return ("T");
3505f4613f2SJohn Marino     default:
3515f4613f2SJohn Marino 	return ("?");
3525f4613f2SJohn Marino     }
3535f4613f2SJohn Marino }
3545f4613f2SJohn Marino 
3555f4613f2SJohn Marino static void
dump_numeric(int val,char * buf)3565f4613f2SJohn Marino dump_numeric(int val, char *buf)
357*32bb5217SDaniel Fojt /* display the value of a numeric capability */
3585f4613f2SJohn Marino {
3595f4613f2SJohn Marino     switch (val) {
3605f4613f2SJohn Marino     case ABSENT_NUMERIC:
3613468e90cSJohn Marino 	_nc_STRCPY(buf, s_absent, MAX_STRING);
3625f4613f2SJohn Marino 	break;
3635f4613f2SJohn Marino     case CANCELLED_NUMERIC:
3643468e90cSJohn Marino 	_nc_STRCPY(buf, s_cancel, MAX_STRING);
3655f4613f2SJohn Marino 	break;
3665f4613f2SJohn Marino     default:
3673468e90cSJohn Marino 	_nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING) "%d", val);
3685f4613f2SJohn Marino 	break;
3695f4613f2SJohn Marino     }
3705f4613f2SJohn Marino }
3715f4613f2SJohn Marino 
3725f4613f2SJohn Marino static void
dump_string(char * val,char * buf)3735f4613f2SJohn Marino dump_string(char *val, char *buf)
3745f4613f2SJohn Marino /* display the value of a string capability */
3755f4613f2SJohn Marino {
3765f4613f2SJohn Marino     if (val == ABSENT_STRING)
3773468e90cSJohn Marino 	_nc_STRCPY(buf, s_absent, MAX_STRING);
3785f4613f2SJohn Marino     else if (val == CANCELLED_STRING)
3793468e90cSJohn Marino 	_nc_STRCPY(buf, s_cancel, MAX_STRING);
3805f4613f2SJohn Marino     else {
3813468e90cSJohn Marino 	_nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING)
3823468e90cSJohn Marino 		    "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val));
3835f4613f2SJohn Marino     }
3845f4613f2SJohn Marino }
3855f4613f2SJohn Marino 
3863468e90cSJohn Marino /*
3873468e90cSJohn Marino  * Show "comparing..." message for the given terminal names.
3883468e90cSJohn Marino  */
3893468e90cSJohn Marino static void
show_comparing(char ** names)3903468e90cSJohn Marino show_comparing(char **names)
3913468e90cSJohn Marino {
3923468e90cSJohn Marino     if (itrace) {
3933468e90cSJohn Marino 	switch (compare) {
3943468e90cSJohn Marino 	case C_DIFFERENCE:
3953468e90cSJohn Marino 	    (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname);
3963468e90cSJohn Marino 	    break;
3973468e90cSJohn Marino 
3983468e90cSJohn Marino 	case C_COMMON:
3993468e90cSJohn Marino 	    (void) fprintf(stderr, "%s: dumping common capabilities\n", _nc_progname);
4003468e90cSJohn Marino 	    break;
4013468e90cSJohn Marino 
4023468e90cSJohn Marino 	case C_NAND:
4033468e90cSJohn Marino 	    (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname);
4043468e90cSJohn Marino 	    break;
4053468e90cSJohn Marino 	}
4063468e90cSJohn Marino     }
4073468e90cSJohn Marino     if (*names) {
4083468e90cSJohn Marino 	printf("comparing %s", *names++);
4093468e90cSJohn Marino 	if (*names) {
4103468e90cSJohn Marino 	    printf(" to %s", *names++);
4113468e90cSJohn Marino 	    while (*names) {
4123468e90cSJohn Marino 		printf(", %s", *names++);
4133468e90cSJohn Marino 	    }
4143468e90cSJohn Marino 	}
4153468e90cSJohn Marino 	printf(".\n");
4163468e90cSJohn Marino     }
4173468e90cSJohn Marino }
4183468e90cSJohn Marino 
4193468e90cSJohn Marino /*
4203468e90cSJohn Marino  * ncurses stores two types of non-standard capabilities:
4213468e90cSJohn Marino  * a) capabilities listed past the "STOP-HERE" comment in the Caps file.
4223468e90cSJohn Marino  *    These are used in the terminfo source file to provide data for termcaps,
4233468e90cSJohn Marino  *    e.g., when there is no equivalent capability in terminfo, as well as for
4243468e90cSJohn Marino  *    widely-used non-standard capabilities.
4253468e90cSJohn Marino  * b) user-definable capabilities, via "tic -x".
4263468e90cSJohn Marino  *
4273468e90cSJohn Marino  * However, if "-x" is omitted from the tic command, both types of
4283468e90cSJohn Marino  * non-standard capability are not loaded into the terminfo database.  This
4293468e90cSJohn Marino  * macro is used for limit-checks against the symbols that tic uses to omit
4303468e90cSJohn Marino  * the two types of non-standard entry.
4313468e90cSJohn Marino  */
4323468e90cSJohn Marino #if NCURSES_XNAMES
4333468e90cSJohn Marino #define check_user_definable(n,limit) if (!_nc_user_definable && (n) > (limit)) break
4343468e90cSJohn Marino #else
4353468e90cSJohn Marino #define check_user_definable(n,limit) if ((n) > (limit)) break
4363468e90cSJohn Marino #endif
4373468e90cSJohn Marino 
4383468e90cSJohn Marino /*
4393468e90cSJohn Marino  * Use these macros to simplify loops on C_COMMON and C_NAND:
4403468e90cSJohn Marino  */
4413468e90cSJohn Marino #define for_each_entry() while (entries[extra].tterm.term_names)
4423468e90cSJohn Marino #define next_entry           (&(entries[extra++].tterm))
4433468e90cSJohn Marino 
4445f4613f2SJohn Marino static void
compare_predicate(PredType type,PredIdx idx,const char * name)4455f4613f2SJohn Marino compare_predicate(PredType type, PredIdx idx, const char *name)
4465f4613f2SJohn Marino /* predicate function to use for entry difference reports */
4475f4613f2SJohn Marino {
4483468e90cSJohn Marino     ENTRY *e1 = &entries[0];
4493468e90cSJohn Marino     ENTRY *e2 = &entries[1];
4503468e90cSJohn Marino     char buf1[MAX_STRING];
4513468e90cSJohn Marino     char buf2[MAX_STRING];
4525f4613f2SJohn Marino     int b1, b2;
4535f4613f2SJohn Marino     int n1, n2;
4545f4613f2SJohn Marino     char *s1, *s2;
4553468e90cSJohn Marino     bool found;
4563468e90cSJohn Marino     int extra = 1;
4575f4613f2SJohn Marino 
4585f4613f2SJohn Marino     switch (type) {
4595f4613f2SJohn Marino     case CMP_BOOLEAN:
4603468e90cSJohn Marino 	check_user_definable(idx, BOOLWRITE);
4615f4613f2SJohn Marino 	b1 = e1->tterm.Booleans[idx];
4625f4613f2SJohn Marino 	switch (compare) {
4635f4613f2SJohn Marino 	case C_DIFFERENCE:
4643468e90cSJohn Marino 	    b2 = next_entry->Booleans[idx];
465*32bb5217SDaniel Fojt 	    if (!(no_boolean(b1) && no_boolean(b2)) && (b1 != b2))
4665f4613f2SJohn Marino 		(void) printf("\t%s: %s%s%s.\n",
4675f4613f2SJohn Marino 			      name,
4685f4613f2SJohn Marino 			      dump_boolean(b1),
4695f4613f2SJohn Marino 			      bool_sep,
4705f4613f2SJohn Marino 			      dump_boolean(b2));
4715f4613f2SJohn Marino 	    break;
4725f4613f2SJohn Marino 
4735f4613f2SJohn Marino 	case C_COMMON:
4743468e90cSJohn Marino 	    if (b1 != ABSENT_BOOLEAN) {
4753468e90cSJohn Marino 		found = TRUE;
4763468e90cSJohn Marino 		for_each_entry() {
4773468e90cSJohn Marino 		    b2 = next_entry->Booleans[idx];
4783468e90cSJohn Marino 		    if (b1 != b2) {
4793468e90cSJohn Marino 			found = FALSE;
4803468e90cSJohn Marino 			break;
4813468e90cSJohn Marino 		    }
4823468e90cSJohn Marino 		}
4833468e90cSJohn Marino 		if (found) {
4845f4613f2SJohn Marino 		    (void) printf("\t%s= %s.\n", name, dump_boolean(b1));
4853468e90cSJohn Marino 		}
4863468e90cSJohn Marino 	    }
4875f4613f2SJohn Marino 	    break;
4885f4613f2SJohn Marino 
4895f4613f2SJohn Marino 	case C_NAND:
4903468e90cSJohn Marino 	    if (b1 == ABSENT_BOOLEAN) {
4913468e90cSJohn Marino 		found = TRUE;
4923468e90cSJohn Marino 		for_each_entry() {
4933468e90cSJohn Marino 		    b2 = next_entry->Booleans[idx];
4943468e90cSJohn Marino 		    if (b1 != b2) {
4953468e90cSJohn Marino 			found = FALSE;
4963468e90cSJohn Marino 			break;
4973468e90cSJohn Marino 		    }
4983468e90cSJohn Marino 		}
4993468e90cSJohn Marino 		if (found) {
5005f4613f2SJohn Marino 		    (void) printf("\t!%s.\n", name);
5013468e90cSJohn Marino 		}
5023468e90cSJohn Marino 	    }
5035f4613f2SJohn Marino 	    break;
5045f4613f2SJohn Marino 	}
5055f4613f2SJohn Marino 	break;
5065f4613f2SJohn Marino 
5075f4613f2SJohn Marino     case CMP_NUMBER:
5083468e90cSJohn Marino 	check_user_definable(idx, NUMWRITE);
5095f4613f2SJohn Marino 	n1 = e1->tterm.Numbers[idx];
5105f4613f2SJohn Marino 	switch (compare) {
5115f4613f2SJohn Marino 	case C_DIFFERENCE:
5123468e90cSJohn Marino 	    n2 = next_entry->Numbers[idx];
513*32bb5217SDaniel Fojt 	    if (!(no_numeric(n1) && no_numeric(n2)) && n1 != n2) {
5143468e90cSJohn Marino 		dump_numeric(n1, buf1);
5153468e90cSJohn Marino 		dump_numeric(n2, buf2);
5165f4613f2SJohn Marino 		(void) printf("\t%s: %s, %s.\n", name, buf1, buf2);
5173468e90cSJohn Marino 	    }
5185f4613f2SJohn Marino 	    break;
5195f4613f2SJohn Marino 
5205f4613f2SJohn Marino 	case C_COMMON:
5213468e90cSJohn Marino 	    if (n1 != ABSENT_NUMERIC) {
5223468e90cSJohn Marino 		found = TRUE;
5233468e90cSJohn Marino 		for_each_entry() {
5243468e90cSJohn Marino 		    n2 = next_entry->Numbers[idx];
5253468e90cSJohn Marino 		    if (n1 != n2) {
5263468e90cSJohn Marino 			found = FALSE;
5273468e90cSJohn Marino 			break;
5283468e90cSJohn Marino 		    }
5293468e90cSJohn Marino 		}
5303468e90cSJohn Marino 		if (found) {
5313468e90cSJohn Marino 		    dump_numeric(n1, buf1);
5325f4613f2SJohn Marino 		    (void) printf("\t%s= %s.\n", name, buf1);
5333468e90cSJohn Marino 		}
5343468e90cSJohn Marino 	    }
5355f4613f2SJohn Marino 	    break;
5365f4613f2SJohn Marino 
5375f4613f2SJohn Marino 	case C_NAND:
5383468e90cSJohn Marino 	    if (n1 == ABSENT_NUMERIC) {
5393468e90cSJohn Marino 		found = TRUE;
5403468e90cSJohn Marino 		for_each_entry() {
5413468e90cSJohn Marino 		    n2 = next_entry->Numbers[idx];
5423468e90cSJohn Marino 		    if (n1 != n2) {
5433468e90cSJohn Marino 			found = FALSE;
5443468e90cSJohn Marino 			break;
5453468e90cSJohn Marino 		    }
5463468e90cSJohn Marino 		}
5473468e90cSJohn Marino 		if (found) {
5485f4613f2SJohn Marino 		    (void) printf("\t!%s.\n", name);
5493468e90cSJohn Marino 		}
5503468e90cSJohn Marino 	    }
5515f4613f2SJohn Marino 	    break;
5525f4613f2SJohn Marino 	}
5535f4613f2SJohn Marino 	break;
5545f4613f2SJohn Marino 
5555f4613f2SJohn Marino     case CMP_STRING:
5563468e90cSJohn Marino 	check_user_definable(idx, STRWRITE);
5575f4613f2SJohn Marino 	s1 = e1->tterm.Strings[idx];
5585f4613f2SJohn Marino 	switch (compare) {
5595f4613f2SJohn Marino 	case C_DIFFERENCE:
5603468e90cSJohn Marino 	    s2 = next_entry->Strings[idx];
561*32bb5217SDaniel Fojt 	    if (!(no_string(s1) && no_string(s2)) && capcmp(idx, s1, s2)) {
5625f4613f2SJohn Marino 		dump_string(s1, buf1);
5635f4613f2SJohn Marino 		dump_string(s2, buf2);
5645f4613f2SJohn Marino 		if (strcmp(buf1, buf2))
5655f4613f2SJohn Marino 		    (void) printf("\t%s: %s, %s.\n", name, buf1, buf2);
5665f4613f2SJohn Marino 	    }
5675f4613f2SJohn Marino 	    break;
5685f4613f2SJohn Marino 
5695f4613f2SJohn Marino 	case C_COMMON:
5703468e90cSJohn Marino 	    if (s1 != ABSENT_STRING) {
5713468e90cSJohn Marino 		found = TRUE;
5723468e90cSJohn Marino 		for_each_entry() {
5733468e90cSJohn Marino 		    s2 = next_entry->Strings[idx];
5743468e90cSJohn Marino 		    if (capcmp(idx, s1, s2) != 0) {
5753468e90cSJohn Marino 			found = FALSE;
5763468e90cSJohn Marino 			break;
5773468e90cSJohn Marino 		    }
5783468e90cSJohn Marino 		}
5793468e90cSJohn Marino 		if (found) {
5805f4613f2SJohn Marino 		    (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1));
5813468e90cSJohn Marino 		}
5823468e90cSJohn Marino 	    }
5835f4613f2SJohn Marino 	    break;
5845f4613f2SJohn Marino 
5855f4613f2SJohn Marino 	case C_NAND:
5863468e90cSJohn Marino 	    if (s1 == ABSENT_STRING) {
5873468e90cSJohn Marino 		found = TRUE;
5883468e90cSJohn Marino 		for_each_entry() {
5893468e90cSJohn Marino 		    s2 = next_entry->Strings[idx];
5903468e90cSJohn Marino 		    if (s2 != s1) {
5913468e90cSJohn Marino 			found = FALSE;
5923468e90cSJohn Marino 			break;
5933468e90cSJohn Marino 		    }
5943468e90cSJohn Marino 		}
5953468e90cSJohn Marino 		if (found) {
5965f4613f2SJohn Marino 		    (void) printf("\t!%s.\n", name);
5973468e90cSJohn Marino 		}
5983468e90cSJohn Marino 	    }
5995f4613f2SJohn Marino 	    break;
6005f4613f2SJohn Marino 	}
6015f4613f2SJohn Marino 	break;
6025f4613f2SJohn Marino 
6035f4613f2SJohn Marino     case CMP_USE:
6045f4613f2SJohn Marino 	/* unlike the other modes, this compares *all* use entries */
6055f4613f2SJohn Marino 	switch (compare) {
6065f4613f2SJohn Marino 	case C_DIFFERENCE:
6075f4613f2SJohn Marino 	    if (!useeq(e1, e2)) {
6085f4613f2SJohn Marino 		(void) fputs("\tuse: ", stdout);
6095f4613f2SJohn Marino 		print_uses(e1, stdout);
6105f4613f2SJohn Marino 		fputs(", ", stdout);
6115f4613f2SJohn Marino 		print_uses(e2, stdout);
6125f4613f2SJohn Marino 		fputs(".\n", stdout);
6135f4613f2SJohn Marino 	    }
6145f4613f2SJohn Marino 	    break;
6155f4613f2SJohn Marino 
6165f4613f2SJohn Marino 	case C_COMMON:
6173468e90cSJohn Marino 	    if (e1->nuses) {
6183468e90cSJohn Marino 		found = TRUE;
6193468e90cSJohn Marino 		for_each_entry() {
6203468e90cSJohn Marino 		    e2 = &entries[extra++];
6213468e90cSJohn Marino 		    if (e2->nuses != e1->nuses || !useeq(e1, e2)) {
6223468e90cSJohn Marino 			found = FALSE;
6233468e90cSJohn Marino 			break;
6243468e90cSJohn Marino 		    }
6253468e90cSJohn Marino 		}
6263468e90cSJohn Marino 		if (found) {
6275f4613f2SJohn Marino 		    (void) fputs("\tuse: ", stdout);
6285f4613f2SJohn Marino 		    print_uses(e1, stdout);
6295f4613f2SJohn Marino 		    fputs(".\n", stdout);
6305f4613f2SJohn Marino 		}
6313468e90cSJohn Marino 	    }
6325f4613f2SJohn Marino 	    break;
6335f4613f2SJohn Marino 
6345f4613f2SJohn Marino 	case C_NAND:
6353468e90cSJohn Marino 	    if (!e1->nuses) {
6363468e90cSJohn Marino 		found = TRUE;
6373468e90cSJohn Marino 		for_each_entry() {
6383468e90cSJohn Marino 		    e2 = &entries[extra++];
6393468e90cSJohn Marino 		    if (e2->nuses != e1->nuses) {
6403468e90cSJohn Marino 			found = FALSE;
6413468e90cSJohn Marino 			break;
6423468e90cSJohn Marino 		    }
6433468e90cSJohn Marino 		}
6443468e90cSJohn Marino 		if (found) {
6455f4613f2SJohn Marino 		    (void) printf("\t!use.\n");
6463468e90cSJohn Marino 		}
6473468e90cSJohn Marino 	    }
6485f4613f2SJohn Marino 	    break;
6495f4613f2SJohn Marino 	}
6505f4613f2SJohn Marino     }
6515f4613f2SJohn Marino }
6525f4613f2SJohn Marino 
6535f4613f2SJohn Marino /***************************************************************************
6545f4613f2SJohn Marino  *
6555f4613f2SJohn Marino  * Init string analysis
6565f4613f2SJohn Marino  *
6575f4613f2SJohn Marino  ***************************************************************************/
6585f4613f2SJohn Marino 
6593468e90cSJohn Marino #define DATA(from, to) { { from }, { to } }
6603468e90cSJohn Marino #define DATAX()        DATA("", "")
6613468e90cSJohn Marino 
6625f4613f2SJohn Marino typedef struct {
6633468e90cSJohn Marino     const char from[4];
6643468e90cSJohn Marino     const char to[12];
6655f4613f2SJohn Marino } assoc;
6665f4613f2SJohn Marino 
6675f4613f2SJohn Marino static const assoc std_caps[] =
6685f4613f2SJohn Marino {
6695f4613f2SJohn Marino     /* these are specified by X.364 and iBCS2 */
6703468e90cSJohn Marino     DATA("\033c", "RIS"),	/* full reset */
6713468e90cSJohn Marino     DATA("\0337", "SC"),	/* save cursor */
6723468e90cSJohn Marino     DATA("\0338", "RC"),	/* restore cursor */
6733468e90cSJohn Marino     DATA("\033[r", "RSR"),	/* not an X.364 mnemonic */
6743468e90cSJohn Marino     DATA("\033[m", "SGR0"),	/* not an X.364 mnemonic */
6753468e90cSJohn Marino     DATA("\033[2J", "ED2"),	/* clear page */
6765f4613f2SJohn Marino 
6775f4613f2SJohn Marino     /* this group is specified by ISO 2022 */
6783468e90cSJohn Marino     DATA("\033(0", "ISO DEC G0"),	/* enable DEC graphics for G0 */
6793468e90cSJohn Marino     DATA("\033(A", "ISO UK G0"),	/* enable UK chars for G0 */
6803468e90cSJohn Marino     DATA("\033(B", "ISO US G0"),	/* enable US chars for G0 */
6813468e90cSJohn Marino     DATA("\033)0", "ISO DEC G1"),	/* enable DEC graphics for G1 */
6823468e90cSJohn Marino     DATA("\033)A", "ISO UK G1"),	/* enable UK chars for G1 */
6833468e90cSJohn Marino     DATA("\033)B", "ISO US G1"),	/* enable US chars for G1 */
6845f4613f2SJohn Marino 
6855f4613f2SJohn Marino     /* these are DEC private controls widely supported by emulators */
6863468e90cSJohn Marino     DATA("\033=", "DECPAM"),	/* application keypad mode */
6873468e90cSJohn Marino     DATA("\033>", "DECPNM"),	/* normal keypad mode */
6883468e90cSJohn Marino     DATA("\033<", "DECANSI"),	/* enter ANSI mode */
6893468e90cSJohn Marino     DATA("\033[!p", "DECSTR"),	/* soft reset */
6903468e90cSJohn Marino     DATA("\033 F", "S7C1T"),	/* 7-bit controls */
6915f4613f2SJohn Marino 
6923468e90cSJohn Marino     DATAX()
6935f4613f2SJohn Marino };
6945f4613f2SJohn Marino 
6955f4613f2SJohn Marino static const assoc std_modes[] =
6965f4613f2SJohn Marino /* ECMA \E[ ... [hl] modes recognized by many emulators */
6975f4613f2SJohn Marino {
6983468e90cSJohn Marino     DATA("2", "AM"),		/* keyboard action mode */
6993468e90cSJohn Marino     DATA("4", "IRM"),		/* insert/replace mode */
7003468e90cSJohn Marino     DATA("12", "SRM"),		/* send/receive mode */
7013468e90cSJohn Marino     DATA("20", "LNM"),		/* linefeed mode */
7023468e90cSJohn Marino     DATAX()
7035f4613f2SJohn Marino };
7045f4613f2SJohn Marino 
7055f4613f2SJohn Marino static const assoc private_modes[] =
7065f4613f2SJohn Marino /* DEC \E[ ... [hl] modes recognized by many emulators */
7075f4613f2SJohn Marino {
7083468e90cSJohn Marino     DATA("1", "CKM"),		/* application cursor keys */
7093468e90cSJohn Marino     DATA("2", "ANM"),		/* set VT52 mode */
7103468e90cSJohn Marino     DATA("3", "COLM"),		/* 132-column mode */
7113468e90cSJohn Marino     DATA("4", "SCLM"),		/* smooth scroll */
7123468e90cSJohn Marino     DATA("5", "SCNM"),		/* reverse video mode */
7133468e90cSJohn Marino     DATA("6", "OM"),		/* origin mode */
7143468e90cSJohn Marino     DATA("7", "AWM"),		/* wraparound mode */
7153468e90cSJohn Marino     DATA("8", "ARM"),		/* auto-repeat mode */
7163468e90cSJohn Marino     DATAX()
7175f4613f2SJohn Marino };
7185f4613f2SJohn Marino 
7195f4613f2SJohn Marino static const assoc ecma_highlights[] =
7205f4613f2SJohn Marino /* recognize ECMA attribute sequences */
7215f4613f2SJohn Marino {
7223468e90cSJohn Marino     DATA("0", "NORMAL"),	/* normal */
7233468e90cSJohn Marino     DATA("1", "+BOLD"),		/* bold on */
7243468e90cSJohn Marino     DATA("2", "+DIM"),		/* dim on */
7253468e90cSJohn Marino     DATA("3", "+ITALIC"),	/* italic on */
7263468e90cSJohn Marino     DATA("4", "+UNDERLINE"),	/* underline on */
7273468e90cSJohn Marino     DATA("5", "+BLINK"),	/* blink on */
7283468e90cSJohn Marino     DATA("6", "+FASTBLINK"),	/* fastblink on */
7293468e90cSJohn Marino     DATA("7", "+REVERSE"),	/* reverse on */
7303468e90cSJohn Marino     DATA("8", "+INVISIBLE"),	/* invisible on */
7313468e90cSJohn Marino     DATA("9", "+DELETED"),	/* deleted on */
7323468e90cSJohn Marino     DATA("10", "MAIN-FONT"),	/* select primary font */
7333468e90cSJohn Marino     DATA("11", "ALT-FONT-1"),	/* select alternate font 1 */
7343468e90cSJohn Marino     DATA("12", "ALT-FONT-2"),	/* select alternate font 2 */
7353468e90cSJohn Marino     DATA("13", "ALT-FONT-3"),	/* select alternate font 3 */
7363468e90cSJohn Marino     DATA("14", "ALT-FONT-4"),	/* select alternate font 4 */
7373468e90cSJohn Marino     DATA("15", "ALT-FONT-5"),	/* select alternate font 5 */
7383468e90cSJohn Marino     DATA("16", "ALT-FONT-6"),	/* select alternate font 6 */
7393468e90cSJohn Marino     DATA("17", "ALT-FONT-7"),	/* select alternate font 7 */
7403468e90cSJohn Marino     DATA("18", "ALT-FONT-1"),	/* select alternate font 1 */
7413468e90cSJohn Marino     DATA("19", "ALT-FONT-1"),	/* select alternate font 1 */
7423468e90cSJohn Marino     DATA("20", "FRAKTUR"),	/* Fraktur font */
7433468e90cSJohn Marino     DATA("21", "DOUBLEUNDER"),	/* double underline */
7443468e90cSJohn Marino     DATA("22", "-DIM"),		/* dim off */
7453468e90cSJohn Marino     DATA("23", "-ITALIC"),	/* italic off */
7463468e90cSJohn Marino     DATA("24", "-UNDERLINE"),	/* underline off */
7473468e90cSJohn Marino     DATA("25", "-BLINK"),	/* blink off */
7483468e90cSJohn Marino     DATA("26", "-FASTBLINK"),	/* fastblink off */
7493468e90cSJohn Marino     DATA("27", "-REVERSE"),	/* reverse off */
7503468e90cSJohn Marino     DATA("28", "-INVISIBLE"),	/* invisible off */
7513468e90cSJohn Marino     DATA("29", "-DELETED"),	/* deleted off */
7523468e90cSJohn Marino     DATAX()
7535f4613f2SJohn Marino };
7545f4613f2SJohn Marino 
7553468e90cSJohn Marino #undef DATA
7563468e90cSJohn Marino 
7575f4613f2SJohn Marino static int
skip_csi(const char * cap)7585f4613f2SJohn Marino skip_csi(const char *cap)
7595f4613f2SJohn Marino {
7605f4613f2SJohn Marino     int result = 0;
7615f4613f2SJohn Marino     if (cap[0] == '\033' && cap[1] == '[')
7625f4613f2SJohn Marino 	result = 2;
7635f4613f2SJohn Marino     else if (UChar(cap[0]) == 0233)
7645f4613f2SJohn Marino 	result = 1;
7655f4613f2SJohn Marino     return result;
7665f4613f2SJohn Marino }
7675f4613f2SJohn Marino 
7685f4613f2SJohn Marino static bool
same_param(const char * table,const char * param,size_t length)7693468e90cSJohn Marino same_param(const char *table, const char *param, size_t length)
7705f4613f2SJohn Marino {
7715f4613f2SJohn Marino     bool result = FALSE;
7725f4613f2SJohn Marino     if (strncmp(table, param, length) == 0) {
7735f4613f2SJohn Marino 	result = !isdigit(UChar(param[length]));
7745f4613f2SJohn Marino     }
7755f4613f2SJohn Marino     return result;
7765f4613f2SJohn Marino }
7775f4613f2SJohn Marino 
7785f4613f2SJohn Marino static char *
lookup_params(const assoc * table,char * dst,char * src)7795f4613f2SJohn Marino lookup_params(const assoc * table, char *dst, char *src)
7805f4613f2SJohn Marino {
7815f4613f2SJohn Marino     char *result = 0;
7825f4613f2SJohn Marino     const char *ep = strtok(src, ";");
7835f4613f2SJohn Marino 
7845f4613f2SJohn Marino     if (ep != 0) {
7855f4613f2SJohn Marino 	const assoc *ap;
7865f4613f2SJohn Marino 
7875f4613f2SJohn Marino 	do {
7885f4613f2SJohn Marino 	    bool found = FALSE;
7895f4613f2SJohn Marino 
7903468e90cSJohn Marino 	    for (ap = table; ap->from[0]; ap++) {
7915f4613f2SJohn Marino 		size_t tlen = strlen(ap->from);
7925f4613f2SJohn Marino 
7935f4613f2SJohn Marino 		if (same_param(ap->from, ep, tlen)) {
7943468e90cSJohn Marino 		    _nc_STRCAT(dst, ap->to, MAX_TERMINFO_LENGTH);
7955f4613f2SJohn Marino 		    found = TRUE;
7965f4613f2SJohn Marino 		    break;
7975f4613f2SJohn Marino 		}
7985f4613f2SJohn Marino 	    }
7995f4613f2SJohn Marino 
8005f4613f2SJohn Marino 	    if (!found)
8013468e90cSJohn Marino 		_nc_STRCAT(dst, ep, MAX_TERMINFO_LENGTH);
8023468e90cSJohn Marino 	    _nc_STRCAT(dst, ";", MAX_TERMINFO_LENGTH);
8035f4613f2SJohn Marino 	} while
8045f4613f2SJohn Marino 	    ((ep = strtok((char *) 0, ";")));
8055f4613f2SJohn Marino 
8065f4613f2SJohn Marino 	dst[strlen(dst) - 1] = '\0';
8075f4613f2SJohn Marino 
8085f4613f2SJohn Marino 	result = dst;
8095f4613f2SJohn Marino     }
8105f4613f2SJohn Marino     return result;
8115f4613f2SJohn Marino }
8125f4613f2SJohn Marino 
8135f4613f2SJohn Marino static void
analyze_string(const char * name,const char * cap,TERMTYPE2 * tp)814*32bb5217SDaniel Fojt analyze_string(const char *name, const char *cap, TERMTYPE2 *tp)
8155f4613f2SJohn Marino {
8165f4613f2SJohn Marino     char buf2[MAX_TERMINFO_LENGTH];
8175f4613f2SJohn Marino     const char *sp;
8185f4613f2SJohn Marino     const assoc *ap;
8195f4613f2SJohn Marino     int tp_lines = tp->Numbers[2];
8205f4613f2SJohn Marino 
8213468e90cSJohn Marino     if (!VALID_STRING(cap))
8225f4613f2SJohn Marino 	return;
8235f4613f2SJohn Marino     (void) printf("%s: ", name);
8245f4613f2SJohn Marino 
8255f4613f2SJohn Marino     for (sp = cap; *sp; sp++) {
8265f4613f2SJohn Marino 	int i;
8275f4613f2SJohn Marino 	int csi;
8285f4613f2SJohn Marino 	size_t len = 0;
8295f4613f2SJohn Marino 	size_t next;
8305f4613f2SJohn Marino 	const char *expansion = 0;
8315f4613f2SJohn Marino 	char buf3[MAX_TERMINFO_LENGTH];
8325f4613f2SJohn Marino 
8335f4613f2SJohn Marino 	/* first, check other capabilities in this entry */
8345f4613f2SJohn Marino 	for (i = 0; i < STRCOUNT; i++) {
8355f4613f2SJohn Marino 	    char *cp = tp->Strings[i];
8365f4613f2SJohn Marino 
8373468e90cSJohn Marino 	    /* don't use function-key capabilities */
8383468e90cSJohn Marino 	    if (strnames[i][0] == 'k' && strnames[i][1] == 'f')
8395f4613f2SJohn Marino 		continue;
8405f4613f2SJohn Marino 
8413468e90cSJohn Marino 	    if (VALID_STRING(cp) &&
8423468e90cSJohn Marino 		cp[0] != '\0' &&
8433468e90cSJohn Marino 		cp != cap) {
8445f4613f2SJohn Marino 		len = strlen(cp);
845*32bb5217SDaniel Fojt 		_nc_STRNCPY(buf2, sp, len);
8465f4613f2SJohn Marino 		buf2[len] = '\0';
8475f4613f2SJohn Marino 
8485f4613f2SJohn Marino 		if (_nc_capcmp(cp, buf2))
8495f4613f2SJohn Marino 		    continue;
8505f4613f2SJohn Marino 
8513468e90cSJohn Marino #define ISRS(s)	(!strncmp((s), "is", (size_t) 2) || !strncmp((s), "rs", (size_t) 2))
8525f4613f2SJohn Marino 		/*
8535f4613f2SJohn Marino 		 * Theoretically we just passed the test for translation
8545f4613f2SJohn Marino 		 * (equality once the padding is stripped).  However, there
8555f4613f2SJohn Marino 		 * are a few more hoops that need to be jumped so that
8565f4613f2SJohn Marino 		 * identical pairs of initialization and reset strings
8575f4613f2SJohn Marino 		 * don't just refer to each other.
8585f4613f2SJohn Marino 		 */
8595f4613f2SJohn Marino 		if (ISRS(name) || ISRS(strnames[i]))
8605f4613f2SJohn Marino 		    if (cap < cp)
8615f4613f2SJohn Marino 			continue;
8625f4613f2SJohn Marino #undef ISRS
8635f4613f2SJohn Marino 
8645f4613f2SJohn Marino 		expansion = strnames[i];
8655f4613f2SJohn Marino 		break;
8665f4613f2SJohn Marino 	    }
8675f4613f2SJohn Marino 	}
8685f4613f2SJohn Marino 
8695f4613f2SJohn Marino 	/* now check the standard capabilities */
8705f4613f2SJohn Marino 	if (!expansion) {
8715f4613f2SJohn Marino 	    csi = skip_csi(sp);
8723468e90cSJohn Marino 	    for (ap = std_caps; ap->from[0]; ap++) {
8735f4613f2SJohn Marino 		size_t adj = (size_t) (csi ? 2 : 0);
8745f4613f2SJohn Marino 
8755f4613f2SJohn Marino 		len = strlen(ap->from);
8765f4613f2SJohn Marino 		if (csi && skip_csi(ap->from) != csi)
8775f4613f2SJohn Marino 		    continue;
8785f4613f2SJohn Marino 		if (len > adj
8795f4613f2SJohn Marino 		    && strncmp(ap->from + adj, sp + csi, len - adj) == 0) {
8805f4613f2SJohn Marino 		    expansion = ap->to;
8815f4613f2SJohn Marino 		    len -= adj;
8825f4613f2SJohn Marino 		    len += (size_t) csi;
8835f4613f2SJohn Marino 		    break;
8845f4613f2SJohn Marino 		}
8855f4613f2SJohn Marino 	    }
8865f4613f2SJohn Marino 	}
8875f4613f2SJohn Marino 
8885f4613f2SJohn Marino 	/* now check for standard-mode sequences */
8895f4613f2SJohn Marino 	if (!expansion
8905f4613f2SJohn Marino 	    && (csi = skip_csi(sp)) != 0
8913468e90cSJohn Marino 	    && (len = (strspn) (sp + csi, "0123456789;"))
8925f4613f2SJohn Marino 	    && (len < sizeof(buf3))
8935f4613f2SJohn Marino 	    && (next = (size_t) csi + len)
8945f4613f2SJohn Marino 	    && ((sp[next] == 'h') || (sp[next] == 'l'))) {
8955f4613f2SJohn Marino 
8963468e90cSJohn Marino 	    _nc_STRCPY(buf2,
8973468e90cSJohn Marino 		       ((sp[next] == 'h')
8983468e90cSJohn Marino 			? "ECMA+"
8993468e90cSJohn Marino 			: "ECMA-"),
9003468e90cSJohn Marino 		       sizeof(buf2));
901*32bb5217SDaniel Fojt 	    _nc_STRNCPY(buf3, sp + csi, len);
9025f4613f2SJohn Marino 	    buf3[len] = '\0';
9035f4613f2SJohn Marino 	    len += (size_t) csi + 1;
9045f4613f2SJohn Marino 
9055f4613f2SJohn Marino 	    expansion = lookup_params(std_modes, buf2, buf3);
9065f4613f2SJohn Marino 	}
9075f4613f2SJohn Marino 
9085f4613f2SJohn Marino 	/* now check for private-mode sequences */
9095f4613f2SJohn Marino 	if (!expansion
9105f4613f2SJohn Marino 	    && (csi = skip_csi(sp)) != 0
9115f4613f2SJohn Marino 	    && sp[csi] == '?'
9123468e90cSJohn Marino 	    && (len = (strspn) (sp + csi + 1, "0123456789;"))
9135f4613f2SJohn Marino 	    && (len < sizeof(buf3))
9145f4613f2SJohn Marino 	    && (next = (size_t) csi + 1 + len)
9155f4613f2SJohn Marino 	    && ((sp[next] == 'h') || (sp[next] == 'l'))) {
9165f4613f2SJohn Marino 
9173468e90cSJohn Marino 	    _nc_STRCPY(buf2,
9183468e90cSJohn Marino 		       ((sp[next] == 'h')
9193468e90cSJohn Marino 			? "DEC+"
9203468e90cSJohn Marino 			: "DEC-"),
9213468e90cSJohn Marino 		       sizeof(buf2));
922*32bb5217SDaniel Fojt 	    _nc_STRNCPY(buf3, sp + csi + 1, len);
9235f4613f2SJohn Marino 	    buf3[len] = '\0';
9245f4613f2SJohn Marino 	    len += (size_t) csi + 2;
9255f4613f2SJohn Marino 
9265f4613f2SJohn Marino 	    expansion = lookup_params(private_modes, buf2, buf3);
9275f4613f2SJohn Marino 	}
9285f4613f2SJohn Marino 
9295f4613f2SJohn Marino 	/* now check for ECMA highlight sequences */
9305f4613f2SJohn Marino 	if (!expansion
9315f4613f2SJohn Marino 	    && (csi = skip_csi(sp)) != 0
9323468e90cSJohn Marino 	    && (len = (strspn) (sp + csi, "0123456789;")) != 0
9335f4613f2SJohn Marino 	    && (len < sizeof(buf3))
9345f4613f2SJohn Marino 	    && (next = (size_t) csi + len)
9355f4613f2SJohn Marino 	    && sp[next] == 'm') {
9365f4613f2SJohn Marino 
9373468e90cSJohn Marino 	    _nc_STRCPY(buf2, "SGR:", sizeof(buf2));
938*32bb5217SDaniel Fojt 	    _nc_STRNCPY(buf3, sp + csi, len);
9395f4613f2SJohn Marino 	    buf3[len] = '\0';
9405f4613f2SJohn Marino 	    len += (size_t) csi + 1;
9415f4613f2SJohn Marino 
9425f4613f2SJohn Marino 	    expansion = lookup_params(ecma_highlights, buf2, buf3);
9435f4613f2SJohn Marino 	}
9445f4613f2SJohn Marino 
9455f4613f2SJohn Marino 	if (!expansion
9465f4613f2SJohn Marino 	    && (csi = skip_csi(sp)) != 0
9475f4613f2SJohn Marino 	    && sp[csi] == 'm') {
9485f4613f2SJohn Marino 	    len = (size_t) csi + 1;
9493468e90cSJohn Marino 	    _nc_STRCPY(buf2, "SGR:", sizeof(buf2));
9503468e90cSJohn Marino 	    _nc_STRCAT(buf2, ecma_highlights[0].to, sizeof(buf2));
9515f4613f2SJohn Marino 	    expansion = buf2;
9525f4613f2SJohn Marino 	}
9535f4613f2SJohn Marino 
9545f4613f2SJohn Marino 	/* now check for scroll region reset */
9555f4613f2SJohn Marino 	if (!expansion
9565f4613f2SJohn Marino 	    && (csi = skip_csi(sp)) != 0) {
9575f4613f2SJohn Marino 	    if (sp[csi] == 'r') {
9585f4613f2SJohn Marino 		expansion = "RSR";
9595f4613f2SJohn Marino 		len = 1;
9605f4613f2SJohn Marino 	    } else {
9613468e90cSJohn Marino 		_nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "1;%dr", tp_lines);
9625f4613f2SJohn Marino 		len = strlen(buf2);
9635f4613f2SJohn Marino 		if (strncmp(buf2, sp + csi, len) == 0)
9645f4613f2SJohn Marino 		    expansion = "RSR";
9655f4613f2SJohn Marino 	    }
9665f4613f2SJohn Marino 	    len += (size_t) csi;
9675f4613f2SJohn Marino 	}
9685f4613f2SJohn Marino 
9695f4613f2SJohn Marino 	/* now check for home-down */
9705f4613f2SJohn Marino 	if (!expansion
9715f4613f2SJohn Marino 	    && (csi = skip_csi(sp)) != 0) {
9723468e90cSJohn Marino 	    _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "%d;1H", tp_lines);
9735f4613f2SJohn Marino 	    len = strlen(buf2);
9745f4613f2SJohn Marino 	    if (strncmp(buf2, sp + csi, len) == 0) {
9755f4613f2SJohn Marino 		expansion = "LL";
9765f4613f2SJohn Marino 	    } else {
9773468e90cSJohn Marino 		_nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "%dH", tp_lines);
9785f4613f2SJohn Marino 		len = strlen(buf2);
9795f4613f2SJohn Marino 		if (strncmp(buf2, sp + csi, len) == 0) {
9805f4613f2SJohn Marino 		    expansion = "LL";
9815f4613f2SJohn Marino 		}
9825f4613f2SJohn Marino 	    }
9835f4613f2SJohn Marino 	    len += (size_t) csi;
9845f4613f2SJohn Marino 	}
9855f4613f2SJohn Marino 
9865f4613f2SJohn Marino 	/* now look at the expansion we got, if any */
9875f4613f2SJohn Marino 	if (expansion) {
9885f4613f2SJohn Marino 	    printf("{%s}", expansion);
9895f4613f2SJohn Marino 	    sp += len - 1;
9905f4613f2SJohn Marino 	} else {
9915f4613f2SJohn Marino 	    /* couldn't match anything */
9925f4613f2SJohn Marino 	    buf2[0] = *sp;
9935f4613f2SJohn Marino 	    buf2[1] = '\0';
9945f4613f2SJohn Marino 	    fputs(TIC_EXPAND(buf2), stdout);
9955f4613f2SJohn Marino 	}
9965f4613f2SJohn Marino     }
9975f4613f2SJohn Marino     putchar('\n');
9985f4613f2SJohn Marino }
9995f4613f2SJohn Marino 
10005f4613f2SJohn Marino /***************************************************************************
10015f4613f2SJohn Marino  *
10025f4613f2SJohn Marino  * File comparison
10035f4613f2SJohn Marino  *
10045f4613f2SJohn Marino  ***************************************************************************/
10055f4613f2SJohn Marino 
10065f4613f2SJohn Marino static void
file_comparison(int argc,char * argv[])10075f4613f2SJohn Marino file_comparison(int argc, char *argv[])
10085f4613f2SJohn Marino {
10095f4613f2SJohn Marino #define MAXCOMPARE	2
10105f4613f2SJohn Marino     /* someday we may allow comparisons on more files */
10115f4613f2SJohn Marino     int filecount = 0;
10125f4613f2SJohn Marino     ENTRY *heads[MAXCOMPARE];
10135f4613f2SJohn Marino     ENTRY *qp, *rp;
10145f4613f2SJohn Marino     int i, n;
10155f4613f2SJohn Marino 
10165f4613f2SJohn Marino     memset(heads, 0, sizeof(heads));
1017*32bb5217SDaniel Fojt     dump_init((char *) 0, F_LITERAL, S_TERMINFO,
1018*32bb5217SDaniel Fojt 	      FALSE, 0, 65535, itrace, FALSE, FALSE, FALSE);
10195f4613f2SJohn Marino 
10205f4613f2SJohn Marino     for (n = 0; n < argc && n < MAXCOMPARE; n++) {
10215f4613f2SJohn Marino 	if (freopen(argv[n], "r", stdin) == 0)
10225f4613f2SJohn Marino 	    _nc_err_abort("Can't open %s", argv[n]);
10235f4613f2SJohn Marino 
10243468e90cSJohn Marino #if NO_LEAKS
10253468e90cSJohn Marino 	entered[n].head = _nc_head;
10263468e90cSJohn Marino 	entered[n].tail = _nc_tail;
10273468e90cSJohn Marino #endif
10285f4613f2SJohn Marino 	_nc_head = _nc_tail = 0;
10295f4613f2SJohn Marino 
10305f4613f2SJohn Marino 	/* parse entries out of the source file */
10315f4613f2SJohn Marino 	_nc_set_source(argv[n]);
10325f4613f2SJohn Marino 	_nc_read_entry_source(stdin, NULL, TRUE, literal, NULLHOOK);
10335f4613f2SJohn Marino 
10345f4613f2SJohn Marino 	if (itrace)
10355f4613f2SJohn Marino 	    (void) fprintf(stderr, "Resolving file %d...\n", n - 0);
10365f4613f2SJohn Marino 
10375f4613f2SJohn Marino 	/* maybe do use resolution */
10385f4613f2SJohn Marino 	if (!_nc_resolve_uses2(!limited, literal)) {
10395f4613f2SJohn Marino 	    (void) fprintf(stderr,
10405f4613f2SJohn Marino 			   "There are unresolved use entries in %s:\n",
10415f4613f2SJohn Marino 			   argv[n]);
10425f4613f2SJohn Marino 	    for_entry_list(qp) {
10435f4613f2SJohn Marino 		if (qp->nuses) {
10445f4613f2SJohn Marino 		    (void) fputs(qp->tterm.term_names, stderr);
10455f4613f2SJohn Marino 		    (void) fputc('\n', stderr);
10465f4613f2SJohn Marino 		}
10475f4613f2SJohn Marino 	    }
10485f4613f2SJohn Marino 	    ExitProgram(EXIT_FAILURE);
10495f4613f2SJohn Marino 	}
10505f4613f2SJohn Marino 
10515f4613f2SJohn Marino 	heads[filecount] = _nc_head;
10525f4613f2SJohn Marino 	filecount++;
10535f4613f2SJohn Marino     }
10545f4613f2SJohn Marino 
10555f4613f2SJohn Marino     /* OK, all entries are in core.  Ready to do the comparison */
10565f4613f2SJohn Marino     if (itrace)
10575f4613f2SJohn Marino 	(void) fprintf(stderr, "Entries are now in core...\n");
10585f4613f2SJohn Marino 
10595f4613f2SJohn Marino     /* The entry-matching loop. Sigh, this is intrinsically quadratic. */
10605f4613f2SJohn Marino     for (qp = heads[0]; qp; qp = qp->next) {
10615f4613f2SJohn Marino 	for (rp = heads[1]; rp; rp = rp->next)
10625f4613f2SJohn Marino 	    if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) {
10635f4613f2SJohn Marino 		if (qp->ncrosslinks < MAX_CROSSLINKS)
10645f4613f2SJohn Marino 		    qp->crosslinks[qp->ncrosslinks] = rp;
10655f4613f2SJohn Marino 		qp->ncrosslinks++;
10665f4613f2SJohn Marino 
10675f4613f2SJohn Marino 		if (rp->ncrosslinks < MAX_CROSSLINKS)
10685f4613f2SJohn Marino 		    rp->crosslinks[rp->ncrosslinks] = qp;
10695f4613f2SJohn Marino 		rp->ncrosslinks++;
10705f4613f2SJohn Marino 	    }
10715f4613f2SJohn Marino     }
10725f4613f2SJohn Marino 
10735f4613f2SJohn Marino     /* now we have two circular lists with crosslinks */
10745f4613f2SJohn Marino     if (itrace)
10755f4613f2SJohn Marino 	(void) fprintf(stderr, "Name matches are done...\n");
10765f4613f2SJohn Marino 
10775f4613f2SJohn Marino     for (qp = heads[0]; qp; qp = qp->next) {
10785f4613f2SJohn Marino 	if (qp->ncrosslinks > 1) {
10795f4613f2SJohn Marino 	    (void) fprintf(stderr,
10805f4613f2SJohn Marino 			   "%s in file 1 (%s) has %d matches in file 2 (%s):\n",
10815f4613f2SJohn Marino 			   _nc_first_name(qp->tterm.term_names),
10825f4613f2SJohn Marino 			   argv[0],
10835f4613f2SJohn Marino 			   qp->ncrosslinks,
10845f4613f2SJohn Marino 			   argv[1]);
10855f4613f2SJohn Marino 	    for (i = 0; i < qp->ncrosslinks; i++)
10865f4613f2SJohn Marino 		(void) fprintf(stderr,
10875f4613f2SJohn Marino 			       "\t%s\n",
10885f4613f2SJohn Marino 			       _nc_first_name((qp->crosslinks[i])->tterm.term_names));
10895f4613f2SJohn Marino 	}
10905f4613f2SJohn Marino     }
10915f4613f2SJohn Marino 
10925f4613f2SJohn Marino     for (rp = heads[1]; rp; rp = rp->next) {
10935f4613f2SJohn Marino 	if (rp->ncrosslinks > 1) {
10945f4613f2SJohn Marino 	    (void) fprintf(stderr,
10955f4613f2SJohn Marino 			   "%s in file 2 (%s) has %d matches in file 1 (%s):\n",
10965f4613f2SJohn Marino 			   _nc_first_name(rp->tterm.term_names),
10975f4613f2SJohn Marino 			   argv[1],
10985f4613f2SJohn Marino 			   rp->ncrosslinks,
10995f4613f2SJohn Marino 			   argv[0]);
11005f4613f2SJohn Marino 	    for (i = 0; i < rp->ncrosslinks; i++)
11015f4613f2SJohn Marino 		(void) fprintf(stderr,
11025f4613f2SJohn Marino 			       "\t%s\n",
11035f4613f2SJohn Marino 			       _nc_first_name((rp->crosslinks[i])->tterm.term_names));
11045f4613f2SJohn Marino 	}
11055f4613f2SJohn Marino     }
11065f4613f2SJohn Marino 
11075f4613f2SJohn Marino     (void) printf("In file 1 (%s) only:\n", argv[0]);
11085f4613f2SJohn Marino     for (qp = heads[0]; qp; qp = qp->next)
11095f4613f2SJohn Marino 	if (qp->ncrosslinks == 0)
11105f4613f2SJohn Marino 	    (void) printf("\t%s\n",
11115f4613f2SJohn Marino 			  _nc_first_name(qp->tterm.term_names));
11125f4613f2SJohn Marino 
11135f4613f2SJohn Marino     (void) printf("In file 2 (%s) only:\n", argv[1]);
11145f4613f2SJohn Marino     for (rp = heads[1]; rp; rp = rp->next)
11155f4613f2SJohn Marino 	if (rp->ncrosslinks == 0)
11165f4613f2SJohn Marino 	    (void) printf("\t%s\n",
11175f4613f2SJohn Marino 			  _nc_first_name(rp->tterm.term_names));
11185f4613f2SJohn Marino 
11195f4613f2SJohn Marino     (void) printf("The following entries are equivalent:\n");
11205f4613f2SJohn Marino     for (qp = heads[0]; qp; qp = qp->next) {
11215f4613f2SJohn Marino 	if (qp->ncrosslinks == 1) {
11225f4613f2SJohn Marino 	    rp = qp->crosslinks[0];
11235f4613f2SJohn Marino 
11245f4613f2SJohn Marino 	    repair_acsc(&qp->tterm);
11255f4613f2SJohn Marino 	    repair_acsc(&rp->tterm);
11265f4613f2SJohn Marino #if NCURSES_XNAMES
11275f4613f2SJohn Marino 	    _nc_align_termtype(&qp->tterm, &rp->tterm);
11285f4613f2SJohn Marino #endif
11295f4613f2SJohn Marino 	    if (entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp)) {
11305f4613f2SJohn Marino 		char name1[NAMESIZE], name2[NAMESIZE];
11315f4613f2SJohn Marino 
11325f4613f2SJohn Marino 		(void) canonical_name(qp->tterm.term_names, name1);
11335f4613f2SJohn Marino 		(void) canonical_name(rp->tterm.term_names, name2);
11345f4613f2SJohn Marino 
11355f4613f2SJohn Marino 		(void) printf("%s = %s\n", name1, name2);
11365f4613f2SJohn Marino 	    }
11375f4613f2SJohn Marino 	}
11385f4613f2SJohn Marino     }
11395f4613f2SJohn Marino 
11405f4613f2SJohn Marino     (void) printf("Differing entries:\n");
11415f4613f2SJohn Marino     termcount = 2;
11425f4613f2SJohn Marino     for (qp = heads[0]; qp; qp = qp->next) {
11435f4613f2SJohn Marino 
11445f4613f2SJohn Marino 	if (qp->ncrosslinks == 1) {
11455f4613f2SJohn Marino 	    rp = qp->crosslinks[0];
11465f4613f2SJohn Marino #if NCURSES_XNAMES
11475f4613f2SJohn Marino 	    /* sorry - we have to do this on each pass */
11485f4613f2SJohn Marino 	    _nc_align_termtype(&qp->tterm, &rp->tterm);
11495f4613f2SJohn Marino #endif
11505f4613f2SJohn Marino 	    if (!(entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp))) {
11515f4613f2SJohn Marino 		char name1[NAMESIZE], name2[NAMESIZE];
11523468e90cSJohn Marino 		char *names[3];
11533468e90cSJohn Marino 
11543468e90cSJohn Marino 		names[0] = name1;
11553468e90cSJohn Marino 		names[1] = name2;
11563468e90cSJohn Marino 		names[2] = 0;
11575f4613f2SJohn Marino 
11585f4613f2SJohn Marino 		entries[0] = *qp;
11595f4613f2SJohn Marino 		entries[1] = *rp;
11605f4613f2SJohn Marino 
11615f4613f2SJohn Marino 		(void) canonical_name(qp->tterm.term_names, name1);
11625f4613f2SJohn Marino 		(void) canonical_name(rp->tterm.term_names, name2);
11635f4613f2SJohn Marino 
11645f4613f2SJohn Marino 		switch (compare) {
11655f4613f2SJohn Marino 		case C_DIFFERENCE:
11663468e90cSJohn Marino 		    show_comparing(names);
11675f4613f2SJohn Marino 		    compare_entry(compare_predicate, &entries->tterm, quiet);
11685f4613f2SJohn Marino 		    break;
11695f4613f2SJohn Marino 
11705f4613f2SJohn Marino 		case C_COMMON:
11713468e90cSJohn Marino 		    show_comparing(names);
11725f4613f2SJohn Marino 		    compare_entry(compare_predicate, &entries->tterm, quiet);
11735f4613f2SJohn Marino 		    break;
11745f4613f2SJohn Marino 
11755f4613f2SJohn Marino 		case C_NAND:
11763468e90cSJohn Marino 		    show_comparing(names);
11775f4613f2SJohn Marino 		    compare_entry(compare_predicate, &entries->tterm, quiet);
11785f4613f2SJohn Marino 		    break;
11795f4613f2SJohn Marino 
11805f4613f2SJohn Marino 		}
11815f4613f2SJohn Marino 	    }
11825f4613f2SJohn Marino 	}
11835f4613f2SJohn Marino     }
11845f4613f2SJohn Marino }
11855f4613f2SJohn Marino 
11865f4613f2SJohn Marino static void
usage(void)11875f4613f2SJohn Marino usage(void)
11885f4613f2SJohn Marino {
11893468e90cSJohn Marino #define DATA(s) s "\n"
11903468e90cSJohn Marino     static const char head[] =
11915f4613f2SJohn Marino     {
11923468e90cSJohn Marino 	DATA("Usage: infocmp [options] [-A directory] [-B directory] [termname...]")
11933468e90cSJohn Marino 	DATA("")
11943468e90cSJohn Marino 	DATA("Options:")
11953468e90cSJohn Marino     };
11963468e90cSJohn Marino #undef DATA
11973468e90cSJohn Marino #define DATA(s) s
11983468e90cSJohn Marino     static const char options[][45] =
11993468e90cSJohn Marino     {
12003468e90cSJohn Marino 	"  -0    print single-row"
12015f4613f2SJohn Marino 	,"  -1    print single-column"
12025f4613f2SJohn Marino 	,"  -C    use termcap-names"
12033468e90cSJohn Marino 	,"  -D    print database locations"
12043468e90cSJohn Marino 	,"  -E    format output as C tables"
12055f4613f2SJohn Marino 	,"  -F    compare terminfo-files"
12063468e90cSJohn Marino 	,"  -G    format %{number} to %'char'"
12075f4613f2SJohn Marino 	,"  -I    use terminfo-names"
12083468e90cSJohn Marino 	,"  -K    use termcap-names and BSD syntax"
12095f4613f2SJohn Marino 	,"  -L    use long names"
12105f4613f2SJohn Marino 	,"  -R subset (see manpage)"
12115f4613f2SJohn Marino 	,"  -T    eliminate size limits (test)"
12123468e90cSJohn Marino 	,"  -U    do not post-process entries"
12135f4613f2SJohn Marino 	,"  -V    print version"
1214*32bb5217SDaniel Fojt 	,"  -W    wrap long strings per -w[n]"
12155f4613f2SJohn Marino #if NCURSES_XNAMES
12165f4613f2SJohn Marino 	,"  -a    with -F, list commented-out caps"
12175f4613f2SJohn Marino #endif
12185f4613f2SJohn Marino 	,"  -c    list common capabilities"
12195f4613f2SJohn Marino 	,"  -d    list different capabilities"
12205f4613f2SJohn Marino 	,"  -e    format output for C initializer"
12215f4613f2SJohn Marino 	,"  -f    with -1, format complex strings"
12225f4613f2SJohn Marino 	,"  -g    format %'char' to %{number}"
12235f4613f2SJohn Marino 	,"  -i    analyze initialization/reset"
12245f4613f2SJohn Marino 	,"  -l    output terminfo names"
12255f4613f2SJohn Marino 	,"  -n    list capabilities in neither"
12265f4613f2SJohn Marino 	,"  -p    ignore padding specifiers"
12273468e90cSJohn Marino 	,"  -Q number  dump compiled description"
12285f4613f2SJohn Marino 	,"  -q    brief listing, removes headers"
12295f4613f2SJohn Marino 	,"  -r    with -C, output in termcap form"
12305f4613f2SJohn Marino 	,"  -r    with -F, resolve use-references"
12315f4613f2SJohn Marino 	,"  -s [d|i|l|c] sort fields"
12325f4613f2SJohn Marino #if NCURSES_XNAMES
12335f4613f2SJohn Marino 	,"  -t    suppress commented-out capabilities"
12345f4613f2SJohn Marino #endif
12355f4613f2SJohn Marino 	,"  -u    produce source with 'use='"
12365f4613f2SJohn Marino 	,"  -v number  (verbose)"
12375f4613f2SJohn Marino 	,"  -w number  (width)"
12385f4613f2SJohn Marino #if NCURSES_XNAMES
12393468e90cSJohn Marino 	,"  -x    unknown capabilities are user-defined"
12405f4613f2SJohn Marino #endif
12415f4613f2SJohn Marino     };
12423468e90cSJohn Marino #undef DATA
12433468e90cSJohn Marino     const size_t last = SIZEOF(options);
12443468e90cSJohn Marino     const size_t left = (last + 1) / 2;
12455f4613f2SJohn Marino     size_t n;
12465f4613f2SJohn Marino 
12473468e90cSJohn Marino     fputs(head, stderr);
12485f4613f2SJohn Marino     for (n = 0; n < left; n++) {
12493468e90cSJohn Marino 	size_t m = n + left;
12505f4613f2SJohn Marino 	if (m < last)
12513468e90cSJohn Marino 	    fprintf(stderr, "%-40.40s%s\n", options[n], options[m]);
12525f4613f2SJohn Marino 	else
12533468e90cSJohn Marino 	    fprintf(stderr, "%s\n", options[n]);
12545f4613f2SJohn Marino     }
12555f4613f2SJohn Marino     ExitProgram(EXIT_FAILURE);
12565f4613f2SJohn Marino }
12575f4613f2SJohn Marino 
12585f4613f2SJohn Marino static char *
any_initializer(const char * fmt,const char * type)12595f4613f2SJohn Marino any_initializer(const char *fmt, const char *type)
12605f4613f2SJohn Marino {
12615f4613f2SJohn Marino     static char *initializer;
12623468e90cSJohn Marino     static size_t need;
12635f4613f2SJohn Marino     char *s;
12645f4613f2SJohn Marino 
12653468e90cSJohn Marino     if (initializer == 0) {
12663468e90cSJohn Marino 	need = (strlen(entries->tterm.term_names)
12673468e90cSJohn Marino 		+ strlen(type)
12683468e90cSJohn Marino 		+ strlen(fmt));
12693468e90cSJohn Marino 	initializer = (char *) malloc(need + 1);
12705f4613f2SJohn Marino 	if (initializer == 0)
12713468e90cSJohn Marino 	    failed("any_initializer");
12723468e90cSJohn Marino     }
12735f4613f2SJohn Marino 
12743468e90cSJohn Marino     _nc_STRCPY(initializer, entries->tterm.term_names, need);
12755f4613f2SJohn Marino     for (s = initializer; *s != 0 && *s != '|'; s++) {
12765f4613f2SJohn Marino 	if (!isalnum(UChar(*s)))
12775f4613f2SJohn Marino 	    *s = '_';
12785f4613f2SJohn Marino     }
12795f4613f2SJohn Marino     *s = 0;
12803468e90cSJohn Marino     _nc_SPRINTF(s, _nc_SLIMIT(need) fmt, type);
12815f4613f2SJohn Marino     return initializer;
12825f4613f2SJohn Marino }
12835f4613f2SJohn Marino 
12845f4613f2SJohn Marino static char *
name_initializer(const char * type)12855f4613f2SJohn Marino name_initializer(const char *type)
12865f4613f2SJohn Marino {
12875f4613f2SJohn Marino     return any_initializer("_%s_data", type);
12885f4613f2SJohn Marino }
12895f4613f2SJohn Marino 
12905f4613f2SJohn Marino static char *
string_variable(const char * type)12915f4613f2SJohn Marino string_variable(const char *type)
12925f4613f2SJohn Marino {
12935f4613f2SJohn Marino     return any_initializer("_s_%s", type);
12945f4613f2SJohn Marino }
12955f4613f2SJohn Marino 
12965f4613f2SJohn Marino /* dump C initializers for the terminal type */
12975f4613f2SJohn Marino static void
dump_initializers(TERMTYPE2 * term)1298*32bb5217SDaniel Fojt dump_initializers(TERMTYPE2 *term)
12995f4613f2SJohn Marino {
13005f4613f2SJohn Marino     unsigned n;
13015f4613f2SJohn Marino     const char *str = 0;
13025f4613f2SJohn Marino 
13035f4613f2SJohn Marino     printf("\nstatic char %s[] = \"%s\";\n\n",
13045f4613f2SJohn Marino 	   name_initializer("alias"), entries->tterm.term_names);
13055f4613f2SJohn Marino 
13065f4613f2SJohn Marino     for_each_string(n, term) {
13075f4613f2SJohn Marino 	char buf[MAX_STRING], *sp, *tp;
13085f4613f2SJohn Marino 
13095f4613f2SJohn Marino 	if (VALID_STRING(term->Strings[n])) {
13105f4613f2SJohn Marino 	    tp = buf;
13113468e90cSJohn Marino #define TP_LIMIT	((MAX_STRING - 5) - (size_t)(tp - buf))
13125f4613f2SJohn Marino 	    *tp++ = '"';
13135f4613f2SJohn Marino 	    for (sp = term->Strings[n];
13143468e90cSJohn Marino 		 *sp != 0 && TP_LIMIT > 2;
13155f4613f2SJohn Marino 		 sp++) {
13165f4613f2SJohn Marino 		if (isascii(UChar(*sp))
13175f4613f2SJohn Marino 		    && isprint(UChar(*sp))
13185f4613f2SJohn Marino 		    && *sp != '\\'
13195f4613f2SJohn Marino 		    && *sp != '"')
13205f4613f2SJohn Marino 		    *tp++ = *sp;
13215f4613f2SJohn Marino 		else {
13223468e90cSJohn Marino 		    _nc_SPRINTF(tp, _nc_SLIMIT(TP_LIMIT) "\\%03o", UChar(*sp));
13235f4613f2SJohn Marino 		    tp += 4;
13245f4613f2SJohn Marino 		}
13255f4613f2SJohn Marino 	    }
13265f4613f2SJohn Marino 	    *tp++ = '"';
13275f4613f2SJohn Marino 	    *tp = '\0';
13285f4613f2SJohn Marino 	    (void) printf("static char %-20s[] = %s;\n",
13293468e90cSJohn Marino 			  string_variable(ExtStrname(term, (int) n, strnames)),
13303468e90cSJohn Marino 			  buf);
13315f4613f2SJohn Marino 	}
13325f4613f2SJohn Marino     }
13335f4613f2SJohn Marino     printf("\n");
13345f4613f2SJohn Marino 
13355f4613f2SJohn Marino     (void) printf("static char %s[] = %s\n", name_initializer("bool"), L_CURL);
13365f4613f2SJohn Marino 
13375f4613f2SJohn Marino     for_each_boolean(n, term) {
13385f4613f2SJohn Marino 	switch ((int) (term->Booleans[n])) {
13395f4613f2SJohn Marino 	case TRUE:
13405f4613f2SJohn Marino 	    str = "TRUE";
13415f4613f2SJohn Marino 	    break;
13425f4613f2SJohn Marino 
13435f4613f2SJohn Marino 	case FALSE:
13445f4613f2SJohn Marino 	    str = "FALSE";
13455f4613f2SJohn Marino 	    break;
13465f4613f2SJohn Marino 
13475f4613f2SJohn Marino 	case ABSENT_BOOLEAN:
13485f4613f2SJohn Marino 	    str = "ABSENT_BOOLEAN";
13495f4613f2SJohn Marino 	    break;
13505f4613f2SJohn Marino 
13515f4613f2SJohn Marino 	case CANCELLED_BOOLEAN:
13525f4613f2SJohn Marino 	    str = "CANCELLED_BOOLEAN";
13535f4613f2SJohn Marino 	    break;
13545f4613f2SJohn Marino 	}
13555f4613f2SJohn Marino 	(void) printf("\t/* %3u: %-8s */\t%s,\n",
13563468e90cSJohn Marino 		      n, ExtBoolname(term, (int) n, boolnames), str);
13575f4613f2SJohn Marino     }
13585f4613f2SJohn Marino     (void) printf("%s;\n", R_CURL);
13595f4613f2SJohn Marino 
13605f4613f2SJohn Marino     (void) printf("static short %s[] = %s\n", name_initializer("number"), L_CURL);
13615f4613f2SJohn Marino 
13625f4613f2SJohn Marino     for_each_number(n, term) {
13635f4613f2SJohn Marino 	char buf[BUFSIZ];
13645f4613f2SJohn Marino 	switch (term->Numbers[n]) {
13655f4613f2SJohn Marino 	case ABSENT_NUMERIC:
13665f4613f2SJohn Marino 	    str = "ABSENT_NUMERIC";
13675f4613f2SJohn Marino 	    break;
13685f4613f2SJohn Marino 	case CANCELLED_NUMERIC:
13695f4613f2SJohn Marino 	    str = "CANCELLED_NUMERIC";
13705f4613f2SJohn Marino 	    break;
13715f4613f2SJohn Marino 	default:
13723468e90cSJohn Marino 	    _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) "%d", term->Numbers[n]);
13735f4613f2SJohn Marino 	    str = buf;
13745f4613f2SJohn Marino 	    break;
13755f4613f2SJohn Marino 	}
13765f4613f2SJohn Marino 	(void) printf("\t/* %3u: %-8s */\t%s,\n", n,
13773468e90cSJohn Marino 		      ExtNumname(term, (int) n, numnames), str);
13785f4613f2SJohn Marino     }
13795f4613f2SJohn Marino     (void) printf("%s;\n", R_CURL);
13805f4613f2SJohn Marino 
13815f4613f2SJohn Marino     (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL);
13825f4613f2SJohn Marino 
13835f4613f2SJohn Marino     for_each_string(n, term) {
13845f4613f2SJohn Marino 
13855f4613f2SJohn Marino 	if (term->Strings[n] == ABSENT_STRING)
13865f4613f2SJohn Marino 	    str = "ABSENT_STRING";
13875f4613f2SJohn Marino 	else if (term->Strings[n] == CANCELLED_STRING)
13885f4613f2SJohn Marino 	    str = "CANCELLED_STRING";
13895f4613f2SJohn Marino 	else {
13903468e90cSJohn Marino 	    str = string_variable(ExtStrname(term, (int) n, strnames));
13915f4613f2SJohn Marino 	}
13925f4613f2SJohn Marino 	(void) printf("\t/* %3u: %-8s */\t%s,\n", n,
13933468e90cSJohn Marino 		      ExtStrname(term, (int) n, strnames), str);
13945f4613f2SJohn Marino     }
13955f4613f2SJohn Marino     (void) printf("%s;\n", R_CURL);
13965f4613f2SJohn Marino 
13975f4613f2SJohn Marino #if NCURSES_XNAMES
13985f4613f2SJohn Marino     if ((NUM_BOOLEANS(term) != BOOLCOUNT)
13995f4613f2SJohn Marino 	|| (NUM_NUMBERS(term) != NUMCOUNT)
14005f4613f2SJohn Marino 	|| (NUM_STRINGS(term) != STRCOUNT)) {
14015f4613f2SJohn Marino 	(void) printf("static char * %s[] = %s\n",
14025f4613f2SJohn Marino 		      name_initializer("string_ext"), L_CURL);
14035f4613f2SJohn Marino 	for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) {
14045f4613f2SJohn Marino 	    (void) printf("\t/* %3u: bool */\t\"%s\",\n",
14053468e90cSJohn Marino 			  n, ExtBoolname(term, (int) n, boolnames));
14065f4613f2SJohn Marino 	}
14075f4613f2SJohn Marino 	for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) {
14085f4613f2SJohn Marino 	    (void) printf("\t/* %3u: num */\t\"%s\",\n",
14093468e90cSJohn Marino 			  n, ExtNumname(term, (int) n, numnames));
14105f4613f2SJohn Marino 	}
14115f4613f2SJohn Marino 	for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) {
14125f4613f2SJohn Marino 	    (void) printf("\t/* %3u: str */\t\"%s\",\n",
14133468e90cSJohn Marino 			  n, ExtStrname(term, (int) n, strnames));
14145f4613f2SJohn Marino 	}
14155f4613f2SJohn Marino 	(void) printf("%s;\n", R_CURL);
14165f4613f2SJohn Marino     }
14175f4613f2SJohn Marino #endif
14185f4613f2SJohn Marino }
14195f4613f2SJohn Marino 
14205f4613f2SJohn Marino /* dump C initializers for the terminal type */
14215f4613f2SJohn Marino static void
dump_termtype(TERMTYPE2 * term)1422*32bb5217SDaniel Fojt dump_termtype(TERMTYPE2 *term)
14235f4613f2SJohn Marino {
14245f4613f2SJohn Marino     (void) printf("\t%s\n\t\t%s,\n", L_CURL, name_initializer("alias"));
14255f4613f2SJohn Marino     (void) printf("\t\t(char *)0,\t/* pointer to string table */\n");
14265f4613f2SJohn Marino 
14275f4613f2SJohn Marino     (void) printf("\t\t%s,\n", name_initializer("bool"));
14285f4613f2SJohn Marino     (void) printf("\t\t%s,\n", name_initializer("number"));
14295f4613f2SJohn Marino 
14305f4613f2SJohn Marino     (void) printf("\t\t%s,\n", name_initializer("string"));
14315f4613f2SJohn Marino 
14325f4613f2SJohn Marino #if NCURSES_XNAMES
14335f4613f2SJohn Marino     (void) printf("#if NCURSES_XNAMES\n");
14345f4613f2SJohn Marino     (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n");
14355f4613f2SJohn Marino     (void) printf("\t\t%s,\t/* ...corresponding names */\n",
14365f4613f2SJohn Marino 		  ((NUM_BOOLEANS(term) != BOOLCOUNT)
14375f4613f2SJohn Marino 		   || (NUM_NUMBERS(term) != NUMCOUNT)
14385f4613f2SJohn Marino 		   || (NUM_STRINGS(term) != STRCOUNT))
14395f4613f2SJohn Marino 		  ? name_initializer("string_ext")
14405f4613f2SJohn Marino 		  : "(char **)0");
14415f4613f2SJohn Marino 
14425f4613f2SJohn Marino     (void) printf("\t\t%d,\t\t/* count total Booleans */\n", NUM_BOOLEANS(term));
14435f4613f2SJohn Marino     (void) printf("\t\t%d,\t\t/* count total Numbers */\n", NUM_NUMBERS(term));
14445f4613f2SJohn Marino     (void) printf("\t\t%d,\t\t/* count total Strings */\n", NUM_STRINGS(term));
14455f4613f2SJohn Marino 
14465f4613f2SJohn Marino     (void) printf("\t\t%d,\t\t/* count extensions to Booleans */\n",
14475f4613f2SJohn Marino 		  NUM_BOOLEANS(term) - BOOLCOUNT);
14485f4613f2SJohn Marino     (void) printf("\t\t%d,\t\t/* count extensions to Numbers */\n",
14495f4613f2SJohn Marino 		  NUM_NUMBERS(term) - NUMCOUNT);
14505f4613f2SJohn Marino     (void) printf("\t\t%d,\t\t/* count extensions to Strings */\n",
14515f4613f2SJohn Marino 		  NUM_STRINGS(term) - STRCOUNT);
14525f4613f2SJohn Marino 
14535f4613f2SJohn Marino     (void) printf("#endif /* NCURSES_XNAMES */\n");
14545f4613f2SJohn Marino #else
14555f4613f2SJohn Marino     (void) term;
14565f4613f2SJohn Marino #endif /* NCURSES_XNAMES */
14575f4613f2SJohn Marino     (void) printf("\t%s\n", R_CURL);
14585f4613f2SJohn Marino }
14595f4613f2SJohn Marino 
14605f4613f2SJohn Marino static int
optarg_to_number(void)14615f4613f2SJohn Marino optarg_to_number(void)
14625f4613f2SJohn Marino {
14635f4613f2SJohn Marino     char *temp = 0;
14645f4613f2SJohn Marino     long value = strtol(optarg, &temp, 0);
14655f4613f2SJohn Marino 
14665f4613f2SJohn Marino     if (temp == 0 || temp == optarg || *temp != 0) {
14675f4613f2SJohn Marino 	fprintf(stderr, "Expected a number, not \"%s\"\n", optarg);
14685f4613f2SJohn Marino 	ExitProgram(EXIT_FAILURE);
14695f4613f2SJohn Marino     }
14705f4613f2SJohn Marino     return (int) value;
14715f4613f2SJohn Marino }
14725f4613f2SJohn Marino 
14735f4613f2SJohn Marino static char *
terminal_env(void)14745f4613f2SJohn Marino terminal_env(void)
14755f4613f2SJohn Marino {
14765f4613f2SJohn Marino     char *terminal;
14775f4613f2SJohn Marino 
14785f4613f2SJohn Marino     if ((terminal = getenv("TERM")) == 0) {
14795f4613f2SJohn Marino 	(void) fprintf(stderr,
14805f4613f2SJohn Marino 		       "%s: environment variable TERM not set\n",
14815f4613f2SJohn Marino 		       _nc_progname);
14825f4613f2SJohn Marino 	exit(EXIT_FAILURE);
14835f4613f2SJohn Marino     }
14845f4613f2SJohn Marino     return terminal;
14855f4613f2SJohn Marino }
14865f4613f2SJohn Marino 
14873468e90cSJohn Marino /*
14883468e90cSJohn Marino  * Show the databases that infocmp knows about.  The location to which it writes is
14893468e90cSJohn Marino  */
14903468e90cSJohn Marino static void
show_databases(void)14913468e90cSJohn Marino show_databases(void)
14923468e90cSJohn Marino {
14933468e90cSJohn Marino     DBDIRS state;
14943468e90cSJohn Marino     int offset;
14953468e90cSJohn Marino     const char *path2;
14963468e90cSJohn Marino 
14973468e90cSJohn Marino     _nc_first_db(&state, &offset);
14983468e90cSJohn Marino     while ((path2 = _nc_next_db(&state, &offset)) != 0) {
14993468e90cSJohn Marino 	printf("%s\n", path2);
15003468e90cSJohn Marino     }
15013468e90cSJohn Marino     _nc_last_db();
15023468e90cSJohn Marino }
15033468e90cSJohn Marino 
15045f4613f2SJohn Marino /***************************************************************************
15055f4613f2SJohn Marino  *
15065f4613f2SJohn Marino  * Main sequence
15075f4613f2SJohn Marino  *
15085f4613f2SJohn Marino  ***************************************************************************/
15095f4613f2SJohn Marino 
15105f4613f2SJohn Marino #if NO_LEAKS
15115f4613f2SJohn Marino #define MAIN_LEAKS() \
15125f4613f2SJohn Marino     free(myargv); \
15135f4613f2SJohn Marino     free(tfile); \
15145f4613f2SJohn Marino     free(tname)
15155f4613f2SJohn Marino #else
15165f4613f2SJohn Marino #define MAIN_LEAKS()		/* nothing */
15175f4613f2SJohn Marino #endif
15185f4613f2SJohn Marino 
15195f4613f2SJohn Marino int
main(int argc,char * argv[])15205f4613f2SJohn Marino main(int argc, char *argv[])
15215f4613f2SJohn Marino {
15225f4613f2SJohn Marino     /* Avoid "local data >32k" error with mwcc */
15235f4613f2SJohn Marino     /* Also avoid overflowing smaller stacks on systems like AmigaOS */
15245f4613f2SJohn Marino     path *tfile = 0;
15255f4613f2SJohn Marino     char **tname = 0;
15263468e90cSJohn Marino     size_t maxterms;
15275f4613f2SJohn Marino 
15285f4613f2SJohn Marino     char **myargv;
15295f4613f2SJohn Marino 
15305f4613f2SJohn Marino     char *firstdir, *restdir;
15315f4613f2SJohn Marino     int c, i, len;
15325f4613f2SJohn Marino     bool formatted = FALSE;
15335f4613f2SJohn Marino     bool filecompare = FALSE;
15345f4613f2SJohn Marino     int initdump = 0;
15355f4613f2SJohn Marino     bool init_analyze = FALSE;
15365f4613f2SJohn Marino     bool suppress_untranslatable = FALSE;
15373468e90cSJohn Marino     int quickdump = 0;
1538*32bb5217SDaniel Fojt     bool wrap_strings = FALSE;
15395f4613f2SJohn Marino 
15405f4613f2SJohn Marino     /* where is the terminfo database location going to default to? */
15415f4613f2SJohn Marino     restdir = firstdir = 0;
15425f4613f2SJohn Marino 
15435f4613f2SJohn Marino #if NCURSES_XNAMES
15445f4613f2SJohn Marino     use_extended_names(FALSE);
15455f4613f2SJohn Marino #endif
15463468e90cSJohn Marino     _nc_strict_bsd = 0;
15475f4613f2SJohn Marino 
15485f4613f2SJohn Marino     _nc_progname = _nc_rootname(argv[0]);
15495f4613f2SJohn Marino 
15505f4613f2SJohn Marino     /* make sure we have enough space to add two terminal entries */
15515f4613f2SJohn Marino     myargv = typeCalloc(char *, (size_t) (argc + 3));
15523468e90cSJohn Marino     if (myargv == 0)
15533468e90cSJohn Marino 	failed("myargv");
15543468e90cSJohn Marino 
15555f4613f2SJohn Marino     memcpy(myargv, argv, (sizeof(char *) * (size_t) argc));
15565f4613f2SJohn Marino     argv = myargv;
15575f4613f2SJohn Marino 
15585f4613f2SJohn Marino     while ((c = getopt(argc,
15595f4613f2SJohn Marino 		       argv,
1560*32bb5217SDaniel Fojt 		       "01A:aB:CcDdEeFfGgIiKLlnpQ:qR:rs:TtUuVv:Ww:x")) != -1) {
15615f4613f2SJohn Marino 	switch (c) {
15623468e90cSJohn Marino 	case '0':
15633468e90cSJohn Marino 	    mwidth = 65535;
15643468e90cSJohn Marino 	    mheight = 1;
15653468e90cSJohn Marino 	    break;
15663468e90cSJohn Marino 
15675f4613f2SJohn Marino 	case '1':
15685f4613f2SJohn Marino 	    mwidth = 0;
15695f4613f2SJohn Marino 	    break;
15705f4613f2SJohn Marino 
15715f4613f2SJohn Marino 	case 'A':
15725f4613f2SJohn Marino 	    firstdir = optarg;
15735f4613f2SJohn Marino 	    break;
15745f4613f2SJohn Marino 
15755f4613f2SJohn Marino #if NCURSES_XNAMES
15765f4613f2SJohn Marino 	case 'a':
15775f4613f2SJohn Marino 	    _nc_disable_period = TRUE;
15785f4613f2SJohn Marino 	    use_extended_names(TRUE);
15795f4613f2SJohn Marino 	    break;
15805f4613f2SJohn Marino #endif
15815f4613f2SJohn Marino 	case 'B':
15825f4613f2SJohn Marino 	    restdir = optarg;
15835f4613f2SJohn Marino 	    break;
15845f4613f2SJohn Marino 
15853468e90cSJohn Marino 	case 'K':
15863468e90cSJohn Marino 	    _nc_strict_bsd = 1;
15873468e90cSJohn Marino 	    /* FALLTHRU */
15885f4613f2SJohn Marino 	case 'C':
15895f4613f2SJohn Marino 	    outform = F_TERMCAP;
15905f4613f2SJohn Marino 	    tversion = "BSD";
15915f4613f2SJohn Marino 	    if (sortmode == S_DEFAULT)
15925f4613f2SJohn Marino 		sortmode = S_TERMCAP;
15935f4613f2SJohn Marino 	    break;
15945f4613f2SJohn Marino 
15953468e90cSJohn Marino 	case 'D':
15963468e90cSJohn Marino 	    show_databases();
15973468e90cSJohn Marino 	    ExitProgram(EXIT_SUCCESS);
15983468e90cSJohn Marino 	    break;
15993468e90cSJohn Marino 
16005f4613f2SJohn Marino 	case 'c':
16015f4613f2SJohn Marino 	    compare = C_COMMON;
16025f4613f2SJohn Marino 	    break;
16035f4613f2SJohn Marino 
16045f4613f2SJohn Marino 	case 'd':
16055f4613f2SJohn Marino 	    compare = C_DIFFERENCE;
16065f4613f2SJohn Marino 	    break;
16075f4613f2SJohn Marino 
16085f4613f2SJohn Marino 	case 'E':
16095f4613f2SJohn Marino 	    initdump |= 2;
16105f4613f2SJohn Marino 	    break;
16115f4613f2SJohn Marino 
16125f4613f2SJohn Marino 	case 'e':
16135f4613f2SJohn Marino 	    initdump |= 1;
16145f4613f2SJohn Marino 	    break;
16155f4613f2SJohn Marino 
16165f4613f2SJohn Marino 	case 'F':
16175f4613f2SJohn Marino 	    filecompare = TRUE;
16185f4613f2SJohn Marino 	    break;
16195f4613f2SJohn Marino 
16205f4613f2SJohn Marino 	case 'f':
16215f4613f2SJohn Marino 	    formatted = TRUE;
16225f4613f2SJohn Marino 	    break;
16235f4613f2SJohn Marino 
16245f4613f2SJohn Marino 	case 'G':
16255f4613f2SJohn Marino 	    numbers = 1;
16265f4613f2SJohn Marino 	    break;
16275f4613f2SJohn Marino 
16285f4613f2SJohn Marino 	case 'g':
16295f4613f2SJohn Marino 	    numbers = -1;
16305f4613f2SJohn Marino 	    break;
16315f4613f2SJohn Marino 
16325f4613f2SJohn Marino 	case 'I':
16335f4613f2SJohn Marino 	    outform = F_TERMINFO;
16345f4613f2SJohn Marino 	    if (sortmode == S_DEFAULT)
16355f4613f2SJohn Marino 		sortmode = S_VARIABLE;
16365f4613f2SJohn Marino 	    tversion = 0;
16375f4613f2SJohn Marino 	    break;
16385f4613f2SJohn Marino 
16395f4613f2SJohn Marino 	case 'i':
16405f4613f2SJohn Marino 	    init_analyze = TRUE;
16415f4613f2SJohn Marino 	    break;
16425f4613f2SJohn Marino 
16435f4613f2SJohn Marino 	case 'L':
16445f4613f2SJohn Marino 	    outform = F_VARIABLE;
16455f4613f2SJohn Marino 	    if (sortmode == S_DEFAULT)
16465f4613f2SJohn Marino 		sortmode = S_VARIABLE;
16475f4613f2SJohn Marino 	    break;
16485f4613f2SJohn Marino 
16495f4613f2SJohn Marino 	case 'l':
16505f4613f2SJohn Marino 	    outform = F_TERMINFO;
16515f4613f2SJohn Marino 	    break;
16525f4613f2SJohn Marino 
16535f4613f2SJohn Marino 	case 'n':
16545f4613f2SJohn Marino 	    compare = C_NAND;
16555f4613f2SJohn Marino 	    break;
16565f4613f2SJohn Marino 
16575f4613f2SJohn Marino 	case 'p':
16585f4613f2SJohn Marino 	    ignorepads = TRUE;
16595f4613f2SJohn Marino 	    break;
16605f4613f2SJohn Marino 
16613468e90cSJohn Marino 	case 'Q':
16623468e90cSJohn Marino 	    quickdump = optarg_to_number();
16633468e90cSJohn Marino 	    break;
16643468e90cSJohn Marino 
16655f4613f2SJohn Marino 	case 'q':
16665f4613f2SJohn Marino 	    quiet = TRUE;
16675f4613f2SJohn Marino 	    s_absent = "-";
16685f4613f2SJohn Marino 	    s_cancel = "@";
16695f4613f2SJohn Marino 	    bool_sep = ", ";
16705f4613f2SJohn Marino 	    break;
16715f4613f2SJohn Marino 
16725f4613f2SJohn Marino 	case 'R':
16735f4613f2SJohn Marino 	    tversion = optarg;
16745f4613f2SJohn Marino 	    break;
16755f4613f2SJohn Marino 
16765f4613f2SJohn Marino 	case 'r':
16775f4613f2SJohn Marino 	    tversion = 0;
16785f4613f2SJohn Marino 	    break;
16795f4613f2SJohn Marino 
16805f4613f2SJohn Marino 	case 's':
16815f4613f2SJohn Marino 	    if (*optarg == 'd')
16825f4613f2SJohn Marino 		sortmode = S_NOSORT;
16835f4613f2SJohn Marino 	    else if (*optarg == 'i')
16845f4613f2SJohn Marino 		sortmode = S_TERMINFO;
16855f4613f2SJohn Marino 	    else if (*optarg == 'l')
16865f4613f2SJohn Marino 		sortmode = S_VARIABLE;
16875f4613f2SJohn Marino 	    else if (*optarg == 'c')
16885f4613f2SJohn Marino 		sortmode = S_TERMCAP;
16895f4613f2SJohn Marino 	    else {
16905f4613f2SJohn Marino 		(void) fprintf(stderr,
16915f4613f2SJohn Marino 			       "%s: unknown sort mode\n",
16925f4613f2SJohn Marino 			       _nc_progname);
16935f4613f2SJohn Marino 		ExitProgram(EXIT_FAILURE);
16945f4613f2SJohn Marino 	    }
16955f4613f2SJohn Marino 	    break;
16965f4613f2SJohn Marino 
16975f4613f2SJohn Marino 	case 'T':
16985f4613f2SJohn Marino 	    limited = FALSE;
16995f4613f2SJohn Marino 	    break;
17005f4613f2SJohn Marino 
17015f4613f2SJohn Marino #if NCURSES_XNAMES
17025f4613f2SJohn Marino 	case 't':
17035f4613f2SJohn Marino 	    _nc_disable_period = FALSE;
17045f4613f2SJohn Marino 	    suppress_untranslatable = TRUE;
17055f4613f2SJohn Marino 	    break;
17065f4613f2SJohn Marino #endif
17075f4613f2SJohn Marino 
17085f4613f2SJohn Marino 	case 'U':
17095f4613f2SJohn Marino 	    literal = TRUE;
17105f4613f2SJohn Marino 	    break;
17115f4613f2SJohn Marino 
17125f4613f2SJohn Marino 	case 'u':
17135f4613f2SJohn Marino 	    compare = C_USEALL;
17145f4613f2SJohn Marino 	    break;
17155f4613f2SJohn Marino 
17165f4613f2SJohn Marino 	case 'V':
17175f4613f2SJohn Marino 	    puts(curses_version());
17185f4613f2SJohn Marino 	    ExitProgram(EXIT_SUCCESS);
17195f4613f2SJohn Marino 
17205f4613f2SJohn Marino 	case 'v':
17213468e90cSJohn Marino 	    itrace = (unsigned) optarg_to_number();
17225f4613f2SJohn Marino 	    set_trace_level(itrace);
17235f4613f2SJohn Marino 	    break;
17245f4613f2SJohn Marino 
1725*32bb5217SDaniel Fojt 	case 'W':
1726*32bb5217SDaniel Fojt 	    wrap_strings = TRUE;
1727*32bb5217SDaniel Fojt 	    break;
1728*32bb5217SDaniel Fojt 
17295f4613f2SJohn Marino 	case 'w':
17305f4613f2SJohn Marino 	    mwidth = optarg_to_number();
17315f4613f2SJohn Marino 	    break;
17325f4613f2SJohn Marino 
17335f4613f2SJohn Marino #if NCURSES_XNAMES
17345f4613f2SJohn Marino 	case 'x':
17355f4613f2SJohn Marino 	    use_extended_names(TRUE);
17365f4613f2SJohn Marino 	    break;
17375f4613f2SJohn Marino #endif
17385f4613f2SJohn Marino 
17395f4613f2SJohn Marino 	default:
17405f4613f2SJohn Marino 	    usage();
17415f4613f2SJohn Marino 	}
17425f4613f2SJohn Marino     }
17435f4613f2SJohn Marino 
17443468e90cSJohn Marino     maxterms = (size_t) (argc + 2 - optind);
17453468e90cSJohn Marino     if ((tfile = typeMalloc(path, maxterms)) == 0)
17463468e90cSJohn Marino 	failed("tfile");
17473468e90cSJohn Marino     if ((tname = typeCalloc(char *, maxterms)) == 0)
17483468e90cSJohn Marino 	  failed("tname");
17493468e90cSJohn Marino     if ((entries = typeCalloc(ENTRY, maxterms)) == 0)
17503468e90cSJohn Marino 	failed("entries");
17513468e90cSJohn Marino #if NO_LEAKS
17523468e90cSJohn Marino     if ((entered = typeCalloc(ENTERED, maxterms)) == 0)
17533468e90cSJohn Marino 	failed("entered");
17543468e90cSJohn Marino #endif
17555f4613f2SJohn Marino 
17565f4613f2SJohn Marino     if (tfile == 0
17575f4613f2SJohn Marino 	|| tname == 0
17585f4613f2SJohn Marino 	|| entries == 0) {
17595f4613f2SJohn Marino 	fprintf(stderr, "%s: not enough memory\n", _nc_progname);
17605f4613f2SJohn Marino 	ExitProgram(EXIT_FAILURE);
17615f4613f2SJohn Marino     }
17625f4613f2SJohn Marino 
17635f4613f2SJohn Marino     /* by default, sort by terminfo name */
17645f4613f2SJohn Marino     if (sortmode == S_DEFAULT)
17655f4613f2SJohn Marino 	sortmode = S_TERMINFO;
17665f4613f2SJohn Marino 
17675f4613f2SJohn Marino     /* make sure we have at least one terminal name to work with */
17685f4613f2SJohn Marino     if (optind >= argc)
17695f4613f2SJohn Marino 	argv[argc++] = terminal_env();
17705f4613f2SJohn Marino 
17715f4613f2SJohn Marino     /* if user is after a comparison, make sure we have two entries */
17725f4613f2SJohn Marino     if (compare != C_DEFAULT && optind >= argc - 1)
17735f4613f2SJohn Marino 	argv[argc++] = terminal_env();
17745f4613f2SJohn Marino 
17753468e90cSJohn Marino     /* exactly one terminal name with no options means display it */
17765f4613f2SJohn Marino     /* exactly two terminal names with no options means do -d */
17773468e90cSJohn Marino     if (compare == C_DEFAULT) {
17783468e90cSJohn Marino 	switch (argc - optind) {
17793468e90cSJohn Marino 	default:
17803468e90cSJohn Marino 	    fprintf(stderr, "%s: too many names to compare\n", _nc_progname);
17813468e90cSJohn Marino 	    ExitProgram(EXIT_FAILURE);
17823468e90cSJohn Marino 	case 1:
17833468e90cSJohn Marino 	    break;
17843468e90cSJohn Marino 	case 2:
17855f4613f2SJohn Marino 	    compare = C_DIFFERENCE;
17863468e90cSJohn Marino 	    break;
17873468e90cSJohn Marino 	}
17883468e90cSJohn Marino     }
17893468e90cSJohn Marino 
17903468e90cSJohn Marino     /* set up for display */
1791*32bb5217SDaniel Fojt     dump_init(tversion, outform, sortmode,
1792*32bb5217SDaniel Fojt 	      wrap_strings, mwidth, mheight, itrace,
17933468e90cSJohn Marino 	      formatted, FALSE, quickdump);
17945f4613f2SJohn Marino 
17955f4613f2SJohn Marino     if (!filecompare) {
17965f4613f2SJohn Marino 	/* grab the entries */
17975f4613f2SJohn Marino 	termcount = 0;
17985f4613f2SJohn Marino 	for (; optind < argc; optind++) {
17995f4613f2SJohn Marino 	    const char *directory = termcount ? restdir : firstdir;
18005f4613f2SJohn Marino 	    int status;
18015f4613f2SJohn Marino 
18025f4613f2SJohn Marino 	    tname[termcount] = argv[optind];
18035f4613f2SJohn Marino 
18045f4613f2SJohn Marino 	    if (directory) {
18053468e90cSJohn Marino #if NCURSES_USE_DATABASE
18065f4613f2SJohn Marino #if MIXEDCASE_FILENAMES
18075f4613f2SJohn Marino #define LEAF_FMT "%c"
18085f4613f2SJohn Marino #else
18095f4613f2SJohn Marino #define LEAF_FMT "%02x"
18105f4613f2SJohn Marino #endif
18113468e90cSJohn Marino 		_nc_SPRINTF(tfile[termcount],
18123468e90cSJohn Marino 			    _nc_SLIMIT(sizeof(path))
18133468e90cSJohn Marino 			    "%s/" LEAF_FMT "/%s",
18145f4613f2SJohn Marino 			    directory,
18155f4613f2SJohn Marino 			    UChar(*argv[optind]), argv[optind]);
18165f4613f2SJohn Marino 		if (itrace)
18175f4613f2SJohn Marino 		    (void) fprintf(stderr,
18185f4613f2SJohn Marino 				   "%s: reading entry %s from file %s\n",
18195f4613f2SJohn Marino 				   _nc_progname,
18205f4613f2SJohn Marino 				   argv[optind], tfile[termcount]);
18215f4613f2SJohn Marino 
18225f4613f2SJohn Marino 		status = _nc_read_file_entry(tfile[termcount],
18235f4613f2SJohn Marino 					     &entries[termcount].tterm);
18245f4613f2SJohn Marino #else
18255f4613f2SJohn Marino 		(void) fprintf(stderr, "%s: terminfo files not supported\n",
18265f4613f2SJohn Marino 			       _nc_progname);
18275f4613f2SJohn Marino 		MAIN_LEAKS();
18285f4613f2SJohn Marino 		ExitProgram(EXIT_FAILURE);
18295f4613f2SJohn Marino #endif
18305f4613f2SJohn Marino 	    } else {
18315f4613f2SJohn Marino 		if (itrace)
18325f4613f2SJohn Marino 		    (void) fprintf(stderr,
18335f4613f2SJohn Marino 				   "%s: reading entry %s from database\n",
18345f4613f2SJohn Marino 				   _nc_progname,
18355f4613f2SJohn Marino 				   tname[termcount]);
18365f4613f2SJohn Marino 
1837*32bb5217SDaniel Fojt 		status = _nc_read_entry2(tname[termcount],
18385f4613f2SJohn Marino 					tfile[termcount],
18395f4613f2SJohn Marino 					&entries[termcount].tterm);
18405f4613f2SJohn Marino 	    }
18415f4613f2SJohn Marino 
18425f4613f2SJohn Marino 	    if (status <= 0) {
18435f4613f2SJohn Marino 		(void) fprintf(stderr,
18445f4613f2SJohn Marino 			       "%s: couldn't open terminfo file %s.\n",
18455f4613f2SJohn Marino 			       _nc_progname,
18465f4613f2SJohn Marino 			       tfile[termcount]);
18475f4613f2SJohn Marino 		MAIN_LEAKS();
18485f4613f2SJohn Marino 		ExitProgram(EXIT_FAILURE);
18495f4613f2SJohn Marino 	    }
18505f4613f2SJohn Marino 	    repair_acsc(&entries[termcount].tterm);
18515f4613f2SJohn Marino 	    termcount++;
18525f4613f2SJohn Marino 	}
18535f4613f2SJohn Marino 
18545f4613f2SJohn Marino #if NCURSES_XNAMES
18555f4613f2SJohn Marino 	if (termcount > 1)
18565f4613f2SJohn Marino 	    _nc_align_termtype(&entries[0].tterm, &entries[1].tterm);
18575f4613f2SJohn Marino #endif
18585f4613f2SJohn Marino 
18595f4613f2SJohn Marino 	/* dump as C initializer for the terminal type */
18605f4613f2SJohn Marino 	if (initdump) {
18615f4613f2SJohn Marino 	    if (initdump & 1)
18625f4613f2SJohn Marino 		dump_termtype(&entries[0].tterm);
18635f4613f2SJohn Marino 	    if (initdump & 2)
18645f4613f2SJohn Marino 		dump_initializers(&entries[0].tterm);
18655f4613f2SJohn Marino 	}
18665f4613f2SJohn Marino 
18675f4613f2SJohn Marino 	/* analyze the init strings */
18685f4613f2SJohn Marino 	else if (init_analyze) {
18695f4613f2SJohn Marino #undef CUR
18705f4613f2SJohn Marino #define CUR	entries[0].tterm.
18715f4613f2SJohn Marino 	    analyze_string("is1", init_1string, &entries[0].tterm);
18725f4613f2SJohn Marino 	    analyze_string("is2", init_2string, &entries[0].tterm);
18735f4613f2SJohn Marino 	    analyze_string("is3", init_3string, &entries[0].tterm);
18745f4613f2SJohn Marino 	    analyze_string("rs1", reset_1string, &entries[0].tterm);
18755f4613f2SJohn Marino 	    analyze_string("rs2", reset_2string, &entries[0].tterm);
18765f4613f2SJohn Marino 	    analyze_string("rs3", reset_3string, &entries[0].tterm);
18775f4613f2SJohn Marino 	    analyze_string("smcup", enter_ca_mode, &entries[0].tterm);
18785f4613f2SJohn Marino 	    analyze_string("rmcup", exit_ca_mode, &entries[0].tterm);
18793468e90cSJohn Marino 	    analyze_string("smkx", keypad_xmit, &entries[0].tterm);
18803468e90cSJohn Marino 	    analyze_string("rmkx", keypad_local, &entries[0].tterm);
18815f4613f2SJohn Marino #undef CUR
18825f4613f2SJohn Marino 	} else {
18835f4613f2SJohn Marino 
18845f4613f2SJohn Marino 	    /*
18855f4613f2SJohn Marino 	     * Here's where the real work gets done
18865f4613f2SJohn Marino 	     */
18875f4613f2SJohn Marino 	    switch (compare) {
18885f4613f2SJohn Marino 	    case C_DEFAULT:
18895f4613f2SJohn Marino 		if (itrace)
18905f4613f2SJohn Marino 		    (void) fprintf(stderr,
18915f4613f2SJohn Marino 				   "%s: about to dump %s\n",
18925f4613f2SJohn Marino 				   _nc_progname,
18935f4613f2SJohn Marino 				   tname[0]);
18943468e90cSJohn Marino 		if (!quiet)
18953468e90cSJohn Marino 		    (void)
18963468e90cSJohn Marino 			printf("#\tReconstructed via infocmp from file: %s\n",
18975f4613f2SJohn Marino 			       tfile[0]);
18985f4613f2SJohn Marino 		dump_entry(&entries[0].tterm,
18995f4613f2SJohn Marino 			   suppress_untranslatable,
19005f4613f2SJohn Marino 			   limited,
19015f4613f2SJohn Marino 			   numbers,
19025f4613f2SJohn Marino 			   NULL);
19035f4613f2SJohn Marino 		len = show_entry();
19045f4613f2SJohn Marino 		if (itrace)
19055f4613f2SJohn Marino 		    (void) fprintf(stderr, "%s: length %d\n", _nc_progname, len);
19065f4613f2SJohn Marino 		break;
19075f4613f2SJohn Marino 
19085f4613f2SJohn Marino 	    case C_DIFFERENCE:
19093468e90cSJohn Marino 		show_comparing(tname);
19105f4613f2SJohn Marino 		compare_entry(compare_predicate, &entries->tterm, quiet);
19115f4613f2SJohn Marino 		break;
19125f4613f2SJohn Marino 
19135f4613f2SJohn Marino 	    case C_COMMON:
19143468e90cSJohn Marino 		show_comparing(tname);
19155f4613f2SJohn Marino 		compare_entry(compare_predicate, &entries->tterm, quiet);
19165f4613f2SJohn Marino 		break;
19175f4613f2SJohn Marino 
19185f4613f2SJohn Marino 	    case C_NAND:
19193468e90cSJohn Marino 		show_comparing(tname);
19205f4613f2SJohn Marino 		compare_entry(compare_predicate, &entries->tterm, quiet);
19215f4613f2SJohn Marino 		break;
19225f4613f2SJohn Marino 
19235f4613f2SJohn Marino 	    case C_USEALL:
19245f4613f2SJohn Marino 		if (itrace)
19255f4613f2SJohn Marino 		    (void) fprintf(stderr, "%s: dumping use entry\n", _nc_progname);
19265f4613f2SJohn Marino 		dump_entry(&entries[0].tterm,
19275f4613f2SJohn Marino 			   suppress_untranslatable,
19285f4613f2SJohn Marino 			   limited,
19295f4613f2SJohn Marino 			   numbers,
19305f4613f2SJohn Marino 			   use_predicate);
19315f4613f2SJohn Marino 		for (i = 1; i < termcount; i++)
19325f4613f2SJohn Marino 		    dump_uses(tname[i], !(outform == F_TERMCAP
19335f4613f2SJohn Marino 					  || outform == F_TCONVERR));
19345f4613f2SJohn Marino 		len = show_entry();
19355f4613f2SJohn Marino 		if (itrace)
19365f4613f2SJohn Marino 		    (void) fprintf(stderr, "%s: length %d\n", _nc_progname, len);
19375f4613f2SJohn Marino 		break;
19385f4613f2SJohn Marino 	    }
19395f4613f2SJohn Marino 	}
19403468e90cSJohn Marino     } else if (compare == C_USEALL) {
19415f4613f2SJohn Marino 	(void) fprintf(stderr, "Sorry, -u doesn't work with -F\n");
19423468e90cSJohn Marino     } else if (compare == C_DEFAULT) {
19435f4613f2SJohn Marino 	(void) fprintf(stderr, "Use `tic -[CI] <file>' for this.\n");
19443468e90cSJohn Marino     } else if (argc - optind != 2) {
19455f4613f2SJohn Marino 	(void) fprintf(stderr,
19465f4613f2SJohn Marino 		       "File comparison needs exactly two file arguments.\n");
19473468e90cSJohn Marino     } else {
19485f4613f2SJohn Marino 	file_comparison(argc - optind, argv + optind);
19493468e90cSJohn Marino     }
19505f4613f2SJohn Marino 
19515f4613f2SJohn Marino     MAIN_LEAKS();
19525f4613f2SJohn Marino     ExitProgram(EXIT_SUCCESS);
19535f4613f2SJohn Marino }
19545f4613f2SJohn Marino 
19555f4613f2SJohn Marino /* infocmp.c ends here */
1956