[BACK]Return to infocmp.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / infocmp

Annotation of src/usr.bin/infocmp/infocmp.c, Revision 1.20

1.20    ! nicm        1: /*     $OpenBSD: infocmp.c,v 1.16 2003/04/06 18:41:03 deraadt Exp $    */
1.1       millert     2:
                      3: /****************************************************************************
1.20    ! nicm        4:  * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *
1.1       millert     5:  *                                                                          *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a  *
                      7:  * copy of this software and associated documentation files (the            *
                      8:  * "Software"), to deal in the Software without restriction, including      *
                      9:  * without limitation the rights to use, copy, modify, merge, publish,      *
                     10:  * distribute, distribute with modifications, sublicense, and/or sell       *
                     11:  * copies of the Software, and to permit persons to whom the Software is    *
                     12:  * furnished to do so, subject to the following conditions:                 *
                     13:  *                                                                          *
                     14:  * The above copyright notice and this permission notice shall be included  *
                     15:  * in all copies or substantial portions of the Software.                   *
                     16:  *                                                                          *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
                     18:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
                     19:  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
                     20:  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
                     21:  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
                     22:  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
                     23:  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
                     24:  *                                                                          *
                     25:  * Except as contained in this notice, the name(s) of the above copyright   *
                     26:  * holders shall not be used in advertising or otherwise to promote the     *
                     27:  * sale, use or other dealings in this Software without prior written       *
                     28:  * authorization.                                                           *
                     29:  ****************************************************************************/
                     30:
                     31: /****************************************************************************
                     32:  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
                     33:  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
1.20    ! nicm       34:  *     and: Thomas E. Dickey                        1996-on                 *
1.1       millert    35:  ****************************************************************************/
                     36:
                     37: /*
                     38:  *     infocmp.c -- decompile an entry, or compare two entries
                     39:  *             written by Eric S. Raymond
1.20    ! nicm       40:  *             and Thomas E Dickey
1.1       millert    41:  */
                     42:
                     43: #include <progs.priv.h>
                     44:
                     45: #include <dump_entry.h>
                     46:
1.20    ! nicm       47: MODULE_ID("$Id: infocmp.c,v 1.103 2008/08/16 22:04:56 tom Exp $")
1.1       millert    48:
                     49: #define L_CURL "{"
                     50: #define R_CURL "}"
                     51:
1.9       millert    52: #define MAX_STRING     1024    /* maximum formatted string */
1.1       millert    53:
                     54: const char *_nc_progname = "infocmp";
                     55:
1.8       millert    56: typedef char path[PATH_MAX];
1.1       millert    57:
                     58: /***************************************************************************
                     59:  *
                     60:  * The following control variables, together with the contents of the
                     61:  * terminfo entries, completely determine the actions of the program.
                     62:  *
                     63:  ***************************************************************************/
                     64:
1.20    ! nicm       65: static ENTRY *entries;         /* terminfo entries */
1.1       millert    66: static int termcount;          /* count of terminal entries */
                     67:
1.9       millert    68: static bool limited = TRUE;    /* "-r" option is not set */
                     69: static bool quiet = FALSE;
1.20    ! nicm       70: static bool literal = FALSE;
1.10      millert    71: static const char *bool_sep = ":";
                     72: static const char *s_absent = "NULL";
                     73: static const char *s_cancel = "NULL";
1.1       millert    74: static const char *tversion;   /* terminfo version selected */
1.9       millert    75: static int itrace;             /* trace flag for debugging */
                     76: static int mwidth = 60;
1.3       millert    77: static int numbers = 0;                /* format "%'char'" to/from "%{number}" */
1.11      millert    78: static int outform = F_TERMINFO;       /* output format */
1.1       millert    79: static int sortmode;           /* sort_mode */
                     80:
                     81: /* main comparison mode */
                     82: static int compare;
                     83: #define C_DEFAULT      0       /* don't force comparison mode */
                     84: #define C_DIFFERENCE   1       /* list differences between two terminals */
                     85: #define C_COMMON       2       /* list common capabilities */
                     86: #define C_NAND         3       /* list capabilities in neither terminal */
                     87: #define C_USEALL       4       /* generate relative use-form entry */
                     88: static bool ignorepads;                /* ignore pad prefixes when diffing */
                     89:
                     90: #if NO_LEAKS
                     91: #undef ExitProgram
1.20    ! nicm       92: static void ExitProgram(int code) GCC_NORETURN;
        !            93: /* prototype is to get gcc to accept the noreturn attribute */
1.8       millert    94: static void
1.20    ! nicm       95: ExitProgram(int code)
1.1       millert    96: {
1.8       millert    97:     while (termcount-- > 0)
1.9       millert    98:        _nc_free_termtype(&entries[termcount].tterm);
1.8       millert    99:     _nc_leaks_dump_entry();
1.20    ! nicm      100:     free(entries);
        !           101:     _nc_free_tic(code);
1.1       millert   102: }
                    103: #endif
                    104:
1.8       millert   105: static char *
1.16      deraadt   106: canonical_name(char *ptr, char *buf, size_t bufl)
1.1       millert   107: /* extract the terminal type's primary name */
                    108: {
1.8       millert   109:     char *bp;
1.1       millert   110:
1.16      deraadt   111:     (void) strlcpy(buf, ptr, bufl);
1.9       millert   112:     if ((bp = strchr(buf, '|')) != 0)
1.1       millert   113:        *bp = '\0';
                    114:
1.8       millert   115:     return (buf);
1.1       millert   116: }
                    117:
                    118: /***************************************************************************
                    119:  *
                    120:  * Predicates for dump function
                    121:  *
                    122:  ***************************************************************************/
                    123:
1.8       millert   124: static int
1.20    ! nicm      125: capcmp(PredIdx idx, const char *s, const char *t)
1.1       millert   126: /* capability comparison function */
                    127: {
                    128:     if (!VALID_STRING(s) && !VALID_STRING(t))
1.9       millert   129:        return (s != t);
1.1       millert   130:     else if (!VALID_STRING(s) || !VALID_STRING(t))
1.8       millert   131:        return (1);
1.1       millert   132:
1.9       millert   133:     if ((idx == acs_chars_index) || !ignorepads)
                    134:        return (strcmp(s, t));
                    135:     else
1.8       millert   136:        return (_nc_capcmp(s, t));
1.1       millert   137: }
                    138:
1.8       millert   139: static int
1.20    ! nicm      140: use_predicate(unsigned type, PredIdx idx)
1.1       millert   141: /* predicate function to use for use decompilation */
                    142: {
1.9       millert   143:     ENTRY *ep;
1.1       millert   144:
1.8       millert   145:     switch (type) {
1.9       millert   146:     case BOOLEAN:
                    147:        {
1.8       millert   148:            int is_set = FALSE;
1.1       millert   149:
1.8       millert   150:            /*
                    151:             * This assumes that multiple use entries are supposed
                    152:             * to contribute the logical or of their boolean capabilities.
                    153:             * This is true if we take the semantics of multiple uses to
                    154:             * be 'each capability gets the first non-default value found
                    155:             * in the sequence of use entries'.
1.9       millert   156:             *
                    157:             * Note that cancelled or absent booleans are stored as FALSE,
                    158:             * unlike numbers and strings, whose cancelled/absent state is
                    159:             * recorded in the terminfo database.
1.8       millert   160:             */
1.9       millert   161:            for (ep = &entries[1]; ep < entries + termcount; ep++)
                    162:                if (ep->tterm.Booleans[idx] == TRUE) {
                    163:                    is_set = entries[0].tterm.Booleans[idx];
1.8       millert   164:                    break;
1.1       millert   165:                }
1.9       millert   166:            if (is_set != entries[0].tterm.Booleans[idx])
1.8       millert   167:                return (!is_set);
                    168:            else
                    169:                return (FAIL);
                    170:        }
1.1       millert   171:
1.9       millert   172:     case NUMBER:
                    173:        {
1.8       millert   174:            int value = ABSENT_NUMERIC;
1.1       millert   175:
1.8       millert   176:            /*
                    177:             * We take the semantics of multiple uses to be 'each
                    178:             * capability gets the first non-default value found
                    179:             * in the sequence of use entries'.
                    180:             */
1.9       millert   181:            for (ep = &entries[1]; ep < entries + termcount; ep++)
                    182:                if (VALID_NUMERIC(ep->tterm.Numbers[idx])) {
                    183:                    value = ep->tterm.Numbers[idx];
1.8       millert   184:                    break;
1.1       millert   185:                }
                    186:
1.9       millert   187:            if (value != entries[0].tterm.Numbers[idx])
1.8       millert   188:                return (value != ABSENT_NUMERIC);
                    189:            else
                    190:                return (FAIL);
                    191:        }
                    192:
1.9       millert   193:     case STRING:
                    194:        {
1.8       millert   195:            char *termstr, *usestr = ABSENT_STRING;
1.1       millert   196:
1.9       millert   197:            termstr = entries[0].tterm.Strings[idx];
1.1       millert   198:
1.8       millert   199:            /*
                    200:             * We take the semantics of multiple uses to be 'each
                    201:             * capability gets the first non-default value found
                    202:             * in the sequence of use entries'.
                    203:             */
1.9       millert   204:            for (ep = &entries[1]; ep < entries + termcount; ep++)
                    205:                if (ep->tterm.Strings[idx]) {
                    206:                    usestr = ep->tterm.Strings[idx];
1.8       millert   207:                    break;
                    208:                }
                    209:
                    210:            if (usestr == ABSENT_STRING && termstr == ABSENT_STRING)
                    211:                return (FAIL);
1.9       millert   212:            else if (!usestr || !termstr || capcmp(idx, usestr, termstr))
1.8       millert   213:                return (TRUE);
                    214:            else
                    215:                return (FAIL);
1.1       millert   216:        }
1.8       millert   217:     }
1.1       millert   218:
1.8       millert   219:     return (FALSE);            /* pacify compiler */
1.1       millert   220: }
                    221:
