[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.1

1.1     ! millert     1: /*     $OpenBSD$       */
        !             2:
        !             3: /****************************************************************************
        !             4:  * Copyright (c) 1998 Free Software Foundation, Inc.                        *
        !             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>                         *
        !            34:  ****************************************************************************/
        !            35:
        !            36:
        !            37: /*
        !            38:  *     infocmp.c -- decompile an entry, or compare two entries
        !            39:  *             written by Eric S. Raymond
        !            40:  */
        !            41:
        !            42: #include <progs.priv.h>
        !            43:
        !            44: #include <term_entry.h>
        !            45: #include <dump_entry.h>
        !            46:
        !            47: MODULE_ID("$From: infocmp.c,v 1.38 1998/10/17 21:32:36 tom Exp $")
        !            48:
        !            49: #define L_CURL "{"
        !            50: #define R_CURL "}"
        !            51:
        !            52: #define MAXTERMS       32      /* max # terminal arguments we can handle */
        !            53:
        !            54: const char *_nc_progname = "infocmp";
        !            55:
        !            56: typedef char   path[PATH_MAX];
        !            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:
        !            65: static char *tname[MAXTERMS];  /* terminal type names */
        !            66: static TERMTYPE term[MAXTERMS];        /* terminfo entries */
        !            67: static int termcount;          /* count of terminal entries */
        !            68:
        !            69: static const char *tversion;   /* terminfo version selected */
        !            70: static bool numbers = TRUE;    /* format "%'char'" to "%{number}" */
        !            71: static int outform;            /* output format */
        !            72: static int sortmode;           /* sort_mode */
        !            73: static int itrace;             /* trace flag for debugging */
        !            74: static int mwidth = 60;
        !            75:
        !            76: /* main comparison mode */
        !            77: static int compare;
        !            78: #define C_DEFAULT      0       /* don't force comparison mode */
        !            79: #define C_DIFFERENCE   1       /* list differences between two terminals */
        !            80: #define C_COMMON       2       /* list common capabilities */
        !            81: #define C_NAND         3       /* list capabilities in neither terminal */
        !            82: #define C_USEALL       4       /* generate relative use-form entry */
        !            83: static bool ignorepads;                /* ignore pad prefixes when diffing */
        !            84:
        !            85: #if NO_LEAKS
        !            86: #undef ExitProgram
        !            87: static void ExitProgram(int code) GCC_NORETURN;
        !            88: static void ExitProgram(int code)
        !            89: {
        !            90:        while (termcount-- > 0)
        !            91:                _nc_free_termtype(&term[termcount], FALSE);
        !            92:        _nc_leaks_dump_entry();
        !            93:        _nc_free_and_exit(code);
        !            94: }
        !            95: #endif
        !            96:
        !            97: static char *canonical_name(char *ptr, char *buf)
        !            98: /* extract the terminal type's primary name */
        !            99: {
        !           100:     char       *bp;
        !           101:
        !           102:     (void) strcpy(buf, ptr);
        !           103:     if ((bp = strchr(buf, '|')) != (char *)NULL)
        !           104:        *bp = '\0';
        !           105:
        !           106:     return(buf);
        !           107: }
        !           108:
        !           109: /***************************************************************************
        !           110:  *
        !           111:  * Predicates for dump function
        !           112:  *
        !           113:  ***************************************************************************/
        !           114:
        !           115: static int capcmp(const char *s, const char *t)
        !           116: /* capability comparison function */
        !           117: {
        !           118:     if (!VALID_STRING(s) && !VALID_STRING(t))
        !           119:        return(0);
        !           120:     else if (!VALID_STRING(s) || !VALID_STRING(t))
        !           121:        return(1);
        !           122:
        !           123:     if (ignorepads)
        !           124:        return(_nc_capcmp(s, t));
        !           125:     else
        !           126:        return(strcmp(s, t));
        !           127: }
        !           128:
        !           129: static int use_predicate(int type, int idx)
        !           130: /* predicate function to use for use decompilation */
        !           131: {
        !           132:        TERMTYPE *tp;
        !           133:
        !           134:        switch(type)
        !           135:        {
        !           136:        case BOOLEAN: {
        !           137:                int is_set = FALSE;
        !           138:
        !           139:                /*
        !           140:                 * This assumes that multiple use entries are supposed
        !           141:                 * to contribute the logical or of their boolean capabilities.
        !           142:                 * This is true if we take the semantics of multiple uses to
        !           143:                 * be 'each capability gets the first non-default value found
        !           144:                 * in the sequence of use entries'.
        !           145:                 */
        !           146:                for (tp = &term[1]; tp < term + termcount; tp++)
        !           147:                        if (tp->Booleans[idx]) {
        !           148:                                is_set = TRUE;
        !           149:                                break;
        !           150:                        }
        !           151:                        if (is_set != term->Booleans[idx])
        !           152:                                return(!is_set);
        !           153:                        else
        !           154:                                return(FAIL);
        !           155:                }
        !           156:
        !           157:        case NUMBER: {
        !           158:                int     value = ABSENT_NUMERIC;
        !           159:
        !           160:                /*
        !           161:                 * We take the semantics of multiple uses to be 'each
        !           162:                 * capability gets the first non-default value found
        !           163:                 * in the sequence of use entries'.
        !           164:                 */
        !           165:                for (tp = &term[1]; tp < term + termcount; tp++)
        !           166:                        if (tp->Numbers[idx] >= 0) {
        !           167:                                value = tp->Numbers[idx];
        !           168:                                break;
        !           169:                        }
        !           170:
        !           171:                if (value != term->Numbers[idx])
        !           172:                        return(value != ABSENT_NUMERIC);
        !           173:                else
        !           174:                        return(FAIL);
        !           175:                }
        !           176:
        !           177:        case STRING: {
        !           178:                char *termstr, *usestr = ABSENT_STRING;
        !           179:
        !           180:                termstr = term->Strings[idx];
        !           181:
        !           182:                /*
        !           183:                 * We take the semantics of multiple uses to be 'each
        !           184:                 * capability gets the first non-default value found
        !           185:                 * in the sequence of use entries'.
        !           186:                 */
        !           187:                for (tp = &term[1]; tp < term + termcount; tp++)
        !           188:                        if (tp->Strings[idx])
        !           189:                        {
        !           190:                                usestr = tp->Strings[idx];
        !           191:                                break;
        !           192:                        }
        !           193:
        !           194:                if (usestr == ABSENT_STRING && termstr == ABSENT_STRING)
        !           195:                        return(FAIL);
        !           196:                else if (!usestr || !termstr || capcmp(usestr, termstr))
        !           197:                        return(TRUE);
        !           198:                else
        !           199:                        return(FAIL);
        !           200:            }
        !           201:        }
        !           202:
        !           203:        return(FALSE);  /* pacify compiler */
        !           204: }
        !           205:
        !           206: static bool entryeq(TERMTYPE *t1, TERMTYPE *t2)
        !           207: /* are two terminal types equal */
        !           208: {
        !           209:     int        i;
        !           210:
        !           211:     for (i = 0; i < BOOLCOUNT; i++)
        !           212:        if (t1->Booleans[i] != t2->Booleans[i])
        !           213:            return(FALSE);
        !           214:
        !           215:     for (i = 0; i < NUMCOUNT; i++)
        !           216:        if (t1->Numbers[i] != t2->Numbers[i])
        !           217:            return(FALSE);
        !           218:
        !           219:     for (i = 0; i < STRCOUNT; i++)
        !           220:        if (capcmp(t1->Strings[i], t2->Strings[i]))
        !           221:            return(FALSE);
        !           222:
        !           223:     return(TRUE);
        !           224: }
        !           225:
        !           226: #define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers)
        !           227:
        !           228: static void compare_predicate(int type, int idx, const char *name)
        !           229: /* predicate function to use for entry difference reports */
        !           230: {
        !           231:        register TERMTYPE *t1 = &term[0];
        !           232:        register TERMTYPE *t2 = &term[1];
        !           233:        char *s1, *s2;
        !           234:
        !           235:        switch(type)
        !           236:        {
        !           237:        case BOOLEAN:
        !           238:                switch(compare)
        !           239:                {
        !           240:                case C_DIFFERENCE:
        !           241:                        if (t1->Booleans[idx] != t2->Booleans[idx])
        !           242:                        (void) printf("\t%s: %c:%c.\n",
        !           243:                                          name,
        !           244:                                          t1->Booleans[idx] ? 'T' : 'F',
        !           245:                                          t2->Booleans[idx] ? 'T' : 'F');
        !           246:                        break;
        !           247:
        !           248:                case C_COMMON:
        !           249:                        if (t1->Booleans[idx] && t2->Booleans[idx])
        !           250:                        (void) printf("\t%s= T.\n", name);
        !           251:                        break;
        !           252:
        !           253:                case C_NAND:
        !           254:                        if (!t1->Booleans[idx] && !t2->Booleans[idx])
        !           255:                        (void) printf("\t!%s.\n", name);
        !           256:                        break;
        !           257:                }
        !           258:                break;
        !           259:
        !           260:        case NUMBER:
        !           261:                switch(compare)
        !           262:                {
        !           263:                case C_DIFFERENCE:
        !           264:                        if (t1->Numbers[idx] != t2->Numbers[idx])
        !           265:                        (void) printf("\t%s: %d:%d.\n",
        !           266:                                          name, t1->Numbers[idx], t2->Numbers[idx]);
        !           267:                        break;
        !           268:
        !           269:                case C_COMMON:
        !           270:                        if (t1->Numbers[idx]!=-1 && t2->Numbers[idx]!=-1
        !           271:                                && t1->Numbers[idx] == t2->Numbers[idx])
        !           272:                        (void) printf("\t%s= %d.\n", name, t1->Numbers[idx]);
        !           273:                        break;
        !           274:
        !           275:                case C_NAND:
        !           276:                        if (t1->Numbers[idx]==-1 && t2->Numbers[idx] == -1)
        !           277:                        (void) printf("\t!%s.\n", name);
        !           278:                        break;
        !           279:                }
        !           280:        break;
        !           281:
        !           282:        case STRING:
        !           283:                s1 = t1->Strings[idx];
        !           284:                s2 = t2->Strings[idx];
        !           285:                switch(compare)
        !           286:                {
        !           287:                case C_DIFFERENCE:
        !           288:                        if (capcmp(s1, s2))
        !           289:                        {
        !           290:                                char    buf1[BUFSIZ], buf2[BUFSIZ];
        !           291:
        !           292:                                if (s1 == (char *)NULL)
        !           293:                                        (void) strcpy(buf1, "NULL");
        !           294:                                else
        !           295:                                {
        !           296:                                        (void) strcpy(buf1, "'");
        !           297:                                        (void) strcat(buf1, TIC_EXPAND(s1));
        !           298:                                        (void) strcat(buf1, "'");
        !           299:                                }
        !           300:
        !           301:                                if (s2 == (char *)NULL)
        !           302:                                        (void) strcpy(buf2, "NULL");
        !           303:                                else
        !           304:                                {
        !           305:                                        (void) strcpy(buf2, "'");
        !           306:                                        (void) strcat(buf2, TIC_EXPAND(s2));
        !           307:                                        (void) strcat(buf2, "'");
        !           308:                                }
        !           309:
        !           310:                                if (strcmp(buf1, buf2))
        !           311:                                        (void) printf("\t%s: %s, %s.\n",
        !           312:                                                      name, buf1, buf2);
        !           313:                        }
        !           314:                        break;
        !           315:
        !           316:                case C_COMMON:
        !           317:                        if (s1 && s2 && !capcmp(s1, s2))
        !           318:                                (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1));
        !           319:                        break;
        !           320:
        !           321:                case C_NAND:
        !           322:                        if (!s1 && !s2)
        !           323:                                (void) printf("\t!%s.\n", name);
        !           324:                        break;
        !           325:                }
        !           326:                break;
        !           327:        }
        !           328:
        !           329: }
        !           330:
        !           331: /***************************************************************************
        !           332:  *
        !           333:  * Init string analysis
        !           334:  *
        !           335:  ***************************************************************************/
        !           336:
        !           337: typedef struct {const char *from; const char *to;} assoc;
        !           338:
        !           339: static const assoc std_caps[] =
        !           340: {
        !           341:     /* these are specified by X.364 and iBCS2 */
        !           342:     {"\033c",  "RIS"},         /* full reset */
        !           343:     {"\0337",  "SC"},          /* save cursor */
        !           344:     {"\0338",  "RC"},          /* restore cursor */
        !           345:     {"\033[r", "RSR"},         /* not an X.364 mnemonic */
        !           346:     {"\033[m", "SGR0"},        /* not an X.364 mnemonic */
        !           347:     {"\033[2J",        "ED2"},         /* clear page */
        !           348:
        !           349:     /* this group is specified by ISO 2022 */
        !           350:     {"\033(0", "ISO DEC G0"},  /* enable DEC graphics for G0 */
        !           351:     {"\033(A", "ISO UK G0"},   /* enable UK chars for G0 */
        !           352:     {"\033(B", "ISO US G0"},   /* enable US chars for G0 */
        !           353:     {"\033)0", "ISO DEC G1"},  /* enable DEC graphics for G1 */
        !           354:     {"\033)A", "ISO UK G1"},   /* enable UK chars for G1 */
        !           355:     {"\033)B", "ISO US G1"},   /* enable US chars for G1 */
        !           356:
        !           357:     /* these are DEC private modes widely supported by emulators */
        !           358:     {"\033=",  "DECPAM"},      /* application keypad mode */
        !           359:     {"\033>",  "DECPNM"},      /* normal keypad mode */
        !           360:     {"\033<",  "DECANSI"},     /* enter ANSI mode */
        !           361:
        !           362:     { (char *)0, (char *)0}
        !           363: };
        !           364:
        !           365: static const assoc private_modes[] =
        !           366: /* DEC \E[ ... [hl] modes recognized by many emulators */
        !           367: {
        !           368:     {"1",      "CKM"},         /* application cursor keys */
        !           369:     {"2",      "ANM"},         /* set VT52 mode */
        !           370:     {"3",      "COLM"},        /* 132-column mode */
        !           371:     {"4",      "SCLM"},        /* smooth scroll */
        !           372:     {"5",      "SCNM"},        /* reverse video mode */
        !           373:     {"6",      "OM"},          /* origin mode */
        !           374:     {"7",      "AWM"},         /* wraparound mode */
        !           375:     {"8",      "ARM"},         /* auto-repeat mode */
        !           376:     {(char *)0, (char *)0}
        !           377: };
        !           378:
        !           379: static const assoc ecma_highlights[] =
        !           380: /* recognize ECMA attribute sequences */
        !           381: {
        !           382:     {"0",      "NORMAL"},      /* normal */
        !           383:     {"1",      "+BOLD"},       /* bold on */
        !           384:     {"2",      "+DIM"},        /* dim on */
        !           385:     {"3",      "+ITALIC"},     /* italic on */
        !           386:     {"4",      "+UNDERLINE"},  /* underline on */
        !           387:     {"5",      "+BLINK"},      /* blink on */
        !           388:     {"6",      "+FASTBLINK"},  /* fastblink on */
        !           389:     {"7",      "+REVERSE"},    /* reverse on */
        !           390:     {"8",      "+INVISIBLE"},  /* invisible on */
        !           391:     {"9",      "+DELETED"},    /* deleted on */
        !           392:     {"10",     "MAIN-FONT"},   /* select primary font */
        !           393:     {"11",     "ALT-FONT-1"},  /* select alternate font 1 */
        !           394:     {"12",     "ALT-FONT-2"},  /* select alternate font 2 */
        !           395:     {"13",     "ALT-FONT-3"},  /* select alternate font 3 */
        !           396:     {"14",     "ALT-FONT-4"},  /* select alternate font 4 */
        !           397:     {"15",     "ALT-FONT-5"},  /* select alternate font 5 */
        !           398:     {"16",     "ALT-FONT-6"},  /* select alternate font 6 */
        !           399:     {"17",     "ALT-FONT-7"},  /* select alternate font 7 */
        !           400:     {"18",     "ALT-FONT-1"},  /* select alternate font 1 */
        !           401:     {"19",     "ALT-FONT-1"},  /* select alternate font 1 */
        !           402:     {"20",     "FRAKTUR"},     /* Fraktur font */
        !           403:     {"21",     "DOUBLEUNDER"}, /* double underline */
        !           404:     {"22",     "-DIM"},        /* dim off */
        !           405:     {"23",     "-ITALIC"},     /* italic off */
        !           406:     {"24",     "-UNDERLINE"},  /* underline off */
        !           407:     {"25",     "-BLINK"},      /* blink off */
        !           408:     {"26",     "-FASTBLINK"},  /* fastblink off */
        !           409:     {"27",     "-REVERSE"},    /* reverse off */
        !           410:     {"28",     "-INVISIBLE"},  /* invisible off */
        !           411:     {"29",     "-DELETED"},    /* deleted off */
        !           412:     {(char *)0, (char *)0}
        !           413: };
        !           414:
        !           415: static void analyze_string(const char *name, const char *cap, TERMTYPE *tp)
        !           416: {
        !           417:     char       buf[MAX_TERMINFO_LENGTH];
        !           418:     char       buf2[MAX_TERMINFO_LENGTH];
        !           419:     const char *sp, *ep;
        !           420:     const assoc        *ap;
        !           421:
        !           422:     if (cap == ABSENT_STRING || cap == CANCELLED_STRING)
        !           423:        return;
        !           424:     (void) printf("%s: ", name);
        !           425:
        !           426:     buf[0] = '\0';
        !           427:     for (sp = cap; *sp; sp++)
        !           428:     {
        !           429:        int     i;
        !           430:        size_t  len = 0;
        !           431:        const char *expansion = 0;
        !           432:
        !           433:        /* first, check other capabilities in this entry */
        !           434:        for (i = 0; i < STRCOUNT; i++)
        !           435:        {
        !           436:            char        *cp = tp->Strings[i];
        !           437:
        !           438:            /* don't use soft-key capabilities */
        !           439:            if (strnames[i][0] == 'k' && strnames[i][0] == 'f')
        !           440:                continue;
        !           441:
        !           442:
        !           443:            if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp != cap)
        !           444:            {
        !           445:                len = strlen(cp);
        !           446:                (void) strncpy(buf2, sp, len);
        !           447:                buf2[len] = '\0';
        !           448:
        !           449:                if (_nc_capcmp(cp, buf2))
        !           450:                    continue;
        !           451:
        !           452: #define ISRS(s)        (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2))
        !           453:                /*
        !           454:                 * Theoretically we just passed the test for translation
        !           455:                 * (equality once the padding is stripped).  However, there
        !           456:                 * are a few more hoops that need to be jumped so that
        !           457:                 * identical pairs of initialization and reset strings
        !           458:                 * don't just refer to each other.
        !           459:                 */
        !           460:                if (ISRS(name) || ISRS(strnames[i]))
        !           461:                    if (cap < cp)
        !           462:                        continue;
        !           463: #undef ISRS
        !           464:
        !           465:                expansion = strnames[i];
        !           466:                break;
        !           467:            }
        !           468:        }
        !           469:
        !           470:        /* now check the standard capabilities */
        !           471:        if (!expansion)
        !           472:            for (ap = std_caps; ap->from; ap++)
        !           473:            {
        !           474:                len = strlen(ap->from);
        !           475:
        !           476:                if (strncmp(ap->from, sp, len) == 0)
        !           477:                {
        !           478:                    expansion = ap->to;
        !           479:                    break;
        !           480:                }
        !           481:            }
        !           482:
        !           483:        /* now check for private-mode sequences */
        !           484:        if (!expansion
        !           485:                    && sp[0] == '\033' && sp[1] == '[' && sp[2] == '?'
        !           486:                    && (len = strspn(sp + 3, "0123456789;"))
        !           487:                    && ((sp[3 + len] == 'h') || (sp[3 + len] == 'l')))
        !           488:        {
        !           489:            char        buf3[MAX_TERMINFO_LENGTH];
        !           490:
        !           491:            (void) strcpy(buf2, (sp[3 + len] == 'h') ? "DEC+" : "DEC-");
        !           492:            (void) strncpy(buf3, sp + 3, len);
        !           493:            len += 4;
        !           494:            buf3[len] = '\0';
        !           495:
        !           496:            ep = strtok(buf3, ";");
        !           497:            do {
        !           498:                   bool found = FALSE;
        !           499:
        !           500:                   for (ap = private_modes; ap->from; ap++)
        !           501:                   {
        !           502:                       size_t tlen = strlen(ap->from);
        !           503:
        !           504:                       if (strncmp(ap->from, ep, tlen) == 0)
        !           505:                       {
        !           506:                           (void) strcat(buf2, ap->to);
        !           507:                           found = TRUE;
        !           508:                           break;
        !           509:                       }
        !           510:                   }
        !           511:
        !           512:                   if (!found)
        !           513:                       (void) strcat(buf2, ep);
        !           514:                   (void) strcat(buf2, ";");
        !           515:               } while
        !           516:                   ((ep = strtok((char *)NULL, ";")));
        !           517:            buf2[strlen(buf2) - 1] = '\0';
        !           518:            expansion = buf2;
        !           519:        }
        !           520:
        !           521:        /* now check for ECMA highlight sequences */
        !           522:        if (!expansion
        !           523:                    && sp[0] == '\033' && sp[1] == '['
        !           524:                    && (len = strspn(sp + 2, "0123456789;"))
        !           525:                    && sp[2 + len] == 'm')
        !           526:        {
        !           527:            char        buf3[MAX_TERMINFO_LENGTH];
        !           528:
        !           529:            (void) strcpy(buf2, "SGR:");
        !           530:            (void) strncpy(buf3, sp + 2, len);
        !           531:            len += 3;
        !           532:            buf3[len] = '\0';
        !           533:
        !           534:            ep = strtok(buf3, ";");
        !           535:            do {
        !           536:                   bool found = FALSE;
        !           537:
        !           538:                   for (ap = ecma_highlights; ap->from; ap++)
        !           539:                   {
        !           540:                       size_t tlen = strlen(ap->from);
        !           541:
        !           542:                       if (strncmp(ap->from, ep, tlen) == 0)
        !           543:                       {
        !           544:                           (void) strcat(buf2, ap->to);
        !           545:                           found = TRUE;
        !           546:                           break;
        !           547:                       }
        !           548:                   }
        !           549:
        !           550:                   if (!found)
        !           551:                       (void) strcat(buf2, ep);
        !           552:                   (void) strcat(buf2, ";");
        !           553:               } while
        !           554:                   ((ep = strtok((char *)NULL, ";")));
        !           555:
        !           556:            buf2[strlen(buf2) - 1] = '\0';
        !           557:            expansion = buf2;
        !           558:        }
        !           559:        /* now check for scroll region reset */
        !           560:        if (!expansion)
        !           561:        {
        !           562:            (void) sprintf(buf2, "\033[1;%dr", tp->Numbers[2]);
        !           563:            len = strlen(buf2);
        !           564:            if (strncmp(buf2, sp, len) == 0)
        !           565:                expansion = "RSR";
        !           566:        }
        !           567:
        !           568:        /* now check for home-down */
        !           569:        if (!expansion)
        !           570:        {
        !           571:            (void) sprintf(buf2, "\033[%d;1H", tp->Numbers[2]);
        !           572:            len = strlen(buf2);
        !           573:            if (strncmp(buf2, sp, len) == 0)
        !           574:                    expansion = "LL";
        !           575:        }
        !           576:
        !           577:        /* now look at the expansion we got, if any */
        !           578:        if (expansion)
        !           579:        {
        !           580:            (void) sprintf(buf + strlen(buf), "{%s}", expansion);
        !           581:            sp += len - 1;
        !           582:            continue;
        !           583:        }
        !           584:        else
        !           585:        {
        !           586:            /* couldn't match anything */
        !           587:            buf2[0] = *sp;
        !           588:            buf2[1] = '\0';
        !           589:            (void) strcat(buf, TIC_EXPAND(buf2));
        !           590:        }
        !           591:     }
        !           592:     (void) printf("%s\n", buf);
        !           593: }
        !           594:
        !           595: /***************************************************************************
        !           596:  *
        !           597:  * File comparison
        !           598:  *
        !           599:  ***************************************************************************/
        !           600:
        !           601: static void file_comparison(int argc, char *argv[])
        !           602: {
        !           603: #define MAXCOMPARE     2
        !           604:     /* someday we may allow comparisons on more files */
        !           605:     int        filecount = 0;
        !           606:     ENTRY      *heads[MAXCOMPARE];
        !           607:     ENTRY      *tails[MAXCOMPARE];
        !           608:     ENTRY      *qp, *rp;
        !           609:     int                i, n;
        !           610:
        !           611:     dump_init((char *)NULL, F_LITERAL, S_TERMINFO, 0, itrace, FALSE);
        !           612:
        !           613:     for (n = 0; n < argc && n < MAXCOMPARE; n++)
        !           614:     {
        !           615:        if (freopen(argv[n], "r", stdin) == NULL)
        !           616:            _nc_err_abort("Can't open %s", argv[n]);
        !           617:
        !           618:        _nc_head = _nc_tail = (ENTRY *)NULL;
        !           619:
        !           620:        /* parse entries out of the source file */
        !           621:        _nc_set_source(argv[n]);
        !           622:        _nc_read_entry_source(stdin, NULL, TRUE, FALSE, NULLHOOK);
        !           623:
        !           624:        if (itrace)
        !           625:            (void) fprintf(stderr, "Resolving file %d...\n", n-0);
        !           626:
        !           627:        /* do use resolution */
        !           628:        if (!_nc_resolve_uses())
        !           629:        {
        !           630:            (void) fprintf(stderr,
        !           631:                           "There are unresolved use entries in %s:\n",
        !           632:                           argv[n]);
        !           633:            for_entry_list(qp)
        !           634:                if (qp->nuses)
        !           635:                {
        !           636:                    (void) fputs(qp->tterm.term_names, stderr);
        !           637:                    (void) fputc('\n', stderr);
        !           638:                }
        !           639:            exit(EXIT_FAILURE);
        !           640:        }
        !           641:
        !           642:        heads[filecount] = _nc_head;
        !           643:        tails[filecount] = _nc_tail;
        !           644:        filecount++;
        !           645:     }
        !           646:
        !           647:     /* OK, all entries are in core.  Ready to do the comparison */
        !           648:     if (itrace)
        !           649:        (void) fprintf(stderr, "Entries are now in core...\n");
        !           650:
        !           651:     /*
        !           652:      * The entry-matching loop.  We're not using the use[]
        !           653:      * slots any more (they got zeroed out by resolve_uses) so
        !           654:      * we stash each entry's matches in the other file there.
        !           655:      * Sigh, this is intrinsically quadratic.
        !           656:      */
        !           657:     for (qp = heads[0]; qp; qp = qp->next)
        !           658:     {
        !           659:        for (rp = heads[1]; rp; rp = rp->next)
        !           660:            if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names))
        !           661:            {
        !           662:                /*
        !           663:                 * This is why the uses structure parent element is
        !           664:                 * (void *) -- so we can have either (char *) for
        !           665:                 * names or entry structure pointers in them and still
        !           666:                 * be type-safe.
        !           667:                 */
        !           668:                if (qp->nuses < MAX_USES)
        !           669:                    qp->uses[qp->nuses].parent = (void *)rp;
        !           670:                qp->nuses++;
        !           671:
        !           672:                if (rp->nuses < MAX_USES)
        !           673:                    rp->uses[rp->nuses].parent = (void *)qp;
        !           674:                rp->nuses++;
        !           675:            }
        !           676:     }
        !           677:
        !           678:     /* now we have two circular lists with crosslinks */
        !           679:     if (itrace)
        !           680:        (void) fprintf(stderr, "Name matches are done...\n");
        !           681:
        !           682:     for (qp = heads[0]; qp; qp = qp->next)
        !           683:        if (qp->nuses > 1)
        !           684:        {
        !           685:            (void) fprintf(stderr,
        !           686:                           "%s in file 1 (%s) has %d matches in file 2 (%s):\n",
        !           687:                           _nc_first_name(qp->tterm.term_names),
        !           688:                           argv[0],
        !           689:                           qp->nuses,
        !           690:                           argv[1]);
        !           691:            for (i = 0; i < qp->nuses; i++)
        !           692:                (void) fprintf(stderr,
        !           693:                               "\t%s\n",
        !           694:                               _nc_first_name(((ENTRY *)qp->uses[i].parent)->tterm.term_names));
        !           695:        }
        !           696:     for (rp = heads[1]; rp; rp = rp->next)
        !           697:        if (rp->nuses > 1)
        !           698:        {
        !           699:            (void) fprintf(stderr,
        !           700:                           "%s in file 2 (%s) has %d matches in file 1 (%s):\n",
        !           701:                           _nc_first_name(rp->tterm.term_names),
        !           702:                           argv[1],
        !           703:                           rp->nuses,
        !           704:                           argv[0]);
        !           705:            for (i = 0; i < rp->nuses; i++)
        !           706:                (void) fprintf(stderr,
        !           707:                               "\t%s\n",
        !           708:                               _nc_first_name(((ENTRY *)rp->uses[i].parent)->tterm.term_names));
        !           709:        }
        !           710:
        !           711:     (void) printf("In file 1 (%s) only:\n", argv[0]);
        !           712:     for (qp = heads[0]; qp; qp = qp->next)
        !           713:        if (qp->nuses == 0)
        !           714:            (void) printf("\t%s\n",
        !           715:                          _nc_first_name(qp->tterm.term_names));
        !           716:
        !           717:     (void) printf("In file 2 (%s) only:\n", argv[1]);
        !           718:     for (rp = heads[1]; rp; rp = rp->next)
        !           719:        if (rp->nuses == 0)
        !           720:            (void) printf("\t%s\n",
        !           721:                          _nc_first_name(rp->tterm.term_names));
        !           722:
        !           723:     (void) printf("The following entries are equivalent:\n");
        !           724:     for (qp = heads[0]; qp; qp = qp->next)
        !           725:     {
        !           726:        rp = (ENTRY *)qp->uses[0].parent;
        !           727:
        !           728:        if (qp->nuses == 1 && entryeq(&qp->tterm, &rp->tterm))
        !           729:        {
        !           730:            char name1[NAMESIZE], name2[NAMESIZE];
        !           731:
        !           732:            (void) canonical_name(qp->tterm.term_names, name1);
        !           733:            (void) canonical_name(rp->tterm.term_names, name2);
        !           734:
        !           735:            (void) printf("%s = %s\n", name1, name2);
        !           736:        }
        !           737:     }
        !           738:
        !           739:     (void) printf("Differing entries:\n");
        !           740:     termcount = 2;
        !           741:     for (qp = heads[0]; qp; qp = qp->next)
        !           742:     {
        !           743:        rp = (ENTRY *)qp->uses[0].parent;
        !           744:
        !           745:        if (qp->nuses == 1 && !entryeq(&qp->tterm, &rp->tterm))
        !           746:        {
        !           747:            char name1[NAMESIZE], name2[NAMESIZE];
        !           748:
        !           749:            memcpy(&term[0], &qp->tterm, sizeof(TERMTYPE));
        !           750:            memcpy(&term[1], &rp->tterm, sizeof(TERMTYPE));
        !           751:
        !           752:            (void) canonical_name(qp->tterm.term_names, name1);
        !           753:            (void) canonical_name(rp->tterm.term_names, name2);
        !           754:
        !           755:            switch (compare)
        !           756:            {
        !           757:            case C_DIFFERENCE:
        !           758:                if (itrace)
        !           759:                    (void)fprintf(stderr, "infocmp: dumping differences\n");
        !           760:                (void) printf("comparing %s to %s.\n", name1, name2);
        !           761:                compare_entry(compare_predicate);
        !           762:                break;
        !           763:
        !           764:            case C_COMMON:
        !           765:                if (itrace)
        !           766:                    (void) fprintf(stderr,
        !           767:                                   "infocmp: dumping common capabilities\n");
        !           768:                (void) printf("comparing %s to %s.\n", name1, name2);
        !           769:                compare_entry(compare_predicate);
        !           770:                break;
        !           771:
        !           772:            case C_NAND:
        !           773:                if (itrace)
        !           774:                    (void) fprintf(stderr,
        !           775:                                   "infocmp: dumping differences\n");
        !           776:                (void) printf("comparing %s to %s.\n", name1, name2);
        !           777:                compare_entry(compare_predicate);
        !           778:                break;
        !           779:
        !           780:            }
        !           781:        }
        !           782:     }
        !           783: }
        !           784:
        !           785: static void usage(void)
        !           786: {
        !           787:        static const char *tbl[] = {
        !           788:             "Usage: infocmp [options] [-A directory] [-B directory] [termname...]"
        !           789:            ,""
        !           790:            ,"Options:"
        !           791:            ,"  -1    print single-column"
        !           792:            ,"  -C    use termcap-names"
        !           793:            ,"  -F    compare terminfo-files"
        !           794:            ,"  -I    use terminfo-names"
        !           795:            ,"  -L    use long names"
        !           796:            ,"  -R subset (see manpage)"
        !           797:            ,"  -T    eliminate size limits (test)"
        !           798:            ,"  -V    print version"
        !           799:            ,"  -c    list common capabilities"
        !           800:            ,"  -d    list different capabilities"
        !           801:            ,"  -e    format output as C initializer"
        !           802:            ,"  -f    with -1, format complex strings"
        !           803:            ,"  -g    format %'char' to %{number}"
        !           804:            ,"  -i    analyze initialization/reset"
        !           805:            ,"  -l    output terminfo names"
        !           806:            ,"  -n    list capabilities in neither"
        !           807:            ,"  -p    ignore padding specifiers"
        !           808:            ,"  -r    with -C, output in termcap form"
        !           809:            ,"  -s [d|i|l|c] sort fields"
        !           810:            ,"  -u    produce source with 'use='"
        !           811:            ,"  -v number  (verbose)"
        !           812:            ,"  -w number  (width)"
        !           813:        };
        !           814:        const size_t first = 3;
        !           815:        const size_t last = sizeof(tbl)/sizeof(tbl[0]);
        !           816:        const size_t left = (last - first + 1) / 2 + first;
        !           817:        size_t n;
        !           818:
        !           819:        for (n = 0; n < left; n++) {
        !           820:                size_t m = (n < first) ? last : n + left - first;
        !           821:                if (m < last)
        !           822:                        fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]);
        !           823:                else
        !           824:                        fprintf(stderr, "%s\n", tbl[n]);
        !           825:        }
        !           826:        exit(EXIT_FAILURE);
        !           827: }
        !           828:
        !           829: /***************************************************************************
        !           830:  *
        !           831:  * Main sequence
        !           832:  *
        !           833:  ***************************************************************************/
        !           834:
        !           835: int main(int argc, char *argv[])
        !           836: {
        !           837:        char *terminal, *firstdir, *restdir;
        !           838:        /* Avoid "local data >32k" error with mwcc */
        !           839:        /* Also avoid overflowing smaller stacks on systems like AmigaOS */
        !           840:        path *tfile = malloc(sizeof(path)*MAXTERMS);
        !           841:        int c, i, len;
        !           842:        bool formatted = FALSE;
        !           843:        bool filecompare = FALSE;
        !           844:        bool initdump = FALSE;
        !           845:        bool init_analyze = FALSE;
        !           846:        bool limited = TRUE;
        !           847:
        !           848:        if ((terminal = getenv("TERM")) == NULL)
        !           849:        {
        !           850:                (void) fprintf(stderr,
        !           851:                        "infocmp: environment variable TERM not set\n");
        !           852:                return EXIT_FAILURE;
        !           853:        }
        !           854:
        !           855:        /* where is the terminfo database location going to default to? */
        !           856:        restdir = firstdir = 0;
        !           857:
        !           858:        while ((c = getopt(argc, argv, "decCfFgIinlLprR:s:uv:Vw:A:B:1T")) != EOF)
        !           859:                switch (c)
        !           860:                {
        !           861:                case 'd':
        !           862:                        compare = C_DIFFERENCE;
        !           863:                        break;
        !           864:
        !           865:                case 'e':
        !           866:                        initdump = TRUE;
        !           867:                        break;
        !           868:
        !           869:                case 'c':
        !           870:                        compare = C_COMMON;
        !           871:                        break;
        !           872:
        !           873:                case 'C':
        !           874:                        outform = F_TERMCAP;
        !           875:                        tversion = "BSD";
        !           876:                        if (sortmode == S_DEFAULT)
        !           877:                            sortmode = S_TERMCAP;
        !           878:                        break;
        !           879:
        !           880:                case 'f':
        !           881:                        formatted = TRUE;
        !           882:                        break;
        !           883:
        !           884:                case 'g':
        !           885:                        numbers = FALSE;
        !           886:                        break;
        !           887:
        !           888:                case 'F':
        !           889:                        filecompare = TRUE;
        !           890:                        break;
        !           891:
        !           892:                case 'I':
        !           893:                        outform = F_TERMINFO;
        !           894:                        if (sortmode == S_DEFAULT)
        !           895:                            sortmode = S_VARIABLE;
        !           896:                        tversion = 0;
        !           897:                        break;
        !           898:
        !           899:                case 'i':
        !           900:                        init_analyze = TRUE;
        !           901:                        break;
        !           902:
        !           903:                case 'l':
        !           904:                        outform = F_TERMINFO;
        !           905:                        break;
        !           906:
        !           907:                case 'L':
        !           908:                        outform = F_VARIABLE;
        !           909:                        if (sortmode == S_DEFAULT)
        !           910:                            sortmode = S_VARIABLE;
        !           911:                        break;
        !           912:
        !           913:                case 'n':
        !           914:                        compare = C_NAND;
        !           915:                        break;
        !           916:
        !           917:                case 'p':
        !           918:                        ignorepads = TRUE;
        !           919:                        break;
        !           920:
        !           921:                case 'r':
        !           922:                        tversion = 0;
        !           923:                        limited = FALSE;
        !           924:                        break;
        !           925:
        !           926:                case 'R':
        !           927:                        tversion = optarg;
        !           928:                        break;
        !           929:
        !           930:                case 's':
        !           931:                        if (*optarg == 'd')
        !           932:                                sortmode = S_NOSORT;
        !           933:                        else if (*optarg == 'i')
        !           934:                                sortmode = S_TERMINFO;
        !           935:                        else if (*optarg == 'l')
        !           936:                                sortmode = S_VARIABLE;
        !           937:                        else if (*optarg == 'c')
        !           938:                                sortmode = S_TERMCAP;
        !           939:                        else
        !           940:                        {
        !           941:                                (void) fprintf(stderr,
        !           942:                                               "infocmp: unknown sort mode\n");
        !           943:                                return EXIT_FAILURE;
        !           944:                        }
        !           945:                        break;
        !           946:
        !           947:                case 'u':
        !           948:                        compare = C_USEALL;
        !           949:                        break;
        !           950:
        !           951:                case 'v':
        !           952:                        itrace = atoi(optarg);
        !           953:                        _nc_tracing = (1 << itrace) - 1;
        !           954:                        break;
        !           955:
        !           956:                case 'V':
        !           957:                        (void) fputs(NCURSES_VERSION, stdout);
        !           958:                        putchar('\n');
        !           959:                        ExitProgram(EXIT_SUCCESS);
        !           960:
        !           961:                case 'w':
        !           962:                        mwidth = atoi(optarg);
        !           963:                        break;
        !           964:
        !           965:                case 'A':
        !           966:                        firstdir = optarg;
        !           967:                        break;
        !           968:
        !           969:                case 'B':
        !           970:                        restdir = optarg;
        !           971:                        break;
        !           972:
        !           973:                case '1':
        !           974:                        mwidth = 0;
        !           975:                        break;
        !           976:
        !           977:                case 'T':
        !           978:                        limited = FALSE;
        !           979:                        break;
        !           980:                default:
        !           981:                        usage();
        !           982:                }
        !           983:
        !           984:        /* by default, sort by terminfo name */
        !           985:        if (sortmode == S_DEFAULT)
        !           986:                sortmode = S_TERMINFO;
        !           987:
        !           988:        /* set up for display */
        !           989:        dump_init(tversion, outform, sortmode, mwidth, itrace, formatted);
        !           990:
        !           991:        /* make sure we have at least one terminal name to work with */
        !           992:        if (optind >= argc)
        !           993:                argv[argc++] = terminal;
        !           994:
        !           995:        /* if user is after a comparison, make sure we have two entries */
        !           996:        if (compare != C_DEFAULT && optind >= argc - 1)
        !           997:                argv[argc++] = terminal;
        !           998:
        !           999:        /* exactly two terminal names with no options means do -d */
        !          1000:        if (argc - optind == 2 && compare == C_DEFAULT)
        !          1001:                compare = C_DIFFERENCE;
        !          1002:
        !          1003:        if (!filecompare)
        !          1004:        {
        !          1005:            /* grab the entries */
        !          1006:            termcount = 0;
        !          1007:            for (; optind < argc; optind++)
        !          1008:            {
        !          1009:                if (termcount >= MAXTERMS)
        !          1010:                {
        !          1011:                    (void) fprintf(stderr,
        !          1012:                           "infocmp: too many terminal type arguments\n");
        !          1013:                    return EXIT_FAILURE;
        !          1014:                }
        !          1015:                else
        !          1016:                {
        !          1017:                    const char  *directory = termcount ? restdir : firstdir;
        !          1018:                    int         status;
        !          1019:
        !          1020:                    tname[termcount] = argv[optind];
        !          1021:
        !          1022:                    if (directory)
        !          1023:                    {
        !          1024:                        (void) sprintf(tfile[termcount], "%s/%c/%s",
        !          1025:                                       directory,
        !          1026:                                       *argv[optind], argv[optind]);
        !          1027:                        if (itrace)
        !          1028:                            (void) fprintf(stderr,
        !          1029:                                           "infocmp: reading entry %s from file %s\n",
        !          1030:                                           argv[optind], tfile[termcount]);
        !          1031:
        !          1032:                        status = _nc_read_file_entry(tfile[termcount],
        !          1033:                                                     &term[termcount]);
        !          1034:                    }
        !          1035:                    else
        !          1036:                    {
        !          1037:                        if (itrace)
        !          1038:                            (void) fprintf(stderr,
        !          1039:                                           "infocmp: reading entry %s from system directories %s\n",
        !          1040:                                           argv[optind], tname[termcount]);
        !          1041:
        !          1042:                        status = _nc_read_entry(tname[termcount],
        !          1043:                                                tfile[termcount],
        !          1044:                                                &term[termcount]);
        !          1045:                        directory = TERMINFO;   /* for error message */
        !          1046:                    }
        !          1047:
        !          1048:                    if (status <= 0)
        !          1049:                    {
        !          1050:                        (void) fprintf(stderr,
        !          1051:                                       "infocmp: couldn't open terminfo file %s.\n",
        !          1052:                                       tfile[termcount]);
        !          1053:                        return EXIT_FAILURE;
        !          1054:                    }
        !          1055:                    termcount++;
        !          1056:                }
        !          1057:            }
        !          1058:
        !          1059:            /* dump as C initializer for the terminal type */
        !          1060:            if (initdump)
        !          1061:            {
        !          1062:                int     n;
        !          1063:                const char *str = 0;
        !          1064:                int     size;
        !          1065:
        !          1066:                (void) printf("\t%s\n\t\t\"%s\",\n",
        !          1067:                              L_CURL, term->term_names);
        !          1068:                (void) printf("\t\t(char *)0,\n");
        !          1069:
        !          1070:                (void) printf("\t\t%s /* BOOLEANS */\n", L_CURL);
        !          1071:                for (n = 0; n < BOOLCOUNT; n++)
        !          1072:                {
        !          1073:                    switch((int)(term->Booleans[n]))
        !          1074:                    {
        !          1075:                    case TRUE:
        !          1076:                        str = "TRUE";
        !          1077:                        break;
        !          1078:
        !          1079:                    case FALSE:
        !          1080:                        str = "FALSE";
        !          1081:                        break;
        !          1082:
        !          1083:                    case ABSENT_BOOLEAN:
        !          1084:                        str = "ABSENT_BOOLEAN";
        !          1085:                        break;
        !          1086:
        !          1087:                    case CANCELLED_BOOLEAN:
        !          1088:                        str = "CANCELLED_BOOLEAN";
        !          1089:                        break;
        !          1090:                    }
        !          1091:                    (void) printf("\t\t/* %s */\t%s%s,\n",
        !          1092:                                  boolnames[n], str,
        !          1093:                                  n == BOOLCOUNT-1 ? R_CURL : "");
        !          1094:                }
        !          1095:
        !          1096:                (void) printf("\t\t%s /* NUMERICS */\n", L_CURL);
        !          1097:                for (n = 0; n < NUMCOUNT; n++)
        !          1098:                {
        !          1099:                    char        buf[BUFSIZ];
        !          1100:                    switch (term->Numbers[n])
        !          1101:                    {
        !          1102:                    case ABSENT_NUMERIC:
        !          1103:                        str = "ABSENT_NUMERIC";
        !          1104:                        break;
        !          1105:                    case CANCELLED_NUMERIC:
        !          1106:                        str = "CANCELLED_NUMERIC";
        !          1107:                        break;
        !          1108:                    default:
        !          1109:                        sprintf(buf, "%d", term->Numbers[n]);
        !          1110:                        str = buf;
        !          1111:                        break;
        !          1112:                    }
        !          1113:                    (void) printf("\t\t/* %s */\t%s%s,\n",
        !          1114:                        numnames[n], str,
        !          1115:                        n == NUMCOUNT-1 ? R_CURL : "");
        !          1116:                }
        !          1117:
        !          1118:                size = sizeof(TERMTYPE)
        !          1119:                    + (BOOLCOUNT * sizeof(term->Booleans[0]))
        !          1120:                    + (NUMCOUNT * sizeof(term->Numbers[0]));
        !          1121:
        !          1122:                (void) printf("\t\t%s /* STRINGS */\n", L_CURL);
        !          1123:                for (n = 0; n < STRCOUNT; n++)
        !          1124:                {
        !          1125:                    char        buf[BUFSIZ], *sp, *tp;
        !          1126:
        !          1127:                    if (term->Strings[n] == ABSENT_STRING)
        !          1128:                        str = "ABSENT_STRING";
        !          1129:                    else if (term->Strings[n] == CANCELLED_STRING)
        !          1130:                        str = "CANCELLED_STRING";
        !          1131:                    else
        !          1132:                    {
        !          1133:                        tp = buf;
        !          1134:                        *tp++ = '"';
        !          1135:                        for (sp = term->Strings[n]; *sp; sp++)
        !          1136:                        {
        !          1137:                            if (isascii(*sp) && isprint(*sp) && *sp !='\\' && *sp != '"')
        !          1138:                                *tp++ = *sp;
        !          1139:                            else
        !          1140:                            {
        !          1141:                                (void) sprintf(tp, "\\%03o", *sp & 0xff);
        !          1142:                                tp += 4;
        !          1143:                            }
        !          1144:                        }
        !          1145:                        *tp++ = '"';
        !          1146:                        *tp = '\0';
        !          1147:                        size += (strlen(term->Strings[n]) + 1);
        !          1148:                        str = buf;
        !          1149:                    }
        !          1150:                    (void) printf("\t\t/* %s */\t%s%s%s\n",
        !          1151:                        strnames[n], str,
        !          1152:                        n == STRCOUNT-1 ? R_CURL : "",
        !          1153:                        n == STRCOUNT-1 ? ""     : ",");
        !          1154:                }
        !          1155:                (void) printf("\t%s /* size = %d */\n", R_CURL, size);
        !          1156:                ExitProgram(EXIT_SUCCESS);
        !          1157:            }
        !          1158:
        !          1159:            /* analyze the init strings */
        !          1160:            if (init_analyze)
        !          1161:            {
        !          1162: #undef CUR
        !          1163: #define CUR    term[0].
        !          1164:                analyze_string("is1", init_1string, &term[0]);
        !          1165:                analyze_string("is2", init_2string, &term[0]);
        !          1166:                analyze_string("is3", init_3string, &term[0]);
        !          1167:                analyze_string("rs1", reset_1string, &term[0]);
        !          1168:                analyze_string("rs2", reset_2string, &term[0]);
        !          1169:                analyze_string("rs3", reset_3string, &term[0]);
        !          1170:                analyze_string("smcup", enter_ca_mode, &term[0]);
        !          1171:                analyze_string("rmcup", exit_ca_mode, &term[0]);
        !          1172: #undef CUR
        !          1173:                ExitProgram(EXIT_SUCCESS);
        !          1174:            }
        !          1175:
        !          1176:            /*
        !          1177:             * Here's where the real work gets done
        !          1178:             */
        !          1179:            switch (compare)
        !          1180:            {
        !          1181:            case C_DEFAULT:
        !          1182:                if (itrace)
        !          1183:                    (void) fprintf(stderr,
        !          1184:                                   "infocmp: about to dump %s\n",
        !          1185:                                   tname[0]);
        !          1186:                (void) printf("#\tReconstructed via infocmp from file: %s\n",
        !          1187:                              tfile[0]);
        !          1188:                len = dump_entry(&term[0], limited, numbers, NULL);
        !          1189:                putchar('\n');
        !          1190:                if (itrace)
        !          1191:                    (void)fprintf(stderr, "infocmp: length %d\n", len);
        !          1192:                break;
        !          1193:
        !          1194:            case C_DIFFERENCE:
        !          1195:                if (itrace)
        !          1196:                    (void)fprintf(stderr, "infocmp: dumping differences\n");
        !          1197:                (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
        !          1198:                compare_entry(compare_predicate);
        !          1199:                break;
        !          1200:
        !          1201:            case C_COMMON:
        !          1202:                if (itrace)
        !          1203:                    (void) fprintf(stderr,
        !          1204:                                   "infocmp: dumping common capabilities\n");
        !          1205:                (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
        !          1206:                compare_entry(compare_predicate);
        !          1207:                break;
        !          1208:
        !          1209:            case C_NAND:
        !          1210:                if (itrace)
        !          1211:                    (void) fprintf(stderr,
        !          1212:                                   "infocmp: dumping differences\n");
        !          1213:                (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
        !          1214:                compare_entry(compare_predicate);
        !          1215:                break;
        !          1216:
        !          1217:            case C_USEALL:
        !          1218:                if (itrace)
        !          1219:                    (void) fprintf(stderr, "infocmp: dumping use entry\n");
        !          1220:                len = dump_entry(&term[0], limited, numbers, use_predicate);
        !          1221:                for (i = 1; i < termcount; i++)
        !          1222:                    len += dump_uses(tname[i], !(outform==F_TERMCAP || outform==F_TCONVERR));
        !          1223:                putchar('\n');
        !          1224:                if (itrace)
        !          1225:                    (void)fprintf(stderr, "infocmp: length %d\n", len);
        !          1226:                break;
        !          1227:            }
        !          1228:        }
        !          1229:        else if (compare == C_USEALL)
        !          1230:            (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n");
        !          1231:        else if (compare == C_DEFAULT)
        !          1232:            (void) fprintf(stderr, "Use `tic -[CI] <file>' for this.\n");
        !          1233:        else if (argc - optind != 2)
        !          1234:            (void) fprintf(stderr,
        !          1235:                "File comparison needs exactly two file arguments.\n");
        !          1236:        else
        !          1237:            file_comparison(argc-optind, argv+optind);
        !          1238:
        !          1239:        ExitProgram(EXIT_SUCCESS);
        !          1240: }
        !          1241:
        !          1242: /* infocmp.c ends here */