10e3d5408SPeter Wemm /**************************************************************************** 215589c42SPeter Wemm * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * 30e3d5408SPeter Wemm * * 40e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 50e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 60e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 70e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 80e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 90e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 100e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 110e3d5408SPeter Wemm * * 120e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 130e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 140e3d5408SPeter Wemm * * 150e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 160e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 170e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 180e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 190e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 200e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 210e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 220e3d5408SPeter Wemm * * 230e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 240e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 250e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 260e3d5408SPeter Wemm * authorization. * 270e3d5408SPeter Wemm ****************************************************************************/ 280e3d5408SPeter Wemm 290e3d5408SPeter Wemm /**************************************************************************** 300e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 310e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 320e3d5408SPeter Wemm ****************************************************************************/ 330e3d5408SPeter Wemm 340e3d5408SPeter Wemm /* 350e3d5408SPeter Wemm * infocmp.c -- decompile an entry, or compare two entries 360e3d5408SPeter Wemm * written by Eric S. Raymond 370e3d5408SPeter Wemm */ 380e3d5408SPeter Wemm 390e3d5408SPeter Wemm #include <progs.priv.h> 400e3d5408SPeter Wemm 410e3d5408SPeter Wemm #include <term_entry.h> 420e3d5408SPeter Wemm #include <dump_entry.h> 430e3d5408SPeter Wemm 44*18259542SPeter Wemm MODULE_ID("$Id: infocmp.c,v 1.57 2000/10/01 01:26:25 tom Exp $") 450e3d5408SPeter Wemm 460e3d5408SPeter Wemm #define L_CURL "{" 470e3d5408SPeter Wemm #define R_CURL "}" 480e3d5408SPeter Wemm 490e3d5408SPeter Wemm #define MAXTERMS 32 /* max # terminal arguments we can handle */ 5015589c42SPeter Wemm #define MAX_STRING 1024 /* maximum formatted string */ 510e3d5408SPeter Wemm 520e3d5408SPeter Wemm const char *_nc_progname = "infocmp"; 530e3d5408SPeter Wemm 540e3d5408SPeter Wemm typedef char path[PATH_MAX]; 550e3d5408SPeter Wemm 560e3d5408SPeter Wemm /*************************************************************************** 570e3d5408SPeter Wemm * 580e3d5408SPeter Wemm * The following control variables, together with the contents of the 590e3d5408SPeter Wemm * terminfo entries, completely determine the actions of the program. 600e3d5408SPeter Wemm * 610e3d5408SPeter Wemm ***************************************************************************/ 620e3d5408SPeter Wemm 630e3d5408SPeter Wemm static char *tname[MAXTERMS]; /* terminal type names */ 6415589c42SPeter Wemm static ENTRY entries[MAXTERMS]; /* terminfo entries */ 650e3d5408SPeter Wemm static int termcount; /* count of terminal entries */ 660e3d5408SPeter Wemm 6715589c42SPeter Wemm static bool limited = TRUE; /* "-r" option is not set */ 6815589c42SPeter Wemm static bool quiet = FALSE; 6915589c42SPeter Wemm static const char *bool_sep = ":"; 7015589c42SPeter Wemm static const char *s_absent = "NULL"; 7115589c42SPeter Wemm static const char *s_cancel = "NULL"; 720e3d5408SPeter Wemm static const char *tversion; /* terminfo version selected */ 730e3d5408SPeter Wemm static int itrace; /* trace flag for debugging */ 740e3d5408SPeter Wemm static int mwidth = 60; 7515589c42SPeter Wemm static int numbers = 0; /* format "%'char'" to/from "%{number}" */ 7615589c42SPeter Wemm static int outform = F_TERMINFO; /* output format */ 7715589c42SPeter Wemm static int sortmode; /* sort_mode */ 780e3d5408SPeter Wemm 790e3d5408SPeter Wemm /* main comparison mode */ 800e3d5408SPeter Wemm static int compare; 810e3d5408SPeter Wemm #define C_DEFAULT 0 /* don't force comparison mode */ 820e3d5408SPeter Wemm #define C_DIFFERENCE 1 /* list differences between two terminals */ 830e3d5408SPeter Wemm #define C_COMMON 2 /* list common capabilities */ 840e3d5408SPeter Wemm #define C_NAND 3 /* list capabilities in neither terminal */ 850e3d5408SPeter Wemm #define C_USEALL 4 /* generate relative use-form entry */ 860e3d5408SPeter Wemm static bool ignorepads; /* ignore pad prefixes when diffing */ 870e3d5408SPeter Wemm 880e3d5408SPeter Wemm #if NO_LEAKS 890e3d5408SPeter Wemm #undef ExitProgram 9015589c42SPeter Wemm static void 9115589c42SPeter Wemm ExitProgram(int code) GCC_NORETURN; 9215589c42SPeter Wemm /* prototype is to get gcc to accept the noreturn attribute */ 9315589c42SPeter Wemm static void 9415589c42SPeter Wemm ExitProgram(int code) 950e3d5408SPeter Wemm { 960e3d5408SPeter Wemm while (termcount-- > 0) 9715589c42SPeter Wemm _nc_free_termtype(&entries[termcount].tterm); 980e3d5408SPeter Wemm _nc_leaks_dump_entry(); 990e3d5408SPeter Wemm _nc_free_and_exit(code); 1000e3d5408SPeter Wemm } 1010e3d5408SPeter Wemm #endif 1020e3d5408SPeter Wemm 10315589c42SPeter Wemm static char * 10415589c42SPeter Wemm canonical_name(char *ptr, char *buf) 1050e3d5408SPeter Wemm /* extract the terminal type's primary name */ 1060e3d5408SPeter Wemm { 1070e3d5408SPeter Wemm char *bp; 1080e3d5408SPeter Wemm 1090e3d5408SPeter Wemm (void) strcpy(buf, ptr); 11015589c42SPeter Wemm if ((bp = strchr(buf, '|')) != 0) 1110e3d5408SPeter Wemm *bp = '\0'; 1120e3d5408SPeter Wemm 1130e3d5408SPeter Wemm return (buf); 1140e3d5408SPeter Wemm } 1150e3d5408SPeter Wemm 1160e3d5408SPeter Wemm /*************************************************************************** 1170e3d5408SPeter Wemm * 1180e3d5408SPeter Wemm * Predicates for dump function 1190e3d5408SPeter Wemm * 1200e3d5408SPeter Wemm ***************************************************************************/ 1210e3d5408SPeter Wemm 12215589c42SPeter Wemm static int 12315589c42SPeter Wemm capcmp(int idx, const char *s, const char *t) 1240e3d5408SPeter Wemm /* capability comparison function */ 1250e3d5408SPeter Wemm { 1260e3d5408SPeter Wemm if (!VALID_STRING(s) && !VALID_STRING(t)) 12715589c42SPeter Wemm return (s != t); 1280e3d5408SPeter Wemm else if (!VALID_STRING(s) || !VALID_STRING(t)) 1290e3d5408SPeter Wemm return (1); 1300e3d5408SPeter Wemm 13115589c42SPeter Wemm if ((idx == acs_chars_index) || !ignorepads) 1320e3d5408SPeter Wemm return (strcmp(s, t)); 13315589c42SPeter Wemm else 13415589c42SPeter Wemm return (_nc_capcmp(s, t)); 1350e3d5408SPeter Wemm } 1360e3d5408SPeter Wemm 13715589c42SPeter Wemm static int 13815589c42SPeter Wemm use_predicate(int type, int idx) 1390e3d5408SPeter Wemm /* predicate function to use for use decompilation */ 1400e3d5408SPeter Wemm { 14115589c42SPeter Wemm ENTRY *ep; 1420e3d5408SPeter Wemm 14315589c42SPeter Wemm switch (type) { 14415589c42SPeter Wemm case BOOLEAN: 1450e3d5408SPeter Wemm { 1460e3d5408SPeter Wemm int is_set = FALSE; 1470e3d5408SPeter Wemm 1480e3d5408SPeter Wemm /* 1490e3d5408SPeter Wemm * This assumes that multiple use entries are supposed 1500e3d5408SPeter Wemm * to contribute the logical or of their boolean capabilities. 1510e3d5408SPeter Wemm * This is true if we take the semantics of multiple uses to 1520e3d5408SPeter Wemm * be 'each capability gets the first non-default value found 1530e3d5408SPeter Wemm * in the sequence of use entries'. 15415589c42SPeter Wemm * 15515589c42SPeter Wemm * Note that cancelled or absent booleans are stored as FALSE, 15615589c42SPeter Wemm * unlike numbers and strings, whose cancelled/absent state is 15715589c42SPeter Wemm * recorded in the terminfo database. 1580e3d5408SPeter Wemm */ 15915589c42SPeter Wemm for (ep = &entries[1]; ep < entries + termcount; ep++) 16015589c42SPeter Wemm if (ep->tterm.Booleans[idx] == TRUE) { 16115589c42SPeter Wemm is_set = entries[0].tterm.Booleans[idx]; 1620e3d5408SPeter Wemm break; 1630e3d5408SPeter Wemm } 16415589c42SPeter Wemm if (is_set != entries[0].tterm.Booleans[idx]) 1650e3d5408SPeter Wemm return (!is_set); 1660e3d5408SPeter Wemm else 1670e3d5408SPeter Wemm return (FAIL); 1680e3d5408SPeter Wemm } 1690e3d5408SPeter Wemm 17015589c42SPeter Wemm case NUMBER: 17115589c42SPeter Wemm { 1720e3d5408SPeter Wemm int value = ABSENT_NUMERIC; 1730e3d5408SPeter Wemm 1740e3d5408SPeter Wemm /* 1750e3d5408SPeter Wemm * We take the semantics of multiple uses to be 'each 1760e3d5408SPeter Wemm * capability gets the first non-default value found 1770e3d5408SPeter Wemm * in the sequence of use entries'. 1780e3d5408SPeter Wemm */ 17915589c42SPeter Wemm for (ep = &entries[1]; ep < entries + termcount; ep++) 18015589c42SPeter Wemm if (VALID_NUMERIC(ep->tterm.Numbers[idx])) { 18115589c42SPeter Wemm value = ep->tterm.Numbers[idx]; 1820e3d5408SPeter Wemm break; 1830e3d5408SPeter Wemm } 1840e3d5408SPeter Wemm 18515589c42SPeter Wemm if (value != entries[0].tterm.Numbers[idx]) 1860e3d5408SPeter Wemm return (value != ABSENT_NUMERIC); 1870e3d5408SPeter Wemm else 1880e3d5408SPeter Wemm return (FAIL); 1890e3d5408SPeter Wemm } 1900e3d5408SPeter Wemm 19115589c42SPeter Wemm case STRING: 19215589c42SPeter Wemm { 1930e3d5408SPeter Wemm char *termstr, *usestr = ABSENT_STRING; 1940e3d5408SPeter Wemm 19515589c42SPeter Wemm termstr = entries[0].tterm.Strings[idx]; 1960e3d5408SPeter Wemm 1970e3d5408SPeter Wemm /* 1980e3d5408SPeter Wemm * We take the semantics of multiple uses to be 'each 1990e3d5408SPeter Wemm * capability gets the first non-default value found 2000e3d5408SPeter Wemm * in the sequence of use entries'. 2010e3d5408SPeter Wemm */ 20215589c42SPeter Wemm for (ep = &entries[1]; ep < entries + termcount; ep++) 20315589c42SPeter Wemm if (ep->tterm.Strings[idx]) { 20415589c42SPeter Wemm usestr = ep->tterm.Strings[idx]; 2050e3d5408SPeter Wemm break; 2060e3d5408SPeter Wemm } 2070e3d5408SPeter Wemm 2080e3d5408SPeter Wemm if (usestr == ABSENT_STRING && termstr == ABSENT_STRING) 2090e3d5408SPeter Wemm return (FAIL); 21015589c42SPeter Wemm else if (!usestr || !termstr || capcmp(idx, usestr, termstr)) 2110e3d5408SPeter Wemm return (TRUE); 2120e3d5408SPeter Wemm else 2130e3d5408SPeter Wemm return (FAIL); 2140e3d5408SPeter Wemm } 2150e3d5408SPeter Wemm } 2160e3d5408SPeter Wemm 2170e3d5408SPeter Wemm return (FALSE); /* pacify compiler */ 2180e3d5408SPeter Wemm } 2190e3d5408SPeter Wemm 22015589c42SPeter Wemm static bool 22115589c42SPeter Wemm useeq(ENTRY * e1, ENTRY * e2) 22215589c42SPeter Wemm /* are the use references in two entries equivalent? */ 22315589c42SPeter Wemm { 22415589c42SPeter Wemm int i, j; 22515589c42SPeter Wemm 22615589c42SPeter Wemm if (e1->nuses != e2->nuses) 22715589c42SPeter Wemm return (FALSE); 22815589c42SPeter Wemm 22915589c42SPeter Wemm /* Ugh...this is quadratic again */ 23015589c42SPeter Wemm for (i = 0; i < e1->nuses; i++) { 23115589c42SPeter Wemm bool foundmatch = FALSE; 23215589c42SPeter Wemm 23315589c42SPeter Wemm /* search second entry for given use reference */ 23415589c42SPeter Wemm for (j = 0; j < e2->nuses; j++) 23515589c42SPeter Wemm if (!strcmp(e1->uses[i].name, e2->uses[j].name)) { 23615589c42SPeter Wemm foundmatch = TRUE; 23715589c42SPeter Wemm break; 23815589c42SPeter Wemm } 23915589c42SPeter Wemm 24015589c42SPeter Wemm if (!foundmatch) 24115589c42SPeter Wemm return (FALSE); 24215589c42SPeter Wemm } 24315589c42SPeter Wemm 24415589c42SPeter Wemm return (TRUE); 24515589c42SPeter Wemm } 24615589c42SPeter Wemm 24715589c42SPeter Wemm static bool 24815589c42SPeter Wemm entryeq(TERMTYPE * t1, TERMTYPE * t2) 24915589c42SPeter Wemm /* are two entries equivalent? */ 2500e3d5408SPeter Wemm { 2510e3d5408SPeter Wemm int i; 2520e3d5408SPeter Wemm 2530e3d5408SPeter Wemm for (i = 0; i < NUM_BOOLEANS(t1); i++) 2540e3d5408SPeter Wemm if (t1->Booleans[i] != t2->Booleans[i]) 2550e3d5408SPeter Wemm return (FALSE); 2560e3d5408SPeter Wemm 2570e3d5408SPeter Wemm for (i = 0; i < NUM_NUMBERS(t1); i++) 2580e3d5408SPeter Wemm if (t1->Numbers[i] != t2->Numbers[i]) 2590e3d5408SPeter Wemm return (FALSE); 2600e3d5408SPeter Wemm 2610e3d5408SPeter Wemm for (i = 0; i < NUM_STRINGS(t1); i++) 26215589c42SPeter Wemm if (capcmp(i, t1->Strings[i], t2->Strings[i])) 2630e3d5408SPeter Wemm return (FALSE); 2640e3d5408SPeter Wemm 2650e3d5408SPeter Wemm return (TRUE); 2660e3d5408SPeter Wemm } 2670e3d5408SPeter Wemm 2680e3d5408SPeter Wemm #define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers) 2690e3d5408SPeter Wemm 27015589c42SPeter Wemm static void 27115589c42SPeter Wemm print_uses(ENTRY * ep, FILE * fp) 27215589c42SPeter Wemm /* print an entry's use references */ 27315589c42SPeter Wemm { 27415589c42SPeter Wemm int i; 27515589c42SPeter Wemm 27615589c42SPeter Wemm if (!ep->nuses) 27715589c42SPeter Wemm fputs("NULL", fp); 27815589c42SPeter Wemm else 27915589c42SPeter Wemm for (i = 0; i < ep->nuses; i++) { 28015589c42SPeter Wemm fputs(ep->uses[i].name, fp); 28115589c42SPeter Wemm if (i < ep->nuses - 1) 28215589c42SPeter Wemm fputs(" ", fp); 28315589c42SPeter Wemm } 28415589c42SPeter Wemm } 28515589c42SPeter Wemm 28615589c42SPeter Wemm static const char * 28715589c42SPeter Wemm dump_boolean(int val) 28815589c42SPeter Wemm /* display the value of a boolean capability */ 28915589c42SPeter Wemm { 29015589c42SPeter Wemm switch (val) { 29115589c42SPeter Wemm case ABSENT_BOOLEAN: 29215589c42SPeter Wemm return (s_absent); 29315589c42SPeter Wemm case CANCELLED_BOOLEAN: 29415589c42SPeter Wemm return (s_cancel); 29515589c42SPeter Wemm case FALSE: 29615589c42SPeter Wemm return ("F"); 29715589c42SPeter Wemm case TRUE: 29815589c42SPeter Wemm return ("T"); 29915589c42SPeter Wemm default: 30015589c42SPeter Wemm return ("?"); 30115589c42SPeter Wemm } 30215589c42SPeter Wemm } 30315589c42SPeter Wemm 30415589c42SPeter Wemm static void 30515589c42SPeter Wemm dump_numeric(int val, char *buf) 30615589c42SPeter Wemm /* display the value of a boolean capability */ 30715589c42SPeter Wemm { 30815589c42SPeter Wemm switch (val) { 30915589c42SPeter Wemm case ABSENT_NUMERIC: 31015589c42SPeter Wemm strcpy(buf, s_absent); 31115589c42SPeter Wemm break; 31215589c42SPeter Wemm case CANCELLED_NUMERIC: 31315589c42SPeter Wemm strcpy(buf, s_cancel); 31415589c42SPeter Wemm break; 31515589c42SPeter Wemm default: 31615589c42SPeter Wemm sprintf(buf, "%d", val); 31715589c42SPeter Wemm break; 31815589c42SPeter Wemm } 31915589c42SPeter Wemm } 32015589c42SPeter Wemm 32115589c42SPeter Wemm static void 32215589c42SPeter Wemm dump_string(char *val, char *buf) 32315589c42SPeter Wemm /* display the value of a string capability */ 32415589c42SPeter Wemm { 32515589c42SPeter Wemm if (val == ABSENT_STRING) 32615589c42SPeter Wemm strcpy(buf, s_absent); 32715589c42SPeter Wemm else if (val == CANCELLED_STRING) 32815589c42SPeter Wemm strcpy(buf, s_cancel); 32915589c42SPeter Wemm else { 33015589c42SPeter Wemm sprintf(buf, "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val)); 33115589c42SPeter Wemm } 33215589c42SPeter Wemm } 33315589c42SPeter Wemm 33415589c42SPeter Wemm static void 33515589c42SPeter Wemm compare_predicate(int type, int idx, const char *name) 3360e3d5408SPeter Wemm /* predicate function to use for entry difference reports */ 3370e3d5408SPeter Wemm { 33815589c42SPeter Wemm register ENTRY *e1 = &entries[0]; 33915589c42SPeter Wemm register ENTRY *e2 = &entries[1]; 34015589c42SPeter Wemm char buf1[MAX_STRING], buf2[MAX_STRING]; 34115589c42SPeter Wemm int b1, b2; 34215589c42SPeter Wemm int n1, n2; 3430e3d5408SPeter Wemm char *s1, *s2; 3440e3d5408SPeter Wemm 34515589c42SPeter Wemm switch (type) { 34615589c42SPeter Wemm case CMP_BOOLEAN: 34715589c42SPeter Wemm b1 = e1->tterm.Booleans[idx]; 34815589c42SPeter Wemm b2 = e2->tterm.Booleans[idx]; 34915589c42SPeter Wemm switch (compare) { 3500e3d5408SPeter Wemm case C_DIFFERENCE: 35115589c42SPeter Wemm if (!(b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) && b1 != b2) 35215589c42SPeter Wemm (void) printf("\t%s: %s%s%s.\n", 3530e3d5408SPeter Wemm name, 35415589c42SPeter Wemm dump_boolean(b1), 35515589c42SPeter Wemm bool_sep, 35615589c42SPeter Wemm dump_boolean(b2)); 3570e3d5408SPeter Wemm break; 3580e3d5408SPeter Wemm 3590e3d5408SPeter Wemm case C_COMMON: 36015589c42SPeter Wemm if (b1 == b2 && b1 != ABSENT_BOOLEAN) 36115589c42SPeter Wemm (void) printf("\t%s= %s.\n", name, dump_boolean(b1)); 3620e3d5408SPeter Wemm break; 3630e3d5408SPeter Wemm 3640e3d5408SPeter Wemm case C_NAND: 36515589c42SPeter Wemm if (b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) 3660e3d5408SPeter Wemm (void) printf("\t!%s.\n", name); 3670e3d5408SPeter Wemm break; 3680e3d5408SPeter Wemm } 3690e3d5408SPeter Wemm break; 3700e3d5408SPeter Wemm 37115589c42SPeter Wemm case CMP_NUMBER: 37215589c42SPeter Wemm n1 = e1->tterm.Numbers[idx]; 37315589c42SPeter Wemm n2 = e2->tterm.Numbers[idx]; 37415589c42SPeter Wemm dump_numeric(n1, buf1); 37515589c42SPeter Wemm dump_numeric(n2, buf2); 37615589c42SPeter Wemm switch (compare) { 3770e3d5408SPeter Wemm case C_DIFFERENCE: 37815589c42SPeter Wemm if (!((n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)) && n1 != n2) 37915589c42SPeter Wemm (void) printf("\t%s: %s, %s.\n", name, buf1, buf2); 3800e3d5408SPeter Wemm break; 3810e3d5408SPeter Wemm 3820e3d5408SPeter Wemm case C_COMMON: 38315589c42SPeter Wemm if (n1 != ABSENT_NUMERIC && n2 != ABSENT_NUMERIC && n1 == n2) 38415589c42SPeter Wemm (void) printf("\t%s= %s.\n", name, buf1); 3850e3d5408SPeter Wemm break; 3860e3d5408SPeter Wemm 3870e3d5408SPeter Wemm case C_NAND: 38815589c42SPeter Wemm if (n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC) 3890e3d5408SPeter Wemm (void) printf("\t!%s.\n", name); 3900e3d5408SPeter Wemm break; 3910e3d5408SPeter Wemm } 3920e3d5408SPeter Wemm break; 3930e3d5408SPeter Wemm 39415589c42SPeter Wemm case CMP_STRING: 39515589c42SPeter Wemm s1 = e1->tterm.Strings[idx]; 39615589c42SPeter Wemm s2 = e2->tterm.Strings[idx]; 39715589c42SPeter Wemm switch (compare) { 3980e3d5408SPeter Wemm case C_DIFFERENCE: 39915589c42SPeter Wemm if (capcmp(idx, s1, s2)) { 40015589c42SPeter Wemm dump_string(s1, buf1); 40115589c42SPeter Wemm dump_string(s2, buf2); 4020e3d5408SPeter Wemm if (strcmp(buf1, buf2)) 40315589c42SPeter Wemm (void) printf("\t%s: %s, %s.\n", name, buf1, buf2); 4040e3d5408SPeter Wemm } 4050e3d5408SPeter Wemm break; 4060e3d5408SPeter Wemm 4070e3d5408SPeter Wemm case C_COMMON: 40815589c42SPeter Wemm if (s1 && s2 && !capcmp(idx, s1, s2)) 4090e3d5408SPeter Wemm (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1)); 4100e3d5408SPeter Wemm break; 4110e3d5408SPeter Wemm 4120e3d5408SPeter Wemm case C_NAND: 4130e3d5408SPeter Wemm if (!s1 && !s2) 4140e3d5408SPeter Wemm (void) printf("\t!%s.\n", name); 4150e3d5408SPeter Wemm break; 4160e3d5408SPeter Wemm } 4170e3d5408SPeter Wemm break; 4180e3d5408SPeter Wemm 41915589c42SPeter Wemm case CMP_USE: 42015589c42SPeter Wemm /* unlike the other modes, this compares *all* use entries */ 42115589c42SPeter Wemm switch (compare) { 42215589c42SPeter Wemm case C_DIFFERENCE: 42315589c42SPeter Wemm if (!useeq(e1, e2)) { 42415589c42SPeter Wemm (void) fputs("\tuse: ", stdout); 42515589c42SPeter Wemm print_uses(e1, stdout); 42615589c42SPeter Wemm fputs(", ", stdout); 42715589c42SPeter Wemm print_uses(e2, stdout); 42815589c42SPeter Wemm fputs(".\n", stdout); 42915589c42SPeter Wemm } 43015589c42SPeter Wemm break; 43115589c42SPeter Wemm 43215589c42SPeter Wemm case C_COMMON: 43315589c42SPeter Wemm if (e1->nuses && e2->nuses && useeq(e1, e2)) { 43415589c42SPeter Wemm (void) fputs("\tuse: ", stdout); 43515589c42SPeter Wemm print_uses(e1, stdout); 43615589c42SPeter Wemm fputs(".\n", stdout); 43715589c42SPeter Wemm } 43815589c42SPeter Wemm break; 43915589c42SPeter Wemm 44015589c42SPeter Wemm case C_NAND: 44115589c42SPeter Wemm if (!e1->nuses && !e2->nuses) 44215589c42SPeter Wemm (void) printf("\t!use.\n"); 44315589c42SPeter Wemm break; 44415589c42SPeter Wemm } 44515589c42SPeter Wemm } 4460e3d5408SPeter Wemm } 4470e3d5408SPeter Wemm 4480e3d5408SPeter Wemm /*************************************************************************** 4490e3d5408SPeter Wemm * 4500e3d5408SPeter Wemm * Init string analysis 4510e3d5408SPeter Wemm * 4520e3d5408SPeter Wemm ***************************************************************************/ 4530e3d5408SPeter Wemm 45415589c42SPeter Wemm typedef struct { 45515589c42SPeter Wemm const char *from; 45615589c42SPeter Wemm const char *to; 45715589c42SPeter Wemm } assoc; 4580e3d5408SPeter Wemm 4590e3d5408SPeter Wemm static const assoc std_caps[] = 4600e3d5408SPeter Wemm { 4610e3d5408SPeter Wemm /* these are specified by X.364 and iBCS2 */ 4620e3d5408SPeter Wemm {"\033c", "RIS"}, /* full reset */ 4630e3d5408SPeter Wemm {"\0337", "SC"}, /* save cursor */ 4640e3d5408SPeter Wemm {"\0338", "RC"}, /* restore cursor */ 4650e3d5408SPeter Wemm {"\033[r", "RSR"}, /* not an X.364 mnemonic */ 4660e3d5408SPeter Wemm {"\033[m", "SGR0"}, /* not an X.364 mnemonic */ 4670e3d5408SPeter Wemm {"\033[2J", "ED2"}, /* clear page */ 4680e3d5408SPeter Wemm 4690e3d5408SPeter Wemm /* this group is specified by ISO 2022 */ 4700e3d5408SPeter Wemm {"\033(0", "ISO DEC G0"}, /* enable DEC graphics for G0 */ 4710e3d5408SPeter Wemm {"\033(A", "ISO UK G0"}, /* enable UK chars for G0 */ 4720e3d5408SPeter Wemm {"\033(B", "ISO US G0"}, /* enable US chars for G0 */ 4730e3d5408SPeter Wemm {"\033)0", "ISO DEC G1"}, /* enable DEC graphics for G1 */ 4740e3d5408SPeter Wemm {"\033)A", "ISO UK G1"}, /* enable UK chars for G1 */ 4750e3d5408SPeter Wemm {"\033)B", "ISO US G1"}, /* enable US chars for G1 */ 4760e3d5408SPeter Wemm 4770e3d5408SPeter Wemm /* these are DEC private modes widely supported by emulators */ 4780e3d5408SPeter Wemm {"\033=", "DECPAM"}, /* application keypad mode */ 4790e3d5408SPeter Wemm {"\033>", "DECPNM"}, /* normal keypad mode */ 4800e3d5408SPeter Wemm {"\033<", "DECANSI"}, /* enter ANSI mode */ 4810e3d5408SPeter Wemm 4820e3d5408SPeter Wemm {(char *) 0, (char *) 0} 4830e3d5408SPeter Wemm }; 4840e3d5408SPeter Wemm 4850e3d5408SPeter Wemm static const assoc private_modes[] = 4860e3d5408SPeter Wemm /* DEC \E[ ... [hl] modes recognized by many emulators */ 4870e3d5408SPeter Wemm { 4880e3d5408SPeter Wemm {"1", "CKM"}, /* application cursor keys */ 4890e3d5408SPeter Wemm {"2", "ANM"}, /* set VT52 mode */ 4900e3d5408SPeter Wemm {"3", "COLM"}, /* 132-column mode */ 4910e3d5408SPeter Wemm {"4", "SCLM"}, /* smooth scroll */ 4920e3d5408SPeter Wemm {"5", "SCNM"}, /* reverse video mode */ 4930e3d5408SPeter Wemm {"6", "OM"}, /* origin mode */ 4940e3d5408SPeter Wemm {"7", "AWM"}, /* wraparound mode */ 4950e3d5408SPeter Wemm {"8", "ARM"}, /* auto-repeat mode */ 4960e3d5408SPeter Wemm {(char *) 0, (char *) 0} 4970e3d5408SPeter Wemm }; 4980e3d5408SPeter Wemm 4990e3d5408SPeter Wemm static const assoc ecma_highlights[] = 5000e3d5408SPeter Wemm /* recognize ECMA attribute sequences */ 5010e3d5408SPeter Wemm { 5020e3d5408SPeter Wemm {"0", "NORMAL"}, /* normal */ 5030e3d5408SPeter Wemm {"1", "+BOLD"}, /* bold on */ 5040e3d5408SPeter Wemm {"2", "+DIM"}, /* dim on */ 5050e3d5408SPeter Wemm {"3", "+ITALIC"}, /* italic on */ 5060e3d5408SPeter Wemm {"4", "+UNDERLINE"}, /* underline on */ 5070e3d5408SPeter Wemm {"5", "+BLINK"}, /* blink on */ 5080e3d5408SPeter Wemm {"6", "+FASTBLINK"}, /* fastblink on */ 5090e3d5408SPeter Wemm {"7", "+REVERSE"}, /* reverse on */ 5100e3d5408SPeter Wemm {"8", "+INVISIBLE"}, /* invisible on */ 5110e3d5408SPeter Wemm {"9", "+DELETED"}, /* deleted on */ 5120e3d5408SPeter Wemm {"10", "MAIN-FONT"}, /* select primary font */ 5130e3d5408SPeter Wemm {"11", "ALT-FONT-1"}, /* select alternate font 1 */ 5140e3d5408SPeter Wemm {"12", "ALT-FONT-2"}, /* select alternate font 2 */ 5150e3d5408SPeter Wemm {"13", "ALT-FONT-3"}, /* select alternate font 3 */ 5160e3d5408SPeter Wemm {"14", "ALT-FONT-4"}, /* select alternate font 4 */ 5170e3d5408SPeter Wemm {"15", "ALT-FONT-5"}, /* select alternate font 5 */ 5180e3d5408SPeter Wemm {"16", "ALT-FONT-6"}, /* select alternate font 6 */ 5190e3d5408SPeter Wemm {"17", "ALT-FONT-7"}, /* select alternate font 7 */ 5200e3d5408SPeter Wemm {"18", "ALT-FONT-1"}, /* select alternate font 1 */ 5210e3d5408SPeter Wemm {"19", "ALT-FONT-1"}, /* select alternate font 1 */ 5220e3d5408SPeter Wemm {"20", "FRAKTUR"}, /* Fraktur font */ 5230e3d5408SPeter Wemm {"21", "DOUBLEUNDER"}, /* double underline */ 5240e3d5408SPeter Wemm {"22", "-DIM"}, /* dim off */ 5250e3d5408SPeter Wemm {"23", "-ITALIC"}, /* italic off */ 5260e3d5408SPeter Wemm {"24", "-UNDERLINE"}, /* underline off */ 5270e3d5408SPeter Wemm {"25", "-BLINK"}, /* blink off */ 5280e3d5408SPeter Wemm {"26", "-FASTBLINK"}, /* fastblink off */ 5290e3d5408SPeter Wemm {"27", "-REVERSE"}, /* reverse off */ 5300e3d5408SPeter Wemm {"28", "-INVISIBLE"}, /* invisible off */ 5310e3d5408SPeter Wemm {"29", "-DELETED"}, /* deleted off */ 5320e3d5408SPeter Wemm {(char *) 0, (char *) 0} 5330e3d5408SPeter Wemm }; 5340e3d5408SPeter Wemm 53515589c42SPeter Wemm static void 53615589c42SPeter Wemm analyze_string(const char *name, const char *cap, TERMTYPE * tp) 5370e3d5408SPeter Wemm { 5380e3d5408SPeter Wemm char buf[MAX_TERMINFO_LENGTH]; 5390e3d5408SPeter Wemm char buf2[MAX_TERMINFO_LENGTH]; 5400e3d5408SPeter Wemm const char *sp, *ep; 5410e3d5408SPeter Wemm const assoc *ap; 5420e3d5408SPeter Wemm 5430e3d5408SPeter Wemm if (cap == ABSENT_STRING || cap == CANCELLED_STRING) 5440e3d5408SPeter Wemm return; 5450e3d5408SPeter Wemm (void) printf("%s: ", name); 5460e3d5408SPeter Wemm 5470e3d5408SPeter Wemm buf[0] = '\0'; 54815589c42SPeter Wemm for (sp = cap; *sp; sp++) { 5490e3d5408SPeter Wemm int i; 5500e3d5408SPeter Wemm size_t len = 0; 5510e3d5408SPeter Wemm const char *expansion = 0; 5520e3d5408SPeter Wemm 5530e3d5408SPeter Wemm /* first, check other capabilities in this entry */ 55415589c42SPeter Wemm for (i = 0; i < STRCOUNT; i++) { 5550e3d5408SPeter Wemm char *cp = tp->Strings[i]; 5560e3d5408SPeter Wemm 5570e3d5408SPeter Wemm /* don't use soft-key capabilities */ 5580e3d5408SPeter Wemm if (strnames[i][0] == 'k' && strnames[i][0] == 'f') 5590e3d5408SPeter Wemm continue; 5600e3d5408SPeter Wemm 56115589c42SPeter Wemm if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp 56215589c42SPeter Wemm != cap) { 5630e3d5408SPeter Wemm len = strlen(cp); 5640e3d5408SPeter Wemm (void) strncpy(buf2, sp, len); 5650e3d5408SPeter Wemm buf2[len] = '\0'; 5660e3d5408SPeter Wemm 5670e3d5408SPeter Wemm if (_nc_capcmp(cp, buf2)) 5680e3d5408SPeter Wemm continue; 5690e3d5408SPeter Wemm 5700e3d5408SPeter Wemm #define ISRS(s) (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2)) 5710e3d5408SPeter Wemm /* 5720e3d5408SPeter Wemm * Theoretically we just passed the test for translation 5730e3d5408SPeter Wemm * (equality once the padding is stripped). However, there 5740e3d5408SPeter Wemm * are a few more hoops that need to be jumped so that 5750e3d5408SPeter Wemm * identical pairs of initialization and reset strings 5760e3d5408SPeter Wemm * don't just refer to each other. 5770e3d5408SPeter Wemm */ 5780e3d5408SPeter Wemm if (ISRS(name) || ISRS(strnames[i])) 5790e3d5408SPeter Wemm if (cap < cp) 5800e3d5408SPeter Wemm continue; 5810e3d5408SPeter Wemm #undef ISRS 5820e3d5408SPeter Wemm 5830e3d5408SPeter Wemm expansion = strnames[i]; 5840e3d5408SPeter Wemm break; 5850e3d5408SPeter Wemm } 5860e3d5408SPeter Wemm } 5870e3d5408SPeter Wemm 5880e3d5408SPeter Wemm /* now check the standard capabilities */ 5890e3d5408SPeter Wemm if (!expansion) 59015589c42SPeter Wemm for (ap = std_caps; ap->from; ap++) { 5910e3d5408SPeter Wemm len = strlen(ap->from); 5920e3d5408SPeter Wemm 59315589c42SPeter Wemm if (strncmp(ap->from, sp, len) == 0) { 5940e3d5408SPeter Wemm expansion = ap->to; 5950e3d5408SPeter Wemm break; 5960e3d5408SPeter Wemm } 5970e3d5408SPeter Wemm } 5980e3d5408SPeter Wemm 5990e3d5408SPeter Wemm /* now check for private-mode sequences */ 6000e3d5408SPeter Wemm if (!expansion 6010e3d5408SPeter Wemm && sp[0] == '\033' && sp[1] == '[' && sp[2] == '?' 6020e3d5408SPeter Wemm && (len = strspn(sp + 3, "0123456789;")) 60315589c42SPeter Wemm && ((sp[3 + len] == 'h') || (sp[3 + len] == 'l'))) { 6040e3d5408SPeter Wemm char buf3[MAX_TERMINFO_LENGTH]; 6050e3d5408SPeter Wemm 6060e3d5408SPeter Wemm (void) strcpy(buf2, (sp[3 + len] == 'h') ? "DEC+" : "DEC-"); 6070e3d5408SPeter Wemm (void) strncpy(buf3, sp + 3, len); 6080e3d5408SPeter Wemm len += 4; 6090e3d5408SPeter Wemm buf3[len] = '\0'; 6100e3d5408SPeter Wemm 6110e3d5408SPeter Wemm ep = strtok(buf3, ";"); 6120e3d5408SPeter Wemm do { 6130e3d5408SPeter Wemm bool found = FALSE; 6140e3d5408SPeter Wemm 61515589c42SPeter Wemm for (ap = private_modes; ap->from; ap++) { 6160e3d5408SPeter Wemm size_t tlen = strlen(ap->from); 6170e3d5408SPeter Wemm 61815589c42SPeter Wemm if (strncmp(ap->from, ep, tlen) == 0) { 6190e3d5408SPeter Wemm (void) strcat(buf2, ap->to); 6200e3d5408SPeter Wemm found = TRUE; 6210e3d5408SPeter Wemm break; 6220e3d5408SPeter Wemm } 6230e3d5408SPeter Wemm } 6240e3d5408SPeter Wemm 6250e3d5408SPeter Wemm if (!found) 6260e3d5408SPeter Wemm (void) strcat(buf2, ep); 6270e3d5408SPeter Wemm (void) strcat(buf2, ";"); 6280e3d5408SPeter Wemm } while 62915589c42SPeter Wemm ((ep = strtok((char *) 0, ";"))); 6300e3d5408SPeter Wemm buf2[strlen(buf2) - 1] = '\0'; 6310e3d5408SPeter Wemm expansion = buf2; 6320e3d5408SPeter Wemm } 6330e3d5408SPeter Wemm 6340e3d5408SPeter Wemm /* now check for ECMA highlight sequences */ 6350e3d5408SPeter Wemm if (!expansion 6360e3d5408SPeter Wemm && sp[0] == '\033' && sp[1] == '[' 6370e3d5408SPeter Wemm && (len = strspn(sp + 2, "0123456789;")) 63815589c42SPeter Wemm && sp[2 + len] == 'm') { 6390e3d5408SPeter Wemm char buf3[MAX_TERMINFO_LENGTH]; 6400e3d5408SPeter Wemm 6410e3d5408SPeter Wemm (void) strcpy(buf2, "SGR:"); 6420e3d5408SPeter Wemm (void) strncpy(buf3, sp + 2, len); 6430e3d5408SPeter Wemm len += 3; 6440e3d5408SPeter Wemm buf3[len] = '\0'; 6450e3d5408SPeter Wemm 6460e3d5408SPeter Wemm ep = strtok(buf3, ";"); 6470e3d5408SPeter Wemm do { 6480e3d5408SPeter Wemm bool found = FALSE; 6490e3d5408SPeter Wemm 65015589c42SPeter Wemm for (ap = ecma_highlights; ap->from; ap++) { 6510e3d5408SPeter Wemm size_t tlen = strlen(ap->from); 6520e3d5408SPeter Wemm 65315589c42SPeter Wemm if (strncmp(ap->from, ep, tlen) == 0) { 6540e3d5408SPeter Wemm (void) strcat(buf2, ap->to); 6550e3d5408SPeter Wemm found = TRUE; 6560e3d5408SPeter Wemm break; 6570e3d5408SPeter Wemm } 6580e3d5408SPeter Wemm } 6590e3d5408SPeter Wemm 6600e3d5408SPeter Wemm if (!found) 6610e3d5408SPeter Wemm (void) strcat(buf2, ep); 6620e3d5408SPeter Wemm (void) strcat(buf2, ";"); 6630e3d5408SPeter Wemm } while 66415589c42SPeter Wemm ((ep = strtok((char *) 0, ";"))); 6650e3d5408SPeter Wemm 6660e3d5408SPeter Wemm buf2[strlen(buf2) - 1] = '\0'; 6670e3d5408SPeter Wemm expansion = buf2; 6680e3d5408SPeter Wemm } 6690e3d5408SPeter Wemm /* now check for scroll region reset */ 67015589c42SPeter Wemm if (!expansion) { 6710e3d5408SPeter Wemm (void) sprintf(buf2, "\033[1;%dr", tp->Numbers[2]); 6720e3d5408SPeter Wemm len = strlen(buf2); 6730e3d5408SPeter Wemm if (strncmp(buf2, sp, len) == 0) 6740e3d5408SPeter Wemm expansion = "RSR"; 6750e3d5408SPeter Wemm } 6760e3d5408SPeter Wemm 6770e3d5408SPeter Wemm /* now check for home-down */ 67815589c42SPeter Wemm if (!expansion) { 6790e3d5408SPeter Wemm (void) sprintf(buf2, "\033[%d;1H", tp->Numbers[2]); 6800e3d5408SPeter Wemm len = strlen(buf2); 6810e3d5408SPeter Wemm if (strncmp(buf2, sp, len) == 0) 6820e3d5408SPeter Wemm expansion = "LL"; 6830e3d5408SPeter Wemm } 6840e3d5408SPeter Wemm 6850e3d5408SPeter Wemm /* now look at the expansion we got, if any */ 68615589c42SPeter Wemm if (expansion) { 6870e3d5408SPeter Wemm (void) sprintf(buf + strlen(buf), "{%s}", expansion); 6880e3d5408SPeter Wemm sp += len - 1; 6890e3d5408SPeter Wemm continue; 69015589c42SPeter Wemm } else { 6910e3d5408SPeter Wemm /* couldn't match anything */ 6920e3d5408SPeter Wemm buf2[0] = *sp; 6930e3d5408SPeter Wemm buf2[1] = '\0'; 6940e3d5408SPeter Wemm (void) strcat(buf, TIC_EXPAND(buf2)); 6950e3d5408SPeter Wemm } 6960e3d5408SPeter Wemm } 6970e3d5408SPeter Wemm (void) printf("%s\n", buf); 6980e3d5408SPeter Wemm } 6990e3d5408SPeter Wemm 7000e3d5408SPeter Wemm /*************************************************************************** 7010e3d5408SPeter Wemm * 7020e3d5408SPeter Wemm * File comparison 7030e3d5408SPeter Wemm * 7040e3d5408SPeter Wemm ***************************************************************************/ 7050e3d5408SPeter Wemm 70615589c42SPeter Wemm static void 70715589c42SPeter Wemm file_comparison(int argc, char *argv[]) 7080e3d5408SPeter Wemm { 7090e3d5408SPeter Wemm #define MAXCOMPARE 2 7100e3d5408SPeter Wemm /* someday we may allow comparisons on more files */ 7110e3d5408SPeter Wemm int filecount = 0; 7120e3d5408SPeter Wemm ENTRY *heads[MAXCOMPARE]; 7130e3d5408SPeter Wemm ENTRY *tails[MAXCOMPARE]; 7140e3d5408SPeter Wemm ENTRY *qp, *rp; 7150e3d5408SPeter Wemm int i, n; 7160e3d5408SPeter Wemm 71715589c42SPeter Wemm dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, itrace, FALSE); 7180e3d5408SPeter Wemm 71915589c42SPeter Wemm for (n = 0; n < argc && n < MAXCOMPARE; n++) { 72015589c42SPeter Wemm if (freopen(argv[n], "r", stdin) == 0) 7210e3d5408SPeter Wemm _nc_err_abort("Can't open %s", argv[n]); 7220e3d5408SPeter Wemm 72315589c42SPeter Wemm _nc_head = _nc_tail = 0; 7240e3d5408SPeter Wemm 7250e3d5408SPeter Wemm /* parse entries out of the source file */ 7260e3d5408SPeter Wemm _nc_set_source(argv[n]); 7270e3d5408SPeter Wemm _nc_read_entry_source(stdin, NULL, TRUE, FALSE, NULLHOOK); 7280e3d5408SPeter Wemm 7290e3d5408SPeter Wemm if (itrace) 7300e3d5408SPeter Wemm (void) fprintf(stderr, "Resolving file %d...\n", n - 0); 7310e3d5408SPeter Wemm 73215589c42SPeter Wemm /* maybe do use resolution */ 73315589c42SPeter Wemm if (!_nc_resolve_uses(!limited)) { 7340e3d5408SPeter Wemm (void) fprintf(stderr, 7350e3d5408SPeter Wemm "There are unresolved use entries in %s:\n", 7360e3d5408SPeter Wemm argv[n]); 73715589c42SPeter Wemm for_entry_list(qp) { 73815589c42SPeter Wemm if (qp->nuses) { 7390e3d5408SPeter Wemm (void) fputs(qp->tterm.term_names, stderr); 7400e3d5408SPeter Wemm (void) fputc('\n', stderr); 7410e3d5408SPeter Wemm } 74215589c42SPeter Wemm } 7430e3d5408SPeter Wemm exit(EXIT_FAILURE); 7440e3d5408SPeter Wemm } 7450e3d5408SPeter Wemm 7460e3d5408SPeter Wemm heads[filecount] = _nc_head; 7470e3d5408SPeter Wemm tails[filecount] = _nc_tail; 7480e3d5408SPeter Wemm filecount++; 7490e3d5408SPeter Wemm } 7500e3d5408SPeter Wemm 7510e3d5408SPeter Wemm /* OK, all entries are in core. Ready to do the comparison */ 7520e3d5408SPeter Wemm if (itrace) 7530e3d5408SPeter Wemm (void) fprintf(stderr, "Entries are now in core...\n"); 7540e3d5408SPeter Wemm 75515589c42SPeter Wemm /* The entry-matching loop. Sigh, this is intrinsically quadratic. */ 75615589c42SPeter Wemm for (qp = heads[0]; qp; qp = qp->next) { 7570e3d5408SPeter Wemm for (rp = heads[1]; rp; rp = rp->next) 75815589c42SPeter Wemm if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) { 75915589c42SPeter Wemm if (qp->ncrosslinks < MAX_CROSSLINKS) 76015589c42SPeter Wemm qp->crosslinks[qp->ncrosslinks] = rp; 76115589c42SPeter Wemm qp->ncrosslinks++; 7620e3d5408SPeter Wemm 76315589c42SPeter Wemm if (rp->ncrosslinks < MAX_CROSSLINKS) 76415589c42SPeter Wemm rp->crosslinks[rp->ncrosslinks] = qp; 76515589c42SPeter Wemm rp->ncrosslinks++; 7660e3d5408SPeter Wemm } 7670e3d5408SPeter Wemm } 7680e3d5408SPeter Wemm 7690e3d5408SPeter Wemm /* now we have two circular lists with crosslinks */ 7700e3d5408SPeter Wemm if (itrace) 7710e3d5408SPeter Wemm (void) fprintf(stderr, "Name matches are done...\n"); 7720e3d5408SPeter Wemm 77315589c42SPeter Wemm for (qp = heads[0]; qp; qp = qp->next) { 77415589c42SPeter Wemm if (qp->ncrosslinks > 1) { 7750e3d5408SPeter Wemm (void) fprintf(stderr, 7760e3d5408SPeter Wemm "%s in file 1 (%s) has %d matches in file 2 (%s):\n", 7770e3d5408SPeter Wemm _nc_first_name(qp->tterm.term_names), 7780e3d5408SPeter Wemm argv[0], 77915589c42SPeter Wemm qp->ncrosslinks, 7800e3d5408SPeter Wemm argv[1]); 78115589c42SPeter Wemm for (i = 0; i < qp->ncrosslinks; i++) 7820e3d5408SPeter Wemm (void) fprintf(stderr, 7830e3d5408SPeter Wemm "\t%s\n", 78415589c42SPeter Wemm _nc_first_name((qp->crosslinks[i])->tterm.term_names)); 7850e3d5408SPeter Wemm } 78615589c42SPeter Wemm } 78715589c42SPeter Wemm 78815589c42SPeter Wemm for (rp = heads[1]; rp; rp = rp->next) { 78915589c42SPeter Wemm if (rp->ncrosslinks > 1) { 7900e3d5408SPeter Wemm (void) fprintf(stderr, 7910e3d5408SPeter Wemm "%s in file 2 (%s) has %d matches in file 1 (%s):\n", 7920e3d5408SPeter Wemm _nc_first_name(rp->tterm.term_names), 7930e3d5408SPeter Wemm argv[1], 79415589c42SPeter Wemm rp->ncrosslinks, 7950e3d5408SPeter Wemm argv[0]); 79615589c42SPeter Wemm for (i = 0; i < rp->ncrosslinks; i++) 7970e3d5408SPeter Wemm (void) fprintf(stderr, 7980e3d5408SPeter Wemm "\t%s\n", 79915589c42SPeter Wemm _nc_first_name((rp->crosslinks[i])->tterm.term_names)); 80015589c42SPeter Wemm } 8010e3d5408SPeter Wemm } 8020e3d5408SPeter Wemm 8030e3d5408SPeter Wemm (void) printf("In file 1 (%s) only:\n", argv[0]); 8040e3d5408SPeter Wemm for (qp = heads[0]; qp; qp = qp->next) 80515589c42SPeter Wemm if (qp->ncrosslinks == 0) 8060e3d5408SPeter Wemm (void) printf("\t%s\n", 8070e3d5408SPeter Wemm _nc_first_name(qp->tterm.term_names)); 8080e3d5408SPeter Wemm 8090e3d5408SPeter Wemm (void) printf("In file 2 (%s) only:\n", argv[1]); 8100e3d5408SPeter Wemm for (rp = heads[1]; rp; rp = rp->next) 81115589c42SPeter Wemm if (rp->ncrosslinks == 0) 8120e3d5408SPeter Wemm (void) printf("\t%s\n", 8130e3d5408SPeter Wemm _nc_first_name(rp->tterm.term_names)); 8140e3d5408SPeter Wemm 8150e3d5408SPeter Wemm (void) printf("The following entries are equivalent:\n"); 81615589c42SPeter Wemm for (qp = heads[0]; qp; qp = qp->next) { 81715589c42SPeter Wemm rp = qp->crosslinks[0]; 8180e3d5408SPeter Wemm 81915589c42SPeter Wemm if (qp->ncrosslinks == 1) { 82015589c42SPeter Wemm rp = qp->crosslinks[0]; 82115589c42SPeter Wemm 82215589c42SPeter Wemm repair_acsc(&qp->tterm); 82315589c42SPeter Wemm repair_acsc(&rp->tterm); 82415589c42SPeter Wemm #if NCURSES_XNAMES 82515589c42SPeter Wemm _nc_align_termtype(&qp->tterm, &rp->tterm); 82615589c42SPeter Wemm #endif 82715589c42SPeter Wemm if (entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp)) { 8280e3d5408SPeter Wemm char name1[NAMESIZE], name2[NAMESIZE]; 8290e3d5408SPeter Wemm 8300e3d5408SPeter Wemm (void) canonical_name(qp->tterm.term_names, name1); 8310e3d5408SPeter Wemm (void) canonical_name(rp->tterm.term_names, name2); 8320e3d5408SPeter Wemm 8330e3d5408SPeter Wemm (void) printf("%s = %s\n", name1, name2); 8340e3d5408SPeter Wemm } 8350e3d5408SPeter Wemm } 83615589c42SPeter Wemm } 8370e3d5408SPeter Wemm 8380e3d5408SPeter Wemm (void) printf("Differing entries:\n"); 8390e3d5408SPeter Wemm termcount = 2; 84015589c42SPeter Wemm for (qp = heads[0]; qp; qp = qp->next) { 8410e3d5408SPeter Wemm 84215589c42SPeter Wemm if (qp->ncrosslinks == 1) { 84315589c42SPeter Wemm rp = qp->crosslinks[0]; 8440e3d5408SPeter Wemm #if NCURSES_XNAMES 84515589c42SPeter Wemm /* sorry - we have to do this on each pass */ 8460e3d5408SPeter Wemm _nc_align_termtype(&qp->tterm, &rp->tterm); 8470e3d5408SPeter Wemm #endif 84815589c42SPeter Wemm if (!(entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp))) { 8490e3d5408SPeter Wemm char name1[NAMESIZE], name2[NAMESIZE]; 8500e3d5408SPeter Wemm 85115589c42SPeter Wemm entries[0] = *qp; 85215589c42SPeter Wemm entries[1] = *rp; 8530e3d5408SPeter Wemm 8540e3d5408SPeter Wemm (void) canonical_name(qp->tterm.term_names, name1); 8550e3d5408SPeter Wemm (void) canonical_name(rp->tterm.term_names, name2); 8560e3d5408SPeter Wemm 85715589c42SPeter Wemm switch (compare) { 8580e3d5408SPeter Wemm case C_DIFFERENCE: 8590e3d5408SPeter Wemm if (itrace) 86015589c42SPeter Wemm (void) fprintf(stderr, 86115589c42SPeter Wemm "infocmp: dumping differences\n"); 8620e3d5408SPeter Wemm (void) printf("comparing %s to %s.\n", name1, name2); 86315589c42SPeter Wemm compare_entry(compare_predicate, &entries->tterm, quiet); 8640e3d5408SPeter Wemm break; 8650e3d5408SPeter Wemm 8660e3d5408SPeter Wemm case C_COMMON: 8670e3d5408SPeter Wemm if (itrace) 8680e3d5408SPeter Wemm (void) fprintf(stderr, 8690e3d5408SPeter Wemm "infocmp: dumping common capabilities\n"); 8700e3d5408SPeter Wemm (void) printf("comparing %s to %s.\n", name1, name2); 87115589c42SPeter Wemm compare_entry(compare_predicate, &entries->tterm, quiet); 8720e3d5408SPeter Wemm break; 8730e3d5408SPeter Wemm 8740e3d5408SPeter Wemm case C_NAND: 8750e3d5408SPeter Wemm if (itrace) 8760e3d5408SPeter Wemm (void) fprintf(stderr, 8770e3d5408SPeter Wemm "infocmp: dumping differences\n"); 8780e3d5408SPeter Wemm (void) printf("comparing %s to %s.\n", name1, name2); 87915589c42SPeter Wemm compare_entry(compare_predicate, &entries->tterm, quiet); 8800e3d5408SPeter Wemm break; 8810e3d5408SPeter Wemm 8820e3d5408SPeter Wemm } 8830e3d5408SPeter Wemm } 8840e3d5408SPeter Wemm } 8850e3d5408SPeter Wemm } 88615589c42SPeter Wemm } 8870e3d5408SPeter Wemm 88815589c42SPeter Wemm static void 88915589c42SPeter Wemm usage(void) 8900e3d5408SPeter Wemm { 89115589c42SPeter Wemm static const char *tbl[] = 89215589c42SPeter Wemm { 8930e3d5408SPeter Wemm "Usage: infocmp [options] [-A directory] [-B directory] [termname...]" 8940e3d5408SPeter Wemm ,"" 8950e3d5408SPeter Wemm ,"Options:" 8960e3d5408SPeter Wemm ," -1 print single-column" 8970e3d5408SPeter Wemm ," -C use termcap-names" 8980e3d5408SPeter Wemm ," -F compare terminfo-files" 8990e3d5408SPeter Wemm ," -I use terminfo-names" 9000e3d5408SPeter Wemm ," -L use long names" 9010e3d5408SPeter Wemm ," -R subset (see manpage)" 9020e3d5408SPeter Wemm ," -T eliminate size limits (test)" 9030e3d5408SPeter Wemm ," -V print version" 90415589c42SPeter Wemm #if NCURSES_XNAMES 90515589c42SPeter Wemm ," -a with -F, list commented-out caps" 90615589c42SPeter Wemm #endif 9070e3d5408SPeter Wemm ," -c list common capabilities" 9080e3d5408SPeter Wemm ," -d list different capabilities" 9090e3d5408SPeter Wemm ," -e format output for C initializer" 9100e3d5408SPeter Wemm ," -E format output as C tables" 9110e3d5408SPeter Wemm ," -f with -1, format complex strings" 9120e3d5408SPeter Wemm ," -G format %{number} to %'char'" 9130e3d5408SPeter Wemm ," -g format %'char' to %{number}" 9140e3d5408SPeter Wemm ," -i analyze initialization/reset" 9150e3d5408SPeter Wemm ," -l output terminfo names" 9160e3d5408SPeter Wemm ," -n list capabilities in neither" 9170e3d5408SPeter Wemm ," -p ignore padding specifiers" 91815589c42SPeter Wemm ," -q brief listing, removes headers" 9190e3d5408SPeter Wemm ," -r with -C, output in termcap form" 92015589c42SPeter Wemm ," -r with -F, resolve use-references" 9210e3d5408SPeter Wemm ," -s [d|i|l|c] sort fields" 9220e3d5408SPeter Wemm ," -u produce source with 'use='" 9230e3d5408SPeter Wemm ," -v number (verbose)" 9240e3d5408SPeter Wemm ," -w number (width)" 9250e3d5408SPeter Wemm }; 9260e3d5408SPeter Wemm const size_t first = 3; 927*18259542SPeter Wemm const size_t last = SIZEOF(tbl); 9280e3d5408SPeter Wemm const size_t left = (last - first + 1) / 2 + first; 9290e3d5408SPeter Wemm size_t n; 9300e3d5408SPeter Wemm 9310e3d5408SPeter Wemm for (n = 0; n < left; n++) { 9320e3d5408SPeter Wemm size_t m = (n < first) ? last : n + left - first; 9330e3d5408SPeter Wemm if (m < last) 9340e3d5408SPeter Wemm fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]); 9350e3d5408SPeter Wemm else 9360e3d5408SPeter Wemm fprintf(stderr, "%s\n", tbl[n]); 9370e3d5408SPeter Wemm } 9380e3d5408SPeter Wemm exit(EXIT_FAILURE); 9390e3d5408SPeter Wemm } 9400e3d5408SPeter Wemm 94115589c42SPeter Wemm static char * 94215589c42SPeter Wemm name_initializer(const char *type) 9430e3d5408SPeter Wemm { 9440e3d5408SPeter Wemm static char *initializer; 9450e3d5408SPeter Wemm char *s; 9460e3d5408SPeter Wemm 9470e3d5408SPeter Wemm if (initializer == 0) 94815589c42SPeter Wemm initializer = (char *) malloc(strlen(entries->tterm.term_names) + 20); 9490e3d5408SPeter Wemm 95015589c42SPeter Wemm (void) sprintf(initializer, "%s_data_%s", type, entries->tterm.term_names); 95115589c42SPeter Wemm for (s = initializer; *s != 0 && *s != '|'; s++) { 9520e3d5408SPeter Wemm if (!isalnum(*s)) 9530e3d5408SPeter Wemm *s = '_'; 9540e3d5408SPeter Wemm } 9550e3d5408SPeter Wemm *s = 0; 9560e3d5408SPeter Wemm return initializer; 9570e3d5408SPeter Wemm } 9580e3d5408SPeter Wemm 9590e3d5408SPeter Wemm /* dump C initializers for the terminal type */ 96015589c42SPeter Wemm static void 96115589c42SPeter Wemm dump_initializers(TERMTYPE * term) 9620e3d5408SPeter Wemm { 9630e3d5408SPeter Wemm int n; 9640e3d5408SPeter Wemm const char *str = 0; 9650e3d5408SPeter Wemm int size; 9660e3d5408SPeter Wemm 96715589c42SPeter Wemm (void) printf("static char %s[] = %s\n", name_initializer("bool"), L_CURL); 9680e3d5408SPeter Wemm 96915589c42SPeter Wemm for_each_boolean(n, term) { 97015589c42SPeter Wemm switch ((int) (term->Booleans[n])) { 9710e3d5408SPeter Wemm case TRUE: 9720e3d5408SPeter Wemm str = "TRUE"; 9730e3d5408SPeter Wemm break; 9740e3d5408SPeter Wemm 9750e3d5408SPeter Wemm case FALSE: 9760e3d5408SPeter Wemm str = "FALSE"; 9770e3d5408SPeter Wemm break; 9780e3d5408SPeter Wemm 9790e3d5408SPeter Wemm case ABSENT_BOOLEAN: 9800e3d5408SPeter Wemm str = "ABSENT_BOOLEAN"; 9810e3d5408SPeter Wemm break; 9820e3d5408SPeter Wemm 9830e3d5408SPeter Wemm case CANCELLED_BOOLEAN: 9840e3d5408SPeter Wemm str = "CANCELLED_BOOLEAN"; 9850e3d5408SPeter Wemm break; 9860e3d5408SPeter Wemm } 9870e3d5408SPeter Wemm (void) printf("\t/* %3d: %-8s */\t%s,\n", 9880e3d5408SPeter Wemm n, ExtBoolname(term, n, boolnames), str); 9890e3d5408SPeter Wemm } 9900e3d5408SPeter Wemm (void) printf("%s;\n", R_CURL); 9910e3d5408SPeter Wemm 9920e3d5408SPeter Wemm (void) printf("static short %s[] = %s\n", name_initializer("number"), L_CURL); 9930e3d5408SPeter Wemm 99415589c42SPeter Wemm for_each_number(n, term) { 9950e3d5408SPeter Wemm char buf[BUFSIZ]; 99615589c42SPeter Wemm switch (term->Numbers[n]) { 9970e3d5408SPeter Wemm case ABSENT_NUMERIC: 9980e3d5408SPeter Wemm str = "ABSENT_NUMERIC"; 9990e3d5408SPeter Wemm break; 10000e3d5408SPeter Wemm case CANCELLED_NUMERIC: 10010e3d5408SPeter Wemm str = "CANCELLED_NUMERIC"; 10020e3d5408SPeter Wemm break; 10030e3d5408SPeter Wemm default: 10040e3d5408SPeter Wemm sprintf(buf, "%d", term->Numbers[n]); 10050e3d5408SPeter Wemm str = buf; 10060e3d5408SPeter Wemm break; 10070e3d5408SPeter Wemm } 1008*18259542SPeter Wemm (void) printf("\t/* %3d: %-8s */\t%s,\n", n, 1009*18259542SPeter Wemm ExtNumname(term, n, numnames), str); 10100e3d5408SPeter Wemm } 10110e3d5408SPeter Wemm (void) printf("%s;\n", R_CURL); 10120e3d5408SPeter Wemm 10130e3d5408SPeter Wemm size = sizeof(TERMTYPE) 10140e3d5408SPeter Wemm + (NUM_BOOLEANS(term) * sizeof(term->Booleans[0])) 10150e3d5408SPeter Wemm + (NUM_NUMBERS(term) * sizeof(term->Numbers[0])); 10160e3d5408SPeter Wemm 10170e3d5408SPeter Wemm (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL); 10180e3d5408SPeter Wemm 101915589c42SPeter Wemm for_each_string(n, term) { 102015589c42SPeter Wemm char buf[MAX_STRING], *sp, *tp; 10210e3d5408SPeter Wemm 10220e3d5408SPeter Wemm if (term->Strings[n] == ABSENT_STRING) 10230e3d5408SPeter Wemm str = "ABSENT_STRING"; 10240e3d5408SPeter Wemm else if (term->Strings[n] == CANCELLED_STRING) 10250e3d5408SPeter Wemm str = "CANCELLED_STRING"; 102615589c42SPeter Wemm else { 10270e3d5408SPeter Wemm tp = buf; 10280e3d5408SPeter Wemm *tp++ = '"'; 102915589c42SPeter Wemm for (sp = term->Strings[n]; 103015589c42SPeter Wemm *sp != 0 && (tp - buf) < MAX_STRING - 6; 103115589c42SPeter Wemm sp++) { 10320e3d5408SPeter Wemm if (isascii(*sp) && isprint(*sp) && *sp != '\\' && *sp != '"') 10330e3d5408SPeter Wemm *tp++ = *sp; 103415589c42SPeter Wemm else { 10350e3d5408SPeter Wemm (void) sprintf(tp, "\\%03o", *sp & 0xff); 10360e3d5408SPeter Wemm tp += 4; 10370e3d5408SPeter Wemm } 10380e3d5408SPeter Wemm } 10390e3d5408SPeter Wemm *tp++ = '"'; 10400e3d5408SPeter Wemm *tp = '\0'; 10410e3d5408SPeter Wemm size += (strlen(term->Strings[n]) + 1); 10420e3d5408SPeter Wemm str = buf; 10430e3d5408SPeter Wemm } 10440e3d5408SPeter Wemm #if NCURSES_XNAMES 104515589c42SPeter Wemm if (n == STRCOUNT) { 10460e3d5408SPeter Wemm (void) printf("%s;\n", R_CURL); 10470e3d5408SPeter Wemm 104815589c42SPeter Wemm (void) printf("static char * %s[] = %s\n", 104915589c42SPeter Wemm name_initializer("string_ext"), L_CURL); 10500e3d5408SPeter Wemm } 10510e3d5408SPeter Wemm #endif 1052*18259542SPeter Wemm (void) printf("\t/* %3d: %-8s */\t%s,\n", n, 1053*18259542SPeter Wemm ExtStrname(term, n, strnames), str); 10540e3d5408SPeter Wemm } 10550e3d5408SPeter Wemm (void) printf("%s;\n", R_CURL); 10560e3d5408SPeter Wemm } 10570e3d5408SPeter Wemm 10580e3d5408SPeter Wemm /* dump C initializers for the terminal type */ 105915589c42SPeter Wemm static void 106015589c42SPeter Wemm dump_termtype(TERMTYPE * term) 10610e3d5408SPeter Wemm { 10620e3d5408SPeter Wemm (void) printf("\t%s\n\t\t\"%s\",\n", L_CURL, term->term_names); 10630e3d5408SPeter Wemm (void) printf("\t\t(char *)0,\t/* pointer to string table */\n"); 10640e3d5408SPeter Wemm 10650e3d5408SPeter Wemm (void) printf("\t\t%s,\n", name_initializer("bool")); 10660e3d5408SPeter Wemm (void) printf("\t\t%s,\n", name_initializer("number")); 10670e3d5408SPeter Wemm 10680e3d5408SPeter Wemm (void) printf("\t\t%s,\n", name_initializer("string")); 10690e3d5408SPeter Wemm 10700e3d5408SPeter Wemm #if NCURSES_XNAMES 10710e3d5408SPeter Wemm (void) printf("#if NCURSES_XNAMES\n"); 10720e3d5408SPeter Wemm (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n"); 10730e3d5408SPeter Wemm (void) printf("\t\t%s,\t/* ...corresponding names */\n", 10740e3d5408SPeter Wemm (NUM_STRINGS(term) != STRCOUNT) 10750e3d5408SPeter Wemm ? name_initializer("string_ext") 10760e3d5408SPeter Wemm : "(char **)0"); 10770e3d5408SPeter Wemm 10780e3d5408SPeter Wemm (void) printf("\t\t%d,\t\t/* count total Booleans */\n", NUM_BOOLEANS(term)); 10790e3d5408SPeter Wemm (void) printf("\t\t%d,\t\t/* count total Numbers */\n", NUM_NUMBERS(term)); 10800e3d5408SPeter Wemm (void) printf("\t\t%d,\t\t/* count total Strings */\n", NUM_STRINGS(term)); 10810e3d5408SPeter Wemm 108215589c42SPeter Wemm (void) printf("\t\t%d,\t\t/* count extensions to Booleans */\n", 108315589c42SPeter Wemm NUM_BOOLEANS(term) - BOOLCOUNT); 108415589c42SPeter Wemm (void) printf("\t\t%d,\t\t/* count extensions to Numbers */\n", 108515589c42SPeter Wemm NUM_NUMBERS(term) - NUMCOUNT); 108615589c42SPeter Wemm (void) printf("\t\t%d,\t\t/* count extensions to Strings */\n", 108715589c42SPeter Wemm NUM_STRINGS(term) - STRCOUNT); 10880e3d5408SPeter Wemm 10890e3d5408SPeter Wemm (void) printf("#endif /* NCURSES_XNAMES */\n"); 10900e3d5408SPeter Wemm #endif /* NCURSES_XNAMES */ 10910e3d5408SPeter Wemm (void) printf("\t%s\n", R_CURL); 10920e3d5408SPeter Wemm } 10930e3d5408SPeter Wemm 1094*18259542SPeter Wemm static int 1095*18259542SPeter Wemm optarg_to_number(void) 1096*18259542SPeter Wemm { 1097*18259542SPeter Wemm char *temp = 0; 1098*18259542SPeter Wemm long value = strtol(optarg, &temp, 0); 1099*18259542SPeter Wemm 1100*18259542SPeter Wemm if (temp == 0 || temp == optarg || *temp != 0) { 1101*18259542SPeter Wemm fprintf(stderr, "Expected a number, not \"%s\"\n", optarg); 1102*18259542SPeter Wemm exit(EXIT_FAILURE); 1103*18259542SPeter Wemm } 1104*18259542SPeter Wemm return (int) value; 1105*18259542SPeter Wemm } 1106*18259542SPeter Wemm 11070e3d5408SPeter Wemm /*************************************************************************** 11080e3d5408SPeter Wemm * 11090e3d5408SPeter Wemm * Main sequence 11100e3d5408SPeter Wemm * 11110e3d5408SPeter Wemm ***************************************************************************/ 11120e3d5408SPeter Wemm 111315589c42SPeter Wemm int 111415589c42SPeter Wemm main(int argc, char *argv[]) 11150e3d5408SPeter Wemm { 11160e3d5408SPeter Wemm char *terminal, *firstdir, *restdir; 11170e3d5408SPeter Wemm /* Avoid "local data >32k" error with mwcc */ 11180e3d5408SPeter Wemm /* Also avoid overflowing smaller stacks on systems like AmigaOS */ 111915589c42SPeter Wemm path *tfile = (path *) malloc(sizeof(path) * MAXTERMS); 11200e3d5408SPeter Wemm int c, i, len; 11210e3d5408SPeter Wemm bool formatted = FALSE; 11220e3d5408SPeter Wemm bool filecompare = FALSE; 11230e3d5408SPeter Wemm int initdump = 0; 11240e3d5408SPeter Wemm bool init_analyze = FALSE; 11250e3d5408SPeter Wemm 112615589c42SPeter Wemm if ((terminal = getenv("TERM")) == 0) { 11270e3d5408SPeter Wemm (void) fprintf(stderr, 11280e3d5408SPeter Wemm "infocmp: environment variable TERM not set\n"); 11290e3d5408SPeter Wemm return EXIT_FAILURE; 11300e3d5408SPeter Wemm } 11310e3d5408SPeter Wemm 11320e3d5408SPeter Wemm /* where is the terminfo database location going to default to? */ 11330e3d5408SPeter Wemm restdir = firstdir = 0; 11340e3d5408SPeter Wemm 113515589c42SPeter Wemm while ((c = getopt(argc, argv, "adeEcCfFGgIinlLpqrR:s:uv:Vw:A:B:1T")) != EOF) 113615589c42SPeter Wemm switch (c) { 113715589c42SPeter Wemm #if NCURSES_XNAMES 113815589c42SPeter Wemm case 'a': 113915589c42SPeter Wemm _nc_disable_period = TRUE; 114015589c42SPeter Wemm use_extended_names(TRUE); 114115589c42SPeter Wemm break; 114215589c42SPeter Wemm #endif 11430e3d5408SPeter Wemm case 'd': 11440e3d5408SPeter Wemm compare = C_DIFFERENCE; 11450e3d5408SPeter Wemm break; 11460e3d5408SPeter Wemm 11470e3d5408SPeter Wemm case 'e': 11480e3d5408SPeter Wemm initdump |= 1; 11490e3d5408SPeter Wemm break; 11500e3d5408SPeter Wemm 11510e3d5408SPeter Wemm case 'E': 11520e3d5408SPeter Wemm initdump |= 2; 11530e3d5408SPeter Wemm break; 11540e3d5408SPeter Wemm 11550e3d5408SPeter Wemm case 'c': 11560e3d5408SPeter Wemm compare = C_COMMON; 11570e3d5408SPeter Wemm break; 11580e3d5408SPeter Wemm 11590e3d5408SPeter Wemm case 'C': 11600e3d5408SPeter Wemm outform = F_TERMCAP; 11610e3d5408SPeter Wemm tversion = "BSD"; 11620e3d5408SPeter Wemm if (sortmode == S_DEFAULT) 11630e3d5408SPeter Wemm sortmode = S_TERMCAP; 11640e3d5408SPeter Wemm break; 11650e3d5408SPeter Wemm 11660e3d5408SPeter Wemm case 'f': 11670e3d5408SPeter Wemm formatted = TRUE; 11680e3d5408SPeter Wemm break; 11690e3d5408SPeter Wemm 11700e3d5408SPeter Wemm case 'G': 11710e3d5408SPeter Wemm numbers = 1; 11720e3d5408SPeter Wemm break; 11730e3d5408SPeter Wemm 11740e3d5408SPeter Wemm case 'g': 11750e3d5408SPeter Wemm numbers = -1; 11760e3d5408SPeter Wemm break; 11770e3d5408SPeter Wemm 11780e3d5408SPeter Wemm case 'F': 11790e3d5408SPeter Wemm filecompare = TRUE; 11800e3d5408SPeter Wemm break; 11810e3d5408SPeter Wemm 11820e3d5408SPeter Wemm case 'I': 11830e3d5408SPeter Wemm outform = F_TERMINFO; 11840e3d5408SPeter Wemm if (sortmode == S_DEFAULT) 11850e3d5408SPeter Wemm sortmode = S_VARIABLE; 11860e3d5408SPeter Wemm tversion = 0; 11870e3d5408SPeter Wemm break; 11880e3d5408SPeter Wemm 11890e3d5408SPeter Wemm case 'i': 11900e3d5408SPeter Wemm init_analyze = TRUE; 11910e3d5408SPeter Wemm break; 11920e3d5408SPeter Wemm 11930e3d5408SPeter Wemm case 'l': 11940e3d5408SPeter Wemm outform = F_TERMINFO; 11950e3d5408SPeter Wemm break; 11960e3d5408SPeter Wemm 11970e3d5408SPeter Wemm case 'L': 11980e3d5408SPeter Wemm outform = F_VARIABLE; 11990e3d5408SPeter Wemm if (sortmode == S_DEFAULT) 12000e3d5408SPeter Wemm sortmode = S_VARIABLE; 12010e3d5408SPeter Wemm break; 12020e3d5408SPeter Wemm 12030e3d5408SPeter Wemm case 'n': 12040e3d5408SPeter Wemm compare = C_NAND; 12050e3d5408SPeter Wemm break; 12060e3d5408SPeter Wemm 12070e3d5408SPeter Wemm case 'p': 12080e3d5408SPeter Wemm ignorepads = TRUE; 12090e3d5408SPeter Wemm break; 12100e3d5408SPeter Wemm 121115589c42SPeter Wemm case 'q': 121215589c42SPeter Wemm quiet = TRUE; 121315589c42SPeter Wemm s_absent = "-"; 121415589c42SPeter Wemm s_cancel = "@"; 121515589c42SPeter Wemm bool_sep = ", "; 121615589c42SPeter Wemm break; 121715589c42SPeter Wemm 12180e3d5408SPeter Wemm case 'r': 12190e3d5408SPeter Wemm tversion = 0; 12200e3d5408SPeter Wemm limited = FALSE; 12210e3d5408SPeter Wemm break; 12220e3d5408SPeter Wemm 12230e3d5408SPeter Wemm case 'R': 12240e3d5408SPeter Wemm tversion = optarg; 12250e3d5408SPeter Wemm break; 12260e3d5408SPeter Wemm 12270e3d5408SPeter Wemm case 's': 12280e3d5408SPeter Wemm if (*optarg == 'd') 12290e3d5408SPeter Wemm sortmode = S_NOSORT; 12300e3d5408SPeter Wemm else if (*optarg == 'i') 12310e3d5408SPeter Wemm sortmode = S_TERMINFO; 12320e3d5408SPeter Wemm else if (*optarg == 'l') 12330e3d5408SPeter Wemm sortmode = S_VARIABLE; 12340e3d5408SPeter Wemm else if (*optarg == 'c') 12350e3d5408SPeter Wemm sortmode = S_TERMCAP; 123615589c42SPeter Wemm else { 12370e3d5408SPeter Wemm (void) fprintf(stderr, 12380e3d5408SPeter Wemm "infocmp: unknown sort mode\n"); 12390e3d5408SPeter Wemm return EXIT_FAILURE; 12400e3d5408SPeter Wemm } 12410e3d5408SPeter Wemm break; 12420e3d5408SPeter Wemm 12430e3d5408SPeter Wemm case 'u': 12440e3d5408SPeter Wemm compare = C_USEALL; 12450e3d5408SPeter Wemm break; 12460e3d5408SPeter Wemm 12470e3d5408SPeter Wemm case 'v': 1248*18259542SPeter Wemm itrace = optarg_to_number(); 124915589c42SPeter Wemm set_trace_level(itrace); 12500e3d5408SPeter Wemm break; 12510e3d5408SPeter Wemm 12520e3d5408SPeter Wemm case 'V': 1253*18259542SPeter Wemm puts(curses_version()); 12540e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 12550e3d5408SPeter Wemm 12560e3d5408SPeter Wemm case 'w': 1257*18259542SPeter Wemm mwidth = optarg_to_number(); 12580e3d5408SPeter Wemm break; 12590e3d5408SPeter Wemm 12600e3d5408SPeter Wemm case 'A': 12610e3d5408SPeter Wemm firstdir = optarg; 12620e3d5408SPeter Wemm break; 12630e3d5408SPeter Wemm 12640e3d5408SPeter Wemm case 'B': 12650e3d5408SPeter Wemm restdir = optarg; 12660e3d5408SPeter Wemm break; 12670e3d5408SPeter Wemm 12680e3d5408SPeter Wemm case '1': 12690e3d5408SPeter Wemm mwidth = 0; 12700e3d5408SPeter Wemm break; 12710e3d5408SPeter Wemm 12720e3d5408SPeter Wemm case 'T': 12730e3d5408SPeter Wemm limited = FALSE; 12740e3d5408SPeter Wemm break; 12750e3d5408SPeter Wemm default: 12760e3d5408SPeter Wemm usage(); 12770e3d5408SPeter Wemm } 12780e3d5408SPeter Wemm 12790e3d5408SPeter Wemm /* by default, sort by terminfo name */ 12800e3d5408SPeter Wemm if (sortmode == S_DEFAULT) 12810e3d5408SPeter Wemm sortmode = S_TERMINFO; 12820e3d5408SPeter Wemm 12830e3d5408SPeter Wemm /* set up for display */ 12840e3d5408SPeter Wemm dump_init(tversion, outform, sortmode, mwidth, itrace, formatted); 12850e3d5408SPeter Wemm 12860e3d5408SPeter Wemm /* make sure we have at least one terminal name to work with */ 12870e3d5408SPeter Wemm if (optind >= argc) 12880e3d5408SPeter Wemm argv[argc++] = terminal; 12890e3d5408SPeter Wemm 12900e3d5408SPeter Wemm /* if user is after a comparison, make sure we have two entries */ 12910e3d5408SPeter Wemm if (compare != C_DEFAULT && optind >= argc - 1) 12920e3d5408SPeter Wemm argv[argc++] = terminal; 12930e3d5408SPeter Wemm 12940e3d5408SPeter Wemm /* exactly two terminal names with no options means do -d */ 12950e3d5408SPeter Wemm if (argc - optind == 2 && compare == C_DEFAULT) 12960e3d5408SPeter Wemm compare = C_DIFFERENCE; 12970e3d5408SPeter Wemm 129815589c42SPeter Wemm if (!filecompare) { 12990e3d5408SPeter Wemm /* grab the entries */ 13000e3d5408SPeter Wemm termcount = 0; 130115589c42SPeter Wemm for (; optind < argc; optind++) { 130215589c42SPeter Wemm if (termcount >= MAXTERMS) { 13030e3d5408SPeter Wemm (void) fprintf(stderr, 13040e3d5408SPeter Wemm "infocmp: too many terminal type arguments\n"); 13050e3d5408SPeter Wemm return EXIT_FAILURE; 130615589c42SPeter Wemm } else { 13070e3d5408SPeter Wemm const char *directory = termcount ? restdir : firstdir; 13080e3d5408SPeter Wemm int status; 13090e3d5408SPeter Wemm 13100e3d5408SPeter Wemm tname[termcount] = argv[optind]; 13110e3d5408SPeter Wemm 131215589c42SPeter Wemm if (directory) { 13130e3d5408SPeter Wemm (void) sprintf(tfile[termcount], "%s/%c/%s", 13140e3d5408SPeter Wemm directory, 13150e3d5408SPeter Wemm *argv[optind], argv[optind]); 13160e3d5408SPeter Wemm if (itrace) 13170e3d5408SPeter Wemm (void) fprintf(stderr, 13180e3d5408SPeter Wemm "infocmp: reading entry %s from file %s\n", 13190e3d5408SPeter Wemm argv[optind], tfile[termcount]); 13200e3d5408SPeter Wemm 13210e3d5408SPeter Wemm status = _nc_read_file_entry(tfile[termcount], 132215589c42SPeter Wemm &entries[termcount].tterm); 132315589c42SPeter Wemm } else { 13240e3d5408SPeter Wemm if (itrace) 13250e3d5408SPeter Wemm (void) fprintf(stderr, 13260e3d5408SPeter Wemm "infocmp: reading entry %s from system directories %s\n", 13270e3d5408SPeter Wemm argv[optind], tname[termcount]); 13280e3d5408SPeter Wemm 13290e3d5408SPeter Wemm status = _nc_read_entry(tname[termcount], 13300e3d5408SPeter Wemm tfile[termcount], 133115589c42SPeter Wemm &entries[termcount].tterm); 13320e3d5408SPeter Wemm directory = TERMINFO; /* for error message */ 13330e3d5408SPeter Wemm } 13340e3d5408SPeter Wemm 133515589c42SPeter Wemm if (status <= 0) { 13360e3d5408SPeter Wemm (void) fprintf(stderr, 13370e3d5408SPeter Wemm "infocmp: couldn't open terminfo file %s.\n", 13380e3d5408SPeter Wemm tfile[termcount]); 13390e3d5408SPeter Wemm return EXIT_FAILURE; 13400e3d5408SPeter Wemm } 134115589c42SPeter Wemm repair_acsc(&entries[termcount].tterm); 13420e3d5408SPeter Wemm termcount++; 13430e3d5408SPeter Wemm } 13440e3d5408SPeter Wemm } 13450e3d5408SPeter Wemm 13460e3d5408SPeter Wemm #if NCURSES_XNAMES 13470e3d5408SPeter Wemm if (termcount > 1) 134815589c42SPeter Wemm _nc_align_termtype(&entries[0].tterm, &entries[1].tterm); 13490e3d5408SPeter Wemm #endif 13500e3d5408SPeter Wemm 13510e3d5408SPeter Wemm /* dump as C initializer for the terminal type */ 135215589c42SPeter Wemm if (initdump) { 13530e3d5408SPeter Wemm if (initdump & 1) 135415589c42SPeter Wemm dump_termtype(&entries[0].tterm); 13550e3d5408SPeter Wemm if (initdump & 2) 135615589c42SPeter Wemm dump_initializers(&entries[0].tterm); 13570e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 13580e3d5408SPeter Wemm } 13590e3d5408SPeter Wemm 13600e3d5408SPeter Wemm /* analyze the init strings */ 136115589c42SPeter Wemm if (init_analyze) { 13620e3d5408SPeter Wemm #undef CUR 136315589c42SPeter Wemm #define CUR entries[0].tterm. 136415589c42SPeter Wemm analyze_string("is1", init_1string, &entries[0].tterm); 136515589c42SPeter Wemm analyze_string("is2", init_2string, &entries[0].tterm); 136615589c42SPeter Wemm analyze_string("is3", init_3string, &entries[0].tterm); 136715589c42SPeter Wemm analyze_string("rs1", reset_1string, &entries[0].tterm); 136815589c42SPeter Wemm analyze_string("rs2", reset_2string, &entries[0].tterm); 136915589c42SPeter Wemm analyze_string("rs3", reset_3string, &entries[0].tterm); 137015589c42SPeter Wemm analyze_string("smcup", enter_ca_mode, &entries[0].tterm); 137115589c42SPeter Wemm analyze_string("rmcup", exit_ca_mode, &entries[0].tterm); 13720e3d5408SPeter Wemm #undef CUR 13730e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 13740e3d5408SPeter Wemm } 13750e3d5408SPeter Wemm 13760e3d5408SPeter Wemm /* 13770e3d5408SPeter Wemm * Here's where the real work gets done 13780e3d5408SPeter Wemm */ 137915589c42SPeter Wemm switch (compare) { 13800e3d5408SPeter Wemm case C_DEFAULT: 13810e3d5408SPeter Wemm if (itrace) 13820e3d5408SPeter Wemm (void) fprintf(stderr, 13830e3d5408SPeter Wemm "infocmp: about to dump %s\n", 13840e3d5408SPeter Wemm tname[0]); 13850e3d5408SPeter Wemm (void) printf("#\tReconstructed via infocmp from file: %s\n", 13860e3d5408SPeter Wemm tfile[0]); 138715589c42SPeter Wemm len = dump_entry(&entries[0].tterm, limited, numbers, NULL); 13880e3d5408SPeter Wemm putchar('\n'); 13890e3d5408SPeter Wemm if (itrace) 13900e3d5408SPeter Wemm (void) fprintf(stderr, "infocmp: length %d\n", len); 13910e3d5408SPeter Wemm break; 13920e3d5408SPeter Wemm 13930e3d5408SPeter Wemm case C_DIFFERENCE: 13940e3d5408SPeter Wemm if (itrace) 13950e3d5408SPeter Wemm (void) fprintf(stderr, "infocmp: dumping differences\n"); 13960e3d5408SPeter Wemm (void) printf("comparing %s to %s.\n", tname[0], tname[1]); 139715589c42SPeter Wemm compare_entry(compare_predicate, &entries->tterm, quiet); 13980e3d5408SPeter Wemm break; 13990e3d5408SPeter Wemm 14000e3d5408SPeter Wemm case C_COMMON: 14010e3d5408SPeter Wemm if (itrace) 14020e3d5408SPeter Wemm (void) fprintf(stderr, 14030e3d5408SPeter Wemm "infocmp: dumping common capabilities\n"); 14040e3d5408SPeter Wemm (void) printf("comparing %s to %s.\n", tname[0], tname[1]); 140515589c42SPeter Wemm compare_entry(compare_predicate, &entries->tterm, quiet); 14060e3d5408SPeter Wemm break; 14070e3d5408SPeter Wemm 14080e3d5408SPeter Wemm case C_NAND: 14090e3d5408SPeter Wemm if (itrace) 14100e3d5408SPeter Wemm (void) fprintf(stderr, 14110e3d5408SPeter Wemm "infocmp: dumping differences\n"); 14120e3d5408SPeter Wemm (void) printf("comparing %s to %s.\n", tname[0], tname[1]); 141315589c42SPeter Wemm compare_entry(compare_predicate, &entries->tterm, quiet); 14140e3d5408SPeter Wemm break; 14150e3d5408SPeter Wemm 14160e3d5408SPeter Wemm case C_USEALL: 14170e3d5408SPeter Wemm if (itrace) 14180e3d5408SPeter Wemm (void) fprintf(stderr, "infocmp: dumping use entry\n"); 141915589c42SPeter Wemm len = dump_entry(&entries[0].tterm, limited, numbers, use_predicate); 14200e3d5408SPeter Wemm for (i = 1; i < termcount; i++) 142115589c42SPeter Wemm len += dump_uses(tname[i], !(outform == F_TERMCAP || outform 142215589c42SPeter Wemm == F_TCONVERR)); 14230e3d5408SPeter Wemm putchar('\n'); 14240e3d5408SPeter Wemm if (itrace) 14250e3d5408SPeter Wemm (void) fprintf(stderr, "infocmp: length %d\n", len); 14260e3d5408SPeter Wemm break; 14270e3d5408SPeter Wemm } 142815589c42SPeter Wemm } else if (compare == C_USEALL) 14290e3d5408SPeter Wemm (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n"); 14300e3d5408SPeter Wemm else if (compare == C_DEFAULT) 14310e3d5408SPeter Wemm (void) fprintf(stderr, "Use `tic -[CI] <file>' for this.\n"); 14320e3d5408SPeter Wemm else if (argc - optind != 2) 14330e3d5408SPeter Wemm (void) fprintf(stderr, 14340e3d5408SPeter Wemm "File comparison needs exactly two file arguments.\n"); 14350e3d5408SPeter Wemm else 14360e3d5408SPeter Wemm file_comparison(argc - optind, argv + optind); 14370e3d5408SPeter Wemm 14380e3d5408SPeter Wemm ExitProgram(EXIT_SUCCESS); 14390e3d5408SPeter Wemm } 14400e3d5408SPeter Wemm 14410e3d5408SPeter Wemm /* infocmp.c ends here */ 1442