1.8       millert   222: static bool
1.9       millert   223: useeq(ENTRY * e1, ENTRY * e2)
                    224: /* are the use references in two entries equivalent? */
                    225: {
1.20    ! nicm      226:     unsigned i, j;
1.9       millert   227:
                    228:     if (e1->nuses != e2->nuses)
                    229:        return (FALSE);
                    230:
                    231:     /* Ugh...this is quadratic again */
                    232:     for (i = 0; i < e1->nuses; i++) {
                    233:        bool foundmatch = FALSE;
                    234:
                    235:        /* search second entry for given use reference */
                    236:        for (j = 0; j < e2->nuses; j++)
                    237:            if (!strcmp(e1->uses[i].name, e2->uses[j].name)) {
                    238:                foundmatch = TRUE;
                    239:                break;
                    240:            }
                    241:
                    242:        if (!foundmatch)
                    243:            return (FALSE);
                    244:     }
                    245:
                    246:     return (TRUE);
                    247: }
                    248:
                    249: static bool
1.20    ! nicm      250: entryeq(TERMTYPE *t1, TERMTYPE *t2)
1.9       millert   251: /* are two entries equivalent? */
1.1       millert   252: {
1.20    ! nicm      253:     unsigned i;
1.1       millert   254:
1.2       millert   255:     for (i = 0; i < NUM_BOOLEANS(t1); i++)
1.1       millert   256:        if (t1->Booleans[i] != t2->Booleans[i])
1.8       millert   257:            return (FALSE);
1.1       millert   258:
1.2       millert   259:     for (i = 0; i < NUM_NUMBERS(t1); i++)
1.1       millert   260:        if (t1->Numbers[i] != t2->Numbers[i])
1.8       millert   261:            return (FALSE);
1.1       millert   262:
1.2       millert   263:     for (i = 0; i < NUM_STRINGS(t1); i++)
1.20    ! nicm      264:        if (capcmp((PredIdx) i, t1->Strings[i], t2->Strings[i]))
1.8       millert   265:            return (FALSE);
1.1       millert   266:
1.8       millert   267:     return (TRUE);
1.1       millert   268: }
                    269:
                    270: #define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers)
                    271:
1.8       millert   272: static void
1.20    ! nicm      273: print_uses(ENTRY * ep, FILE *fp)
1.9       millert   274: /* print an entry's use references */
                    275: {
1.20    ! nicm      276:     unsigned i;
1.9       millert   277:
                    278:     if (!ep->nuses)
                    279:        fputs("NULL", fp);
                    280:     else
                    281:        for (i = 0; i < ep->nuses; i++) {
                    282:            fputs(ep->uses[i].name, fp);
                    283:            if (i < ep->nuses - 1)
                    284:                fputs(" ", fp);
                    285:        }
                    286: }
                    287:
1.10      millert   288: static const char *
1.9       millert   289: dump_boolean(int val)
                    290: /* display the value of a boolean capability */
                    291: {
                    292:     switch (val) {
                    293:     case ABSENT_BOOLEAN:
                    294:        return (s_absent);
                    295:     case CANCELLED_BOOLEAN:
                    296:        return (s_cancel);
                    297:     case FALSE:
                    298:        return ("F");
                    299:     case TRUE:
                    300:        return ("T");
                    301:     default:
                    302:        return ("?");
                    303:     }
                    304: }
                    305:
                    306: static void
1.16      deraadt   307: dump_numeric(int val, char *buf, size_t bufl)
1.9       millert   308: /* display the value of a boolean capability */
                    309: {
                    310:     switch (val) {
                    311:     case ABSENT_NUMERIC:
1.16      deraadt   312:        strlcpy(buf, s_absent, bufl);
1.9       millert   313:        break;
                    314:     case CANCELLED_NUMERIC:
1.16      deraadt   315:        strlcpy(buf, s_cancel, bufl);
1.9       millert   316:        break;
                    317:     default:
1.16      deraadt   318:        snprintf(buf, bufl, "%d", val);
1.9       millert   319:        break;
                    320:     }
                    321: }
                    322:
                    323: static void
1.16      deraadt   324: dump_string(char *val, char *buf, size_t bufl)
1.9       millert   325: /* display the value of a string capability */
                    326: {
                    327:     if (val == ABSENT_STRING)
1.16      deraadt   328:        strlcpy(buf, s_absent, bufl);
1.9       millert   329:     else if (val == CANCELLED_STRING)
1.16      deraadt   330:        strlcpy(buf, s_cancel, bufl);
1.9       millert   331:     else {
1.16      deraadt   332:        snprintf(buf, bufl, "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val));
1.9       millert   333:     }
                    334: }
                    335:
                    336: static void
1.20    ! nicm      337: compare_predicate(PredType type, PredIdx idx, const char *name)
1.1       millert   338: /* predicate function to use for entry difference reports */
                    339: {
1.15      mpech     340:     ENTRY *e1 = &entries[0];
                    341:     ENTRY *e2 = &entries[1];
1.9       millert   342:     char buf1[MAX_STRING], buf2[MAX_STRING];
                    343:     int b1, b2;
                    344:     int n1, n2;
1.8       millert   345:     char *s1, *s2;
                    346:
                    347:     switch (type) {
1.9       millert   348:     case CMP_BOOLEAN:
                    349:        b1 = e1->tterm.Booleans[idx];
                    350:        b2 = e2->tterm.Booleans[idx];
1.8       millert   351:        switch (compare) {
                    352:        case C_DIFFERENCE:
1.9       millert   353:            if (!(b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) && b1 != b2)
                    354:                (void) printf("\t%s: %s%s%s.\n",
1.11      millert   355:                              name,
                    356:                              dump_boolean(b1),
                    357:                              bool_sep,
                    358:                              dump_boolean(b2));
1.8       millert   359:            break;
                    360:
                    361:        case C_COMMON:
1.9       millert   362:            if (b1 == b2 && b1 != ABSENT_BOOLEAN)
                    363:                (void) printf("\t%s= %s.\n", name, dump_boolean(b1));
1.8       millert   364:            break;
                    365:
                    366:        case C_NAND:
1.9       millert   367:            if (b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN)
1.8       millert   368:                (void) printf("\t!%s.\n", name);
                    369:            break;
                    370:        }
                    371:        break;
1.1       millert   372:
1.9       millert   373:     case CMP_NUMBER:
                    374:        n1 = e1->tterm.Numbers[idx];
                    375:        n2 = e2->tterm.Numbers[idx];
1.16      deraadt   376:        dump_numeric(n1, buf1, sizeof buf1);
                    377:        dump_numeric(n2, buf2, sizeof buf2);
1.8       millert   378:        switch (compare) {
                    379:        case C_DIFFERENCE:
1.9       millert   380:            if (!((n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)) && n1 != n2)
                    381:                (void) printf("\t%s: %s, %s.\n", name, buf1, buf2);
1.8       millert   382:            break;
1.1       millert   383:
1.8       millert   384:        case C_COMMON:
1.9       millert   385:            if (n1 != ABSENT_NUMERIC && n2 != ABSENT_NUMERIC && n1 == n2)
                    386:                (void) printf("\t%s= %s.\n", name, buf1);
1.8       millert   387:            break;
1.1       millert   388:
1.8       millert   389:        case C_NAND:
1.9       millert   390:            if (n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)
1.8       millert   391:                (void) printf("\t!%s.\n", name);
                    392:            break;
                    393:        }
                    394:        break;
1.1       millert   395:
1.9       millert   396:     case CMP_STRING:
                    397:        s1 = e1->tterm.Strings[idx];
                    398:        s2 = e2->tterm.Strings[idx];
1.8       millert   399:        switch (compare) {
                    400:        case C_DIFFERENCE:
1.9       millert   401:            if (capcmp(idx, s1, s2)) {
1.16      deraadt   402:                dump_string(s1, buf1, sizeof buf1);
                    403:                dump_string(s2, buf2, sizeof buf2);
1.8       millert   404:                if (strcmp(buf1, buf2))
1.9       millert   405:                    (void) printf("\t%s: %s, %s.\n", name, buf1, buf2);
1.8       millert   406:            }
                    407:            break;
1.1       millert   408:
1.8       millert   409:        case C_COMMON:
1.9       millert   410:            if (s1 && s2 && !capcmp(idx, s1, s2))
1.8       millert   411:                (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1));
                    412:            break;
1.1       millert   413:
1.8       millert   414:        case C_NAND:
                    415:            if (!s1 && !s2)
                    416:                (void) printf("\t!%s.\n", name);
                    417:            break;
1.1       millert   418:        }
1.8       millert   419:        break;
1.9       millert   420:
                    421:     case CMP_USE:
                    422:        /* unlike the other modes, this compares *all* use entries */
                    423:        switch (compare) {
                    424:        case C_DIFFERENCE:
                    425:            if (!useeq(e1, e2)) {
                    426:                (void) fputs("\tuse: ", stdout);
                    427:                print_uses(e1, stdout);
                    428:                fputs(", ", stdout);
                    429:                print_uses(e2, stdout);
                    430:                fputs(".\n", stdout);
                    431:            }
                    432:            break;
                    433:
                    434:        case C_COMMON:
                    435:            if (e1->nuses && e2->nuses && useeq(e1, e2)) {
                    436:                (void) fputs("\tuse: ", stdout);
                    437:                print_uses(e1, stdout);
                    438:                fputs(".\n", stdout);
                    439:            }
                    440:            break;
                    441:
                    442:        case C_NAND:
                    443:            if (!e1->nuses && !e2->nuses)
                    444:                (void) printf("\t!use.\n");
                    445:            break;
                    446:        }
1.8       millert   447:     }
1.1       millert   448: }
                    449:
                    450: /***************************************************************************
                    451:  *
                    452:  * Init string analysis
                    453:  *
                    454:  ***************************************************************************/
                    455:
