dump_entry.c revision 166124
150276Speter/**************************************************************************** 2166124Srafan * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 3298503Speter * and: Thomas E. Dickey 1996 on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter#define __INTERNAL_CAPS_VISIBLE 3650276Speter#include <progs.priv.h> 3750276Speter 3850276Speter#include "dump_entry.h" 3950276Speter#include "termsort.c" /* this C file is generated */ 4050276Speter#include <parametrized.h> /* so is this */ 4150276Speter 42166124SrafanMODULE_ID("$Id: dump_entry.c,v 1.79 2006/09/30 20:18:15 tom Exp $") 4350276Speter 4450276Speter#define INDENT 8 4550276Speter#define DISCARD(string) string = ABSENT_STRING 4662449Speter#define PRINTF (void) printf 4750276Speter 4862449Spetertypedef struct { 4962449Speter char *text; 5062449Speter size_t used; 5162449Speter size_t size; 5262449Speter} DYNBUF; 5362449Speter 5450276Speterstatic int tversion; /* terminfo version */ 5550276Speterstatic int outform; /* output format to use */ 5650276Speterstatic int sortmode; /* sort mode to use */ 5750276Speterstatic int width = 60; /* max line width for listings */ 5850276Speterstatic int column; /* current column, limited by 'width' */ 5950276Speterstatic int oldcol; /* last value of column before wrap */ 6050276Speterstatic bool pretty; /* true if we format if-then-else strings */ 6150276Speter 62166124Srafanstatic char *save_sgr; 63166124Srafan 6462449Speterstatic DYNBUF outbuf; 6562449Speterstatic DYNBUF tmpbuf; 6650276Speter 6750276Speter/* indirection pointers for implementing sort and display modes */ 68166124Srafanstatic const PredIdx *bool_indirect, *num_indirect, *str_indirect; 6962449Speterstatic NCURSES_CONST char *const *bool_names; 7062449Speterstatic NCURSES_CONST char *const *num_names; 7162449Speterstatic NCURSES_CONST char *const *str_names; 7250276Speter 7350276Speterstatic const char *separator, *trailer; 7450276Speter 7550276Speter/* cover various ports and variants of terminfo */ 7650276Speter#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ 7750276Speter#define V_SVR1 1 /* SVR1, Ultrix */ 7850276Speter#define V_HPUX 2 /* HP/UX */ 7950276Speter#define V_AIX 3 /* AIX */ 8050276Speter#define V_BSD 4 /* BSD */ 8150276Speter 8262449Speter#if NCURSES_XNAMES 8362449Speter#define OBSOLETE(n) (!_nc_user_definable && (n[0] == 'O' && n[1] == 'T')) 8462449Speter#else 8550276Speter#define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') 8662449Speter#endif 8750276Speter 8862449Speter#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n)) 8962449Speter 9050276Speter#if NCURSES_XNAMES 9150276Speter#define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) 9250276Speter#define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j])) 9350276Speter#define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j])) 9450276Speter#else 9550276Speter#define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j]) 9650276Speter#define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j]) 9750276Speter#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) 9850276Speter#endif 9950276Speter 10062449Speterstatic void 10162449Speterstrncpy_DYN(DYNBUF * dst, const char *src, size_t need) 10262449Speter{ 10362449Speter size_t want = need + dst->used + 1; 10462449Speter if (want > dst->size) { 10562449Speter dst->size += (want + 1024); /* be generous */ 10662449Speter dst->text = typeRealloc(char, dst->size, dst->text); 10762449Speter } 10862449Speter (void) strncpy(dst->text + dst->used, src, need); 10962449Speter dst->used += need; 11062449Speter dst->text[dst->used] = 0; 11162449Speter} 11262449Speter 11362449Speterstatic void 11462449Speterstrcpy_DYN(DYNBUF * dst, const char *src) 11562449Speter{ 11662449Speter if (src == 0) { 11762449Speter dst->used = 0; 11862449Speter strcpy_DYN(dst, ""); 11962449Speter } else { 12062449Speter strncpy_DYN(dst, src, strlen(src)); 12162449Speter } 12262449Speter} 12362449Speter 12450276Speter#if NO_LEAKS 12562449Speterstatic void 12662449Speterfree_DYN(DYNBUF * p) 12750276Speter{ 12862449Speter if (p->text != 0) 12962449Speter free(p->text); 13062449Speter p->text = 0; 13162449Speter p->size = 0; 13262449Speter p->used = 0; 13350276Speter} 13462449Speter 13562449Spetervoid 13662449Speter_nc_leaks_dump_entry(void) 13762449Speter{ 13862449Speter free_DYN(&outbuf); 13962449Speter free_DYN(&tmpbuf); 14062449Speter} 14150276Speter#endif 14250276Speter 14362449SpeterNCURSES_CONST char * 14462449Speternametrans(const char *name) 14550276Speter/* translate a capability name from termcap to terminfo */ 14650276Speter{ 14762449Speter const struct name_table_entry *np; 14850276Speter 14950276Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) 15062449Speter switch (np->nte_type) { 15150276Speter case BOOLEAN: 15250276Speter if (bool_from_termcap[np->nte_index]) 15362449Speter return (boolcodes[np->nte_index]); 15450276Speter break; 15550276Speter 15650276Speter case NUMBER: 15750276Speter if (num_from_termcap[np->nte_index]) 15862449Speter return (numcodes[np->nte_index]); 15950276Speter break; 16050276Speter 16150276Speter case STRING: 16250276Speter if (str_from_termcap[np->nte_index]) 16362449Speter return (strcodes[np->nte_index]); 16450276Speter break; 16550276Speter } 16650276Speter 16762449Speter return (0); 16850276Speter} 16950276Speter 17062449Spetervoid 17162449Speterdump_init(const char *version, int mode, int sort, int twidth, int traceval, 17298503Speter bool formatted) 17350276Speter/* set up for entry display */ 17450276Speter{ 17550276Speter width = twidth; 17650276Speter pretty = formatted; 17750276Speter 17850276Speter /* versions */ 17950276Speter if (version == 0) 18050276Speter tversion = V_ALLCAPS; 18150276Speter else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1") 18298503Speter || !strcmp(version, "Ultrix")) 18350276Speter tversion = V_SVR1; 18450276Speter else if (!strcmp(version, "HP")) 18550276Speter tversion = V_HPUX; 18650276Speter else if (!strcmp(version, "AIX")) 18750276Speter tversion = V_AIX; 18850276Speter else if (!strcmp(version, "BSD")) 18950276Speter tversion = V_BSD; 19050276Speter else 19150276Speter tversion = V_ALLCAPS; 19250276Speter 19350276Speter /* implement display modes */ 19462449Speter switch (outform = mode) { 19550276Speter case F_LITERAL: 19650276Speter case F_TERMINFO: 19750276Speter bool_names = boolnames; 19850276Speter num_names = numnames; 19950276Speter str_names = strnames; 20050276Speter separator = twidth ? ", " : ","; 20150276Speter trailer = "\n\t"; 20250276Speter break; 20350276Speter 20450276Speter case F_VARIABLE: 20550276Speter bool_names = boolfnames; 20650276Speter num_names = numfnames; 20750276Speter str_names = strfnames; 20850276Speter separator = twidth ? ", " : ","; 20950276Speter trailer = "\n\t"; 21050276Speter break; 21150276Speter 21250276Speter case F_TERMCAP: 21350276Speter case F_TCONVERR: 21450276Speter bool_names = boolcodes; 21550276Speter num_names = numcodes; 21650276Speter str_names = strcodes; 21750276Speter separator = ":"; 21850276Speter trailer = "\\\n\t:"; 21950276Speter break; 22050276Speter } 22150276Speter 22250276Speter /* implement sort modes */ 22362449Speter switch (sortmode = sort) { 22450276Speter case S_NOSORT: 22550276Speter if (traceval) 22650276Speter (void) fprintf(stderr, 22798503Speter "%s: sorting by term structure order\n", _nc_progname); 22850276Speter break; 22950276Speter 23050276Speter case S_TERMINFO: 23150276Speter if (traceval) 23250276Speter (void) fprintf(stderr, 23398503Speter "%s: sorting by terminfo name order\n", _nc_progname); 23450276Speter bool_indirect = bool_terminfo_sort; 23550276Speter num_indirect = num_terminfo_sort; 23650276Speter str_indirect = str_terminfo_sort; 23750276Speter break; 23850276Speter 23950276Speter case S_VARIABLE: 24050276Speter if (traceval) 24150276Speter (void) fprintf(stderr, 24298503Speter "%s: sorting by C variable order\n", _nc_progname); 24350276Speter bool_indirect = bool_variable_sort; 24450276Speter num_indirect = num_variable_sort; 24550276Speter str_indirect = str_variable_sort; 24650276Speter break; 24750276Speter 24850276Speter case S_TERMCAP: 24950276Speter if (traceval) 25050276Speter (void) fprintf(stderr, 25198503Speter "%s: sorting by termcap name order\n", _nc_progname); 25250276Speter bool_indirect = bool_termcap_sort; 25350276Speter num_indirect = num_termcap_sort; 25450276Speter str_indirect = str_termcap_sort; 25550276Speter break; 25650276Speter } 25750276Speter 25850276Speter if (traceval) 25950276Speter (void) fprintf(stderr, 26098503Speter "%s: width = %d, tversion = %d, outform = %d\n", 26198503Speter _nc_progname, width, tversion, outform); 26250276Speter} 26350276Speter 26462449Speterstatic TERMTYPE *cur_type; 26550276Speter 26662449Speterstatic int 267166124Srafandump_predicate(PredType type, PredIdx idx) 26850276Speter/* predicate function to use for ordinary decompilation */ 26950276Speter{ 27062449Speter switch (type) { 27162449Speter case BOOLEAN: 27262449Speter return (cur_type->Booleans[idx] == FALSE) 27362449Speter ? FAIL : cur_type->Booleans[idx]; 27450276Speter 27562449Speter case NUMBER: 27662449Speter return (cur_type->Numbers[idx] == ABSENT_NUMERIC) 27762449Speter ? FAIL : cur_type->Numbers[idx]; 27850276Speter 27962449Speter case STRING: 28062449Speter return (cur_type->Strings[idx] != ABSENT_STRING) 28162449Speter ? (int) TRUE : FAIL; 28262449Speter } 28350276Speter 28462449Speter return (FALSE); /* pacify compiler */ 28550276Speter} 28650276Speter 287166124Srafanstatic void set_obsolete_termcaps(TERMTYPE *tp); 28850276Speter 28950276Speter/* is this the index of a function key string? */ 29050276Speter#define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268)) 29150276Speter 292166124Srafan/* 293166124Srafan * If we configure with a different Caps file, the offsets into the arrays 294166124Srafan * will change. So we use an address expression. 295166124Srafan */ 296166124Srafan#define BOOL_IDX(name) (&(name) - &(CUR Booleans[0])) 297166124Srafan#define NUM_IDX(name) (&(name) - &(CUR Numbers[0])) 298166124Srafan#define STR_IDX(name) (&(name) - &(CUR Strings[0])) 299166124Srafan 30062449Speterstatic bool 301166124Srafanversion_filter(PredType type, PredIdx idx) 30250276Speter/* filter out capabilities we may want to suppress */ 30350276Speter{ 30462449Speter switch (tversion) { 30562449Speter case V_ALLCAPS: /* SVr4, XSI Curses */ 30662449Speter return (TRUE); 30750276Speter 30862449Speter case V_SVR1: /* System V Release 1, Ultrix */ 30962449Speter switch (type) { 31050276Speter case BOOLEAN: 311166124Srafan return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); 31250276Speter case NUMBER: 313166124Srafan return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE); 31450276Speter case STRING: 315166124Srafan return ((idx <= STR_IDX(prtr_non)) ? TRUE : FALSE); 31650276Speter } 31750276Speter break; 31850276Speter 31950276Speter case V_HPUX: /* Hewlett-Packard */ 32062449Speter switch (type) { 32150276Speter case BOOLEAN: 322166124Srafan return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); 32350276Speter case NUMBER: 324166124Srafan return ((idx <= NUM_IDX(label_width)) ? TRUE : FALSE); 32550276Speter case STRING: 326166124Srafan if (idx <= STR_IDX(prtr_non)) 32762449Speter return (TRUE); 32850276Speter else if (FNKEY(idx)) /* function keys */ 32962449Speter return (TRUE); 330166124Srafan else if (idx == STR_IDX(plab_norm) 331166124Srafan || idx == STR_IDX(label_on) 332166124Srafan || idx == STR_IDX(label_off)) 33362449Speter return (TRUE); 33450276Speter else 33562449Speter return (FALSE); 33650276Speter } 33750276Speter break; 33850276Speter 33950276Speter case V_AIX: /* AIX */ 34062449Speter switch (type) { 34150276Speter case BOOLEAN: 342166124Srafan return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); 34350276Speter case NUMBER: 344166124Srafan return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE); 34550276Speter case STRING: 346166124Srafan if (idx <= STR_IDX(prtr_non)) 34762449Speter return (TRUE); 34850276Speter else if (FNKEY(idx)) /* function keys */ 34962449Speter return (TRUE); 35050276Speter else 35162449Speter return (FALSE); 35250276Speter } 35350276Speter break; 35450276Speter 35550276Speter case V_BSD: /* BSD */ 35662449Speter switch (type) { 35750276Speter case BOOLEAN: 35850276Speter return bool_from_termcap[idx]; 35950276Speter case NUMBER: 36050276Speter return num_from_termcap[idx]; 36150276Speter case STRING: 36250276Speter return str_from_termcap[idx]; 36350276Speter } 36450276Speter break; 36550276Speter } 36650276Speter 36762449Speter return (FALSE); /* pacify the compiler */ 36850276Speter} 36950276Speter 37062449Speterstatic void 371166124Srafantrim_trailing(void) 372166124Srafan{ 373166124Srafan while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ') 374166124Srafan outbuf.text[--outbuf.used] = '\0'; 375166124Srafan} 376166124Srafan 377166124Srafanstatic void 37862449Speterforce_wrap(void) 37950276Speter{ 38062449Speter oldcol = column; 381166124Srafan trim_trailing(); 38262449Speter strcpy_DYN(&outbuf, trailer); 38362449Speter column = INDENT; 38450276Speter} 38550276Speter 38662449Speterstatic void 38762449Speterwrap_concat(const char *src) 38850276Speter{ 38962449Speter int need = strlen(src); 39062449Speter int want = strlen(separator) + need; 39150276Speter 39262449Speter if (column > INDENT 39362449Speter && column + want > width) { 39462449Speter force_wrap(); 39562449Speter } 39662449Speter strcpy_DYN(&outbuf, src); 39762449Speter strcpy_DYN(&outbuf, separator); 39862449Speter column += need; 39950276Speter} 40050276Speter 40150276Speter#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ 40250276Speter if ((size_t)(last - first) > sizeof(sep_trail)-1 \ 40350276Speter && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ 40450276Speter first += sizeof(sep_trail)-2 40550276Speter 40650276Speter/* Returns the nominal length of the buffer assuming it is termcap format, 40750276Speter * i.e., the continuation sequence is treated as a single character ":". 40850276Speter * 40950276Speter * There are several implementations of termcap which read the text into a 41050276Speter * fixed-size buffer. Generally they strip the newlines from the text, but may 41150276Speter * not do it until after the buffer is read. Also, "tc=" resolution may be 41250276Speter * expanded in the same buffer. This function is useful for measuring the size 41350276Speter * of the best fixed-buffer implementation; the worst case may be much worse. 41450276Speter */ 41550276Speter#ifdef TEST_TERMCAP_LENGTH 41662449Speterstatic int 41762449Spetertermcap_length(const char *src) 41850276Speter{ 41962449Speter static const char pattern[] = ":\\\n\t:"; 42050276Speter 42162449Speter int len = 0; 42262449Speter const char *const t = src + strlen(src); 42350276Speter 42462449Speter while (*src != '\0') { 42562449Speter IGNORE_SEP_TRAIL(src, t, pattern); 42662449Speter src++; 42762449Speter len++; 42862449Speter } 42962449Speter return len; 43050276Speter} 43150276Speter#else 43250276Speter#define termcap_length(src) strlen(src) 43350276Speter#endif 43450276Speter 435166124Srafanstatic void 436166124Srafanindent_DYN(DYNBUF * buffer, int level) 437166124Srafan{ 438166124Srafan int n; 439166124Srafan 440166124Srafan for (n = 0; n < level; n++) 441166124Srafan strncpy_DYN(buffer, "\t", 1); 442166124Srafan} 443166124Srafan 444166124Srafanstatic bool 445166124Srafanhas_params(const char *src) 446166124Srafan{ 447166124Srafan bool result = FALSE; 448166124Srafan int len = strlen(src); 449166124Srafan int n; 450166124Srafan bool ifthen = FALSE; 451166124Srafan bool params = FALSE; 452166124Srafan 453166124Srafan for (n = 0; n < len - 1; ++n) { 454166124Srafan if (!strncmp(src + n, "%p", 2)) { 455166124Srafan params = TRUE; 456166124Srafan } else if (!strncmp(src + n, "%;", 2)) { 457166124Srafan ifthen = TRUE; 458166124Srafan result = params; 459166124Srafan break; 460166124Srafan } 461166124Srafan } 462166124Srafan if (!ifthen) { 463166124Srafan result = ((len > 50) && params); 464166124Srafan } 465166124Srafan return result; 466166124Srafan} 467166124Srafan 46862449Speterstatic char * 46962449Speterfmt_complex(char *src, int level) 47050276Speter{ 471166124Srafan bool percent = FALSE; 472166124Srafan bool params = has_params(src); 47350276Speter 47462449Speter while (*src != '\0') { 47562449Speter switch (*src) { 47662449Speter case '\\': 477166124Srafan percent = FALSE; 47862449Speter strncpy_DYN(&tmpbuf, src++, 1); 47962449Speter break; 48062449Speter case '%': 481166124Srafan percent = TRUE; 48262449Speter break; 48362449Speter case '?': /* "if" */ 48462449Speter case 't': /* "then" */ 48562449Speter case 'e': /* "else" */ 48662449Speter if (percent) { 487166124Srafan percent = FALSE; 48862449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 489166124Srafan /* treat a "%e" as else-if, on the same level */ 490166124Srafan if (*src == 'e') { 491166124Srafan indent_DYN(&tmpbuf, level); 49262449Speter strncpy_DYN(&tmpbuf, "%", 1); 493166124Srafan strncpy_DYN(&tmpbuf, src, 1); 494166124Srafan src++; 495166124Srafan params = has_params(src); 496166124Srafan if (!params && *src != '\0' && *src != '%') { 497166124Srafan strncpy_DYN(&tmpbuf, "\n", 1); 498166124Srafan indent_DYN(&tmpbuf, level + 1); 499166124Srafan } 50062449Speter } else { 501166124Srafan indent_DYN(&tmpbuf, level + 1); 50262449Speter strncpy_DYN(&tmpbuf, "%", 1); 50362449Speter strncpy_DYN(&tmpbuf, src, 1); 50462449Speter if (*src++ == '?') { 50562449Speter src = fmt_complex(src, level + 1); 506166124Srafan if (*src != '\0' && *src != '%') { 507166124Srafan strncpy_DYN(&tmpbuf, "\n", 1); 508166124Srafan indent_DYN(&tmpbuf, level + 1); 509166124Srafan } 51062449Speter } else if (level == 1) { 51162449Speter _nc_warning("%%%c without %%?", *src); 51262449Speter } 51350276Speter } 51462449Speter continue; 51562449Speter } 51662449Speter break; 51762449Speter case ';': /* "endif" */ 51862449Speter if (percent) { 519166124Srafan percent = FALSE; 52062449Speter if (level > 1) { 52162449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 522166124Srafan indent_DYN(&tmpbuf, level); 52362449Speter strncpy_DYN(&tmpbuf, "%", 1); 52462449Speter strncpy_DYN(&tmpbuf, src++, 1); 52562449Speter return src; 52662449Speter } 52762449Speter _nc_warning("%%; without %%?"); 52862449Speter } 52962449Speter break; 53062449Speter case 'p': 53162449Speter if (percent && params) { 53262449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 533166124Srafan indent_DYN(&tmpbuf, level + 1); 53462449Speter strncpy_DYN(&tmpbuf, "%", 1); 53562449Speter } 536166124Srafan params = FALSE; 537166124Srafan percent = FALSE; 53862449Speter break; 53962449Speter default: 540166124Srafan percent = FALSE; 54162449Speter break; 54250276Speter } 54362449Speter strncpy_DYN(&tmpbuf, src++, 1); 54462449Speter } 54562449Speter return src; 54650276Speter} 54750276Speter 548166124Srafan#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) 549166124Srafan 55062449Speterint 551166124Srafanfmt_entry(TERMTYPE *tterm, 552166124Srafan PredFunc pred, 553166124Srafan bool content_only, 55498503Speter bool suppress_untranslatable, 55598503Speter bool infodump, 55698503Speter int numbers) 55750276Speter{ 558166124Srafan PredIdx i, j; 55962449Speter char buffer[MAX_TERMINFO_LENGTH]; 560166124Srafan char *capability; 56162449Speter NCURSES_CONST char *name; 56262449Speter int predval, len; 563166124Srafan PredIdx num_bools = 0; 564166124Srafan PredIdx num_values = 0; 565166124Srafan PredIdx num_strings = 0; 56662449Speter bool outcount = 0; 56750276Speter 56850276Speter#define WRAP_CONCAT \ 56950276Speter wrap_concat(buffer); \ 57050276Speter outcount = TRUE 57150276Speter 57250276Speter len = 12; /* terminfo file-header */ 57350276Speter 57450276Speter if (pred == 0) { 57550276Speter cur_type = tterm; 57650276Speter pred = dump_predicate; 57750276Speter } 57850276Speter 57962449Speter strcpy_DYN(&outbuf, 0); 580166124Srafan if (content_only) { 581166124Srafan column = INDENT; /* FIXME: workaround to prevent empty lines */ 582166124Srafan } else { 583166124Srafan strcpy_DYN(&outbuf, tterm->term_names); 584166124Srafan strcpy_DYN(&outbuf, separator); 585166124Srafan column = outbuf.used; 586166124Srafan force_wrap(); 587166124Srafan } 58850276Speter 58962449Speter for_each_boolean(j, tterm) { 59050276Speter i = BoolIndirect(j); 59162449Speter name = ExtBoolname(tterm, i, bool_names); 59250276Speter 59350276Speter if (!version_filter(BOOLEAN, i)) 59450276Speter continue; 59562449Speter else if (isObsolete(outform, name)) 59650276Speter continue; 59750276Speter 59850276Speter predval = pred(BOOLEAN, i); 59950276Speter if (predval != FAIL) { 60050276Speter (void) strcpy(buffer, name); 60150276Speter if (predval <= 0) 60250276Speter (void) strcat(buffer, "@"); 60350276Speter else if (i + 1 > num_bools) 60450276Speter num_bools = i + 1; 60550276Speter WRAP_CONCAT; 60650276Speter } 60750276Speter } 60850276Speter 60950276Speter if (column != INDENT) 61050276Speter force_wrap(); 61150276Speter 61262449Speter for_each_number(j, tterm) { 61350276Speter i = NumIndirect(j); 61462449Speter name = ExtNumname(tterm, i, num_names); 61550276Speter 61650276Speter if (!version_filter(NUMBER, i)) 61750276Speter continue; 61862449Speter else if (isObsolete(outform, name)) 61950276Speter continue; 62050276Speter 62150276Speter predval = pred(NUMBER, i); 62250276Speter if (predval != FAIL) { 62350276Speter if (tterm->Numbers[i] < 0) { 62450276Speter sprintf(buffer, "%s@", name); 62550276Speter } else { 62650276Speter sprintf(buffer, "%s#%d", name, tterm->Numbers[i]); 62750276Speter if (i + 1 > num_values) 62850276Speter num_values = i + 1; 62950276Speter } 63050276Speter WRAP_CONCAT; 63150276Speter } 63250276Speter } 63350276Speter 63450276Speter if (column != INDENT) 63550276Speter force_wrap(); 63650276Speter 63750276Speter len += num_bools 63862449Speter + num_values * 2 63962449Speter + strlen(tterm->term_names) + 1; 64050276Speter if (len & 1) 64162449Speter len++; 64250276Speter 64362449Speter#undef CUR 64462449Speter#define CUR tterm-> 64562449Speter if (outform == F_TERMCAP) { 64662449Speter if (termcap_reset != ABSENT_STRING) { 64762449Speter if (init_3string != ABSENT_STRING 64862449Speter && !strcmp(init_3string, termcap_reset)) 64962449Speter DISCARD(init_3string); 65062449Speter 65162449Speter if (reset_2string != ABSENT_STRING 65262449Speter && !strcmp(reset_2string, termcap_reset)) 65362449Speter DISCARD(reset_2string); 65462449Speter } 65562449Speter } 65662449Speter 65750276Speter for_each_string(j, tterm) { 65850276Speter i = StrIndirect(j); 65962449Speter name = ExtStrname(tterm, i, str_names); 660166124Srafan capability = tterm->Strings[i]; 66150276Speter 66250276Speter if (!version_filter(STRING, i)) 66350276Speter continue; 66462449Speter else if (isObsolete(outform, name)) 66550276Speter continue; 66650276Speter 667166124Srafan#if NCURSES_XNAMES 66850276Speter /* 669166124Srafan * Extended names can be longer than 2 characters, but termcap programs 670166124Srafan * cannot read those (filter them out). 67150276Speter */ 672166124Srafan if (outform == F_TERMCAP && (strlen(name) > 2)) 673166124Srafan continue; 674166124Srafan#endif 675166124Srafan 67662449Speter if (outform == F_TERMCAP) { 677166124Srafan /* 678166124Srafan * Some older versions of vi want rmir/smir to be defined 679166124Srafan * for ich/ich1 to work. If they're not defined, force 680166124Srafan * them to be output as defined and empty. 681166124Srafan */ 682166124Srafan if (PRESENT(insert_character) || PRESENT(parm_ich)) { 683166124Srafan if (SAME_CAP(i, enter_insert_mode) 68462449Speter && enter_insert_mode == ABSENT_STRING) { 68550276Speter (void) strcpy(buffer, "im="); 68662449Speter WRAP_CONCAT; 68762449Speter continue; 68850276Speter } 68950276Speter 690166124Srafan if (SAME_CAP(i, exit_insert_mode) 69162449Speter && exit_insert_mode == ABSENT_STRING) { 69250276Speter (void) strcpy(buffer, "ei="); 69362449Speter WRAP_CONCAT; 69462449Speter continue; 69550276Speter } 69650276Speter } 697166124Srafan /* 698166124Srafan * termcap applications such as screen will be confused if sgr0 699166124Srafan * is translated to a string containing rmacs. Filter that out. 700166124Srafan */ 701166124Srafan if (PRESENT(exit_attribute_mode)) { 702166124Srafan if (SAME_CAP(i, exit_attribute_mode)) { 703166124Srafan char *trimmed_sgr0; 704166124Srafan char *my_sgr = set_attributes; 705166124Srafan 706166124Srafan set_attributes = save_sgr; 707166124Srafan 708166124Srafan trimmed_sgr0 = _nc_trim_sgr0(tterm); 709166124Srafan if (strcmp(capability, trimmed_sgr0)) 710166124Srafan capability = trimmed_sgr0; 711166124Srafan 712166124Srafan set_attributes = my_sgr; 713166124Srafan } 714166124Srafan } 71550276Speter } 71650276Speter 71750276Speter predval = pred(STRING, i); 71850276Speter buffer[0] = '\0'; 71962449Speter 72050276Speter if (predval != FAIL) { 721166124Srafan if (capability != ABSENT_STRING 72262449Speter && i + 1 > num_strings) 72350276Speter num_strings = i + 1; 72462449Speter 725166124Srafan if (!VALID_STRING(capability)) { 72650276Speter sprintf(buffer, "%s@", name); 72762449Speter WRAP_CONCAT; 72862449Speter } else if (outform == F_TERMCAP || outform == F_TCONVERR) { 72998503Speter int params = ((i < (int) SIZEOF(parametrized)) 73098503Speter ? parametrized[i] 73198503Speter : 0); 732166124Srafan char *srccap = _nc_tic_expand(capability, TRUE, numbers); 73366963Speter char *cv = _nc_infotocap(name, srccap, params); 73450276Speter 73562449Speter if (cv == 0) { 73662449Speter if (outform == F_TCONVERR) { 73762449Speter sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", 73898503Speter name, srccap); 73962449Speter } else if (suppress_untranslatable) { 74050276Speter continue; 74162449Speter } else { 74262449Speter char *s = srccap, *d = buffer; 74362449Speter sprintf(d, "..%s=", name); 74462449Speter d += strlen(d); 74562449Speter while ((*d = *s++) != 0) { 74662449Speter if (*d == ':') { 74762449Speter *d++ = '\\'; 74862449Speter *d = ':'; 74962449Speter } else if (*d == '\\') { 75062449Speter *++d = *s++; 75162449Speter } 75262449Speter d++; 75362449Speter } 75462449Speter } 75562449Speter } else { 75662449Speter sprintf(buffer, "%s=%s", name, cv); 75750276Speter } 758166124Srafan len += strlen(capability) + 1; 75962449Speter WRAP_CONCAT; 76062449Speter } else { 761166124Srafan char *src = _nc_tic_expand(capability, 76298503Speter outform == F_TERMINFO, numbers); 76362449Speter 76462449Speter strcpy_DYN(&tmpbuf, 0); 76562449Speter strcpy_DYN(&tmpbuf, name); 76662449Speter strcpy_DYN(&tmpbuf, "="); 76762449Speter if (pretty 76862449Speter && (outform == F_TERMINFO 76962449Speter || outform == F_VARIABLE)) { 77062449Speter fmt_complex(src, 1); 77162449Speter } else { 77262449Speter strcpy_DYN(&tmpbuf, src); 77362449Speter } 774166124Srafan len += strlen(capability) + 1; 77562449Speter wrap_concat(tmpbuf.text); 77662449Speter outcount = TRUE; 77750276Speter } 77850276Speter } 779166124Srafan /* e.g., trimmed_sgr0 */ 780166124Srafan if (capability != tterm->Strings[i]) 781166124Srafan free(capability); 78250276Speter } 78350276Speter len += num_strings * 2; 78450276Speter 78550276Speter /* 78650276Speter * This piece of code should be an effective inverse of the functions 787166124Srafan * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c. 78850276Speter * Much more work should be done on this to support dumping termcaps. 78950276Speter */ 79062449Speter if (tversion == V_HPUX) { 79162449Speter if (memory_lock) { 79250276Speter (void) sprintf(buffer, "meml=%s", memory_lock); 79350276Speter WRAP_CONCAT; 79450276Speter } 79562449Speter if (memory_unlock) { 79650276Speter (void) sprintf(buffer, "memu=%s", memory_unlock); 79750276Speter WRAP_CONCAT; 79850276Speter } 79962449Speter } else if (tversion == V_AIX) { 80062449Speter if (VALID_STRING(acs_chars)) { 80162449Speter bool box_ok = TRUE; 80262449Speter const char *acstrans = "lqkxjmwuvtn"; 80362449Speter const char *cp; 80462449Speter char *tp, *sp, boxchars[11]; 80550276Speter 80650276Speter tp = boxchars; 80762449Speter for (cp = acstrans; *cp; cp++) { 80850276Speter sp = strchr(acs_chars, *cp); 80950276Speter if (sp) 81050276Speter *tp++ = sp[1]; 81162449Speter else { 81250276Speter box_ok = FALSE; 81350276Speter break; 81450276Speter } 81550276Speter } 81650276Speter tp[0] = '\0'; 81750276Speter 81862449Speter if (box_ok) { 81950276Speter (void) strcpy(buffer, "box1="); 82062449Speter (void) strcat(buffer, _nc_tic_expand(boxchars, 82198503Speter outform == F_TERMINFO, numbers)); 82250276Speter WRAP_CONCAT; 82350276Speter } 82450276Speter } 82550276Speter } 82650276Speter 82750276Speter /* 82850276Speter * kludge: trim off trailer to avoid an extra blank line 82950276Speter * in infocmp -u output when there are no string differences 83050276Speter */ 83162449Speter if (outcount) { 83262449Speter bool trimmed = FALSE; 83362449Speter j = outbuf.used; 83450276Speter if (j >= 2 83562449Speter && outbuf.text[j - 1] == '\t' 83662449Speter && outbuf.text[j - 2] == '\n') { 83762449Speter outbuf.used -= 2; 83862449Speter trimmed = TRUE; 83950276Speter } else if (j >= 4 84098503Speter && outbuf.text[j - 1] == ':' 84198503Speter && outbuf.text[j - 2] == '\t' 84298503Speter && outbuf.text[j - 3] == '\n' 84398503Speter && outbuf.text[j - 4] == '\\') { 84462449Speter outbuf.used -= 4; 84562449Speter trimmed = TRUE; 84650276Speter } 84762449Speter if (trimmed) { 84862449Speter outbuf.text[outbuf.used] = '\0'; 84962449Speter column = oldcol; 850166124Srafan strcpy_DYN(&outbuf, " "); 85162449Speter } 85250276Speter } 85350276Speter#if 0 85450276Speter fprintf(stderr, "num_bools = %d\n", num_bools); 85550276Speter fprintf(stderr, "num_values = %d\n", num_values); 85650276Speter fprintf(stderr, "num_strings = %d\n", num_strings); 85750276Speter fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n", 85898503Speter tterm->term_names, len, outbuf.used, outbuf.text); 85950276Speter#endif 86050276Speter /* 86150276Speter * Here's where we use infodump to trigger a more stringent length check 86250276Speter * for termcap-translation purposes. 86350276Speter * Return the length of the raw entry, without tc= expansions, 86450276Speter * It gives an idea of which entries are deadly to even *scan past*, 86550276Speter * as opposed to *use*. 86650276Speter */ 86776726Speter return (infodump ? len : (int) termcap_length(outbuf.text)); 86850276Speter} 86950276Speter 87098503Speterstatic bool 871166124Srafankill_string(TERMTYPE *tterm, char *cap) 87298503Speter{ 87398503Speter int n; 874166124Srafan for (n = 0; n < NUM_STRINGS(tterm); ++n) { 87598503Speter if (cap == tterm->Strings[n]) { 87698503Speter tterm->Strings[n] = ABSENT_STRING; 87798503Speter return TRUE; 87898503Speter } 87998503Speter } 88098503Speter return FALSE; 88198503Speter} 88298503Speter 88398503Speterstatic char * 884166124Srafanfind_string(TERMTYPE *tterm, char *name) 88598503Speter{ 886166124Srafan PredIdx n; 887166124Srafan for (n = 0; n < NUM_STRINGS(tterm); ++n) { 88898503Speter if (version_filter(STRING, n) 88998503Speter && !strcmp(name, strnames[n])) { 89098503Speter char *cap = tterm->Strings[n]; 89198503Speter if (VALID_STRING(cap)) { 89298503Speter return cap; 89398503Speter } 89498503Speter break; 89598503Speter } 89698503Speter } 89798503Speter return ABSENT_STRING; 89898503Speter} 89998503Speter 90098503Speter/* 90198503Speter * This is used to remove function-key labels from a termcap entry to 90298503Speter * make it smaller. 90398503Speter */ 90498503Speterstatic int 905166124Srafankill_labels(TERMTYPE *tterm, int target) 90698503Speter{ 90798503Speter int n; 90898503Speter int result = 0; 90998503Speter char *cap; 91098503Speter char name[10]; 91198503Speter 91298503Speter for (n = 0; n <= 10; ++n) { 91398503Speter sprintf(name, "lf%d", n); 91498503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 91598503Speter && kill_string(tterm, cap)) { 91698503Speter target -= (strlen(cap) + 5); 91798503Speter ++result; 91898503Speter if (target < 0) 91998503Speter break; 92098503Speter } 92198503Speter } 92298503Speter return result; 92398503Speter} 92498503Speter 92598503Speter/* 92698503Speter * This is used to remove function-key definitions from a termcap entry to 92798503Speter * make it smaller. 92898503Speter */ 92998503Speterstatic int 930166124Srafankill_fkeys(TERMTYPE *tterm, int target) 93198503Speter{ 93298503Speter int n; 93398503Speter int result = 0; 93498503Speter char *cap; 93598503Speter char name[10]; 93698503Speter 93798503Speter for (n = 60; n >= 0; --n) { 93898503Speter sprintf(name, "kf%d", n); 93998503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 94098503Speter && kill_string(tterm, cap)) { 94198503Speter target -= (strlen(cap) + 5); 94298503Speter ++result; 94398503Speter if (target < 0) 94498503Speter break; 94598503Speter } 94698503Speter } 94798503Speter return result; 94898503Speter} 94998503Speter 950166124Srafan/* 951166124Srafan * Check if the given acsc string is a 1-1 mapping, i.e., just-like-vt100. 952166124Srafan * Also, since this is for termcap, we only care about the line-drawing map. 953166124Srafan */ 954166124Srafan#define isLine(c) (strchr("lmkjtuvwqxn", c) != 0) 955166124Srafan 956166124Srafanstatic bool 957166124Srafanone_one_mapping(const char *mapping) 958166124Srafan{ 959166124Srafan bool result = TRUE; 960166124Srafan 961166124Srafan if (mapping != ABSENT_STRING) { 962166124Srafan int n = 0; 963166124Srafan while (mapping[n] != '\0') { 964166124Srafan if (isLine(mapping[n]) && 965166124Srafan mapping[n] != mapping[n + 1]) { 966166124Srafan result = FALSE; 967166124Srafan break; 968166124Srafan } 969166124Srafan n += 2; 970166124Srafan } 971166124Srafan } 972166124Srafan return result; 973166124Srafan} 974166124Srafan 975166124Srafan#define FMT_ENTRY() \ 976166124Srafan fmt_entry(tterm, pred, \ 977166124Srafan 0, \ 978166124Srafan suppress_untranslatable, \ 979166124Srafan infodump, numbers) 980166124Srafan 981166124Srafan#define SHOW_WHY PRINTF 982166124Srafan 983166124Srafanstatic bool 984166124Srafanpurged_acs(TERMTYPE *tterm) 985166124Srafan{ 986166124Srafan bool result = FALSE; 987166124Srafan 988166124Srafan if (VALID_STRING(acs_chars)) { 989166124Srafan if (!one_one_mapping(acs_chars)) { 990166124Srafan enter_alt_charset_mode = ABSENT_STRING; 991166124Srafan exit_alt_charset_mode = ABSENT_STRING; 992166124Srafan SHOW_WHY("# (rmacs/smacs removed for consistency)\n"); 993166124Srafan } 994166124Srafan result = TRUE; 995166124Srafan } 996166124Srafan return result; 997166124Srafan} 998166124Srafan 999166124Srafan/* 1000166124Srafan * Dump a single entry. 1001166124Srafan */ 1002166124Srafanvoid 1003166124Srafandump_entry(TERMTYPE *tterm, 1004166124Srafan bool suppress_untranslatable, 100598503Speter bool limited, 100698503Speter int numbers, 1007166124Srafan PredFunc pred) 100850276Speter{ 1009166124Srafan TERMTYPE save_tterm; 101062449Speter int len, critlen; 101162449Speter const char *legend; 101262449Speter bool infodump; 101350276Speter 101462449Speter if (outform == F_TERMCAP || outform == F_TCONVERR) { 101550276Speter critlen = MAX_TERMCAP_LENGTH; 101650276Speter legend = "older termcap"; 101750276Speter infodump = FALSE; 101850276Speter set_obsolete_termcaps(tterm); 101962449Speter } else { 102050276Speter critlen = MAX_TERMINFO_LENGTH; 102150276Speter legend = "terminfo"; 102250276Speter infodump = TRUE; 102350276Speter } 102450276Speter 1025166124Srafan save_sgr = set_attributes; 1026166124Srafan 1027166124Srafan if (((len = FMT_ENTRY()) > critlen) 102862449Speter && limited) { 1029166124Srafan 1030166124Srafan save_tterm = *tterm; 1031166124Srafan if (!suppress_untranslatable) { 1032166124Srafan SHOW_WHY("# (untranslatable capabilities removed to fit entry within %d bytes)\n", 1033166124Srafan critlen); 1034166124Srafan suppress_untranslatable = TRUE; 1035166124Srafan } 1036166124Srafan if ((len = FMT_ENTRY()) > critlen) { 103750276Speter /* 103850276Speter * We pick on sgr because it's a nice long string capability that 103962449Speter * is really just an optimization hack. Another good candidate is 104062449Speter * acsc since it is both long and unused by BSD termcap. 104150276Speter */ 1042166124Srafan bool changed = FALSE; 1043166124Srafan 1044166124Srafan#if NCURSES_XNAMES 1045166124Srafan /* 1046166124Srafan * Extended names are most likely function-key definitions. Drop 1047166124Srafan * those first. 1048166124Srafan */ 1049166124Srafan int n; 1050166124Srafan for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { 1051166124Srafan const char *name = ExtStrname(tterm, n, strnames); 1052166124Srafan 1053166124Srafan if (VALID_STRING(tterm->Strings[n])) { 1054166124Srafan set_attributes = ABSENT_STRING; 1055166124Srafan /* we remove long names anyway - only report the short */ 1056166124Srafan if (strlen(name) <= 2) { 1057166124Srafan SHOW_WHY("# (%s removed to fit entry within %d bytes)\n", 1058166124Srafan name, 1059166124Srafan critlen); 1060166124Srafan } 1061166124Srafan changed = TRUE; 1062166124Srafan if ((len = FMT_ENTRY()) <= critlen) 1063166124Srafan break; 1064166124Srafan } 106562449Speter } 1066166124Srafan#endif 1067166124Srafan if (VALID_STRING(set_attributes)) { 1068166124Srafan set_attributes = ABSENT_STRING; 1069166124Srafan SHOW_WHY("# (sgr removed to fit entry within %d bytes)\n", 1070166124Srafan critlen); 1071166124Srafan changed = TRUE; 1072166124Srafan } 1073166124Srafan if (!changed || ((len = FMT_ENTRY()) > critlen)) { 1074166124Srafan if (purged_acs(tterm)) { 1075166124Srafan acs_chars = ABSENT_STRING; 1076166124Srafan SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n", 1077166124Srafan critlen); 1078166124Srafan changed = TRUE; 1079166124Srafan } 1080166124Srafan } 1081166124Srafan if (!changed || ((len = FMT_ENTRY()) > critlen)) { 108250276Speter int oldversion = tversion; 108350276Speter 108450276Speter tversion = V_BSD; 1085166124Srafan SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", 1086166124Srafan critlen); 108750276Speter 1088166124Srafan len = FMT_ENTRY(); 108998503Speter if (len > critlen 109098503Speter && kill_labels(tterm, len - critlen)) { 1091166124Srafan SHOW_WHY("# (some labels capabilities suppressed to fit entry within %d bytes)\n", 1092166124Srafan critlen); 1093166124Srafan len = FMT_ENTRY(); 109498503Speter } 109598503Speter if (len > critlen 109698503Speter && kill_fkeys(tterm, len - critlen)) { 1097166124Srafan SHOW_WHY("# (some function-key capabilities suppressed to fit entry within %d bytes)\n", 1098166124Srafan critlen); 1099166124Srafan len = FMT_ENTRY(); 110098503Speter } 110198503Speter if (len > critlen) { 110250276Speter (void) fprintf(stderr, 110398503Speter "warning: %s entry is %d bytes long\n", 110498503Speter _nc_first_name(tterm->term_names), 110598503Speter len); 1106166124Srafan SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", 1107166124Srafan len, legend); 110850276Speter } 110950276Speter tversion = oldversion; 111050276Speter } 1111166124Srafan set_attributes = save_sgr; 1112166124Srafan *tterm = save_tterm; 111350276Speter } 1114166124Srafan } else if (!version_filter(STRING, STR_IDX(acs_chars))) { 1115166124Srafan save_tterm = *tterm; 1116166124Srafan if (purged_acs(tterm)) { 1117166124Srafan len = FMT_ENTRY(); 1118166124Srafan } 1119166124Srafan *tterm = save_tterm; 112050276Speter } 112150276Speter} 112250276Speter 1123166124Srafanvoid 112462449Speterdump_uses(const char *name, bool infodump) 112550276Speter/* dump "use=" clauses in the appropriate format */ 112650276Speter{ 112750276Speter char buffer[MAX_TERMINFO_LENGTH]; 112850276Speter 1129166124Srafan if (outform == F_TERMCAP || outform == F_TCONVERR) 1130166124Srafan trim_trailing(); 113162449Speter (void) sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name); 113250276Speter wrap_concat(buffer); 1133166124Srafan} 1134166124Srafan 1135166124Srafanint 1136166124Srafanshow_entry(void) 1137166124Srafan{ 1138166124Srafan trim_trailing(); 113962449Speter (void) fputs(outbuf.text, stdout); 1140166124Srafan putchar('\n'); 114162449Speter return outbuf.used; 114250276Speter} 114350276Speter 114462449Spetervoid 1145166124Srafancompare_entry(void (*hook) (PredType t, PredIdx i, const char *name), 1146166124Srafan TERMTYPE *tp GCC_UNUSED, 1147166124Srafan bool quiet) 114850276Speter/* compare two entries */ 114950276Speter{ 1150166124Srafan PredIdx i, j; 115162449Speter NCURSES_CONST char *name; 115250276Speter 115362449Speter if (!quiet) 115462449Speter fputs(" comparing booleans.\n", stdout); 115562449Speter for_each_boolean(j, tp) { 115650276Speter i = BoolIndirect(j); 115762449Speter name = ExtBoolname(tp, i, bool_names); 115850276Speter 115962449Speter if (isObsolete(outform, name)) 116050276Speter continue; 116150276Speter 116262449Speter (*hook) (CMP_BOOLEAN, i, name); 116350276Speter } 116450276Speter 116562449Speter if (!quiet) 116662449Speter fputs(" comparing numbers.\n", stdout); 116762449Speter for_each_number(j, tp) { 116850276Speter i = NumIndirect(j); 116962449Speter name = ExtNumname(tp, i, num_names); 117050276Speter 117162449Speter if (isObsolete(outform, name)) 117250276Speter continue; 117350276Speter 117462449Speter (*hook) (CMP_NUMBER, i, name); 117550276Speter } 117650276Speter 117762449Speter if (!quiet) 117862449Speter fputs(" comparing strings.\n", stdout); 117962449Speter for_each_string(j, tp) { 118050276Speter i = StrIndirect(j); 118162449Speter name = ExtStrname(tp, i, str_names); 118250276Speter 118362449Speter if (isObsolete(outform, name)) 118450276Speter continue; 118550276Speter 118662449Speter (*hook) (CMP_STRING, i, name); 118750276Speter } 118862449Speter 118962449Speter /* (void) fputs(" comparing use entries.\n", stdout); */ 119062449Speter (*hook) (CMP_USE, 0, "use"); 119162449Speter 119250276Speter} 119350276Speter 119450276Speter#define NOTSET(s) ((s) == 0) 119550276Speter 119650276Speter/* 119750276Speter * This bit of legerdemain turns all the terminfo variable names into 119850276Speter * references to locations in the arrays Booleans, Numbers, and Strings --- 119950276Speter * precisely what's needed. 120050276Speter */ 120150276Speter#undef CUR 120250276Speter#define CUR tp-> 120350276Speter 120462449Speterstatic void 1205166124Srafanset_obsolete_termcaps(TERMTYPE *tp) 120650276Speter{ 120750276Speter#include "capdefaults.c" 120850276Speter} 120950276Speter 121050276Speter/* 121150276Speter * Convert an alternate-character-set string to canonical form: sorted and 121250276Speter * unique. 121350276Speter */ 121462449Spetervoid 1215166124Srafanrepair_acsc(TERMTYPE *tp) 121650276Speter{ 121762449Speter if (VALID_STRING(acs_chars)) { 121862449Speter size_t n, m; 121962449Speter char mapped[256]; 122062449Speter char extra = 0; 122162449Speter unsigned source; 122262449Speter unsigned target; 122362449Speter bool fix_needed = FALSE; 122450276Speter 122562449Speter for (n = 0, source = 0; acs_chars[n] != 0; n++) { 122662449Speter target = acs_chars[n]; 122762449Speter if (source >= target) { 122862449Speter fix_needed = TRUE; 122962449Speter break; 123062449Speter } 123162449Speter source = target; 123262449Speter if (acs_chars[n + 1]) 123362449Speter n++; 123462449Speter } 123562449Speter if (fix_needed) { 123662449Speter memset(mapped, 0, sizeof(mapped)); 123762449Speter for (n = 0; acs_chars[n] != 0; n++) { 123862449Speter source = acs_chars[n]; 123962449Speter if ((target = (unsigned char) acs_chars[n + 1]) != 0) { 124062449Speter mapped[source] = target; 124162449Speter n++; 124262449Speter } else { 124362449Speter extra = source; 124450276Speter } 124550276Speter } 124662449Speter for (n = m = 0; n < sizeof(mapped); n++) { 124762449Speter if (mapped[n]) { 124862449Speter acs_chars[m++] = n; 124962449Speter acs_chars[m++] = mapped[n]; 125050276Speter } 125150276Speter } 125262449Speter if (extra) 125362449Speter acs_chars[m++] = extra; /* garbage in, garbage out */ 125462449Speter acs_chars[m] = 0; 125550276Speter } 125662449Speter } 125750276Speter} 1258