15f4613f2SJohn Marino /****************************************************************************
2*32bb5217SDaniel Fojt * Copyright 2018-2019,2020 Thomas E. Dickey *
3*32bb5217SDaniel Fojt * Copyright 1998-2016,2017 Free Software Foundation, Inc. *
45f4613f2SJohn Marino * *
55f4613f2SJohn Marino * Permission is hereby granted, free of charge, to any person obtaining a *
65f4613f2SJohn Marino * copy of this software and associated documentation files (the *
75f4613f2SJohn Marino * "Software"), to deal in the Software without restriction, including *
85f4613f2SJohn Marino * without limitation the rights to use, copy, modify, merge, publish, *
95f4613f2SJohn Marino * distribute, distribute with modifications, sublicense, and/or sell *
105f4613f2SJohn Marino * copies of the Software, and to permit persons to whom the Software is *
115f4613f2SJohn Marino * furnished to do so, subject to the following conditions: *
125f4613f2SJohn Marino * *
135f4613f2SJohn Marino * The above copyright notice and this permission notice shall be included *
145f4613f2SJohn Marino * in all copies or substantial portions of the Software. *
155f4613f2SJohn Marino * *
165f4613f2SJohn Marino * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
175f4613f2SJohn Marino * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
185f4613f2SJohn Marino * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
195f4613f2SJohn Marino * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
205f4613f2SJohn Marino * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
215f4613f2SJohn Marino * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
225f4613f2SJohn Marino * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
235f4613f2SJohn Marino * *
245f4613f2SJohn Marino * Except as contained in this notice, the name(s) of the above copyright *
255f4613f2SJohn Marino * holders shall not be used in advertising or otherwise to promote the *
265f4613f2SJohn Marino * sale, use or other dealings in this Software without prior written *
275f4613f2SJohn Marino * authorization. *
285f4613f2SJohn Marino ****************************************************************************/
295f4613f2SJohn Marino
305f4613f2SJohn Marino /****************************************************************************
315f4613f2SJohn Marino * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
325f4613f2SJohn Marino * and: Eric S. Raymond <esr@snark.thyrsus.com> *
335f4613f2SJohn Marino * and: Thomas E. Dickey 1996 on *
345f4613f2SJohn Marino ****************************************************************************/
355f4613f2SJohn Marino
365f4613f2SJohn Marino #define __INTERNAL_CAPS_VISIBLE
375f4613f2SJohn Marino #include <progs.priv.h>
385f4613f2SJohn Marino
395f4613f2SJohn Marino #include "dump_entry.h"
405f4613f2SJohn Marino #include "termsort.c" /* this C file is generated */
415f4613f2SJohn Marino #include <parametrized.h> /* so is this */
425f4613f2SJohn Marino
43*32bb5217SDaniel Fojt MODULE_ID("$Id: dump_entry.c,v 1.176 2020/02/02 23:34:34 tom Exp $")
445f4613f2SJohn Marino
455f4613f2SJohn Marino #define DISCARD(string) string = ABSENT_STRING
465f4613f2SJohn Marino #define PRINTF (void) printf
47*32bb5217SDaniel Fojt #define WRAPPED 32
485f4613f2SJohn Marino
495f4613f2SJohn Marino #define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array))
50*32bb5217SDaniel Fojt #define TcOutput() (outform == F_TERMCAP || outform == F_TCONVERR)
515f4613f2SJohn Marino
525f4613f2SJohn Marino typedef struct {
535f4613f2SJohn Marino char *text;
545f4613f2SJohn Marino size_t used;
555f4613f2SJohn Marino size_t size;
565f4613f2SJohn Marino } DYNBUF;
575f4613f2SJohn Marino
585f4613f2SJohn Marino static int tversion; /* terminfo version */
595f4613f2SJohn Marino static int outform; /* output format to use */
605f4613f2SJohn Marino static int sortmode; /* sort mode to use */
615f4613f2SJohn Marino static int width = 60; /* max line width for listings */
623468e90cSJohn Marino static int height = 65535; /* max number of lines for listings */
635f4613f2SJohn Marino static int column; /* current column, limited by 'width' */
645f4613f2SJohn Marino static int oldcol; /* last value of column before wrap */
655f4613f2SJohn Marino static bool pretty; /* true if we format if-then-else strings */
66*32bb5217SDaniel Fojt static bool wrapped; /* true if we wrap too-long strings */
67*32bb5217SDaniel Fojt static bool did_wrap; /* true if last wrap_concat did wrapping */
683468e90cSJohn Marino static bool checking; /* true if we are checking for tic */
693468e90cSJohn Marino static int quickdump; /* true if we are dumping compiled data */
705f4613f2SJohn Marino
715f4613f2SJohn Marino static char *save_sgr;
725f4613f2SJohn Marino
735f4613f2SJohn Marino static DYNBUF outbuf;
745f4613f2SJohn Marino static DYNBUF tmpbuf;
755f4613f2SJohn Marino
765f4613f2SJohn Marino /* indirection pointers for implementing sort and display modes */
775f4613f2SJohn Marino static const PredIdx *bool_indirect, *num_indirect, *str_indirect;
785f4613f2SJohn Marino static NCURSES_CONST char *const *bool_names;
795f4613f2SJohn Marino static NCURSES_CONST char *const *num_names;
805f4613f2SJohn Marino static NCURSES_CONST char *const *str_names;
815f4613f2SJohn Marino
823468e90cSJohn Marino static const char *separator = "", *trailer = "";
833468e90cSJohn Marino static int indent = 8;
845f4613f2SJohn Marino
855f4613f2SJohn Marino /* cover various ports and variants of terminfo */
865f4613f2SJohn Marino #define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */
875f4613f2SJohn Marino #define V_SVR1 1 /* SVR1, Ultrix */
885f4613f2SJohn Marino #define V_HPUX 2 /* HP/UX */
895f4613f2SJohn Marino #define V_AIX 3 /* AIX */
905f4613f2SJohn Marino #define V_BSD 4 /* BSD */
915f4613f2SJohn Marino
925f4613f2SJohn Marino #if NCURSES_XNAMES
935f4613f2SJohn Marino #define OBSOLETE(n) (!_nc_user_definable && (n[0] == 'O' && n[1] == 'T'))
945f4613f2SJohn Marino #else
955f4613f2SJohn Marino #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T')
965f4613f2SJohn Marino #endif
975f4613f2SJohn Marino
98*32bb5217SDaniel Fojt #define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && (sortmode != S_VARIABLE) && OBSOLETE(n))
995f4613f2SJohn Marino
1005f4613f2SJohn Marino #if NCURSES_XNAMES
1015f4613f2SJohn Marino #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j]))
1025f4613f2SJohn Marino #define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j]))
1035f4613f2SJohn Marino #define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j]))
1045f4613f2SJohn Marino #else
1055f4613f2SJohn Marino #define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j])
1065f4613f2SJohn Marino #define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j])
1075f4613f2SJohn Marino #define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j])
1085f4613f2SJohn Marino #endif
1095f4613f2SJohn Marino
1103468e90cSJohn Marino static void failed(const char *) GCC_NORETURN;
1113468e90cSJohn Marino
1123468e90cSJohn Marino static void
failed(const char * s)1133468e90cSJohn Marino failed(const char *s)
1143468e90cSJohn Marino {
1153468e90cSJohn Marino perror(s);
1163468e90cSJohn Marino ExitProgram(EXIT_FAILURE);
1173468e90cSJohn Marino }
1183468e90cSJohn Marino
1195f4613f2SJohn Marino static void
strncpy_DYN(DYNBUF * dst,const char * src,size_t need)1205f4613f2SJohn Marino strncpy_DYN(DYNBUF * dst, const char *src, size_t need)
1215f4613f2SJohn Marino {
1225f4613f2SJohn Marino size_t want = need + dst->used + 1;
1235f4613f2SJohn Marino if (want > dst->size) {
1245f4613f2SJohn Marino dst->size += (want + 1024); /* be generous */
1255f4613f2SJohn Marino dst->text = typeRealloc(char, dst->size, dst->text);
1263468e90cSJohn Marino if (dst->text == 0)
1273468e90cSJohn Marino failed("strncpy_DYN");
1285f4613f2SJohn Marino }
129*32bb5217SDaniel Fojt _nc_STRNCPY(dst->text + dst->used, src, need + 1);
1305f4613f2SJohn Marino dst->used += need;
1315f4613f2SJohn Marino dst->text[dst->used] = 0;
1325f4613f2SJohn Marino }
1335f4613f2SJohn Marino
1345f4613f2SJohn Marino static void
strcpy_DYN(DYNBUF * dst,const char * src)1355f4613f2SJohn Marino strcpy_DYN(DYNBUF * dst, const char *src)
1365f4613f2SJohn Marino {
1375f4613f2SJohn Marino if (src == 0) {
1385f4613f2SJohn Marino dst->used = 0;
1395f4613f2SJohn Marino strcpy_DYN(dst, "");
1405f4613f2SJohn Marino } else {
1415f4613f2SJohn Marino strncpy_DYN(dst, src, strlen(src));
1425f4613f2SJohn Marino }
1435f4613f2SJohn Marino }
1445f4613f2SJohn Marino
1455f4613f2SJohn Marino #if NO_LEAKS
1465f4613f2SJohn Marino static void
free_DYN(DYNBUF * p)1475f4613f2SJohn Marino free_DYN(DYNBUF * p)
1485f4613f2SJohn Marino {
1495f4613f2SJohn Marino if (p->text != 0)
1505f4613f2SJohn Marino free(p->text);
1515f4613f2SJohn Marino p->text = 0;
1525f4613f2SJohn Marino p->size = 0;
1535f4613f2SJohn Marino p->used = 0;
1545f4613f2SJohn Marino }
1555f4613f2SJohn Marino
1565f4613f2SJohn Marino void
_nc_leaks_dump_entry(void)1575f4613f2SJohn Marino _nc_leaks_dump_entry(void)
1585f4613f2SJohn Marino {
1595f4613f2SJohn Marino free_DYN(&outbuf);
1605f4613f2SJohn Marino free_DYN(&tmpbuf);
1615f4613f2SJohn Marino }
1625f4613f2SJohn Marino #endif
1635f4613f2SJohn Marino
1645f4613f2SJohn Marino #define NameTrans(check,result) \
1653468e90cSJohn Marino if ((np->nte_index <= OK_ ## check) \
1665f4613f2SJohn Marino && check[np->nte_index]) \
1675f4613f2SJohn Marino return (result[np->nte_index])
1685f4613f2SJohn Marino
1695f4613f2SJohn Marino NCURSES_CONST char *
nametrans(const char * name)1705f4613f2SJohn Marino nametrans(const char *name)
1713468e90cSJohn Marino /* translate a capability name to termcap from terminfo */
1725f4613f2SJohn Marino {
1735f4613f2SJohn Marino const struct name_table_entry *np;
1745f4613f2SJohn Marino
1753468e90cSJohn Marino if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) {
1765f4613f2SJohn Marino switch (np->nte_type) {
1775f4613f2SJohn Marino case BOOLEAN:
1785f4613f2SJohn Marino NameTrans(bool_from_termcap, boolcodes);
1795f4613f2SJohn Marino break;
1805f4613f2SJohn Marino
1815f4613f2SJohn Marino case NUMBER:
1825f4613f2SJohn Marino NameTrans(num_from_termcap, numcodes);
1835f4613f2SJohn Marino break;
1845f4613f2SJohn Marino
1855f4613f2SJohn Marino case STRING:
1865f4613f2SJohn Marino NameTrans(str_from_termcap, strcodes);
1875f4613f2SJohn Marino break;
1885f4613f2SJohn Marino }
1893468e90cSJohn Marino }
1905f4613f2SJohn Marino
1915f4613f2SJohn Marino return (0);
1925f4613f2SJohn Marino }
1935f4613f2SJohn Marino
1945f4613f2SJohn Marino void
dump_init(const char * version,int mode,int sort,bool wrap_strings,int twidth,int theight,unsigned traceval,bool formatted,bool check,int quick)1953468e90cSJohn Marino dump_init(const char *version,
1963468e90cSJohn Marino int mode,
1973468e90cSJohn Marino int sort,
198*32bb5217SDaniel Fojt bool wrap_strings,
1993468e90cSJohn Marino int twidth,
2003468e90cSJohn Marino int theight,
2013468e90cSJohn Marino unsigned traceval,
2023468e90cSJohn Marino bool formatted,
2033468e90cSJohn Marino bool check,
2043468e90cSJohn Marino int quick)
2055f4613f2SJohn Marino /* set up for entry display */
2065f4613f2SJohn Marino {
2075f4613f2SJohn Marino width = twidth;
2083468e90cSJohn Marino height = theight;
2095f4613f2SJohn Marino pretty = formatted;
210*32bb5217SDaniel Fojt wrapped = wrap_strings;
2113468e90cSJohn Marino checking = check;
2123468e90cSJohn Marino quickdump = (quick & 3);
2135f4613f2SJohn Marino
214*32bb5217SDaniel Fojt did_wrap = (width <= 0);
215*32bb5217SDaniel Fojt
2165f4613f2SJohn Marino /* versions */
2175f4613f2SJohn Marino if (version == 0)
2185f4613f2SJohn Marino tversion = V_ALLCAPS;
2195f4613f2SJohn Marino else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1")
2205f4613f2SJohn Marino || !strcmp(version, "Ultrix"))
2215f4613f2SJohn Marino tversion = V_SVR1;
2225f4613f2SJohn Marino else if (!strcmp(version, "HP"))
2235f4613f2SJohn Marino tversion = V_HPUX;
2245f4613f2SJohn Marino else if (!strcmp(version, "AIX"))
2255f4613f2SJohn Marino tversion = V_AIX;
2265f4613f2SJohn Marino else if (!strcmp(version, "BSD"))
2275f4613f2SJohn Marino tversion = V_BSD;
2285f4613f2SJohn Marino else
2295f4613f2SJohn Marino tversion = V_ALLCAPS;
2305f4613f2SJohn Marino
2315f4613f2SJohn Marino /* implement display modes */
2325f4613f2SJohn Marino switch (outform = mode) {
2335f4613f2SJohn Marino case F_LITERAL:
2345f4613f2SJohn Marino case F_TERMINFO:
2355f4613f2SJohn Marino bool_names = boolnames;
2365f4613f2SJohn Marino num_names = numnames;
2375f4613f2SJohn Marino str_names = strnames;
2383468e90cSJohn Marino separator = (twidth > 0 && theight > 1) ? ", " : ",";
2395f4613f2SJohn Marino trailer = "\n\t";
2405f4613f2SJohn Marino break;
2415f4613f2SJohn Marino
2425f4613f2SJohn Marino case F_VARIABLE:
2435f4613f2SJohn Marino bool_names = boolfnames;
2445f4613f2SJohn Marino num_names = numfnames;
2455f4613f2SJohn Marino str_names = strfnames;
2463468e90cSJohn Marino separator = (twidth > 0 && theight > 1) ? ", " : ",";
2475f4613f2SJohn Marino trailer = "\n\t";
2485f4613f2SJohn Marino break;
2495f4613f2SJohn Marino
2505f4613f2SJohn Marino case F_TERMCAP:
2515f4613f2SJohn Marino case F_TCONVERR:
2525f4613f2SJohn Marino bool_names = boolcodes;
2535f4613f2SJohn Marino num_names = numcodes;
2545f4613f2SJohn Marino str_names = strcodes;
2555f4613f2SJohn Marino separator = ":";
2565f4613f2SJohn Marino trailer = "\\\n\t:";
2575f4613f2SJohn Marino break;
2585f4613f2SJohn Marino }
2593468e90cSJohn Marino indent = 8;
2605f4613f2SJohn Marino
2615f4613f2SJohn Marino /* implement sort modes */
2625f4613f2SJohn Marino switch (sortmode = sort) {
2635f4613f2SJohn Marino case S_NOSORT:
2645f4613f2SJohn Marino if (traceval)
2655f4613f2SJohn Marino (void) fprintf(stderr,
2665f4613f2SJohn Marino "%s: sorting by term structure order\n", _nc_progname);
2675f4613f2SJohn Marino break;
2685f4613f2SJohn Marino
2695f4613f2SJohn Marino case S_TERMINFO:
2705f4613f2SJohn Marino if (traceval)
2715f4613f2SJohn Marino (void) fprintf(stderr,
2725f4613f2SJohn Marino "%s: sorting by terminfo name order\n", _nc_progname);
2735f4613f2SJohn Marino bool_indirect = bool_terminfo_sort;
2745f4613f2SJohn Marino num_indirect = num_terminfo_sort;
2755f4613f2SJohn Marino str_indirect = str_terminfo_sort;
2765f4613f2SJohn Marino break;
2775f4613f2SJohn Marino
2785f4613f2SJohn Marino case S_VARIABLE:
2795f4613f2SJohn Marino if (traceval)
2805f4613f2SJohn Marino (void) fprintf(stderr,
2815f4613f2SJohn Marino "%s: sorting by C variable order\n", _nc_progname);
2825f4613f2SJohn Marino bool_indirect = bool_variable_sort;
2835f4613f2SJohn Marino num_indirect = num_variable_sort;
2845f4613f2SJohn Marino str_indirect = str_variable_sort;
2855f4613f2SJohn Marino break;
2865f4613f2SJohn Marino
2875f4613f2SJohn Marino case S_TERMCAP:
2885f4613f2SJohn Marino if (traceval)
2895f4613f2SJohn Marino (void) fprintf(stderr,
2905f4613f2SJohn Marino "%s: sorting by termcap name order\n", _nc_progname);
2915f4613f2SJohn Marino bool_indirect = bool_termcap_sort;
2925f4613f2SJohn Marino num_indirect = num_termcap_sort;
2935f4613f2SJohn Marino str_indirect = str_termcap_sort;
2945f4613f2SJohn Marino break;
2955f4613f2SJohn Marino }
2965f4613f2SJohn Marino
2975f4613f2SJohn Marino if (traceval)
2985f4613f2SJohn Marino (void) fprintf(stderr,
2995f4613f2SJohn Marino "%s: width = %d, tversion = %d, outform = %d\n",
3005f4613f2SJohn Marino _nc_progname, width, tversion, outform);
3015f4613f2SJohn Marino }
3025f4613f2SJohn Marino
303*32bb5217SDaniel Fojt static TERMTYPE2 *cur_type;
3045f4613f2SJohn Marino
3055f4613f2SJohn Marino static int
dump_predicate(PredType type,PredIdx idx)3065f4613f2SJohn Marino dump_predicate(PredType type, PredIdx idx)
3075f4613f2SJohn Marino /* predicate function to use for ordinary decompilation */
3085f4613f2SJohn Marino {
3095f4613f2SJohn Marino switch (type) {
3105f4613f2SJohn Marino case BOOLEAN:
3115f4613f2SJohn Marino return (cur_type->Booleans[idx] == FALSE)
3125f4613f2SJohn Marino ? FAIL : cur_type->Booleans[idx];
3135f4613f2SJohn Marino
3145f4613f2SJohn Marino case NUMBER:
3155f4613f2SJohn Marino return (cur_type->Numbers[idx] == ABSENT_NUMERIC)
3165f4613f2SJohn Marino ? FAIL : cur_type->Numbers[idx];
3175f4613f2SJohn Marino
3185f4613f2SJohn Marino case STRING:
3195f4613f2SJohn Marino return (cur_type->Strings[idx] != ABSENT_STRING)
3205f4613f2SJohn Marino ? (int) TRUE : FAIL;
3215f4613f2SJohn Marino }
3225f4613f2SJohn Marino
3235f4613f2SJohn Marino return (FALSE); /* pacify compiler */
3245f4613f2SJohn Marino }
3255f4613f2SJohn Marino
326*32bb5217SDaniel Fojt static void set_obsolete_termcaps(TERMTYPE2 *tp);
3275f4613f2SJohn Marino
3285f4613f2SJohn Marino /* is this the index of a function key string? */
3293468e90cSJohn Marino #define FNKEY(i) \
3303468e90cSJohn Marino (((i) >= STR_IDX(key_f0) && \
3313468e90cSJohn Marino (i) <= STR_IDX(key_f9)) || \
3323468e90cSJohn Marino ((i) >= STR_IDX(key_f11) && \
3333468e90cSJohn Marino (i) <= STR_IDX(key_f63)))
3345f4613f2SJohn Marino
3355f4613f2SJohn Marino /*
3365f4613f2SJohn Marino * If we configure with a different Caps file, the offsets into the arrays
3375f4613f2SJohn Marino * will change. So we use an address expression.
3385f4613f2SJohn Marino */
3395f4613f2SJohn Marino #define BOOL_IDX(name) (PredType) (&(name) - &(CUR Booleans[0]))
3405f4613f2SJohn Marino #define NUM_IDX(name) (PredType) (&(name) - &(CUR Numbers[0]))
3415f4613f2SJohn Marino #define STR_IDX(name) (PredType) (&(name) - &(CUR Strings[0]))
3425f4613f2SJohn Marino
3435f4613f2SJohn Marino static bool
version_filter(PredType type,PredIdx idx)3445f4613f2SJohn Marino version_filter(PredType type, PredIdx idx)
3455f4613f2SJohn Marino /* filter out capabilities we may want to suppress */
3465f4613f2SJohn Marino {
3475f4613f2SJohn Marino switch (tversion) {
3485f4613f2SJohn Marino case V_ALLCAPS: /* SVr4, XSI Curses */
3495f4613f2SJohn Marino return (TRUE);
3505f4613f2SJohn Marino
3515f4613f2SJohn Marino case V_SVR1: /* System V Release 1, Ultrix */
3525f4613f2SJohn Marino switch (type) {
3535f4613f2SJohn Marino case BOOLEAN:
3545f4613f2SJohn Marino return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
3555f4613f2SJohn Marino case NUMBER:
3565f4613f2SJohn Marino return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE);
3575f4613f2SJohn Marino case STRING:
3585f4613f2SJohn Marino return ((idx <= STR_IDX(prtr_non)) ? TRUE : FALSE);
3595f4613f2SJohn Marino }
3605f4613f2SJohn Marino break;
3615f4613f2SJohn Marino
3625f4613f2SJohn Marino case V_HPUX: /* Hewlett-Packard */
3635f4613f2SJohn Marino switch (type) {
3645f4613f2SJohn Marino case BOOLEAN:
3655f4613f2SJohn Marino return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
3665f4613f2SJohn Marino case NUMBER:
3675f4613f2SJohn Marino return ((idx <= NUM_IDX(label_width)) ? TRUE : FALSE);
3685f4613f2SJohn Marino case STRING:
3695f4613f2SJohn Marino if (idx <= STR_IDX(prtr_non))
3705f4613f2SJohn Marino return (TRUE);
3715f4613f2SJohn Marino else if (FNKEY(idx)) /* function keys */
3725f4613f2SJohn Marino return (TRUE);
3735f4613f2SJohn Marino else if (idx == STR_IDX(plab_norm)
3745f4613f2SJohn Marino || idx == STR_IDX(label_on)
3755f4613f2SJohn Marino || idx == STR_IDX(label_off))
3765f4613f2SJohn Marino return (TRUE);
3775f4613f2SJohn Marino else
3785f4613f2SJohn Marino return (FALSE);
3795f4613f2SJohn Marino }
3805f4613f2SJohn Marino break;
3815f4613f2SJohn Marino
3825f4613f2SJohn Marino case V_AIX: /* AIX */
3835f4613f2SJohn Marino switch (type) {
3845f4613f2SJohn Marino case BOOLEAN:
3855f4613f2SJohn Marino return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
3865f4613f2SJohn Marino case NUMBER:
3875f4613f2SJohn Marino return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE);
3885f4613f2SJohn Marino case STRING:
3895f4613f2SJohn Marino if (idx <= STR_IDX(prtr_non))
3905f4613f2SJohn Marino return (TRUE);
3915f4613f2SJohn Marino else if (FNKEY(idx)) /* function keys */
3925f4613f2SJohn Marino return (TRUE);
3935f4613f2SJohn Marino else
3945f4613f2SJohn Marino return (FALSE);
3955f4613f2SJohn Marino }
3965f4613f2SJohn Marino break;
3975f4613f2SJohn Marino
3985f4613f2SJohn Marino #define is_termcap(type) (OkIndex(idx, type##_from_termcap) && \
3995f4613f2SJohn Marino type##_from_termcap[idx])
4005f4613f2SJohn Marino
4015f4613f2SJohn Marino case V_BSD: /* BSD */
4025f4613f2SJohn Marino switch (type) {
4035f4613f2SJohn Marino case BOOLEAN:
4045f4613f2SJohn Marino return is_termcap(bool);
4055f4613f2SJohn Marino case NUMBER:
4065f4613f2SJohn Marino return is_termcap(num);
4075f4613f2SJohn Marino case STRING:
4085f4613f2SJohn Marino return is_termcap(str);
4095f4613f2SJohn Marino }
4105f4613f2SJohn Marino break;
4115f4613f2SJohn Marino }
4125f4613f2SJohn Marino
4135f4613f2SJohn Marino return (FALSE); /* pacify the compiler */
4145f4613f2SJohn Marino }
4155f4613f2SJohn Marino
4165f4613f2SJohn Marino static void
trim_trailing(void)4175f4613f2SJohn Marino trim_trailing(void)
4185f4613f2SJohn Marino {
4195f4613f2SJohn Marino while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ')
4205f4613f2SJohn Marino outbuf.text[--outbuf.used] = '\0';
4215f4613f2SJohn Marino }
4225f4613f2SJohn Marino
4235f4613f2SJohn Marino static void
force_wrap(void)4245f4613f2SJohn Marino force_wrap(void)
4255f4613f2SJohn Marino {
4265f4613f2SJohn Marino oldcol = column;
4275f4613f2SJohn Marino trim_trailing();
4285f4613f2SJohn Marino strcpy_DYN(&outbuf, trailer);
4293468e90cSJohn Marino column = indent;
4305f4613f2SJohn Marino }
4315f4613f2SJohn Marino
432*32bb5217SDaniel Fojt static int
op_length(const char * src,int offset)433*32bb5217SDaniel Fojt op_length(const char *src, int offset)
4345f4613f2SJohn Marino {
435*32bb5217SDaniel Fojt int result = 0;
436*32bb5217SDaniel Fojt int ch;
437*32bb5217SDaniel Fojt if (offset > 0 && src[offset - 1] == '\\') {
438*32bb5217SDaniel Fojt result = 0;
439*32bb5217SDaniel Fojt } else {
440*32bb5217SDaniel Fojt result++; /* for '%' mark */
441*32bb5217SDaniel Fojt ch = src[offset + result];
442*32bb5217SDaniel Fojt if (TcOutput()) {
443*32bb5217SDaniel Fojt if (ch == '>') {
444*32bb5217SDaniel Fojt result += 3;
445*32bb5217SDaniel Fojt } else if (ch == '+') {
446*32bb5217SDaniel Fojt result += 2;
447*32bb5217SDaniel Fojt } else {
448*32bb5217SDaniel Fojt result++;
449*32bb5217SDaniel Fojt }
450*32bb5217SDaniel Fojt } else if (ch == '\'') {
451*32bb5217SDaniel Fojt result += 3;
452*32bb5217SDaniel Fojt } else if (ch == L_CURL[0]) {
453*32bb5217SDaniel Fojt int n = result;
454*32bb5217SDaniel Fojt while ((ch = src[offset + n]) != '\0') {
455*32bb5217SDaniel Fojt if (ch == R_CURL[0]) {
456*32bb5217SDaniel Fojt result = ++n;
457*32bb5217SDaniel Fojt break;
458*32bb5217SDaniel Fojt }
459*32bb5217SDaniel Fojt n++;
460*32bb5217SDaniel Fojt }
461*32bb5217SDaniel Fojt } else if (strchr("pPg", ch) != 0) {
462*32bb5217SDaniel Fojt result += 2;
463*32bb5217SDaniel Fojt } else {
464*32bb5217SDaniel Fojt result++; /* ordinary operator */
465*32bb5217SDaniel Fojt }
466*32bb5217SDaniel Fojt }
467*32bb5217SDaniel Fojt return result;
468*32bb5217SDaniel Fojt }
4695f4613f2SJohn Marino
470*32bb5217SDaniel Fojt /*
471*32bb5217SDaniel Fojt * When wrapping too-long strings, avoid splitting a backslash sequence, or
472*32bb5217SDaniel Fojt * a terminfo '%' operator. That will leave things a little ragged, but avoids
473*32bb5217SDaniel Fojt * a stray backslash at the end of the line, as well as making the result a
474*32bb5217SDaniel Fojt * little more readable.
475*32bb5217SDaniel Fojt */
476*32bb5217SDaniel Fojt static int
find_split(const char * src,int step,int size)477*32bb5217SDaniel Fojt find_split(const char *src, int step, int size)
478*32bb5217SDaniel Fojt {
479*32bb5217SDaniel Fojt int result = size;
480*32bb5217SDaniel Fojt int n;
481*32bb5217SDaniel Fojt if (size > 0) {
482*32bb5217SDaniel Fojt /* check if that would split a backslash-sequence */
483*32bb5217SDaniel Fojt int mark = size;
484*32bb5217SDaniel Fojt for (n = size - 1; n > 0; --n) {
485*32bb5217SDaniel Fojt int ch = UChar(src[step + n]);
486*32bb5217SDaniel Fojt if (ch == '\\') {
487*32bb5217SDaniel Fojt if (n > 0 && src[step + n - 1] == ch)
488*32bb5217SDaniel Fojt --n;
489*32bb5217SDaniel Fojt mark = n;
490*32bb5217SDaniel Fojt break;
491*32bb5217SDaniel Fojt } else if (!isalnum(ch)) {
492*32bb5217SDaniel Fojt break;
493*32bb5217SDaniel Fojt }
494*32bb5217SDaniel Fojt }
495*32bb5217SDaniel Fojt if (mark < size) {
496*32bb5217SDaniel Fojt result = mark;
497*32bb5217SDaniel Fojt } else {
498*32bb5217SDaniel Fojt /* check if that would split a backslash-sequence */
499*32bb5217SDaniel Fojt for (n = size - 1; n > 0; --n) {
500*32bb5217SDaniel Fojt int ch = UChar(src[step + n]);
501*32bb5217SDaniel Fojt if (ch == '%') {
502*32bb5217SDaniel Fojt int need = op_length(src, step + n);
503*32bb5217SDaniel Fojt if ((n + need) > size) {
504*32bb5217SDaniel Fojt mark = n;
505*32bb5217SDaniel Fojt }
506*32bb5217SDaniel Fojt break;
507*32bb5217SDaniel Fojt }
508*32bb5217SDaniel Fojt }
509*32bb5217SDaniel Fojt if (mark < size) {
510*32bb5217SDaniel Fojt result = mark;
511*32bb5217SDaniel Fojt }
512*32bb5217SDaniel Fojt }
513*32bb5217SDaniel Fojt }
514*32bb5217SDaniel Fojt return result;
515*32bb5217SDaniel Fojt }
516*32bb5217SDaniel Fojt
517*32bb5217SDaniel Fojt /*
518*32bb5217SDaniel Fojt * If we are going to wrap lines, we cannot leave literal spaces because that
519*32bb5217SDaniel Fojt * would be ambiguous if we split on that space.
520*32bb5217SDaniel Fojt */
521*32bb5217SDaniel Fojt static char *
fill_spaces(const char * src)522*32bb5217SDaniel Fojt fill_spaces(const char *src)
523*32bb5217SDaniel Fojt {
524*32bb5217SDaniel Fojt const char *fill = "\\s";
525*32bb5217SDaniel Fojt size_t need = strlen(src);
526*32bb5217SDaniel Fojt size_t size = strlen(fill);
527*32bb5217SDaniel Fojt char *result = 0;
528*32bb5217SDaniel Fojt int pass;
529*32bb5217SDaniel Fojt int s, d;
530*32bb5217SDaniel Fojt for (pass = 0; pass < 2; ++pass) {
531*32bb5217SDaniel Fojt for (s = d = 0; src[s] != '\0'; ++s) {
532*32bb5217SDaniel Fojt if (src[s] == ' ') {
533*32bb5217SDaniel Fojt if (pass) {
534*32bb5217SDaniel Fojt _nc_STRCPY(&result[d], fill, need + 1 - d);
535*32bb5217SDaniel Fojt d += (int) size;
536*32bb5217SDaniel Fojt } else {
537*32bb5217SDaniel Fojt need += size;
538*32bb5217SDaniel Fojt }
539*32bb5217SDaniel Fojt } else {
540*32bb5217SDaniel Fojt if (pass) {
541*32bb5217SDaniel Fojt result[d++] = src[s];
542*32bb5217SDaniel Fojt } else {
543*32bb5217SDaniel Fojt ++d;
544*32bb5217SDaniel Fojt }
545*32bb5217SDaniel Fojt }
546*32bb5217SDaniel Fojt }
547*32bb5217SDaniel Fojt if (pass) {
548*32bb5217SDaniel Fojt result[d] = '\0';
549*32bb5217SDaniel Fojt } else {
550*32bb5217SDaniel Fojt result = malloc(need + 1);
551*32bb5217SDaniel Fojt if (result == 0)
552*32bb5217SDaniel Fojt failed("fill_spaces");
553*32bb5217SDaniel Fojt }
554*32bb5217SDaniel Fojt }
555*32bb5217SDaniel Fojt return result;
556*32bb5217SDaniel Fojt }
557*32bb5217SDaniel Fojt
558*32bb5217SDaniel Fojt typedef enum {
559*32bb5217SDaniel Fojt wOFF = 0
560*32bb5217SDaniel Fojt ,w1ST = 1
561*32bb5217SDaniel Fojt ,w2ND = 2
562*32bb5217SDaniel Fojt ,wEND = 4
563*32bb5217SDaniel Fojt ,wERR = 8
564*32bb5217SDaniel Fojt } WRAPMODE;
565*32bb5217SDaniel Fojt
566*32bb5217SDaniel Fojt #define wrap_1ST(mode) ((mode)&w1ST)
567*32bb5217SDaniel Fojt #define wrap_END(mode) ((mode)&wEND)
568*32bb5217SDaniel Fojt #define wrap_ERR(mode) ((mode)&wERR)
569*32bb5217SDaniel Fojt
570*32bb5217SDaniel Fojt static void
wrap_concat(const char * src,int need,unsigned mode)571*32bb5217SDaniel Fojt wrap_concat(const char *src, int need, unsigned mode)
572*32bb5217SDaniel Fojt {
573*32bb5217SDaniel Fojt int gaps = (int) strlen(separator);
574*32bb5217SDaniel Fojt int want = gaps + need;
575*32bb5217SDaniel Fojt
576*32bb5217SDaniel Fojt did_wrap = (width <= 0);
577*32bb5217SDaniel Fojt if (wrap_1ST(mode)
578*32bb5217SDaniel Fojt && column > indent
579*32bb5217SDaniel Fojt && column + want > width) {
5805f4613f2SJohn Marino force_wrap();
5815f4613f2SJohn Marino }
582*32bb5217SDaniel Fojt if ((wrap_END(mode) && !wrap_ERR(mode)) &&
583*32bb5217SDaniel Fojt wrapped &&
584*32bb5217SDaniel Fojt (width >= 0) &&
585*32bb5217SDaniel Fojt (column + want) > width) {
586*32bb5217SDaniel Fojt int step = 0;
587*32bb5217SDaniel Fojt int used = width > WRAPPED ? width : WRAPPED;
588*32bb5217SDaniel Fojt int size;
589*32bb5217SDaniel Fojt int base = 0;
590*32bb5217SDaniel Fojt char *p, align[9];
591*32bb5217SDaniel Fojt const char *my_t = trailer;
592*32bb5217SDaniel Fojt char *fill = fill_spaces(src);
593*32bb5217SDaniel Fojt int last = (int) strlen(fill);
594*32bb5217SDaniel Fojt
595*32bb5217SDaniel Fojt need = last;
596*32bb5217SDaniel Fojt
597*32bb5217SDaniel Fojt if (TcOutput())
598*32bb5217SDaniel Fojt trailer = "\\\n\t ";
599*32bb5217SDaniel Fojt
600*32bb5217SDaniel Fojt if (!TcOutput() && (p = strchr(fill, '=')) != 0) {
601*32bb5217SDaniel Fojt base = (int) (p + 1 - fill);
602*32bb5217SDaniel Fojt if (base > 8)
603*32bb5217SDaniel Fojt base = 8;
604*32bb5217SDaniel Fojt _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " ");
605*32bb5217SDaniel Fojt } else if (column > 8) {
606*32bb5217SDaniel Fojt base = column - 8;
607*32bb5217SDaniel Fojt if (base > 8)
608*32bb5217SDaniel Fojt base = 8;
609*32bb5217SDaniel Fojt _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " ");
610*32bb5217SDaniel Fojt } else {
611*32bb5217SDaniel Fojt align[base] = '\0';
612*32bb5217SDaniel Fojt }
613*32bb5217SDaniel Fojt /* "pretty" overrides wrapping if it already split the line */
614*32bb5217SDaniel Fojt if (!pretty || strchr(fill, '\n') == 0) {
615*32bb5217SDaniel Fojt int tag = 0;
616*32bb5217SDaniel Fojt
617*32bb5217SDaniel Fojt if (TcOutput() && outbuf.used && !wrap_1ST(mode)) {
618*32bb5217SDaniel Fojt tag = 3;
619*32bb5217SDaniel Fojt }
620*32bb5217SDaniel Fojt
621*32bb5217SDaniel Fojt while ((column + (need + gaps)) > used) {
622*32bb5217SDaniel Fojt size = used - tag;
623*32bb5217SDaniel Fojt if (step) {
624*32bb5217SDaniel Fojt strcpy_DYN(&outbuf, align);
625*32bb5217SDaniel Fojt size -= base;
626*32bb5217SDaniel Fojt }
627*32bb5217SDaniel Fojt if (size > (last - step)) {
628*32bb5217SDaniel Fojt size = (last - step);
629*32bb5217SDaniel Fojt }
630*32bb5217SDaniel Fojt size = find_split(fill, step, size);
631*32bb5217SDaniel Fojt strncpy_DYN(&outbuf, fill + step, (size_t) size);
632*32bb5217SDaniel Fojt step += size;
633*32bb5217SDaniel Fojt need -= size;
634*32bb5217SDaniel Fojt if (need > 0) {
635*32bb5217SDaniel Fojt force_wrap();
636*32bb5217SDaniel Fojt did_wrap = TRUE;
637*32bb5217SDaniel Fojt tag = 0;
638*32bb5217SDaniel Fojt }
639*32bb5217SDaniel Fojt }
640*32bb5217SDaniel Fojt }
641*32bb5217SDaniel Fojt if (need > 0) {
642*32bb5217SDaniel Fojt if (step)
643*32bb5217SDaniel Fojt strcpy_DYN(&outbuf, align);
644*32bb5217SDaniel Fojt strcpy_DYN(&outbuf, fill + step);
645*32bb5217SDaniel Fojt }
646*32bb5217SDaniel Fojt if (wrap_END(mode))
6475f4613f2SJohn Marino strcpy_DYN(&outbuf, separator);
648*32bb5217SDaniel Fojt trailer = my_t;
649*32bb5217SDaniel Fojt force_wrap();
650*32bb5217SDaniel Fojt
651*32bb5217SDaniel Fojt free(fill);
652*32bb5217SDaniel Fojt } else {
653*32bb5217SDaniel Fojt strcpy_DYN(&outbuf, src);
654*32bb5217SDaniel Fojt if (wrap_END(mode))
655*32bb5217SDaniel Fojt strcpy_DYN(&outbuf, separator);
656*32bb5217SDaniel Fojt column += (int) strlen(src);
657*32bb5217SDaniel Fojt }
658*32bb5217SDaniel Fojt }
659*32bb5217SDaniel Fojt
660*32bb5217SDaniel Fojt static void
wrap_concat1(const char * src)661*32bb5217SDaniel Fojt wrap_concat1(const char *src)
662*32bb5217SDaniel Fojt {
663*32bb5217SDaniel Fojt int need = (int) strlen(src);
664*32bb5217SDaniel Fojt wrap_concat(src, need, w1ST | wEND);
665*32bb5217SDaniel Fojt }
666*32bb5217SDaniel Fojt
667*32bb5217SDaniel Fojt static void
wrap_concat3(const char * name,const char * eqls,const char * value)668*32bb5217SDaniel Fojt wrap_concat3(const char *name, const char *eqls, const char *value)
669*32bb5217SDaniel Fojt {
670*32bb5217SDaniel Fojt int nlen = (int) strlen(name);
671*32bb5217SDaniel Fojt int elen = (int) strlen(eqls);
672*32bb5217SDaniel Fojt int vlen = (int) strlen(value);
673*32bb5217SDaniel Fojt
674*32bb5217SDaniel Fojt wrap_concat(name, nlen + elen + vlen, w1ST);
675*32bb5217SDaniel Fojt wrap_concat(eqls, elen + vlen, w2ND);
676*32bb5217SDaniel Fojt wrap_concat(value, vlen, wEND);
6775f4613f2SJohn Marino }
6785f4613f2SJohn Marino
6795f4613f2SJohn Marino #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
6805f4613f2SJohn Marino if ((size_t)(last - first) > sizeof(sep_trail)-1 \
6815f4613f2SJohn Marino && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
6825f4613f2SJohn Marino first += sizeof(sep_trail)-2
6835f4613f2SJohn Marino
6845f4613f2SJohn Marino /* Returns the nominal length of the buffer assuming it is termcap format,
6855f4613f2SJohn Marino * i.e., the continuation sequence is treated as a single character ":".
6865f4613f2SJohn Marino *
6875f4613f2SJohn Marino * There are several implementations of termcap which read the text into a
6885f4613f2SJohn Marino * fixed-size buffer. Generally they strip the newlines from the text, but may
6895f4613f2SJohn Marino * not do it until after the buffer is read. Also, "tc=" resolution may be
6905f4613f2SJohn Marino * expanded in the same buffer. This function is useful for measuring the size
6915f4613f2SJohn Marino * of the best fixed-buffer implementation; the worst case may be much worse.
6925f4613f2SJohn Marino */
6935f4613f2SJohn Marino #ifdef TEST_TERMCAP_LENGTH
6945f4613f2SJohn Marino static int
termcap_length(const char * src)6955f4613f2SJohn Marino termcap_length(const char *src)
6965f4613f2SJohn Marino {
6975f4613f2SJohn Marino static const char pattern[] = ":\\\n\t:";
6985f4613f2SJohn Marino
6995f4613f2SJohn Marino int len = 0;
7005f4613f2SJohn Marino const char *const t = src + strlen(src);
7015f4613f2SJohn Marino
7025f4613f2SJohn Marino while (*src != '\0') {
7035f4613f2SJohn Marino IGNORE_SEP_TRAIL(src, t, pattern);
7045f4613f2SJohn Marino src++;
7055f4613f2SJohn Marino len++;
7065f4613f2SJohn Marino }
7075f4613f2SJohn Marino return len;
7085f4613f2SJohn Marino }
7095f4613f2SJohn Marino #else
7105f4613f2SJohn Marino #define termcap_length(src) strlen(src)
7115f4613f2SJohn Marino #endif
7125f4613f2SJohn Marino
7135f4613f2SJohn Marino static void
indent_DYN(DYNBUF * buffer,int level)7145f4613f2SJohn Marino indent_DYN(DYNBUF * buffer, int level)
7155f4613f2SJohn Marino {
7165f4613f2SJohn Marino int n;
7175f4613f2SJohn Marino
7185f4613f2SJohn Marino for (n = 0; n < level; n++)
7193468e90cSJohn Marino strncpy_DYN(buffer, "\t", (size_t) 1);
7205f4613f2SJohn Marino }
7215f4613f2SJohn Marino
722*32bb5217SDaniel Fojt /*
723*32bb5217SDaniel Fojt * Check if the current line which was begun consists only of a tab and the
724*32bb5217SDaniel Fojt * given leading text.
725*32bb5217SDaniel Fojt */
726*32bb5217SDaniel Fojt static bool
leading_DYN(DYNBUF * buffer,const char * leading)727*32bb5217SDaniel Fojt leading_DYN(DYNBUF * buffer, const char *leading)
728*32bb5217SDaniel Fojt {
729*32bb5217SDaniel Fojt bool result = FALSE;
730*32bb5217SDaniel Fojt size_t need = strlen(leading);
731*32bb5217SDaniel Fojt if (buffer->used > need) {
732*32bb5217SDaniel Fojt need = buffer->used - need;
733*32bb5217SDaniel Fojt if (!strcmp(buffer->text + need, leading)) {
734*32bb5217SDaniel Fojt result = TRUE;
735*32bb5217SDaniel Fojt while (--need != 0) {
736*32bb5217SDaniel Fojt if (buffer->text[need] == '\n') {
737*32bb5217SDaniel Fojt break;
738*32bb5217SDaniel Fojt }
739*32bb5217SDaniel Fojt if (buffer->text[need] != '\t') {
740*32bb5217SDaniel Fojt result = FALSE;
741*32bb5217SDaniel Fojt break;
742*32bb5217SDaniel Fojt }
743*32bb5217SDaniel Fojt }
744*32bb5217SDaniel Fojt }
745*32bb5217SDaniel Fojt }
746*32bb5217SDaniel Fojt return result;
747*32bb5217SDaniel Fojt }
748*32bb5217SDaniel Fojt
7493468e90cSJohn Marino bool
has_params(const char * src)7505f4613f2SJohn Marino has_params(const char *src)
7515f4613f2SJohn Marino {
7525f4613f2SJohn Marino bool result = FALSE;
7535f4613f2SJohn Marino int len = (int) strlen(src);
7545f4613f2SJohn Marino int n;
7555f4613f2SJohn Marino bool ifthen = FALSE;
7565f4613f2SJohn Marino bool params = FALSE;
7575f4613f2SJohn Marino
7585f4613f2SJohn Marino for (n = 0; n < len - 1; ++n) {
7593468e90cSJohn Marino if (!strncmp(src + n, "%p", (size_t) 2)) {
7605f4613f2SJohn Marino params = TRUE;
7613468e90cSJohn Marino } else if (!strncmp(src + n, "%;", (size_t) 2)) {
7625f4613f2SJohn Marino ifthen = TRUE;
7635f4613f2SJohn Marino result = params;
7645f4613f2SJohn Marino break;
7655f4613f2SJohn Marino }
7665f4613f2SJohn Marino }
7675f4613f2SJohn Marino if (!ifthen) {
7685f4613f2SJohn Marino result = ((len > 50) && params);
7695f4613f2SJohn Marino }
7705f4613f2SJohn Marino return result;
7715f4613f2SJohn Marino }
7725f4613f2SJohn Marino
7735f4613f2SJohn Marino static char *
fmt_complex(TERMTYPE2 * tterm,const char * capability,char * src,int level)774*32bb5217SDaniel Fojt fmt_complex(TERMTYPE2 *tterm, const char *capability, char *src, int level)
7755f4613f2SJohn Marino {
7765f4613f2SJohn Marino bool percent = FALSE;
7775f4613f2SJohn Marino bool params = has_params(src);
7785f4613f2SJohn Marino
7795f4613f2SJohn Marino while (*src != '\0') {
7805f4613f2SJohn Marino switch (*src) {
7813468e90cSJohn Marino case '^':
7823468e90cSJohn Marino percent = FALSE;
7833468e90cSJohn Marino strncpy_DYN(&tmpbuf, src++, (size_t) 1);
7843468e90cSJohn Marino break;
7855f4613f2SJohn Marino case '\\':
7865f4613f2SJohn Marino percent = FALSE;
7873468e90cSJohn Marino strncpy_DYN(&tmpbuf, src++, (size_t) 1);
7885f4613f2SJohn Marino break;
7895f4613f2SJohn Marino case '%':
7905f4613f2SJohn Marino percent = TRUE;
7915f4613f2SJohn Marino break;
7925f4613f2SJohn Marino case '?': /* "if" */
7935f4613f2SJohn Marino case 't': /* "then" */
7945f4613f2SJohn Marino case 'e': /* "else" */
7955f4613f2SJohn Marino if (percent) {
7965f4613f2SJohn Marino percent = FALSE;
7975f4613f2SJohn Marino tmpbuf.text[tmpbuf.used - 1] = '\n';
7985f4613f2SJohn Marino /* treat a "%e" as else-if, on the same level */
7995f4613f2SJohn Marino if (*src == 'e') {
8005f4613f2SJohn Marino indent_DYN(&tmpbuf, level);
8013468e90cSJohn Marino strncpy_DYN(&tmpbuf, "%", (size_t) 1);
8023468e90cSJohn Marino strncpy_DYN(&tmpbuf, src, (size_t) 1);
8035f4613f2SJohn Marino src++;
8045f4613f2SJohn Marino params = has_params(src);
8055f4613f2SJohn Marino if (!params && *src != '\0' && *src != '%') {
8063468e90cSJohn Marino strncpy_DYN(&tmpbuf, "\n", (size_t) 1);
8075f4613f2SJohn Marino indent_DYN(&tmpbuf, level + 1);
8085f4613f2SJohn Marino }
8095f4613f2SJohn Marino } else {
8105f4613f2SJohn Marino indent_DYN(&tmpbuf, level + 1);
8113468e90cSJohn Marino strncpy_DYN(&tmpbuf, "%", (size_t) 1);
8123468e90cSJohn Marino strncpy_DYN(&tmpbuf, src, (size_t) 1);
8135f4613f2SJohn Marino if (*src++ == '?') {
8143468e90cSJohn Marino src = fmt_complex(tterm, capability, src, level + 1);
8155f4613f2SJohn Marino if (*src != '\0' && *src != '%') {
8163468e90cSJohn Marino strncpy_DYN(&tmpbuf, "\n", (size_t) 1);
8175f4613f2SJohn Marino indent_DYN(&tmpbuf, level + 1);
8185f4613f2SJohn Marino }
8195f4613f2SJohn Marino } else if (level == 1) {
8203468e90cSJohn Marino if (checking)
8213468e90cSJohn Marino _nc_warning("%s: %%%c without %%? in %s",
8223468e90cSJohn Marino _nc_first_name(tterm->term_names),
8233468e90cSJohn Marino *src, capability);
8245f4613f2SJohn Marino }
8255f4613f2SJohn Marino }
8265f4613f2SJohn Marino continue;
8275f4613f2SJohn Marino }
8285f4613f2SJohn Marino break;
8295f4613f2SJohn Marino case ';': /* "endif" */
8305f4613f2SJohn Marino if (percent) {
8315f4613f2SJohn Marino percent = FALSE;
8325f4613f2SJohn Marino if (level > 1) {
8335f4613f2SJohn Marino tmpbuf.text[tmpbuf.used - 1] = '\n';
8345f4613f2SJohn Marino indent_DYN(&tmpbuf, level);
8353468e90cSJohn Marino strncpy_DYN(&tmpbuf, "%", (size_t) 1);
8363468e90cSJohn Marino strncpy_DYN(&tmpbuf, src++, (size_t) 1);
8373468e90cSJohn Marino if (src[0] == '%'
8383468e90cSJohn Marino && src[1] != '\0'
8393468e90cSJohn Marino && (strchr("?e;", src[1])) == 0) {
8403468e90cSJohn Marino tmpbuf.text[tmpbuf.used++] = '\n';
8413468e90cSJohn Marino indent_DYN(&tmpbuf, level);
8423468e90cSJohn Marino }
8435f4613f2SJohn Marino return src;
8445f4613f2SJohn Marino }
8453468e90cSJohn Marino if (checking)
8463468e90cSJohn Marino _nc_warning("%s: %%; without %%? in %s",
8473468e90cSJohn Marino _nc_first_name(tterm->term_names),
8483468e90cSJohn Marino capability);
8495f4613f2SJohn Marino }
8505f4613f2SJohn Marino break;
8515f4613f2SJohn Marino case 'p':
852*32bb5217SDaniel Fojt if (percent && params && !leading_DYN(&tmpbuf, "%")) {
8535f4613f2SJohn Marino tmpbuf.text[tmpbuf.used - 1] = '\n';
8545f4613f2SJohn Marino indent_DYN(&tmpbuf, level + 1);
8553468e90cSJohn Marino strncpy_DYN(&tmpbuf, "%", (size_t) 1);
8565f4613f2SJohn Marino }
8575f4613f2SJohn Marino params = FALSE;
8585f4613f2SJohn Marino percent = FALSE;
8595f4613f2SJohn Marino break;
8605f4613f2SJohn Marino case ' ':
8613468e90cSJohn Marino strncpy_DYN(&tmpbuf, "\\s", (size_t) 2);
8625f4613f2SJohn Marino ++src;
8635f4613f2SJohn Marino continue;
8645f4613f2SJohn Marino default:
8655f4613f2SJohn Marino percent = FALSE;
8665f4613f2SJohn Marino break;
8675f4613f2SJohn Marino }
8683468e90cSJohn Marino strncpy_DYN(&tmpbuf, src++, (size_t) 1);
8695f4613f2SJohn Marino }
8705f4613f2SJohn Marino return src;
8715f4613f2SJohn Marino }
8725f4613f2SJohn Marino
873*32bb5217SDaniel Fojt /*
874*32bb5217SDaniel Fojt * Make "large" numbers a little easier to read by showing them in hexadecimal
875*32bb5217SDaniel Fojt * if they are "close" to a power of two.
876*32bb5217SDaniel Fojt */
877*32bb5217SDaniel Fojt static const char *
number_format(int value)878*32bb5217SDaniel Fojt number_format(int value)
879*32bb5217SDaniel Fojt {
880*32bb5217SDaniel Fojt const char *result = "%d";
881*32bb5217SDaniel Fojt if ((outform != F_TERMCAP) && (value > 255)) {
882*32bb5217SDaniel Fojt unsigned long lv = (unsigned long) value;
883*32bb5217SDaniel Fojt unsigned long mm;
884*32bb5217SDaniel Fojt int bits = sizeof(unsigned long) * 8;
885*32bb5217SDaniel Fojt int nn;
886*32bb5217SDaniel Fojt for (nn = 8; nn < bits; ++nn) {
887*32bb5217SDaniel Fojt mm = 1UL << nn;
888*32bb5217SDaniel Fojt if ((mm - 16) <= lv && (mm + 16) > lv) {
889*32bb5217SDaniel Fojt result = "%#x";
890*32bb5217SDaniel Fojt break;
891*32bb5217SDaniel Fojt }
892*32bb5217SDaniel Fojt }
893*32bb5217SDaniel Fojt }
894*32bb5217SDaniel Fojt return result;
895*32bb5217SDaniel Fojt }
896*32bb5217SDaniel Fojt
8975f4613f2SJohn Marino #define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap)
8985f4613f2SJohn Marino #define EXTRA_CAP 20
8995f4613f2SJohn Marino
9005f4613f2SJohn Marino int
fmt_entry(TERMTYPE2 * tterm,PredFunc pred,int content_only,int suppress_untranslatable,int infodump,int numbers)901*32bb5217SDaniel Fojt fmt_entry(TERMTYPE2 *tterm,
9025f4613f2SJohn Marino PredFunc pred,
9033468e90cSJohn Marino int content_only,
9043468e90cSJohn Marino int suppress_untranslatable,
9053468e90cSJohn Marino int infodump,
9065f4613f2SJohn Marino int numbers)
9075f4613f2SJohn Marino {
9085f4613f2SJohn Marino PredIdx i, j;
9095f4613f2SJohn Marino char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP];
9105f4613f2SJohn Marino char *capability;
9115f4613f2SJohn Marino NCURSES_CONST char *name;
9125f4613f2SJohn Marino int predval, len;
9135f4613f2SJohn Marino PredIdx num_bools = 0;
9145f4613f2SJohn Marino PredIdx num_values = 0;
9155f4613f2SJohn Marino PredIdx num_strings = 0;
9165f4613f2SJohn Marino bool outcount = 0;
9175f4613f2SJohn Marino
918*32bb5217SDaniel Fojt #define WRAP_CONCAT1(s) wrap_concat1(s); outcount = TRUE
919*32bb5217SDaniel Fojt #define WRAP_CONCAT WRAP_CONCAT1(buffer)
9205f4613f2SJohn Marino
9215f4613f2SJohn Marino len = 12; /* terminfo file-header */
9225f4613f2SJohn Marino
9235f4613f2SJohn Marino if (pred == 0) {
9245f4613f2SJohn Marino cur_type = tterm;
9255f4613f2SJohn Marino pred = dump_predicate;
9265f4613f2SJohn Marino }
9275f4613f2SJohn Marino
9285f4613f2SJohn Marino strcpy_DYN(&outbuf, 0);
9295f4613f2SJohn Marino if (content_only) {
9303468e90cSJohn Marino column = indent; /* FIXME: workaround to prevent empty lines */
9315f4613f2SJohn Marino } else {
9325f4613f2SJohn Marino strcpy_DYN(&outbuf, tterm->term_names);
9333468e90cSJohn Marino
9343468e90cSJohn Marino /*
9353468e90cSJohn Marino * Colon is legal in terminfo descriptions, but not in termcap.
9363468e90cSJohn Marino */
9373468e90cSJohn Marino if (!infodump) {
9383468e90cSJohn Marino char *p = outbuf.text;
9393468e90cSJohn Marino while (*p) {
9403468e90cSJohn Marino if (*p == ':') {
9413468e90cSJohn Marino *p = '=';
9423468e90cSJohn Marino }
9433468e90cSJohn Marino ++p;
9443468e90cSJohn Marino }
9453468e90cSJohn Marino }
9465f4613f2SJohn Marino strcpy_DYN(&outbuf, separator);
9475f4613f2SJohn Marino column = (int) outbuf.used;
9483468e90cSJohn Marino if (height > 1)
9495f4613f2SJohn Marino force_wrap();
9505f4613f2SJohn Marino }
9515f4613f2SJohn Marino
9525f4613f2SJohn Marino for_each_boolean(j, tterm) {
9535f4613f2SJohn Marino i = BoolIndirect(j);
9543468e90cSJohn Marino name = ExtBoolname(tterm, (int) i, bool_names);
9555f4613f2SJohn Marino assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
9565f4613f2SJohn Marino
9575f4613f2SJohn Marino if (!version_filter(BOOLEAN, i))
9585f4613f2SJohn Marino continue;
9595f4613f2SJohn Marino else if (isObsolete(outform, name))
9605f4613f2SJohn Marino continue;
9615f4613f2SJohn Marino
9625f4613f2SJohn Marino predval = pred(BOOLEAN, i);
9635f4613f2SJohn Marino if (predval != FAIL) {
9643468e90cSJohn Marino _nc_STRCPY(buffer, name, sizeof(buffer));
9655f4613f2SJohn Marino if (predval <= 0)
9663468e90cSJohn Marino _nc_STRCAT(buffer, "@", sizeof(buffer));
9675f4613f2SJohn Marino else if (i + 1 > num_bools)
9685f4613f2SJohn Marino num_bools = i + 1;
9695f4613f2SJohn Marino WRAP_CONCAT;
9705f4613f2SJohn Marino }
9715f4613f2SJohn Marino }
9725f4613f2SJohn Marino
9733468e90cSJohn Marino if (column != indent && height > 1)
9745f4613f2SJohn Marino force_wrap();
9755f4613f2SJohn Marino
9765f4613f2SJohn Marino for_each_number(j, tterm) {
9775f4613f2SJohn Marino i = NumIndirect(j);
9783468e90cSJohn Marino name = ExtNumname(tterm, (int) i, num_names);
9795f4613f2SJohn Marino assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
9805f4613f2SJohn Marino
9815f4613f2SJohn Marino if (!version_filter(NUMBER, i))
9825f4613f2SJohn Marino continue;
9835f4613f2SJohn Marino else if (isObsolete(outform, name))
9845f4613f2SJohn Marino continue;
9855f4613f2SJohn Marino
9865f4613f2SJohn Marino predval = pred(NUMBER, i);
9875f4613f2SJohn Marino if (predval != FAIL) {
9885f4613f2SJohn Marino if (tterm->Numbers[i] < 0) {
9893468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
9903468e90cSJohn Marino "%s@", name);
9915f4613f2SJohn Marino } else {
992*32bb5217SDaniel Fojt size_t nn;
9933468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
994*32bb5217SDaniel Fojt "%s#", name);
995*32bb5217SDaniel Fojt nn = strlen(buffer);
996*32bb5217SDaniel Fojt _nc_SPRINTF(buffer + nn, _nc_SLIMIT(sizeof(buffer) - nn)
997*32bb5217SDaniel Fojt number_format(tterm->Numbers[i]),
998*32bb5217SDaniel Fojt tterm->Numbers[i]);
9995f4613f2SJohn Marino if (i + 1 > num_values)
10005f4613f2SJohn Marino num_values = i + 1;
10015f4613f2SJohn Marino }
10025f4613f2SJohn Marino WRAP_CONCAT;
10035f4613f2SJohn Marino }
10045f4613f2SJohn Marino }
10055f4613f2SJohn Marino
10063468e90cSJohn Marino if (column != indent && height > 1)
10075f4613f2SJohn Marino force_wrap();
10085f4613f2SJohn Marino
10095f4613f2SJohn Marino len += (int) (num_bools
10105f4613f2SJohn Marino + num_values * 2
10115f4613f2SJohn Marino + strlen(tterm->term_names) + 1);
10125f4613f2SJohn Marino if (len & 1)
10135f4613f2SJohn Marino len++;
10145f4613f2SJohn Marino
10155f4613f2SJohn Marino #undef CUR
10165f4613f2SJohn Marino #define CUR tterm->
10175f4613f2SJohn Marino if (outform == F_TERMCAP) {
1018*32bb5217SDaniel Fojt if (VALID_STRING(termcap_reset)) {
1019*32bb5217SDaniel Fojt if (VALID_STRING(init_3string)
10205f4613f2SJohn Marino && !strcmp(init_3string, termcap_reset))
10215f4613f2SJohn Marino DISCARD(init_3string);
10225f4613f2SJohn Marino
1023*32bb5217SDaniel Fojt if (VALID_STRING(reset_2string)
10245f4613f2SJohn Marino && !strcmp(reset_2string, termcap_reset))
10255f4613f2SJohn Marino DISCARD(reset_2string);
10265f4613f2SJohn Marino }
10275f4613f2SJohn Marino }
10285f4613f2SJohn Marino
10295f4613f2SJohn Marino for_each_string(j, tterm) {
10305f4613f2SJohn Marino i = StrIndirect(j);
10313468e90cSJohn Marino name = ExtStrname(tterm, (int) i, str_names);
10325f4613f2SJohn Marino assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
10335f4613f2SJohn Marino
10345f4613f2SJohn Marino capability = tterm->Strings[i];
10355f4613f2SJohn Marino
10365f4613f2SJohn Marino if (!version_filter(STRING, i))
10375f4613f2SJohn Marino continue;
10385f4613f2SJohn Marino else if (isObsolete(outform, name))
10395f4613f2SJohn Marino continue;
10405f4613f2SJohn Marino
10415f4613f2SJohn Marino #if NCURSES_XNAMES
10425f4613f2SJohn Marino /*
10435f4613f2SJohn Marino * Extended names can be longer than 2 characters, but termcap programs
10445f4613f2SJohn Marino * cannot read those (filter them out).
10455f4613f2SJohn Marino */
10465f4613f2SJohn Marino if (outform == F_TERMCAP && (strlen(name) > 2))
10475f4613f2SJohn Marino continue;
10485f4613f2SJohn Marino #endif
10495f4613f2SJohn Marino
10505f4613f2SJohn Marino if (outform == F_TERMCAP) {
10515f4613f2SJohn Marino /*
10525f4613f2SJohn Marino * Some older versions of vi want rmir/smir to be defined
10535f4613f2SJohn Marino * for ich/ich1 to work. If they're not defined, force
10545f4613f2SJohn Marino * them to be output as defined and empty.
10555f4613f2SJohn Marino */
10565f4613f2SJohn Marino if (PRESENT(insert_character) || PRESENT(parm_ich)) {
10575f4613f2SJohn Marino if (SAME_CAP(i, enter_insert_mode)
10585f4613f2SJohn Marino && enter_insert_mode == ABSENT_STRING) {
10593468e90cSJohn Marino _nc_STRCPY(buffer, "im=", sizeof(buffer));
10605f4613f2SJohn Marino WRAP_CONCAT;
10615f4613f2SJohn Marino continue;
10625f4613f2SJohn Marino }
10635f4613f2SJohn Marino
10645f4613f2SJohn Marino if (SAME_CAP(i, exit_insert_mode)
10655f4613f2SJohn Marino && exit_insert_mode == ABSENT_STRING) {
10663468e90cSJohn Marino _nc_STRCPY(buffer, "ei=", sizeof(buffer));
10675f4613f2SJohn Marino WRAP_CONCAT;
10685f4613f2SJohn Marino continue;
10695f4613f2SJohn Marino }
10705f4613f2SJohn Marino }
10715f4613f2SJohn Marino /*
10725f4613f2SJohn Marino * termcap applications such as screen will be confused if sgr0
10735f4613f2SJohn Marino * is translated to a string containing rmacs. Filter that out.
10745f4613f2SJohn Marino */
10755f4613f2SJohn Marino if (PRESENT(exit_attribute_mode)) {
10765f4613f2SJohn Marino if (SAME_CAP(i, exit_attribute_mode)) {
10775f4613f2SJohn Marino char *trimmed_sgr0;
10785f4613f2SJohn Marino char *my_sgr = set_attributes;
10795f4613f2SJohn Marino
10805f4613f2SJohn Marino set_attributes = save_sgr;
10815f4613f2SJohn Marino
10825f4613f2SJohn Marino trimmed_sgr0 = _nc_trim_sgr0(tterm);
1083*32bb5217SDaniel Fojt if (strcmp(capability, trimmed_sgr0)) {
10845f4613f2SJohn Marino capability = trimmed_sgr0;
1085*32bb5217SDaniel Fojt } else {
10863468e90cSJohn Marino if (trimmed_sgr0 != exit_attribute_mode)
10873468e90cSJohn Marino free(trimmed_sgr0);
10883468e90cSJohn Marino }
10895f4613f2SJohn Marino
10905f4613f2SJohn Marino set_attributes = my_sgr;
10915f4613f2SJohn Marino }
10925f4613f2SJohn Marino }
10935f4613f2SJohn Marino }
10945f4613f2SJohn Marino
10955f4613f2SJohn Marino predval = pred(STRING, i);
10965f4613f2SJohn Marino buffer[0] = '\0';
10975f4613f2SJohn Marino
10985f4613f2SJohn Marino if (predval != FAIL) {
1099*32bb5217SDaniel Fojt if (VALID_STRING(capability)
11005f4613f2SJohn Marino && i + 1 > num_strings)
11015f4613f2SJohn Marino num_strings = i + 1;
11025f4613f2SJohn Marino
11035f4613f2SJohn Marino if (!VALID_STRING(capability)) {
11043468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
11053468e90cSJohn Marino "%s@", name);
11065f4613f2SJohn Marino WRAP_CONCAT;
1107*32bb5217SDaniel Fojt } else if (TcOutput()) {
11085f4613f2SJohn Marino char *srccap = _nc_tic_expand(capability, TRUE, numbers);
1109*32bb5217SDaniel Fojt int params = ((i < (int) SIZEOF(parametrized))
11103468e90cSJohn Marino ? parametrized[i]
11113468e90cSJohn Marino : ((*srccap == 'k')
11123468e90cSJohn Marino ? 0
11133468e90cSJohn Marino : has_params(srccap)));
11145f4613f2SJohn Marino char *cv = _nc_infotocap(name, srccap, params);
11155f4613f2SJohn Marino
11165f4613f2SJohn Marino if (cv == 0) {
11175f4613f2SJohn Marino if (outform == F_TCONVERR) {
11183468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
11193468e90cSJohn Marino "%s=!!! %s WILL NOT CONVERT !!!",
11205f4613f2SJohn Marino name, srccap);
1121*32bb5217SDaniel Fojt WRAP_CONCAT;
11225f4613f2SJohn Marino } else if (suppress_untranslatable) {
11235f4613f2SJohn Marino continue;
11245f4613f2SJohn Marino } else {
11255f4613f2SJohn Marino char *s = srccap, *d = buffer;
1126*32bb5217SDaniel Fojt int need = 3 + (int) strlen(name);
11275f4613f2SJohn Marino while ((*d = *s++) != 0) {
1128*32bb5217SDaniel Fojt if ((d - buffer + 1) >= (int) sizeof(buffer)) {
1129*32bb5217SDaniel Fojt fprintf(stderr,
1130*32bb5217SDaniel Fojt "%s: value for %s is too long\n",
1131*32bb5217SDaniel Fojt _nc_progname,
1132*32bb5217SDaniel Fojt name);
1133*32bb5217SDaniel Fojt *d = '\0';
1134*32bb5217SDaniel Fojt break;
1135*32bb5217SDaniel Fojt }
11365f4613f2SJohn Marino if (*d == ':') {
11375f4613f2SJohn Marino *d++ = '\\';
11385f4613f2SJohn Marino *d = ':';
11395f4613f2SJohn Marino } else if (*d == '\\') {
1140*32bb5217SDaniel Fojt if ((*++d = *s++) == '\0')
1141*32bb5217SDaniel Fojt break;
11425f4613f2SJohn Marino }
11435f4613f2SJohn Marino d++;
1144*32bb5217SDaniel Fojt *d = '\0';
11455f4613f2SJohn Marino }
1146*32bb5217SDaniel Fojt need += (int) (d - buffer);
1147*32bb5217SDaniel Fojt wrap_concat("..", need, w1ST | wERR);
1148*32bb5217SDaniel Fojt need -= 2;
1149*32bb5217SDaniel Fojt wrap_concat(name, need, wOFF | wERR);
1150*32bb5217SDaniel Fojt need -= (int) strlen(name);
1151*32bb5217SDaniel Fojt wrap_concat("=", need, w2ND | wERR);
1152*32bb5217SDaniel Fojt need -= 1;
1153*32bb5217SDaniel Fojt wrap_concat(buffer, need, wEND | wERR);
1154*32bb5217SDaniel Fojt outcount = TRUE;
11555f4613f2SJohn Marino }
11565f4613f2SJohn Marino } else {
1157*32bb5217SDaniel Fojt wrap_concat3(name, "=", cv);
11585f4613f2SJohn Marino }
11595f4613f2SJohn Marino len += (int) strlen(capability) + 1;
11605f4613f2SJohn Marino } else {
11615f4613f2SJohn Marino char *src = _nc_tic_expand(capability,
11625f4613f2SJohn Marino outform == F_TERMINFO, numbers);
11635f4613f2SJohn Marino
11645f4613f2SJohn Marino strcpy_DYN(&tmpbuf, 0);
11655f4613f2SJohn Marino strcpy_DYN(&tmpbuf, name);
11665f4613f2SJohn Marino strcpy_DYN(&tmpbuf, "=");
11675f4613f2SJohn Marino if (pretty
11685f4613f2SJohn Marino && (outform == F_TERMINFO
11695f4613f2SJohn Marino || outform == F_VARIABLE)) {
11703468e90cSJohn Marino fmt_complex(tterm, name, src, 1);
11715f4613f2SJohn Marino } else {
11725f4613f2SJohn Marino strcpy_DYN(&tmpbuf, src);
11735f4613f2SJohn Marino }
11745f4613f2SJohn Marino len += (int) strlen(capability) + 1;
1175*32bb5217SDaniel Fojt WRAP_CONCAT1(tmpbuf.text);
11765f4613f2SJohn Marino }
11775f4613f2SJohn Marino }
11785f4613f2SJohn Marino /* e.g., trimmed_sgr0 */
1179*32bb5217SDaniel Fojt if (VALID_STRING(capability) &&
11803468e90cSJohn Marino capability != tterm->Strings[i])
11815f4613f2SJohn Marino free(capability);
11825f4613f2SJohn Marino }
11835f4613f2SJohn Marino len += (int) (num_strings * 2);
11845f4613f2SJohn Marino
11855f4613f2SJohn Marino /*
11865f4613f2SJohn Marino * This piece of code should be an effective inverse of the functions
11875f4613f2SJohn Marino * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c.
11885f4613f2SJohn Marino * Much more work should be done on this to support dumping termcaps.
11895f4613f2SJohn Marino */
11905f4613f2SJohn Marino if (tversion == V_HPUX) {
11915f4613f2SJohn Marino if (VALID_STRING(memory_lock)) {
11923468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
11933468e90cSJohn Marino "meml=%s", memory_lock);
11945f4613f2SJohn Marino WRAP_CONCAT;
11955f4613f2SJohn Marino }
11965f4613f2SJohn Marino if (VALID_STRING(memory_unlock)) {
11973468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
11983468e90cSJohn Marino "memu=%s", memory_unlock);
11995f4613f2SJohn Marino WRAP_CONCAT;
12005f4613f2SJohn Marino }
12015f4613f2SJohn Marino } else if (tversion == V_AIX) {
12025f4613f2SJohn Marino if (VALID_STRING(acs_chars)) {
12035f4613f2SJohn Marino bool box_ok = TRUE;
12045f4613f2SJohn Marino const char *acstrans = "lqkxjmwuvtn";
12055f4613f2SJohn Marino const char *cp;
12065f4613f2SJohn Marino char *tp, *sp, boxchars[11];
12075f4613f2SJohn Marino
12085f4613f2SJohn Marino tp = boxchars;
12095f4613f2SJohn Marino for (cp = acstrans; *cp; cp++) {
12103468e90cSJohn Marino sp = (strchr) (acs_chars, *cp);
12115f4613f2SJohn Marino if (sp)
12125f4613f2SJohn Marino *tp++ = sp[1];
12135f4613f2SJohn Marino else {
12145f4613f2SJohn Marino box_ok = FALSE;
12155f4613f2SJohn Marino break;
12165f4613f2SJohn Marino }
12175f4613f2SJohn Marino }
12185f4613f2SJohn Marino tp[0] = '\0';
12195f4613f2SJohn Marino
12205f4613f2SJohn Marino if (box_ok) {
12213468e90cSJohn Marino char *tmp = _nc_tic_expand(boxchars,
12223468e90cSJohn Marino (outform == F_TERMINFO),
12233468e90cSJohn Marino numbers);
12243468e90cSJohn Marino _nc_STRCPY(buffer, "box1=", sizeof(buffer));
12253468e90cSJohn Marino while (*tmp != '\0') {
12263468e90cSJohn Marino size_t have = strlen(buffer);
12273468e90cSJohn Marino size_t next = strlen(tmp);
12283468e90cSJohn Marino size_t want = have + next + 1;
12293468e90cSJohn Marino size_t last = next;
12303468e90cSJohn Marino char save = '\0';
12313468e90cSJohn Marino
12323468e90cSJohn Marino /*
12333468e90cSJohn Marino * If the expanded string is too long for the buffer,
12343468e90cSJohn Marino * chop it off and save the location where we chopped it.
12353468e90cSJohn Marino */
12363468e90cSJohn Marino if (want >= sizeof(buffer)) {
12373468e90cSJohn Marino save = tmp[last];
12383468e90cSJohn Marino tmp[last] = '\0';
12393468e90cSJohn Marino }
12403468e90cSJohn Marino _nc_STRCAT(buffer, tmp, sizeof(buffer));
12413468e90cSJohn Marino
12423468e90cSJohn Marino /*
12433468e90cSJohn Marino * If we chopped the buffer, replace the missing piece and
12443468e90cSJohn Marino * shift everything to append the remainder.
12453468e90cSJohn Marino */
12463468e90cSJohn Marino if (save != '\0') {
12473468e90cSJohn Marino next = 0;
12483468e90cSJohn Marino tmp[last] = save;
12493468e90cSJohn Marino while ((tmp[next] = tmp[last + next]) != '\0') {
12503468e90cSJohn Marino ++next;
12513468e90cSJohn Marino }
12523468e90cSJohn Marino } else {
12533468e90cSJohn Marino break;
12543468e90cSJohn Marino }
12553468e90cSJohn Marino }
12565f4613f2SJohn Marino WRAP_CONCAT;
12575f4613f2SJohn Marino }
12585f4613f2SJohn Marino }
12595f4613f2SJohn Marino }
12605f4613f2SJohn Marino
12615f4613f2SJohn Marino /*
12625f4613f2SJohn Marino * kludge: trim off trailer to avoid an extra blank line
12635f4613f2SJohn Marino * in infocmp -u output when there are no string differences
12645f4613f2SJohn Marino */
12655f4613f2SJohn Marino if (outcount) {
12665f4613f2SJohn Marino bool trimmed = FALSE;
12673468e90cSJohn Marino j = (PredIdx) outbuf.used;
1268*32bb5217SDaniel Fojt if (wrapped && did_wrap) {
1269*32bb5217SDaniel Fojt /* EMPTY */ ;
1270*32bb5217SDaniel Fojt } else if (j >= 2
12715f4613f2SJohn Marino && outbuf.text[j - 1] == '\t'
12725f4613f2SJohn Marino && outbuf.text[j - 2] == '\n') {
12735f4613f2SJohn Marino outbuf.used -= 2;
12745f4613f2SJohn Marino trimmed = TRUE;
12755f4613f2SJohn Marino } else if (j >= 4
12765f4613f2SJohn Marino && outbuf.text[j - 1] == ':'
12775f4613f2SJohn Marino && outbuf.text[j - 2] == '\t'
12785f4613f2SJohn Marino && outbuf.text[j - 3] == '\n'
12795f4613f2SJohn Marino && outbuf.text[j - 4] == '\\') {
12805f4613f2SJohn Marino outbuf.used -= 4;
12815f4613f2SJohn Marino trimmed = TRUE;
12825f4613f2SJohn Marino }
12835f4613f2SJohn Marino if (trimmed) {
12845f4613f2SJohn Marino outbuf.text[outbuf.used] = '\0';
12855f4613f2SJohn Marino column = oldcol;
12865f4613f2SJohn Marino strcpy_DYN(&outbuf, " ");
12875f4613f2SJohn Marino }
12885f4613f2SJohn Marino }
12895f4613f2SJohn Marino #if 0
12905f4613f2SJohn Marino fprintf(stderr, "num_bools = %d\n", num_bools);
12915f4613f2SJohn Marino fprintf(stderr, "num_values = %d\n", num_values);
12925f4613f2SJohn Marino fprintf(stderr, "num_strings = %d\n", num_strings);
12935f4613f2SJohn Marino fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
12945f4613f2SJohn Marino tterm->term_names, len, outbuf.used, outbuf.text);
12955f4613f2SJohn Marino #endif
12965f4613f2SJohn Marino /*
12975f4613f2SJohn Marino * Here's where we use infodump to trigger a more stringent length check
12985f4613f2SJohn Marino * for termcap-translation purposes.
12995f4613f2SJohn Marino * Return the length of the raw entry, without tc= expansions,
13005f4613f2SJohn Marino * It gives an idea of which entries are deadly to even *scan past*,
13015f4613f2SJohn Marino * as opposed to *use*.
13025f4613f2SJohn Marino */
13035f4613f2SJohn Marino return (infodump ? len : (int) termcap_length(outbuf.text));
13045f4613f2SJohn Marino }
13055f4613f2SJohn Marino
13065f4613f2SJohn Marino static bool
kill_string(TERMTYPE2 * tterm,char * cap)1307*32bb5217SDaniel Fojt kill_string(TERMTYPE2 *tterm, char *cap)
13085f4613f2SJohn Marino {
13095f4613f2SJohn Marino unsigned n;
13105f4613f2SJohn Marino for (n = 0; n < NUM_STRINGS(tterm); ++n) {
13115f4613f2SJohn Marino if (cap == tterm->Strings[n]) {
13125f4613f2SJohn Marino tterm->Strings[n] = ABSENT_STRING;
13135f4613f2SJohn Marino return TRUE;
13145f4613f2SJohn Marino }
13155f4613f2SJohn Marino }
13165f4613f2SJohn Marino return FALSE;
13175f4613f2SJohn Marino }
13185f4613f2SJohn Marino
13195f4613f2SJohn Marino static char *
find_string(TERMTYPE2 * tterm,char * name)1320*32bb5217SDaniel Fojt find_string(TERMTYPE2 *tterm, char *name)
13215f4613f2SJohn Marino {
13225f4613f2SJohn Marino PredIdx n;
13235f4613f2SJohn Marino for (n = 0; n < NUM_STRINGS(tterm); ++n) {
13245f4613f2SJohn Marino if (version_filter(STRING, n)
13255f4613f2SJohn Marino && !strcmp(name, strnames[n])) {
13265f4613f2SJohn Marino char *cap = tterm->Strings[n];
13275f4613f2SJohn Marino if (VALID_STRING(cap)) {
13285f4613f2SJohn Marino return cap;
13295f4613f2SJohn Marino }
13305f4613f2SJohn Marino break;
13315f4613f2SJohn Marino }
13325f4613f2SJohn Marino }
13335f4613f2SJohn Marino return ABSENT_STRING;
13345f4613f2SJohn Marino }
13355f4613f2SJohn Marino
13365f4613f2SJohn Marino /*
13375f4613f2SJohn Marino * This is used to remove function-key labels from a termcap entry to
13385f4613f2SJohn Marino * make it smaller.
13395f4613f2SJohn Marino */
13405f4613f2SJohn Marino static int
kill_labels(TERMTYPE2 * tterm,int target)1341*32bb5217SDaniel Fojt kill_labels(TERMTYPE2 *tterm, int target)
13425f4613f2SJohn Marino {
13435f4613f2SJohn Marino int n;
13445f4613f2SJohn Marino int result = 0;
13455f4613f2SJohn Marino char *cap;
13465f4613f2SJohn Marino char name[10];
13475f4613f2SJohn Marino
13485f4613f2SJohn Marino for (n = 0; n <= 10; ++n) {
13493468e90cSJohn Marino _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n);
1350*32bb5217SDaniel Fojt cap = find_string(tterm, name);
1351*32bb5217SDaniel Fojt if (VALID_STRING(cap)
13525f4613f2SJohn Marino && kill_string(tterm, cap)) {
13535f4613f2SJohn Marino target -= (int) (strlen(cap) + 5);
13545f4613f2SJohn Marino ++result;
13555f4613f2SJohn Marino if (target < 0)
13565f4613f2SJohn Marino break;
13575f4613f2SJohn Marino }
13585f4613f2SJohn Marino }
13595f4613f2SJohn Marino return result;
13605f4613f2SJohn Marino }
13615f4613f2SJohn Marino
13625f4613f2SJohn Marino /*
13635f4613f2SJohn Marino * This is used to remove function-key definitions from a termcap entry to
13645f4613f2SJohn Marino * make it smaller.
13655f4613f2SJohn Marino */
13665f4613f2SJohn Marino static int
kill_fkeys(TERMTYPE2 * tterm,int target)1367*32bb5217SDaniel Fojt kill_fkeys(TERMTYPE2 *tterm, int target)
13685f4613f2SJohn Marino {
13695f4613f2SJohn Marino int n;
13705f4613f2SJohn Marino int result = 0;
13715f4613f2SJohn Marino char *cap;
13725f4613f2SJohn Marino char name[10];
13735f4613f2SJohn Marino
13745f4613f2SJohn Marino for (n = 60; n >= 0; --n) {
13753468e90cSJohn Marino _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n);
1376*32bb5217SDaniel Fojt cap = find_string(tterm, name);
1377*32bb5217SDaniel Fojt if (VALID_STRING(cap)
13785f4613f2SJohn Marino && kill_string(tterm, cap)) {
13795f4613f2SJohn Marino target -= (int) (strlen(cap) + 5);
13805f4613f2SJohn Marino ++result;
13815f4613f2SJohn Marino if (target < 0)
13825f4613f2SJohn Marino break;
13835f4613f2SJohn Marino }
13845f4613f2SJohn Marino }
13855f4613f2SJohn Marino return result;
13865f4613f2SJohn Marino }
13875f4613f2SJohn Marino
13885f4613f2SJohn Marino /*
13895f4613f2SJohn Marino * Check if the given acsc string is a 1-1 mapping, i.e., just-like-vt100.
13905f4613f2SJohn Marino * Also, since this is for termcap, we only care about the line-drawing map.
13915f4613f2SJohn Marino */
13925f4613f2SJohn Marino #define isLine(c) (strchr("lmkjtuvwqxn", c) != 0)
13935f4613f2SJohn Marino
13945f4613f2SJohn Marino static bool
one_one_mapping(const char * mapping)13955f4613f2SJohn Marino one_one_mapping(const char *mapping)
13965f4613f2SJohn Marino {
13975f4613f2SJohn Marino bool result = TRUE;
13985f4613f2SJohn Marino
1399*32bb5217SDaniel Fojt if (VALID_STRING(mapping)) {
14005f4613f2SJohn Marino int n = 0;
1401*32bb5217SDaniel Fojt while (mapping[n] != '\0' && mapping[n + 1] != '\0') {
14025f4613f2SJohn Marino if (isLine(mapping[n]) &&
14035f4613f2SJohn Marino mapping[n] != mapping[n + 1]) {
14045f4613f2SJohn Marino result = FALSE;
14055f4613f2SJohn Marino break;
14065f4613f2SJohn Marino }
14075f4613f2SJohn Marino n += 2;
14085f4613f2SJohn Marino }
14095f4613f2SJohn Marino }
14105f4613f2SJohn Marino return result;
14115f4613f2SJohn Marino }
14125f4613f2SJohn Marino
14135f4613f2SJohn Marino #define FMT_ENTRY() \
14145f4613f2SJohn Marino fmt_entry(tterm, pred, \
14155f4613f2SJohn Marino 0, \
14165f4613f2SJohn Marino suppress_untranslatable, \
14175f4613f2SJohn Marino infodump, numbers)
14185f4613f2SJohn Marino
14195f4613f2SJohn Marino #define SHOW_WHY PRINTF
14205f4613f2SJohn Marino
14215f4613f2SJohn Marino static bool
purged_acs(TERMTYPE2 * tterm)1422*32bb5217SDaniel Fojt purged_acs(TERMTYPE2 *tterm)
14235f4613f2SJohn Marino {
14245f4613f2SJohn Marino bool result = FALSE;
14255f4613f2SJohn Marino
14265f4613f2SJohn Marino if (VALID_STRING(acs_chars)) {
14275f4613f2SJohn Marino if (!one_one_mapping(acs_chars)) {
14285f4613f2SJohn Marino enter_alt_charset_mode = ABSENT_STRING;
14295f4613f2SJohn Marino exit_alt_charset_mode = ABSENT_STRING;
14305f4613f2SJohn Marino SHOW_WHY("# (rmacs/smacs removed for consistency)\n");
14315f4613f2SJohn Marino }
14325f4613f2SJohn Marino result = TRUE;
14335f4613f2SJohn Marino }
14345f4613f2SJohn Marino return result;
14355f4613f2SJohn Marino }
14365f4613f2SJohn Marino
14373468e90cSJohn Marino static void
encode_b64(char * target,char * source,unsigned state,int * saved)14383468e90cSJohn Marino encode_b64(char *target, char *source, unsigned state, int *saved)
14393468e90cSJohn Marino {
14403468e90cSJohn Marino /* RFC-4648 */
14413468e90cSJohn Marino static const char data[] =
14423468e90cSJohn Marino "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
14433468e90cSJohn Marino "abcdefghijklmnopqrstuvwxyz"
14443468e90cSJohn Marino "0123456789" "-_";
14453468e90cSJohn Marino int ch = UChar(source[state]);
14463468e90cSJohn Marino
14473468e90cSJohn Marino switch (state % 3) {
14483468e90cSJohn Marino case 0:
1449*32bb5217SDaniel Fojt *target++ = data[(ch >> 2) & 077];
1450*32bb5217SDaniel Fojt *saved = (ch << 4);
14513468e90cSJohn Marino break;
14523468e90cSJohn Marino case 1:
1453*32bb5217SDaniel Fojt *target++ = data[((ch >> 4) | *saved) & 077];
1454*32bb5217SDaniel Fojt *saved = (ch << 2);
14553468e90cSJohn Marino break;
14563468e90cSJohn Marino case 2:
1457*32bb5217SDaniel Fojt *target++ = data[((ch >> 6) | *saved) & 077];
1458*32bb5217SDaniel Fojt *target++ = data[ch & 077];
14593468e90cSJohn Marino *saved = 0;
14603468e90cSJohn Marino break;
14613468e90cSJohn Marino }
14623468e90cSJohn Marino *target = '\0';
14633468e90cSJohn Marino }
14643468e90cSJohn Marino
14655f4613f2SJohn Marino /*
14665f4613f2SJohn Marino * Dump a single entry.
14675f4613f2SJohn Marino */
14685f4613f2SJohn Marino void
dump_entry(TERMTYPE2 * tterm,int suppress_untranslatable,int limited,int numbers,PredFunc pred)1469*32bb5217SDaniel Fojt dump_entry(TERMTYPE2 *tterm,
14703468e90cSJohn Marino int suppress_untranslatable,
14713468e90cSJohn Marino int limited,
14725f4613f2SJohn Marino int numbers,
14735f4613f2SJohn Marino PredFunc pred)
14745f4613f2SJohn Marino {
1475*32bb5217SDaniel Fojt TERMTYPE2 save_tterm;
14765f4613f2SJohn Marino int len, critlen;
14775f4613f2SJohn Marino const char *legend;
14785f4613f2SJohn Marino bool infodump;
14795f4613f2SJohn Marino
14803468e90cSJohn Marino if (quickdump) {
14813468e90cSJohn Marino char bigbuf[65536];
14823468e90cSJohn Marino unsigned n;
14833468e90cSJohn Marino unsigned offset = 0;
14843468e90cSJohn Marino separator = "";
14853468e90cSJohn Marino trailer = "\n";
14863468e90cSJohn Marino indent = 0;
14873468e90cSJohn Marino if (_nc_write_object(tterm, bigbuf, &offset, sizeof(bigbuf)) == OK) {
14883468e90cSJohn Marino char numbuf[80];
14893468e90cSJohn Marino if (quickdump & 1) {
14903468e90cSJohn Marino if (outbuf.used)
1491*32bb5217SDaniel Fojt wrap_concat1("\n");
1492*32bb5217SDaniel Fojt wrap_concat1("hex:");
14933468e90cSJohn Marino for (n = 0; n < offset; ++n) {
1494*32bb5217SDaniel Fojt _nc_SPRINTF(numbuf, _nc_SLIMIT(sizeof(numbuf))
1495*32bb5217SDaniel Fojt "%02X", UChar(bigbuf[n]));
1496*32bb5217SDaniel Fojt wrap_concat1(numbuf);
14973468e90cSJohn Marino }
14983468e90cSJohn Marino }
14993468e90cSJohn Marino if (quickdump & 2) {
1500*32bb5217SDaniel Fojt static char padding[] =
1501*32bb5217SDaniel Fojt {0, 0};
15023468e90cSJohn Marino int value = 0;
15033468e90cSJohn Marino if (outbuf.used)
1504*32bb5217SDaniel Fojt wrap_concat1("\n");
1505*32bb5217SDaniel Fojt wrap_concat1("b64:");
15063468e90cSJohn Marino for (n = 0; n < offset; ++n) {
15073468e90cSJohn Marino encode_b64(numbuf, bigbuf, n, &value);
1508*32bb5217SDaniel Fojt wrap_concat1(numbuf);
15093468e90cSJohn Marino }
15103468e90cSJohn Marino switch (n % 3) {
15113468e90cSJohn Marino case 0:
15123468e90cSJohn Marino break;
15133468e90cSJohn Marino case 1:
1514*32bb5217SDaniel Fojt encode_b64(numbuf, padding, 1, &value);
1515*32bb5217SDaniel Fojt wrap_concat1(numbuf);
1516*32bb5217SDaniel Fojt wrap_concat1("==");
15173468e90cSJohn Marino break;
15183468e90cSJohn Marino case 2:
1519*32bb5217SDaniel Fojt encode_b64(numbuf, padding, 1, &value);
1520*32bb5217SDaniel Fojt wrap_concat1(numbuf);
1521*32bb5217SDaniel Fojt wrap_concat1("=");
15223468e90cSJohn Marino break;
15233468e90cSJohn Marino }
15243468e90cSJohn Marino }
15253468e90cSJohn Marino }
15263468e90cSJohn Marino return;
15273468e90cSJohn Marino }
15283468e90cSJohn Marino
1529*32bb5217SDaniel Fojt if (TcOutput()) {
15305f4613f2SJohn Marino critlen = MAX_TERMCAP_LENGTH;
15315f4613f2SJohn Marino legend = "older termcap";
15325f4613f2SJohn Marino infodump = FALSE;
15335f4613f2SJohn Marino set_obsolete_termcaps(tterm);
15345f4613f2SJohn Marino } else {
15355f4613f2SJohn Marino critlen = MAX_TERMINFO_LENGTH;
15365f4613f2SJohn Marino legend = "terminfo";
15375f4613f2SJohn Marino infodump = TRUE;
15385f4613f2SJohn Marino }
15395f4613f2SJohn Marino
15405f4613f2SJohn Marino save_sgr = set_attributes;
15415f4613f2SJohn Marino
15425f4613f2SJohn Marino if ((FMT_ENTRY() > critlen)
15435f4613f2SJohn Marino && limited) {
15445f4613f2SJohn Marino
15455f4613f2SJohn Marino save_tterm = *tterm;
15465f4613f2SJohn Marino if (!suppress_untranslatable) {
15475f4613f2SJohn Marino SHOW_WHY("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
15485f4613f2SJohn Marino critlen);
15495f4613f2SJohn Marino suppress_untranslatable = TRUE;
15505f4613f2SJohn Marino }
15515f4613f2SJohn Marino if (FMT_ENTRY() > critlen) {
15525f4613f2SJohn Marino /*
15535f4613f2SJohn Marino * We pick on sgr because it's a nice long string capability that
15545f4613f2SJohn Marino * is really just an optimization hack. Another good candidate is
15555f4613f2SJohn Marino * acsc since it is both long and unused by BSD termcap.
15565f4613f2SJohn Marino */
15575f4613f2SJohn Marino bool changed = FALSE;
15585f4613f2SJohn Marino
15595f4613f2SJohn Marino #if NCURSES_XNAMES
15605f4613f2SJohn Marino /*
15615f4613f2SJohn Marino * Extended names are most likely function-key definitions. Drop
15625f4613f2SJohn Marino * those first.
15635f4613f2SJohn Marino */
15645f4613f2SJohn Marino unsigned n;
15655f4613f2SJohn Marino for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) {
15663468e90cSJohn Marino const char *name = ExtStrname(tterm, (int) n, strnames);
15675f4613f2SJohn Marino
15685f4613f2SJohn Marino if (VALID_STRING(tterm->Strings[n])) {
15695f4613f2SJohn Marino set_attributes = ABSENT_STRING;
15705f4613f2SJohn Marino /* we remove long names anyway - only report the short */
15715f4613f2SJohn Marino if (strlen(name) <= 2) {
15725f4613f2SJohn Marino SHOW_WHY("# (%s removed to fit entry within %d bytes)\n",
15735f4613f2SJohn Marino name,
15745f4613f2SJohn Marino critlen);
15755f4613f2SJohn Marino }
15765f4613f2SJohn Marino changed = TRUE;
15775f4613f2SJohn Marino if (FMT_ENTRY() <= critlen)
15785f4613f2SJohn Marino break;
15795f4613f2SJohn Marino }
15805f4613f2SJohn Marino }
15815f4613f2SJohn Marino #endif
15825f4613f2SJohn Marino if (VALID_STRING(set_attributes)) {
15835f4613f2SJohn Marino set_attributes = ABSENT_STRING;
15845f4613f2SJohn Marino SHOW_WHY("# (sgr removed to fit entry within %d bytes)\n",
15855f4613f2SJohn Marino critlen);
15865f4613f2SJohn Marino changed = TRUE;
15875f4613f2SJohn Marino }
15885f4613f2SJohn Marino if (!changed || (FMT_ENTRY() > critlen)) {
15895f4613f2SJohn Marino if (purged_acs(tterm)) {
15905f4613f2SJohn Marino acs_chars = ABSENT_STRING;
15915f4613f2SJohn Marino SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n",
15925f4613f2SJohn Marino critlen);
15935f4613f2SJohn Marino changed = TRUE;
15945f4613f2SJohn Marino }
15955f4613f2SJohn Marino }
15965f4613f2SJohn Marino if (!changed || (FMT_ENTRY() > critlen)) {
15975f4613f2SJohn Marino int oldversion = tversion;
15985f4613f2SJohn Marino
15995f4613f2SJohn Marino tversion = V_BSD;
16005f4613f2SJohn Marino SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
16015f4613f2SJohn Marino critlen);
16025f4613f2SJohn Marino
16035f4613f2SJohn Marino len = FMT_ENTRY();
16045f4613f2SJohn Marino if (len > critlen
16055f4613f2SJohn Marino && kill_labels(tterm, len - critlen)) {
16065f4613f2SJohn Marino SHOW_WHY("# (some labels capabilities suppressed to fit entry within %d bytes)\n",
16075f4613f2SJohn Marino critlen);
16085f4613f2SJohn Marino len = FMT_ENTRY();
16095f4613f2SJohn Marino }
16105f4613f2SJohn Marino if (len > critlen
16115f4613f2SJohn Marino && kill_fkeys(tterm, len - critlen)) {
16125f4613f2SJohn Marino SHOW_WHY("# (some function-key capabilities suppressed to fit entry within %d bytes)\n",
16135f4613f2SJohn Marino critlen);
16145f4613f2SJohn Marino len = FMT_ENTRY();
16155f4613f2SJohn Marino }
16165f4613f2SJohn Marino if (len > critlen) {
16175f4613f2SJohn Marino (void) fprintf(stderr,
1618*32bb5217SDaniel Fojt "%s: %s entry is %d bytes long\n",
1619*32bb5217SDaniel Fojt _nc_progname,
16205f4613f2SJohn Marino _nc_first_name(tterm->term_names),
16215f4613f2SJohn Marino len);
16225f4613f2SJohn Marino SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
16235f4613f2SJohn Marino len, legend);
16245f4613f2SJohn Marino }
16255f4613f2SJohn Marino tversion = oldversion;
16265f4613f2SJohn Marino }
16275f4613f2SJohn Marino set_attributes = save_sgr;
16285f4613f2SJohn Marino *tterm = save_tterm;
16295f4613f2SJohn Marino }
16305f4613f2SJohn Marino } else if (!version_filter(STRING, STR_IDX(acs_chars))) {
16315f4613f2SJohn Marino save_tterm = *tterm;
16325f4613f2SJohn Marino if (purged_acs(tterm)) {
16335f4613f2SJohn Marino (void) FMT_ENTRY();
16345f4613f2SJohn Marino }
16355f4613f2SJohn Marino *tterm = save_tterm;
16365f4613f2SJohn Marino }
16375f4613f2SJohn Marino }
16385f4613f2SJohn Marino
16395f4613f2SJohn Marino void
dump_uses(const char * name,bool infodump)16405f4613f2SJohn Marino dump_uses(const char *name, bool infodump)
16415f4613f2SJohn Marino /* dump "use=" clauses in the appropriate format */
16425f4613f2SJohn Marino {
16435f4613f2SJohn Marino char buffer[MAX_TERMINFO_LENGTH];
16445f4613f2SJohn Marino
1645*32bb5217SDaniel Fojt if (TcOutput())
16465f4613f2SJohn Marino trim_trailing();
16473468e90cSJohn Marino _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
16483468e90cSJohn Marino "%s%s", infodump ? "use=" : "tc=", name);
1649*32bb5217SDaniel Fojt wrap_concat1(buffer);
16505f4613f2SJohn Marino }
16515f4613f2SJohn Marino
16525f4613f2SJohn Marino int
show_entry(void)16535f4613f2SJohn Marino show_entry(void)
16545f4613f2SJohn Marino {
16553468e90cSJohn Marino /*
16563468e90cSJohn Marino * Trim any remaining whitespace.
16573468e90cSJohn Marino */
16583468e90cSJohn Marino if (outbuf.used != 0) {
1659*32bb5217SDaniel Fojt bool infodump = !TcOutput();
16603468e90cSJohn Marino char delim = (char) (infodump ? ',' : ':');
16613468e90cSJohn Marino int j;
16623468e90cSJohn Marino
16633468e90cSJohn Marino for (j = (int) outbuf.used - 1; j > 0; --j) {
16643468e90cSJohn Marino char ch = outbuf.text[j];
16653468e90cSJohn Marino if (ch == '\n') {
16663468e90cSJohn Marino ;
16673468e90cSJohn Marino } else if (isspace(UChar(ch))) {
16683468e90cSJohn Marino outbuf.used = (size_t) j;
16693468e90cSJohn Marino } else if (!infodump && ch == '\\') {
16703468e90cSJohn Marino outbuf.used = (size_t) j;
16713468e90cSJohn Marino } else if (ch == delim && (j == 0 || outbuf.text[j - 1] != '\\')) {
16723468e90cSJohn Marino outbuf.used = (size_t) (j + 1);
16733468e90cSJohn Marino } else {
16743468e90cSJohn Marino break;
16753468e90cSJohn Marino }
16763468e90cSJohn Marino }
16773468e90cSJohn Marino outbuf.text[outbuf.used] = '\0';
16783468e90cSJohn Marino }
16793468e90cSJohn Marino if (outbuf.text != 0) {
16805f4613f2SJohn Marino (void) fputs(outbuf.text, stdout);
16815f4613f2SJohn Marino putchar('\n');
16823468e90cSJohn Marino }
16835f4613f2SJohn Marino return (int) outbuf.used;
16845f4613f2SJohn Marino }
16855f4613f2SJohn Marino
16865f4613f2SJohn Marino void
compare_entry(PredHook hook,TERMTYPE2 * tp GCC_UNUSED,bool quiet)16873468e90cSJohn Marino compare_entry(PredHook hook,
1688*32bb5217SDaniel Fojt TERMTYPE2 *tp GCC_UNUSED,
16895f4613f2SJohn Marino bool quiet)
16905f4613f2SJohn Marino /* compare two entries */
16915f4613f2SJohn Marino {
16925f4613f2SJohn Marino PredIdx i, j;
16935f4613f2SJohn Marino NCURSES_CONST char *name;
16945f4613f2SJohn Marino
16955f4613f2SJohn Marino if (!quiet)
16965f4613f2SJohn Marino fputs(" comparing booleans.\n", stdout);
16975f4613f2SJohn Marino for_each_boolean(j, tp) {
16985f4613f2SJohn Marino i = BoolIndirect(j);
16993468e90cSJohn Marino name = ExtBoolname(tp, (int) i, bool_names);
17005f4613f2SJohn Marino
17015f4613f2SJohn Marino if (isObsolete(outform, name))
17025f4613f2SJohn Marino continue;
17035f4613f2SJohn Marino
17045f4613f2SJohn Marino (*hook) (CMP_BOOLEAN, i, name);
17055f4613f2SJohn Marino }
17065f4613f2SJohn Marino
17075f4613f2SJohn Marino if (!quiet)
17085f4613f2SJohn Marino fputs(" comparing numbers.\n", stdout);
17095f4613f2SJohn Marino for_each_number(j, tp) {
17105f4613f2SJohn Marino i = NumIndirect(j);
17113468e90cSJohn Marino name = ExtNumname(tp, (int) i, num_names);
17125f4613f2SJohn Marino
17135f4613f2SJohn Marino if (isObsolete(outform, name))
17145f4613f2SJohn Marino continue;
17155f4613f2SJohn Marino
17165f4613f2SJohn Marino (*hook) (CMP_NUMBER, i, name);
17175f4613f2SJohn Marino }
17185f4613f2SJohn Marino
17195f4613f2SJohn Marino if (!quiet)
17205f4613f2SJohn Marino fputs(" comparing strings.\n", stdout);
17215f4613f2SJohn Marino for_each_string(j, tp) {
17225f4613f2SJohn Marino i = StrIndirect(j);
17233468e90cSJohn Marino name = ExtStrname(tp, (int) i, str_names);
17245f4613f2SJohn Marino
17255f4613f2SJohn Marino if (isObsolete(outform, name))
17265f4613f2SJohn Marino continue;
17275f4613f2SJohn Marino
17285f4613f2SJohn Marino (*hook) (CMP_STRING, i, name);
17295f4613f2SJohn Marino }
17305f4613f2SJohn Marino
17315f4613f2SJohn Marino /* (void) fputs(" comparing use entries.\n", stdout); */
17325f4613f2SJohn Marino (*hook) (CMP_USE, 0, "use");
17335f4613f2SJohn Marino
17345f4613f2SJohn Marino }
17355f4613f2SJohn Marino
17365f4613f2SJohn Marino #define NOTSET(s) ((s) == 0)
17375f4613f2SJohn Marino
17385f4613f2SJohn Marino /*
17395f4613f2SJohn Marino * This bit of legerdemain turns all the terminfo variable names into
17405f4613f2SJohn Marino * references to locations in the arrays Booleans, Numbers, and Strings ---
17415f4613f2SJohn Marino * precisely what's needed.
17425f4613f2SJohn Marino */
17435f4613f2SJohn Marino #undef CUR
17445f4613f2SJohn Marino #define CUR tp->
17455f4613f2SJohn Marino
17465f4613f2SJohn Marino static void
set_obsolete_termcaps(TERMTYPE2 * tp)1747*32bb5217SDaniel Fojt set_obsolete_termcaps(TERMTYPE2 *tp)
17485f4613f2SJohn Marino {
17495f4613f2SJohn Marino #include "capdefaults.c"
17505f4613f2SJohn Marino }
17515f4613f2SJohn Marino
17525f4613f2SJohn Marino /*
17535f4613f2SJohn Marino * Convert an alternate-character-set string to canonical form: sorted and
17545f4613f2SJohn Marino * unique.
17555f4613f2SJohn Marino */
17565f4613f2SJohn Marino void
repair_acsc(TERMTYPE2 * tp)1757*32bb5217SDaniel Fojt repair_acsc(TERMTYPE2 *tp)
17585f4613f2SJohn Marino {
17595f4613f2SJohn Marino if (VALID_STRING(acs_chars)) {
17605f4613f2SJohn Marino size_t n, m;
17615f4613f2SJohn Marino char mapped[256];
17625f4613f2SJohn Marino char extra = 0;
17635f4613f2SJohn Marino unsigned source;
17645f4613f2SJohn Marino unsigned target;
17655f4613f2SJohn Marino bool fix_needed = FALSE;
17665f4613f2SJohn Marino
17675f4613f2SJohn Marino for (n = 0, source = 0; acs_chars[n] != 0; n++) {
17685f4613f2SJohn Marino target = UChar(acs_chars[n]);
17695f4613f2SJohn Marino if (source >= target) {
17705f4613f2SJohn Marino fix_needed = TRUE;
17715f4613f2SJohn Marino break;
17725f4613f2SJohn Marino }
17735f4613f2SJohn Marino source = target;
17745f4613f2SJohn Marino if (acs_chars[n + 1])
17755f4613f2SJohn Marino n++;
17765f4613f2SJohn Marino }
17775f4613f2SJohn Marino if (fix_needed) {
17785f4613f2SJohn Marino memset(mapped, 0, sizeof(mapped));
17795f4613f2SJohn Marino for (n = 0; acs_chars[n] != 0; n++) {
17805f4613f2SJohn Marino source = UChar(acs_chars[n]);
17815f4613f2SJohn Marino if ((target = (unsigned char) acs_chars[n + 1]) != 0) {
17825f4613f2SJohn Marino mapped[source] = (char) target;
17835f4613f2SJohn Marino n++;
17845f4613f2SJohn Marino } else {
17855f4613f2SJohn Marino extra = (char) source;
17865f4613f2SJohn Marino }
17875f4613f2SJohn Marino }
17885f4613f2SJohn Marino for (n = m = 0; n < sizeof(mapped); n++) {
17895f4613f2SJohn Marino if (mapped[n]) {
17905f4613f2SJohn Marino acs_chars[m++] = (char) n;
17915f4613f2SJohn Marino acs_chars[m++] = mapped[n];
17925f4613f2SJohn Marino }
17935f4613f2SJohn Marino }
17945f4613f2SJohn Marino if (extra)
17955f4613f2SJohn Marino acs_chars[m++] = extra; /* garbage in, garbage out */
17965f4613f2SJohn Marino acs_chars[m] = 0;
17975f4613f2SJohn Marino }
17985f4613f2SJohn Marino }
17995f4613f2SJohn Marino }
1800