1.8       millert   456: typedef struct {
                    457:     const char *from;
                    458:     const char *to;
                    459: } assoc;
1.1       millert   460:
                    461: static const assoc std_caps[] =
                    462: {
                    463:     /* these are specified by X.364 and iBCS2 */
1.8       millert   464:     {"\033c", "RIS"},          /* full reset */
                    465:     {"\0337", "SC"},           /* save cursor */
                    466:     {"\0338", "RC"},           /* restore cursor */
                    467:     {"\033[r", "RSR"},         /* not an X.364 mnemonic */
                    468:     {"\033[m", "SGR0"},                /* not an X.364 mnemonic */
                    469:     {"\033[2J", "ED2"},                /* clear page */
1.1       millert   470:
                    471:     /* this group is specified by ISO 2022 */
1.8       millert   472:     {"\033(0", "ISO DEC G0"},  /* enable DEC graphics for G0 */
                    473:     {"\033(A", "ISO UK G0"},   /* enable UK chars for G0 */
                    474:     {"\033(B", "ISO US G0"},   /* enable US chars for G0 */
                    475:     {"\033)0", "ISO DEC G1"},  /* enable DEC graphics for G1 */
                    476:     {"\033)A", "ISO UK G1"},   /* enable UK chars for G1 */
                    477:     {"\033)B", "ISO US G1"},   /* enable US chars for G1 */
1.1       millert   478:
1.20    ! nicm      479:     /* these are DEC private controls widely supported by emulators */
1.8       millert   480:     {"\033=", "DECPAM"},       /* application keypad mode */
                    481:     {"\033>", "DECPNM"},       /* normal keypad mode */
                    482:     {"\033<", "DECANSI"},      /* enter ANSI mode */
1.20    ! nicm      483:     {"\033[!p", "DECSTR"},     /* soft reset */
        !           484:     {"\033 F", "S7C1T"},       /* 7-bit controls */
1.1       millert   485:
1.8       millert   486:     {(char *) 0, (char *) 0}
1.1       millert   487: };
                    488:
1.20    ! nicm      489: static const assoc std_modes[] =
        !           490: /* ECMA \E[ ... [hl] modes recognized by many emulators */
        !           491: {
        !           492:     {"2", "AM"},               /* keyboard action mode */
        !           493:     {"4", "IRM"},              /* insert/replace mode */
        !           494:     {"12", "SRM"},             /* send/receive mode */
        !           495:     {"20", "LNM"},             /* linefeed mode */
        !           496:     {(char *) 0, (char *) 0}
        !           497: };
        !           498:
1.1       millert   499: static const assoc private_modes[] =
                    500: /* DEC \E[ ... [hl] modes recognized by many emulators */
                    501: {
1.8       millert   502:     {"1", "CKM"},              /* application cursor keys */
                    503:     {"2", "ANM"},              /* set VT52 mode */
                    504:     {"3", "COLM"},             /* 132-column mode */
                    505:     {"4", "SCLM"},             /* smooth scroll */
                    506:     {"5", "SCNM"},             /* reverse video mode */
                    507:     {"6", "OM"},               /* origin mode */
                    508:     {"7", "AWM"},              /* wraparound mode */
                    509:     {"8", "ARM"},              /* auto-repeat mode */
                    510:     {(char *) 0, (char *) 0}
1.1       millert   511: };
                    512:
                    513: static const assoc ecma_highlights[] =
                    514: /* recognize ECMA attribute sequences */
                    515: {
1.8       millert   516:     {"0", "NORMAL"},           /* normal */
                    517:     {"1", "+BOLD"},            /* bold on */
                    518:     {"2", "+DIM"},             /* dim on */
                    519:     {"3", "+ITALIC"},          /* italic on */
                    520:     {"4", "+UNDERLINE"},       /* underline on */
                    521:     {"5", "+BLINK"},           /* blink on */
                    522:     {"6", "+FASTBLINK"},       /* fastblink on */
                    523:     {"7", "+REVERSE"},         /* reverse on */
                    524:     {"8", "+INVISIBLE"},       /* invisible on */
                    525:     {"9", "+DELETED"},         /* deleted on */
                    526:     {"10", "MAIN-FONT"},       /* select primary font */
                    527:     {"11", "ALT-FONT-1"},      /* select alternate font 1 */
                    528:     {"12", "ALT-FONT-2"},      /* select alternate font 2 */
                    529:     {"13", "ALT-FONT-3"},      /* select alternate font 3 */
                    530:     {"14", "ALT-FONT-4"},      /* select alternate font 4 */
                    531:     {"15", "ALT-FONT-5"},      /* select alternate font 5 */
                    532:     {"16", "ALT-FONT-6"},      /* select alternate font 6 */
                    533:     {"17", "ALT-FONT-7"},      /* select alternate font 7 */
                    534:     {"18", "ALT-FONT-1"},      /* select alternate font 1 */
                    535:     {"19", "ALT-FONT-1"},      /* select alternate font 1 */
                    536:     {"20", "FRAKTUR"},         /* Fraktur font */
                    537:     {"21", "DOUBLEUNDER"},     /* double underline */
                    538:     {"22", "-DIM"},            /* dim off */
                    539:     {"23", "-ITALIC"},         /* italic off */
                    540:     {"24", "-UNDERLINE"},      /* underline off */
                    541:     {"25", "-BLINK"},          /* blink off */
                    542:     {"26", "-FASTBLINK"},      /* fastblink off */
                    543:     {"27", "-REVERSE"},                /* reverse off */
                    544:     {"28", "-INVISIBLE"},      /* invisible off */
                    545:     {"29", "-DELETED"},                /* deleted off */
                    546:     {(char *) 0, (char *) 0}
1.1       millert   547: };
                    548:
1.20    ! nicm      549: static int
        !           550: skip_csi(const char *cap)
        !           551: {
        !           552:     int result = 0;
        !           553:     if (cap[0] == '\033' && cap[1] == '[')
        !           554:        result = 2;
        !           555:     else if (UChar(cap[0]) == 0233)
        !           556:        result = 1;
        !           557:     return result;
        !           558: }
        !           559:
        !           560: static bool
        !           561: same_param(const char *table, const char *param, unsigned length)
        !           562: {
        !           563:     bool result = FALSE;
        !           564:     if (strncmp(table, param, length) == 0) {
        !           565:        result = !isdigit(UChar(param[length]));
        !           566:     }
        !           567:     return result;
        !           568: }
        !           569:
        !           570: static char *
        !           571: lookup_params(const assoc * table, char *dst, char *src, size_t dstlen)
        !           572: {
        !           573:     char *result = 0;
        !           574:     const char *ep = strtok(src, ";");
        !           575:
        !           576:     if (ep != 0) {
        !           577:        const assoc *ap;
        !           578:
        !           579:        do {
        !           580:            bool found = FALSE;
        !           581:
        !           582:            for (ap = table; ap->from; ap++) {
        !           583:                size_t tlen = strlen(ap->from);
        !           584:
        !           585:                if (same_param(ap->from, ep, tlen)) {
        !           586:                    (void) strlcat(dst, ap->to, dstlen);
        !           587:                    found = TRUE;
        !           588:                    break;
        !           589:                }
        !           590:            }
        !           591:
        !           592:            if (!found)
        !           593:                (void) strlcat(dst, ep, dstlen);
        !           594:            (void) strlcat(dst, ";", dstlen);
        !           595:        } while
        !           596:            ((ep = strtok((char *) 0, ";")));
        !           597:
        !           598:        if (dst[0] != '\0' && dst[strlen(dst) - 1] == ';')
        !           599:            dst[strlen(dst) - 1] = '\0';
        !           600:
        !           601:        result = dst;
        !           602:     }
        !           603:     return result;
        !           604: }
        !           605:
1.8       millert   606: static void
1.20    ! nicm      607: analyze_string(const char *name, const char *cap, TERMTYPE *tp)
1.1       millert   608: {
1.8       millert   609:     char buf2[MAX_TERMINFO_LENGTH];
1.20    ! nicm      610:     const char *sp;
1.8       millert   611:     const assoc *ap;
1.20    ! nicm      612:     int tp_lines = tp->Numbers[2];
1.1       millert   613:
                    614:     if (cap == ABSENT_STRING || cap == CANCELLED_STRING)
                    615:        return;
                    616:     (void) printf("%s: ", name);
                    617:
1.8       millert   618:     for (sp = cap; *sp; sp++) {
                    619:        int i;
1.20    ! nicm      620:        int csi;
1.8       millert   621:        size_t len = 0;
1.20    ! nicm      622:        size_t next;
1.1       millert   623:        const char *expansion = 0;
1.20    ! nicm      624:        char buf3[MAX_TERMINFO_LENGTH];
1.1       millert   625:
                    626:        /* first, check other capabilities in this entry */
1.8       millert   627:        for (i = 0; i < STRCOUNT; i++) {
                    628:            char *cp = tp->Strings[i];
1.1       millert   629:
                    630:            /* don't use soft-key capabilities */
                    631:            if (strnames[i][0] == 'k' && strnames[i][0] == 'f')
                    632:                continue;
                    633:
1.8       millert   634:            if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp
                    635:                != cap) {
1.1       millert   636:                len = strlen(cp);
                    637:                (void) strncpy(buf2, sp, len);
                    638:                buf2[len] = '\0';
                    639:
                    640:                if (_nc_capcmp(cp, buf2))
                    641:                    continue;
                    642:
                    643: #define ISRS(s)        (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2))
                    644:                /*
                    645:                 * Theoretically we just passed the test for translation
                    646:                 * (equality once the padding is stripped).  However, there
                    647:                 * are a few more hoops that need to be jumped so that
                    648:                 * identical pairs of initialization and reset strings
                    649:                 * don't just refer to each other.
                    650:                 */
                    651:                if (ISRS(name) || ISRS(strnames[i]))
                    652:                    if (cap < cp)
                    653:                        continue;
                    654: #undef ISRS
                    655:
                    656:                expansion = strnames[i];
                    657:                break;
                    658:            }
                    659:        }
                    660:
                    661:        /* now check the standard capabilities */
1.20    ! nicm      662:        if (!expansion) {
        !           663:            csi = skip_csi(sp);
1.8       millert   664:            for (ap = std_caps; ap->from; ap++) {
1.20    ! nicm      665:                size_t adj = (size_t) (csi ? 2 : 0);
        !           666:
1.1       millert   667:                len = strlen(ap->from);
1.20    ! nicm      668:                if (csi && skip_csi(ap->from) != csi)
        !           669:                    continue;
        !           670:                if (len > adj
        !           671:                    && strncmp(ap->from + adj, sp + csi, len - adj) == 0) {
1.1       millert   672:                    expansion = ap->to;
1.20    ! nicm      673:                    len -= adj;
        !           674:                    len += (size_t) csi;
1.1       millert   675:                    break;
                    676:                }
                    677:            }
1.20    ! nicm      678:        }
        !           679:
        !           680:        /* now check for standard-mode sequences */
        !           681:        if (!expansion
        !           682:            && (csi = skip_csi(sp)) != 0
        !           683:            && (len = strspn(sp + csi, "0123456789;"))
        !           684:            && (len < sizeof(buf3))
        !           685:            && (next = (size_t) csi + len)
        !           686:            && ((sp[next] == 'h') || (sp[next] == 'l'))) {
        !           687:
        !           688:            (void) strlcpy(buf2, (sp[next] == 'h') ? "ECMA+" : "ECMA-",
        !           689:                sizeof buf2);
        !           690:            (void) strncpy(buf3, sp + csi, len);
        !           691:            buf3[len] = '\0';
        !           692:            len += (size_t) csi + 1;
        !           693:
        !           694:            expansion = lookup_params(std_modes, buf2, buf3, sizeof buf2);
        !           695:        }
1.1       millert   696:
                    697:        /* now check for private-mode sequences */
                    698:        if (!expansion
1.20    ! nicm      699:            && (csi = skip_csi(sp)) != 0
        !           700:            && sp[csi] == '?'
        !           701:            && (len = strspn(sp + csi + 1, "0123456789;"))
        !           702:            && (len < sizeof(buf3))
        !           703:            && (next = (size_t) csi + 1 + len)
        !           704:            && ((sp[next] == 'h') || (sp[next] == 'l'))) {
1.1       millert   705:
1.20    ! nicm      706:            (void) strlcpy(buf2, (sp[next] == 'h') ? "DEC+" : "DEC-",
1.16      deraadt   707:                sizeof buf2);
1.20    ! nicm      708:            (void) strncpy(buf3, sp + csi + 1, len);
1.1       millert   709:            buf3[len] = '\0';
1.20    ! nicm      710:            len += (size_t) csi + 2;
1.1       millert   711:
1.20    ! nicm      712:            expansion = lookup_params(private_modes, buf2, buf3, sizeof buf2);
1.1       millert   713:        }
                    714:
                    715:        /* now check for ECMA highlight sequences */
                    716:        if (!expansion
1.20    ! nicm      717:            && (csi = skip_csi(sp)) != 0
        !           718:            && (len = strspn(sp + csi, "0123456789;")) != 0
        !           719:            && (len < sizeof(buf3))
        !           720:            && (next = (size_t) csi + len)
        !           721:            && sp[next] == 'm') {
1.1       millert   722:
1.16      deraadt   723:            (void) strlcpy(buf2, "SGR:", sizeof buf2);
1.20    ! nicm      724:            (void) strncpy(buf3, sp + csi, len);
1.1       millert   725:            buf3[len] = '\0';
1.20    ! nicm      726:            len += (size_t) csi + 1;
1.1       millert   727:
1.20    ! nicm      728:            expansion = lookup_params(ecma_highlights, buf2, buf3, sizeof buf2);
        !           729:        }
1.1       millert   730:
1.20    ! nicm      731:        if (!expansion
        !           732:            && (csi = skip_csi(sp)) != 0
        !           733:            && sp[csi] == 'm') {
        !           734:            len = (size_t) csi + 1;
        !           735:            (void) strlcpy(buf2, "SGR:", sizeof buf2);
        !           736:            strlcat(buf2, ecma_highlights[0].to, sizeof buf2);
1.1       millert   737:            expansion = buf2;
                    738:        }
1.20    ! nicm      739:
1.1       millert   740:        /* now check for scroll region reset */
1.20    ! nicm      741:        if (!expansion
        !           742:            && (csi = skip_csi(sp)) != 0) {
        !           743:            if (sp[csi] == 'r') {
1.1       millert   744:                expansion = "RSR";
1.20    ! nicm      745:                len = 1;
        !           746:            } else {
        !           747:                (void) snprintf(buf2, sizeof buf2, "1;%dr", tp_lines);
        !           748:                len = strlen(buf2);
        !           749:                if (strncmp(buf2, sp + csi, len) == 0)
        !           750:                    expansion = "RSR";
        !           751:            }
        !           752:            len += (size_t) csi;
1.1       millert   753:        }
                    754:
                    755:        /* now check for home-down */
1.20    ! nicm      756:        if (!expansion
        !           757:            && (csi = skip_csi(sp)) != 0) {
        !           758:            (void) snprintf(buf2, sizeof buf2, "%d;1H", tp_lines);
1.1       millert   759:            len = strlen(buf2);
1.20    ! nicm      760:            if (strncmp(buf2, sp + csi, len) == 0) {
1.8       millert   761:                expansion = "LL";
1.20    ! nicm      762:            } else {
        !           763:                (void) snprintf(buf2, sizeof buf2, "%dH", tp_lines);
        !           764:                len = strlen(buf2);
        !           765:                if (strncmp(buf2, sp + csi, len) == 0) {
        !           766:                    expansion = "LL";
        !           767:                }
        !           768:            }
        !           769:            len += (size_t) csi;
1.1       millert   770:        }
                    771:
                    772:        /* now look at the expansion we got, if any */
1.8       millert   773:        if (expansion) {
1.20    ! nicm      774:            printf("{%s}", expansion);
1.1       millert   775:            sp += len - 1;
1.8       millert   776:        } else {
1.1       millert   777:            /* couldn't match anything */
                    778:            buf2[0] = *sp;
                    779:            buf2[1] = '\0';
1.20    ! nicm      780:            fputs(TIC_EXPAND(buf2), stdout);
1.1       millert   781:        }
                    782:     }
1.20    ! nicm      783:     putchar('\n');
1.1       millert   784: }
                    785:
                    786: /***************************************************************************
                    787:  *
                    788:  * File comparison
                    789:  *
                    790:  ***************************************************************************/
                    791:
1.8       millert   792: static void
                    793: file_comparison(int argc, char *argv[])
1.1       millert   794: {
                    795: #define MAXCOMPARE     2
                    796:     /* someday we may allow comparisons on more files */
1.8       millert   797:     int filecount = 0;
                    798:     ENTRY *heads[MAXCOMPARE];
                    799:     ENTRY *qp, *rp;
                    800:     int i, n;
1.1       millert   801:
1.20    ! nicm      802:     memset(heads, 0, sizeof(heads));
1.9       millert   803:     dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, itrace, FALSE);
1.1       millert   804:
1.8       millert   805:     for (n = 0; n < argc && n < MAXCOMPARE; n++) {
1.9       millert   806:        if (freopen(argv[n], "r", stdin) == 0)
1.1       millert   807:            _nc_err_abort("Can't open %s", argv[n]);
                    808:
1.9       millert   809:        _nc_head = _nc_tail = 0;
1.1       millert   810:
                    811:        /* parse entries out of the source file */
                    812:        _nc_set_source(argv[n]);
1.20    ! nicm      813:        _nc_read_entry_source(stdin, NULL, TRUE, literal, NULLHOOK);
1.1       millert   814:
                    815:        if (itrace)
1.8       millert   816:            (void) fprintf(stderr, "Resolving file %d...\n", n - 0);
1.1       millert   817:
1.9       millert   818:        /* maybe do use resolution */
1.20    ! nicm      819:        if (!_nc_resolve_uses2(!limited, literal)) {
1.1       millert   820:            (void) fprintf(stderr,
1.11      millert   821:                           "There are unresolved use entries in %s:\n",
                    822:                           argv[n]);
1.9       millert   823:            for_entry_list(qp) {
1.8       millert   824:                if (qp->nuses) {
1.9       millert   825:                    (void) fputs(qp->tterm.term_names, stderr);
                    826:                    (void) fputc('\n', stderr);
                    827:                }
1.8       millert   828:            }
1.20    ! nicm      829:            ExitProgram(EXIT_FAILURE);
1.1       millert   830:        }
                    831:
                    832:        heads[filecount] = _nc_head;
                    833:        filecount++;
                    834:     }
                    835:
                    836:     /* OK, all entries are in core.  Ready to do the comparison */
                    837:     if (itrace)
                    838:        (void) fprintf(stderr, "Entries are now in core...\n");
                    839:
1.9       millert   840:     /* The entry-matching loop. Sigh, this is intrinsically quadratic. */
1.8       millert   841:     for (qp = heads[0]; qp; qp = qp->next) {
1.1       millert   842:        for (rp = heads[1]; rp; rp = rp->next)
1.8       millert   843:            if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) {
1.9       millert   844:                if (qp->ncrosslinks < MAX_CROSSLINKS)
                    845:                    qp->crosslinks[qp->ncrosslinks] = rp;
                    846:                qp->ncrosslinks++;
                    847:
                    848:                if (rp->ncrosslinks < MAX_CROSSLINKS)
                    849:                    rp->crosslinks[rp->ncrosslinks] = qp;
                    850:                rp->ncrosslinks++;
1.1       millert   851:            }
                    852:     }
                    853:
                    854:     /* now we have two circular lists with crosslinks */
                    855:     if (itrace)
                    856:        (void) fprintf(stderr, "Name matches are done...\n");
                    857:
1.9       millert   858:     for (qp = heads[0]; qp; qp = qp->next) {
                    859:        if (qp->ncrosslinks > 1) {
1.1       millert   860:            (void) fprintf(stderr,
1.11      millert   861:                           "%s in file 1 (%s) has %d matches in file 2 (%s):\n",
                    862:                           _nc_first_name(qp->tterm.term_names),
                    863:                           argv[0],
                    864:                           qp->ncrosslinks,
                    865:                           argv[1]);
1.9       millert   866:            for (i = 0; i < qp->ncrosslinks; i++)
1.1       millert   867:                (void) fprintf(stderr,
1.11      millert   868:                               "\t%s\n",
                    869:                               _nc_first_name((qp->crosslinks[i])->tterm.term_names));
1.1       millert   870:        }
1.9       millert   871:     }
                    872:
                    873:     for (rp = heads[1]; rp; rp = rp->next) {
                    874:        if (rp->ncrosslinks > 1) {
1.1       millert   875:            (void) fprintf(stderr,
1.11      millert   876:                           "%s in file 2 (%s) has %d matches in file 1 (%s):\n",
                    877:                           _nc_first_name(rp->tterm.term_names),
                    878:                           argv[1],
                    879:                           rp->ncrosslinks,
                    880:                           argv[0]);
1.9       millert   881:            for (i = 0; i < rp->ncrosslinks; i++)
1.1       millert   882:                (void) fprintf(stderr,
1.11      millert   883:                               "\t%s\n",
                    884:                               _nc_first_name((rp->crosslinks[i])->tterm.term_names));
1.1       millert   885:        }
1.9       millert   886:     }
1.1       millert   887:
                    888:     (void) printf("In file 1 (%s) only:\n", argv[0]);
                    889:     for (qp = heads[0]; qp; qp = qp->next)
1.9       millert   890:        if (qp->ncrosslinks == 0)
1.1       millert   891:            (void) printf("\t%s\n",
1.11      millert   892:                          _nc_first_name(qp->tterm.term_names));
1.1       millert   893:
                    894:     (void) printf("In file 2 (%s) only:\n", argv[1]);
                    895:     for (rp = heads[1]; rp; rp = rp->next)
1.9       millert   896:        if (rp->ncrosslinks == 0)
1.1       millert   897:            (void) printf("\t%s\n",
1.11      millert   898:                          _nc_first_name(rp->tterm.term_names));
1.1       millert   899:
                    900:     (void) printf("The following entries are equivalent:\n");
1.8       millert   901:     for (qp = heads[0]; qp; qp = qp->next) {
1.9       millert   902:        rp = qp->crosslinks[0];
                    903:
                    904:        if (qp->ncrosslinks == 1) {
                    905:            rp = qp->crosslinks[0];
1.1       millert   906:
1.9       millert   907:            repair_acsc(&qp->tterm);
                    908:            repair_acsc(&rp->tterm);
                    909: #if NCURSES_XNAMES
                    910:            _nc_align_termtype(&qp->tterm, &rp->tterm);
                    911: #endif
                    912:            if (entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp)) {
                    913:                char name1[NAMESIZE], name2[NAMESIZE];
1.1       millert   914:
1.16      deraadt   915:                (void) canonical_name(qp->tterm.term_names, name1, sizeof name1);
                    916:                (void) canonical_name(rp->tterm.term_names, name2, sizeof name2);
1.1       millert   917:
1.9       millert   918:                (void) printf("%s = %s\n", name1, name2);
                    919:            }
1.1       millert   920:        }
                    921:     }
                    922:
                    923:     (void) printf("Differing entries:\n");
                    924:     termcount = 2;
1.8       millert   925:     for (qp = heads[0]; qp; qp = qp->next) {
1.1       millert   926:
1.9       millert   927:        if (qp->ncrosslinks == 1) {
                    928:            rp = qp->crosslinks[0];
1.2       millert   929: #if NCURSES_XNAMES
1.9       millert   930:            /* sorry - we have to do this on each pass */
1.2       millert   931:            _nc_align_termtype(&qp->tterm, &rp->tterm);
                    932: #endif
1.9       millert   933:            if (!(entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp))) {
                    934:                char name1[NAMESIZE], name2[NAMESIZE];
1.1       millert   935:
1.9       millert   936:                entries[0] = *qp;
                    937:                entries[1] = *rp;
1.1       millert   938:
1.16      deraadt   939:                (void) canonical_name(qp->tterm.term_names, name1, sizeof name1);
                    940:                (void) canonical_name(rp->tterm.term_names, name2, sizeof name2);
1.1       millert   941:
1.9       millert   942:                switch (compare) {
                    943:                case C_DIFFERENCE:
                    944:                    if (itrace)
                    945:                        (void) fprintf(stderr,
1.20    ! nicm      946:                                       "%s: dumping differences\n",
        !           947:                                       _nc_progname);
1.9       millert   948:                    (void) printf("comparing %s to %s.\n", name1, name2);
                    949:                    compare_entry(compare_predicate, &entries->tterm, quiet);
                    950:                    break;
1.1       millert   951:
1.9       millert   952:                case C_COMMON:
                    953:                    if (itrace)
                    954:                        (void) fprintf(stderr,
1.20    ! nicm      955:                                       "%s: dumping common capabilities\n",
        !           956:                                       _nc_progname);
1.9       millert   957:                    (void) printf("comparing %s to %s.\n", name1, name2);
                    958:                    compare_entry(compare_predicate, &entries->tterm, quiet);
                    959:                    break;
1.1       millert   960:
1.9       millert   961:                case C_NAND:
                    962:                    if (itrace)
                    963:                        (void) fprintf(stderr,
1.20    ! nicm      964:                                       "%s: dumping differences\n",
        !           965:                                       _nc_progname);
1.9       millert   966:                    (void) printf("comparing %s to %s.\n", name1, name2);
                    967:                    compare_entry(compare_predicate, &entries->tterm, quiet);
                    968:                    break;
1.1       millert   969:
1.9       millert   970:                }
1.1       millert   971:            }
                    972:        }
                    973:     }
                    974: }
                    975:
1.8       millert   976: static void
                    977: usage(void)
1.1       millert   978: {
1.8       millert   979:     static const char *tbl[] =
                    980:     {
                    981:        "Usage: infocmp [options] [-A directory] [-B directory] [termname...]"
                    982:        ,""
                    983:        ,"Options:"
                    984:        ,"  -1    print single-column"
                    985:        ,"  -C    use termcap-names"
                    986:        ,"  -F    compare terminfo-files"
                    987:        ,"  -I    use terminfo-names"
                    988:        ,"  -L    use long names"
                    989:        ,"  -R subset (see manpage)"
                    990:        ,"  -T    eliminate size limits (test)"
1.20    ! nicm      991:        ,"  -U    eliminate post-processing of entries"
1.8       millert   992:        ,"  -V    print version"
1.10      millert   993: #if NCURSES_XNAMES
                    994:        ,"  -a    with -F, list commented-out caps"
                    995: #endif
1.8       millert   996:        ,"  -c    list common capabilities"
                    997:        ,"  -d    list different capabilities"
                    998:        ,"  -e    format output for C initializer"
                    999:        ,"  -E    format output as C tables"
                   1000:        ,"  -f    with -1, format complex strings"
                   1001:        ,"  -G    format %{number} to %'char'"
                   1002:        ,"  -g    format %'char' to %{number}"
                   1003:        ,"  -i    analyze initialization/reset"
                   1004:        ,"  -l    output terminfo names"
                   1005:        ,"  -n    list capabilities in neither"
                   1006:        ,"  -p    ignore padding specifiers"
1.9       millert  1007:        ,"  -q    brief listing, removes headers"
1.8       millert  1008:        ,"  -r    with -C, output in termcap form"
1.9       millert  1009:        ,"  -r    with -F, resolve use-references"
1.8       millert  1010:        ,"  -s [d|i|l|c] sort fields"
1.20    ! nicm     1011: #if NCURSES_XNAMES
        !          1012:        ,"  -t    suppress commented-out capabilities"
        !          1013: #endif
1.8       millert  1014:        ,"  -u    produce source with 'use='"
                   1015:        ,"  -v number  (verbose)"
                   1016:        ,"  -w number  (width)"
1.20    ! nicm     1017: #if NCURSES_XNAMES
        !          1018:        ,"  -x    treat unknown capabilities as user-defined"
        !          1019: #endif
1.8       millert  1020:     };
                   1021:     const size_t first = 3;
1.11      millert  1022:     const size_t last = SIZEOF(tbl);
1.8       millert  1023:     const size_t left = (last - first + 1) / 2 + first;
                   1024:     size_t n;
                   1025:
                   1026:     for (n = 0; n < left; n++) {
                   1027:        size_t m = (n < first) ? last : n + left - first;
                   1028:        if (m < last)
                   1029:            fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]);
                   1030:        else
                   1031:            fprintf(stderr, "%s\n", tbl[n]);
                   1032:     }
1.20    ! nicm     1033:     ExitProgram(EXIT_FAILURE);
1.1       millert  1034: }
                   1035:
1.8       millert  1036: static char *
1.20    ! nicm     1037: any_initializer(const char *fmt, const char *type)
1.5       millert  1038: {
                   1039:     static char *initializer;
1.16      deraadt  1040:     static size_t len;
1.5       millert  1041:     char *s;
                   1042:
1.16      deraadt  1043:     if (initializer == 0) {
1.20    ! nicm     1044:        len = strlen(entries->tterm.term_names) + strlen(type) + strlen(fmt);
1.16      deraadt  1045:        initializer = (char *) malloc(len);
                   1046:     }
1.5       millert  1047:
1.20    ! nicm     1048:     (void) strlcpy(initializer, entries->tterm.term_names, len);
1.8       millert  1049:     for (s = initializer; *s != 0 && *s != '|'; s++) {
1.20    ! nicm     1050:        if (!isalnum(UChar(*s)))
1.5       millert  1051:            *s = '_';
                   1052:     }
                   1053:     *s = 0;
1.20    ! nicm     1054:     (void) snprintf(s, len - (s - initializer), fmt, type);
1.5       millert  1055:     return initializer;
                   1056: }
                   1057:
1.20    ! nicm     1058: static char *
        !          1059: name_initializer(const char *type)
        !          1060: {
        !          1061:     return any_initializer("_%s_data", type);
        !          1062: }
        !          1063:
        !          1064: static char *
        !          1065: string_variable(const char *type)
        !          1066: {
        !          1067:     return any_initializer("_s_%s", type);
        !          1068: }
        !          1069:
1.5       millert  1070: /* dump C initializers for the terminal type */
1.8       millert  1071: static void
1.20    ! nicm     1072: dump_initializers(TERMTYPE *term)
1.5       millert  1073: {
1.20    ! nicm     1074:     unsigned n;
1.5       millert  1075:     const char *str = 0;
1.20    ! nicm     1076:
        !          1077:     printf("\nstatic char %s[] = \"%s\";\n\n",
        !          1078:           name_initializer("alias"), entries->tterm.term_names);
        !          1079:
        !          1080:     for_each_string(n, term) {
        !          1081:        char buf[MAX_STRING], *sp, *tp;
        !          1082:
        !          1083:        if (VALID_STRING(term->Strings[n])) {
        !          1084:            tp = buf;
        !          1085:            *tp++ = '"';
        !          1086:            for (sp = term->Strings[n];
        !          1087:                 *sp != 0 && (tp - buf) < MAX_STRING - 6;
        !          1088:                 sp++) {
        !          1089:                if (isascii(UChar(*sp))
        !          1090:                    && isprint(UChar(*sp))
        !          1091:                    && *sp != '\\'
        !          1092:                    && *sp != '"')
        !          1093:                    *tp++ = *sp;
        !          1094:                else {
        !          1095:                    (void) snprintf(tp, buf + sizeof buf - tp, "\\%03o",
        !          1096:                        UChar(*sp));
        !          1097:                    tp += strlen(tp);
        !          1098:                }
        !          1099:            }
        !          1100:            *tp++ = '"';
        !          1101:            *tp = '\0';
        !          1102:            (void) printf("static char %-20s[] = %s;\n",
        !          1103:                          string_variable(ExtStrname(term, n, strnames)), buf);
        !          1104:        }
        !          1105:     }
        !          1106:     printf("\n");
1.5       millert  1107:
1.6       millert  1108:     (void) printf("static char %s[] = %s\n", name_initializer("bool"), L_CURL);
1.5       millert  1109:
1.8       millert  1110:     for_each_boolean(n, term) {
                   1111:        switch ((int) (term->Booleans[n])) {
1.5       millert  1112:        case TRUE:
                   1113:            str = "TRUE";
                   1114:            break;
                   1115:
                   1116:        case FALSE:
                   1117:            str = "FALSE";
                   1118:            break;
                   1119:
                   1120:        case ABSENT_BOOLEAN:
                   1121:            str = "ABSENT_BOOLEAN";
                   1122:            break;
                   1123:
                   1124:        case CANCELLED_BOOLEAN:
                   1125:            str = "CANCELLED_BOOLEAN";
                   1126:            break;
                   1127:        }
1.20    ! nicm     1128:        (void) printf("\t/* %3u: %-8s */\t%s,\n",
1.11      millert  1129:                      n, ExtBoolname(term, n, boolnames), str);
1.5       millert  1130:     }
                   1131:     (void) printf("%s;\n", R_CURL);
                   1132:
                   1133:     (void) printf("static short %s[] = %s\n", name_initializer("number"), L_CURL);
                   1134:
1.8       millert  1135:     for_each_number(n, term) {
                   1136:        char buf[BUFSIZ];
                   1137:        switch (term->Numbers[n]) {
1.5       millert  1138:        case ABSENT_NUMERIC:
                   1139:            str = "ABSENT_NUMERIC";
                   1140:            break;
                   1141:        case CANCELLED_NUMERIC:
                   1142:            str = "CANCELLED_NUMERIC";
                   1143:            break;
                   1144:        default:
1.16      deraadt  1145:            snprintf(buf, sizeof buf, "%d", term->Numbers[n]);
1.5       millert  1146:            str = buf;
                   1147:            break;
                   1148:        }
1.20    ! nicm     1149:        (void) printf("\t/* %3u: %-8s */\t%s,\n", n,
1.11      millert  1150:                      ExtNumname(term, n, numnames), str);
1.5       millert  1151:     }
                   1152:     (void) printf("%s;\n", R_CURL);
                   1153:
                   1154:     (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL);
                   1155:
1.8       millert  1156:     for_each_string(n, term) {
1.5       millert  1157:
                   1158:        if (term->Strings[n] == ABSENT_STRING)
                   1159:            str = "ABSENT_STRING";
                   1160:        else if (term->Strings[n] == CANCELLED_STRING)
                   1161:            str = "CANCELLED_STRING";
1.8       millert  1162:        else {
1.20    ! nicm     1163:            str = string_variable(ExtStrname(term, n, strnames));
1.5       millert  1164:        }
1.20    ! nicm     1165:        (void) printf("\t/* %3u: %-8s */\t%s,\n", n,
        !          1166:                      ExtStrname(term, n, strnames), str);
        !          1167:     }
        !          1168:     (void) printf("%s;\n", R_CURL);
        !          1169:
1.5       millert  1170: #if NCURSES_XNAMES
1.20    ! nicm     1171:     if ((NUM_BOOLEANS(term) != BOOLCOUNT)
        !          1172:        || (NUM_NUMBERS(term) != NUMCOUNT)
        !          1173:        || (NUM_STRINGS(term) != STRCOUNT)) {
        !          1174:        (void) printf("static char * %s[] = %s\n",
        !          1175:                      name_initializer("string_ext"), L_CURL);
        !          1176:        for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) {
        !          1177:            (void) printf("\t/* %3u: bool */\t\"%s\",\n",
        !          1178:                          n, ExtBoolname(term, n, boolnames));
        !          1179:        }
        !          1180:        for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) {
        !          1181:            (void) printf("\t/* %3u: num */\t\"%s\",\n",
        !          1182:                          n, ExtNumname(term, n, numnames));
        !          1183:        }
        !          1184:        for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) {
        !          1185:            (void) printf("\t/* %3u: str */\t\"%s\",\n",
        !          1186:                          n, ExtStrname(term, n, strnames));
1.5       millert  1187:        }
1.20    ! nicm     1188:        (void) printf("%s;\n", R_CURL);
        !          1189:     }
1.5       millert  1190: #endif
                   1191: }
                   1192:
                   1193: /* dump C initializers for the terminal type */
1.8       millert  1194: static void
1.20    ! nicm     1195: dump_termtype(TERMTYPE *term)
1.5       millert  1196: {
1.20    ! nicm     1197:     (void) printf("\t%s\n\t\t%s,\n", L_CURL, name_initializer("alias"));
1.5       millert  1198:     (void) printf("\t\t(char *)0,\t/* pointer to string table */\n");
                   1199:
                   1200:     (void) printf("\t\t%s,\n", name_initializer("bool"));
                   1201:     (void) printf("\t\t%s,\n", name_initializer("number"));
                   1202:
                   1203:     (void) printf("\t\t%s,\n", name_initializer("string"));
                   1204:
                   1205: #if NCURSES_XNAMES
                   1206:     (void) printf("#if NCURSES_XNAMES\n");
                   1207:     (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n");
                   1208:     (void) printf("\t\t%s,\t/* ...corresponding names */\n",
1.20    ! nicm     1209:                  ((NUM_BOOLEANS(term) != BOOLCOUNT)
        !          1210:                   || (NUM_NUMBERS(term) != NUMCOUNT)
        !          1211:                   || (NUM_STRINGS(term) != STRCOUNT))
1.11      millert  1212:                  ? name_initializer("string_ext")
                   1213:                  : "(char **)0");
1.5       millert  1214:
                   1215:     (void) printf("\t\t%d,\t\t/* count total Booleans */\n", NUM_BOOLEANS(term));
1.8       millert  1216:     (void) printf("\t\t%d,\t\t/* count total Numbers */\n", NUM_NUMBERS(term));
                   1217:     (void) printf("\t\t%d,\t\t/* count total Strings */\n", NUM_STRINGS(term));
1.5       millert  1218:
1.8       millert  1219:     (void) printf("\t\t%d,\t\t/* count extensions to Booleans */\n",
1.11      millert  1220:                  NUM_BOOLEANS(term) - BOOLCOUNT);
1.8       millert  1221:     (void) printf("\t\t%d,\t\t/* count extensions to Numbers */\n",
1.11      millert  1222:                  NUM_NUMBERS(term) - NUMCOUNT);
1.8       millert  1223:     (void) printf("\t\t%d,\t\t/* count extensions to Strings */\n",
1.11      millert  1224:                  NUM_STRINGS(term) - STRCOUNT);
1.5       millert  1225:
                   1226:     (void) printf("#endif /* NCURSES_XNAMES */\n");
1.20    ! nicm     1227: #else
        !          1228:     (void) term;
1.5       millert  1229: #endif /* NCURSES_XNAMES */
                   1230:     (void) printf("\t%s\n", R_CURL);
                   1231: }
                   1232:
1.11      millert  1233: static int
                   1234: optarg_to_number(void)
                   1235: {
                   1236:     char *temp = 0;
                   1237:     long value = strtol(optarg, &temp, 0);
                   1238:
                   1239:     if (temp == 0 || temp == optarg || *temp != 0) {
                   1240:        fprintf(stderr, "Expected a number, not \"%s\"\n", optarg);
1.20    ! nicm     1241:        ExitProgram(EXIT_FAILURE);
        !          1242:     }
        !          1243:     return (int) value;
        !          1244: }
        !          1245:
        !          1246: static char *
        !          1247: terminal_env(void)
        !          1248: {
        !          1249:     char *terminal;
        !          1250:
        !          1251:     if ((terminal = getenv("TERM")) == 0) {
        !          1252:        (void) fprintf(stderr,
        !          1253:                       "%s: environment variable TERM not set\n",
        !          1254:                       _nc_progname);
1.11      millert  1255:        exit(EXIT_FAILURE);
                   1256:     }
1.20    ! nicm     1257:     return terminal;
1.11      millert  1258: }
                   1259:
1.1       millert  1260: /***************************************************************************
                   1261:  *
                   1262:  * Main sequence
                   1263:  *
                   1264:  ***************************************************************************/
                   1265:
1.8       millert  1266: int
                   1267: main(int argc, char *argv[])
1.1       millert  1268: {
1.8       millert  1269:     /* Avoid "local data >32k" error with mwcc */
                   1270:     /* Also avoid overflowing smaller stacks on systems like AmigaOS */
1.20    ! nicm     1271:     path *tfile = 0;
        !          1272:     char **tname = 0;
        !          1273:     int maxterms;
        !          1274:
        !          1275:     char **myargv;
        !          1276:
        !          1277:     char *firstdir, *restdir;
1.8       millert  1278:     int c, i, len;
                   1279:     bool formatted = FALSE;
                   1280:     bool filecompare = FALSE;
                   1281:     int initdump = 0;
                   1282:     bool init_analyze = FALSE;
1.20    ! nicm     1283:     bool suppress_untranslatable = FALSE;
1.1       millert  1284:
1.8       millert  1285:     /* where is the terminfo database location going to default to? */
                   1286:     restdir = firstdir = 0;
                   1287:
1.20    ! nicm     1288: #if NCURSES_XNAMES
        !          1289:     use_extended_names(FALSE);
        !          1290: #endif
        !          1291:
        !          1292:     _nc_progname = _nc_rootname(argv[0]);
        !          1293:
        !          1294:     /* make sure we have enough space to add two terminal entries */
        !          1295:     myargv = typeCalloc(char *, (size_t) (argc + 3));
        !          1296:     memcpy(myargv, argv, (sizeof(char *) * (size_t) argc));
        !          1297:     argv = myargv;
        !          1298:
        !          1299:     while ((c = getopt(argc,
        !          1300:                       argv,
        !          1301:                       "1A:aB:CcdEeFfGgIiLlnpqR:rs:TtUuVv:w:x")) != -1) {
1.8       millert  1302:        switch (c) {
1.20    ! nicm     1303:        case '1':
        !          1304:            mwidth = 0;
        !          1305:            break;
        !          1306:
        !          1307:        case 'A':
        !          1308:            firstdir = optarg;
        !          1309:            break;
        !          1310:
1.10      millert  1311: #if NCURSES_XNAMES
                   1312:        case 'a':
                   1313:            _nc_disable_period = TRUE;
                   1314:            use_extended_names(TRUE);
                   1315:            break;
                   1316: #endif
1.20    ! nicm     1317:        case 'B':
        !          1318:            restdir = optarg;
        !          1319:            break;
        !          1320:
        !          1321:        case 'C':
        !          1322:            outform = F_TERMCAP;
        !          1323:            tversion = "BSD";
        !          1324:            if (sortmode == S_DEFAULT)
        !          1325:                sortmode = S_TERMCAP;
        !          1326:            break;
        !          1327:
        !          1328:        case 'c':
        !          1329:            compare = C_COMMON;
        !          1330:            break;
        !          1331:
1.8       millert  1332:        case 'd':
                   1333:            compare = C_DIFFERENCE;
                   1334:            break;
1.1       millert  1335:
1.8       millert  1336:        case 'E':
                   1337:            initdump |= 2;
                   1338:            break;
1.1       millert  1339:
1.20    ! nicm     1340:        case 'e':
        !          1341:            initdump |= 1;
1.8       millert  1342:            break;
1.5       millert  1343:
1.20    ! nicm     1344:        case 'F':
        !          1345:            filecompare = TRUE;
1.8       millert  1346:            break;
1.1       millert  1347:
1.8       millert  1348:        case 'f':
                   1349:            formatted = TRUE;
                   1350:            break;
1.1       millert  1351:
1.8       millert  1352:        case 'G':
                   1353:            numbers = 1;
                   1354:            break;
1.1       millert  1355:
1.8       millert  1356:        case 'g':
                   1357:            numbers = -1;
                   1358:            break;
1.1       millert  1359:
1.8       millert  1360:        case 'I':
                   1361:            outform = F_TERMINFO;
                   1362:            if (sortmode == S_DEFAULT)
                   1363:                sortmode = S_VARIABLE;
                   1364:            tversion = 0;
                   1365:            break;
1.1       millert  1366:
1.8       millert  1367:        case 'i':
                   1368:            init_analyze = TRUE;
                   1369:            break;
1.1       millert  1370:
1.8       millert  1371:        case 'L':
                   1372:            outform = F_VARIABLE;
                   1373:            if (sortmode == S_DEFAULT)
                   1374:                sortmode = S_VARIABLE;
                   1375:            break;
1.1       millert  1376:
1.20    ! nicm     1377:        case 'l':
        !          1378:            outform = F_TERMINFO;
        !          1379:            break;
        !          1380:
1.8       millert  1381:        case 'n':
                   1382:            compare = C_NAND;
                   1383:            break;
1.1       millert  1384:
1.8       millert  1385:        case 'p':
                   1386:            ignorepads = TRUE;
                   1387:            break;
1.1       millert  1388:
1.9       millert  1389:        case 'q':
                   1390:            quiet = TRUE;
                   1391:            s_absent = "-";
                   1392:            s_cancel = "@";
                   1393:            bool_sep = ", ";
                   1394:            break;
                   1395:
1.20    ! nicm     1396:        case 'R':
        !          1397:            tversion = optarg;
        !          1398:            break;
        !          1399:
1.8       millert  1400:        case 'r':
                   1401:            tversion = 0;
                   1402:            break;
1.1       millert  1403:
1.8       millert  1404:        case 's':
                   1405:            if (*optarg == 'd')
                   1406:                sortmode = S_NOSORT;
                   1407:            else if (*optarg == 'i')
                   1408:                sortmode = S_TERMINFO;
                   1409:            else if (*optarg == 'l')
                   1410:                sortmode = S_VARIABLE;
                   1411:            else if (*optarg == 'c')
                   1412:                sortmode = S_TERMCAP;
                   1413:            else {
                   1414:                (void) fprintf(stderr,
1.20    ! nicm     1415:                               "%s: unknown sort mode\n",
        !          1416:                               _nc_progname);
        !          1417:                ExitProgram(EXIT_FAILURE);
1.8       millert  1418:            }
                   1419:            break;
1.1       millert  1420:
1.20    ! nicm     1421:        case 'T':
        !          1422:            limited = FALSE;
        !          1423:            break;
        !          1424:
        !          1425: #if NCURSES_XNAMES
        !          1426:        case 't':
        !          1427:            _nc_disable_period = FALSE;
        !          1428:            suppress_untranslatable = TRUE;
        !          1429:            break;
        !          1430: #endif
        !          1431:
        !          1432:        case 'U':
        !          1433:            literal = TRUE;
        !          1434:            break;
        !          1435:
1.8       millert  1436:        case 'u':
                   1437:            compare = C_USEALL;
                   1438:            break;
1.1       millert  1439:
1.20    ! nicm     1440:        case 'V':
        !          1441:            puts(curses_version());
        !          1442:            ExitProgram(EXIT_SUCCESS);
        !          1443:
1.8       millert  1444:        case 'v':
1.11      millert  1445:            itrace = optarg_to_number();
1.8       millert  1446:            set_trace_level(itrace);
                   1447:            break;
1.1       millert  1448:
1.8       millert  1449:        case 'w':
1.11      millert  1450:            mwidth = optarg_to_number();
1.8       millert  1451:            break;
1.1       millert  1452:
1.20    ! nicm     1453: #if NCURSES_XNAMES
        !          1454:        case 'x':
        !          1455:            use_extended_names(TRUE);
1.8       millert  1456:            break;
1.20    ! nicm     1457: #endif
1.1       millert  1458:
1.8       millert  1459:        default:
                   1460:            usage();
                   1461:        }
1.20    ! nicm     1462:     }
        !          1463:
        !          1464:     maxterms = (argc + 2 - optind);
        !          1465:     tfile = typeMalloc(path, maxterms);
        !          1466:     tname = typeCalloc(char *, maxterms);
        !          1467:     entries = typeCalloc(ENTRY, maxterms);
        !          1468:
        !          1469:     if (tfile == 0
        !          1470:        || tname == 0
        !          1471:        || entries == 0) {
        !          1472:        fprintf(stderr, "%s: not enough memory\n", _nc_progname);
        !          1473:        ExitProgram(EXIT_FAILURE);
        !          1474:     }
1.1       millert  1475:
1.8       millert  1476:     /* by default, sort by terminfo name */
                   1477:     if (sortmode == S_DEFAULT)
                   1478:        sortmode = S_TERMINFO;
1.1       millert  1479:
1.8       millert  1480:     /* set up for display */
                   1481:     dump_init(tversion, outform, sortmode, mwidth, itrace, formatted);
1.1       millert  1482:
1.8       millert  1483:     /* make sure we have at least one terminal name to work with */
                   1484:     if (optind >= argc)
1.20    ! nicm     1485:        argv[argc++] = terminal_env();
1.1       millert  1486:
1.8       millert  1487:     /* if user is after a comparison, make sure we have two entries */
                   1488:     if (compare != C_DEFAULT && optind >= argc - 1)
1.20    ! nicm     1489:        argv[argc++] = terminal_env();
1.1       millert  1490:
1.8       millert  1491:     /* exactly two terminal names with no options means do -d */
                   1492:     if (argc - optind == 2 && compare == C_DEFAULT)
                   1493:        compare = C_DIFFERENCE;
1.1       millert  1494:
1.8       millert  1495:     if (!filecompare) {
                   1496:        /* grab the entries */
                   1497:        termcount = 0;
                   1498:        for (; optind < argc; optind++) {
1.20    ! nicm     1499:            const char *directory = termcount ? restdir : firstdir;
        !          1500:            int status;
1.8       millert  1501:
1.20    ! nicm     1502:            tname[termcount] = argv[optind];
1.8       millert  1503:
1.20    ! nicm     1504:            if (directory) {
        !          1505: #if USE_DATABASE
        !          1506: #if MIXEDCASE_FILENAMES
        !          1507: #define LEAF_FMT "%c"
        !          1508: #else
        !          1509: #define LEAF_FMT "%02x"
        !          1510: #endif
        !          1511:                (void) snprintf(tfile[termcount], sizeof (path),
        !          1512:                               "%s/" LEAF_FMT "/%s", directory,
        !          1513:                               UChar(*argv[optind]), argv[optind]);
        !          1514:                if (itrace)
        !          1515:                    (void) fprintf(stderr,
        !          1516:                                   "%s: reading entry %s from file %s\n",
        !          1517:                                   _nc_progname,
        !          1518:                                   argv[optind], tfile[termcount]);
        !          1519:
        !          1520:                status = _nc_read_file_entry(tfile[termcount],
        !          1521:                                             &entries[termcount].tterm);
        !          1522: #else
        !          1523:                (void) fprintf(stderr, "%s: terminfo files not supported\n",
        !          1524:                               _nc_progname);
        !          1525:                ExitProgram(EXIT_FAILURE);
        !          1526: #endif
        !          1527:            } else {
        !          1528:                if (itrace)
        !          1529:                    (void) fprintf(stderr,
        !          1530:                                   "%s: reading entry %s from database\n",
        !          1531:                                   _nc_progname,
        !          1532:                                   tname[termcount]);
        !          1533:
        !          1534:                status = _nc_read_entry(tname[termcount],
        !          1535:                                        tfile[termcount],
        !          1536:                                        &entries[termcount].tterm);
        !          1537:                directory = TERMINFO;   /* for error message */
        !          1538:            }
1.1       millert  1539:
1.20    ! nicm     1540:            if (status <= 0) {
        !          1541:                (void) fprintf(stderr,
        !          1542:                               "%s: couldn't open terminfo file %s.\n",
        !          1543:                               _nc_progname,
        !          1544:                               tfile[termcount]);
        !          1545:                ExitProgram(EXIT_FAILURE);
1.1       millert  1546:            }
1.20    ! nicm     1547:            repair_acsc(&entries[termcount].tterm);
        !          1548:            termcount++;
1.8       millert  1549:        }
1.1       millert  1550:
1.2       millert  1551: #if NCURSES_XNAMES
1.8       millert  1552:        if (termcount > 1)
1.9       millert  1553:            _nc_align_termtype(&entries[0].tterm, &entries[1].tterm);
1.2       millert  1554: #endif
                   1555:
1.8       millert  1556:        /* dump as C initializer for the terminal type */
                   1557:        if (initdump) {
                   1558:            if (initdump & 1)
1.9       millert  1559:                dump_termtype(&entries[0].tterm);
1.8       millert  1560:            if (initdump & 2)
1.9       millert  1561:                dump_initializers(&entries[0].tterm);
1.8       millert  1562:        }
1.1       millert  1563:
1.8       millert  1564:        /* analyze the init strings */
1.20    ! nicm     1565:        else if (init_analyze) {
1.1       millert  1566: #undef CUR
1.9       millert  1567: #define CUR    entries[0].tterm.
                   1568:            analyze_string("is1", init_1string, &entries[0].tterm);
                   1569:            analyze_string("is2", init_2string, &entries[0].tterm);
                   1570:            analyze_string("is3", init_3string, &entries[0].tterm);
                   1571:            analyze_string("rs1", reset_1string, &entries[0].tterm);
                   1572:            analyze_string("rs2", reset_2string, &entries[0].tterm);
                   1573:            analyze_string("rs3", reset_3string, &entries[0].tterm);
                   1574:            analyze_string("smcup", enter_ca_mode, &entries[0].tterm);
                   1575:            analyze_string("rmcup", exit_ca_mode, &entries[0].tterm);
1.1       millert  1576: #undef CUR
1.20    ! nicm     1577:        } else {
1.1       millert  1578:
1.20    ! nicm     1579:            /*
        !          1580:             * Here's where the real work gets done
        !          1581:             */
        !          1582:            switch (compare) {
        !          1583:            case C_DEFAULT:
        !          1584:                if (itrace)
        !          1585:                    (void) fprintf(stderr,
        !          1586:                                   "%s: about to dump %s\n",
        !          1587:                                   _nc_progname,
        !          1588:                                   tname[0]);
        !          1589:                (void) printf("#\tReconstructed via infocmp from file: %s\n",
        !          1590:                              tfile[0]);
        !          1591:                dump_entry(&entries[0].tterm,
        !          1592:                           suppress_untranslatable,
        !          1593:                           limited,
        !          1594:                           numbers,
        !          1595:                           NULL);
        !          1596:                len = show_entry();
        !          1597:                if (itrace)
        !          1598:                    (void) fprintf(stderr, "%s: length %d\n", _nc_progname, len);
        !          1599:                break;
1.1       millert  1600:
1.20    ! nicm     1601:            case C_DIFFERENCE:
        !          1602:                if (itrace)
        !          1603:                    (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname);
        !          1604:                (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
        !          1605:                compare_entry(compare_predicate, &entries->tterm, quiet);
        !          1606:                break;
1.1       millert  1607:
1.20    ! nicm     1608:            case C_COMMON:
        !          1609:                if (itrace)
        !          1610:                    (void) fprintf(stderr,
        !          1611:                                   "%s: dumping common capabilities\n",
        !          1612:                                   _nc_progname);
        !          1613:                (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
        !          1614:                compare_entry(compare_predicate, &entries->tterm, quiet);
        !          1615:                break;
1.1       millert  1616:
1.20    ! nicm     1617:            case C_NAND:
        !          1618:                if (itrace)
        !          1619:                    (void) fprintf(stderr,
        !          1620:                                   "%s: dumping differences\n",
        !          1621:                                   _nc_progname);
        !          1622:                (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
        !          1623:                compare_entry(compare_predicate, &entries->tterm, quiet);
        !          1624:                break;
1.1       millert  1625:
1.20    ! nicm     1626:            case C_USEALL:
        !          1627:                if (itrace)
        !          1628:                    (void) fprintf(stderr, "%s: dumping use entry\n", _nc_progname);
        !          1629:                dump_entry(&entries[0].tterm,
        !          1630:                           suppress_untranslatable,
        !          1631:                           limited,
        !          1632:                           numbers,
        !          1633:                           use_predicate);
        !          1634:                for (i = 1; i < termcount; i++)
        !          1635:                    dump_uses(tname[i], !(outform == F_TERMCAP
        !          1636:                                          || outform == F_TCONVERR));
        !          1637:                len = show_entry();
        !          1638:                if (itrace)
        !          1639:                    (void) fprintf(stderr, "%s: length %d\n", _nc_progname, len);
        !          1640:                break;
        !          1641:            }
1.1       millert  1642:        }
1.8       millert  1643:     } else if (compare == C_USEALL)
                   1644:        (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n");
                   1645:     else if (compare == C_DEFAULT)
                   1646:        (void) fprintf(stderr, "Use `tic -[CI] <file>' for this.\n");
                   1647:     else if (argc - optind != 2)
                   1648:        (void) fprintf(stderr,
1.11      millert  1649:                       "File comparison needs exactly two file arguments.\n");
1.8       millert  1650:     else
                   1651:        file_comparison(argc - optind, argv + optind);
1.1       millert  1652:
1.20    ! nicm     1653: #if NO_LEAKS
        !          1654:     free(myargv);
        !          1655:     free(tfile);
        !          1656:     free(tname);
        !          1657: #endif
1.8       millert  1658:     ExitProgram(EXIT_SUCCESS);
1.1       millert  1659: }
                   1660:
                   1661: /* infocmp.c ends here */