150276Speter/**************************************************************************** 2178866Srafan * Copyright (c) 1998-2007,2008 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> * 32184989Srafan * 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 42184989SrafanMODULE_ID("$Id: dump_entry.c,v 1.88 2008/08/04 12:36:12 tom Exp $") 4350276Speter 4450276Speter#define INDENT 8 4550276Speter#define DISCARD(string) string = ABSENT_STRING 4662449Speter#define PRINTF (void) printf 4750276Speter 48184989Srafan#define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array)) 49184989Srafan 5062449Spetertypedef struct { 5162449Speter char *text; 5262449Speter size_t used; 5362449Speter size_t size; 5462449Speter} DYNBUF; 5562449Speter 5650276Speterstatic int tversion; /* terminfo version */ 5750276Speterstatic int outform; /* output format to use */ 5850276Speterstatic int sortmode; /* sort mode to use */ 5950276Speterstatic int width = 60; /* max line width for listings */ 6050276Speterstatic int column; /* current column, limited by 'width' */ 6150276Speterstatic int oldcol; /* last value of column before wrap */ 6250276Speterstatic bool pretty; /* true if we format if-then-else strings */ 6350276Speter 64166124Srafanstatic char *save_sgr; 65166124Srafan 6662449Speterstatic DYNBUF outbuf; 6762449Speterstatic DYNBUF tmpbuf; 6850276Speter 6950276Speter/* indirection pointers for implementing sort and display modes */ 70166124Srafanstatic const PredIdx *bool_indirect, *num_indirect, *str_indirect; 7162449Speterstatic NCURSES_CONST char *const *bool_names; 7262449Speterstatic NCURSES_CONST char *const *num_names; 7362449Speterstatic NCURSES_CONST char *const *str_names; 7450276Speter 7550276Speterstatic const char *separator, *trailer; 7650276Speter 7750276Speter/* cover various ports and variants of terminfo */ 7850276Speter#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ 7950276Speter#define V_SVR1 1 /* SVR1, Ultrix */ 8050276Speter#define V_HPUX 2 /* HP/UX */ 8150276Speter#define V_AIX 3 /* AIX */ 8250276Speter#define V_BSD 4 /* BSD */ 8350276Speter 8462449Speter#if NCURSES_XNAMES 8562449Speter#define OBSOLETE(n) (!_nc_user_definable && (n[0] == 'O' && n[1] == 'T')) 8662449Speter#else 8750276Speter#define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') 8862449Speter#endif 8950276Speter 9062449Speter#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n)) 9162449Speter 9250276Speter#if NCURSES_XNAMES 9350276Speter#define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) 9450276Speter#define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j])) 9550276Speter#define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j])) 9650276Speter#else 9750276Speter#define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j]) 9850276Speter#define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j]) 9950276Speter#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) 10050276Speter#endif 10150276Speter 10262449Speterstatic void 10362449Speterstrncpy_DYN(DYNBUF * dst, const char *src, size_t need) 10462449Speter{ 10562449Speter size_t want = need + dst->used + 1; 10662449Speter if (want > dst->size) { 10762449Speter dst->size += (want + 1024); /* be generous */ 10862449Speter dst->text = typeRealloc(char, dst->size, dst->text); 10962449Speter } 11062449Speter (void) strncpy(dst->text + dst->used, src, need); 11162449Speter dst->used += need; 11262449Speter dst->text[dst->used] = 0; 11362449Speter} 11462449Speter 11562449Speterstatic void 11662449Speterstrcpy_DYN(DYNBUF * dst, const char *src) 11762449Speter{ 11862449Speter if (src == 0) { 11962449Speter dst->used = 0; 12062449Speter strcpy_DYN(dst, ""); 12162449Speter } else { 12262449Speter strncpy_DYN(dst, src, strlen(src)); 12362449Speter } 12462449Speter} 12562449Speter 12650276Speter#if NO_LEAKS 12762449Speterstatic void 12862449Speterfree_DYN(DYNBUF * p) 12950276Speter{ 13062449Speter if (p->text != 0) 13162449Speter free(p->text); 13262449Speter p->text = 0; 13362449Speter p->size = 0; 13462449Speter p->used = 0; 13550276Speter} 13662449Speter 13762449Spetervoid 13862449Speter_nc_leaks_dump_entry(void) 13962449Speter{ 14062449Speter free_DYN(&outbuf); 14162449Speter free_DYN(&tmpbuf); 14262449Speter} 14350276Speter#endif 14450276Speter 145184989Srafan#define NameTrans(check,result) \ 146184989Srafan if (OkIndex(np->nte_index, check) \ 147184989Srafan && check[np->nte_index]) \ 148184989Srafan return (result[np->nte_index]) 149184989Srafan 15062449SpeterNCURSES_CONST char * 15162449Speternametrans(const char *name) 15250276Speter/* translate a capability name from termcap to terminfo */ 15350276Speter{ 15462449Speter const struct name_table_entry *np; 15550276Speter 15650276Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) 15762449Speter switch (np->nte_type) { 15850276Speter case BOOLEAN: 159184989Srafan NameTrans(bool_from_termcap, boolcodes); 16050276Speter break; 16150276Speter 16250276Speter case NUMBER: 163184989Srafan NameTrans(num_from_termcap, numcodes); 16450276Speter break; 16550276Speter 16650276Speter case STRING: 167184989Srafan NameTrans(str_from_termcap, strcodes); 16850276Speter break; 16950276Speter } 17050276Speter 17162449Speter return (0); 17250276Speter} 17350276Speter 17462449Spetervoid 17562449Speterdump_init(const char *version, int mode, int sort, int twidth, int traceval, 17698503Speter bool formatted) 17750276Speter/* set up for entry display */ 17850276Speter{ 17950276Speter width = twidth; 18050276Speter pretty = formatted; 18150276Speter 18250276Speter /* versions */ 18350276Speter if (version == 0) 18450276Speter tversion = V_ALLCAPS; 18550276Speter else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1") 18698503Speter || !strcmp(version, "Ultrix")) 18750276Speter tversion = V_SVR1; 18850276Speter else if (!strcmp(version, "HP")) 18950276Speter tversion = V_HPUX; 19050276Speter else if (!strcmp(version, "AIX")) 19150276Speter tversion = V_AIX; 19250276Speter else if (!strcmp(version, "BSD")) 19350276Speter tversion = V_BSD; 19450276Speter else 19550276Speter tversion = V_ALLCAPS; 19650276Speter 19750276Speter /* implement display modes */ 19862449Speter switch (outform = mode) { 19950276Speter case F_LITERAL: 20050276Speter case F_TERMINFO: 20150276Speter bool_names = boolnames; 20250276Speter num_names = numnames; 20350276Speter str_names = strnames; 20450276Speter separator = twidth ? ", " : ","; 20550276Speter trailer = "\n\t"; 20650276Speter break; 20750276Speter 20850276Speter case F_VARIABLE: 20950276Speter bool_names = boolfnames; 21050276Speter num_names = numfnames; 21150276Speter str_names = strfnames; 21250276Speter separator = twidth ? ", " : ","; 21350276Speter trailer = "\n\t"; 21450276Speter break; 21550276Speter 21650276Speter case F_TERMCAP: 21750276Speter case F_TCONVERR: 21850276Speter bool_names = boolcodes; 21950276Speter num_names = numcodes; 22050276Speter str_names = strcodes; 22150276Speter separator = ":"; 22250276Speter trailer = "\\\n\t:"; 22350276Speter break; 22450276Speter } 22550276Speter 22650276Speter /* implement sort modes */ 22762449Speter switch (sortmode = sort) { 22850276Speter case S_NOSORT: 22950276Speter if (traceval) 23050276Speter (void) fprintf(stderr, 23198503Speter "%s: sorting by term structure order\n", _nc_progname); 23250276Speter break; 23350276Speter 23450276Speter case S_TERMINFO: 23550276Speter if (traceval) 23650276Speter (void) fprintf(stderr, 23798503Speter "%s: sorting by terminfo name order\n", _nc_progname); 23850276Speter bool_indirect = bool_terminfo_sort; 23950276Speter num_indirect = num_terminfo_sort; 24050276Speter str_indirect = str_terminfo_sort; 24150276Speter break; 24250276Speter 24350276Speter case S_VARIABLE: 24450276Speter if (traceval) 24550276Speter (void) fprintf(stderr, 24698503Speter "%s: sorting by C variable order\n", _nc_progname); 24750276Speter bool_indirect = bool_variable_sort; 24850276Speter num_indirect = num_variable_sort; 24950276Speter str_indirect = str_variable_sort; 25050276Speter break; 25150276Speter 25250276Speter case S_TERMCAP: 25350276Speter if (traceval) 25450276Speter (void) fprintf(stderr, 25598503Speter "%s: sorting by termcap name order\n", _nc_progname); 25650276Speter bool_indirect = bool_termcap_sort; 25750276Speter num_indirect = num_termcap_sort; 25850276Speter str_indirect = str_termcap_sort; 25950276Speter break; 26050276Speter } 26150276Speter 26250276Speter if (traceval) 26350276Speter (void) fprintf(stderr, 26498503Speter "%s: width = %d, tversion = %d, outform = %d\n", 26598503Speter _nc_progname, width, tversion, outform); 26650276Speter} 26750276Speter 26862449Speterstatic TERMTYPE *cur_type; 26950276Speter 27062449Speterstatic int 271166124Srafandump_predicate(PredType type, PredIdx idx) 27250276Speter/* predicate function to use for ordinary decompilation */ 27350276Speter{ 27462449Speter switch (type) { 27562449Speter case BOOLEAN: 27662449Speter return (cur_type->Booleans[idx] == FALSE) 27762449Speter ? FAIL : cur_type->Booleans[idx]; 27850276Speter 27962449Speter case NUMBER: 28062449Speter return (cur_type->Numbers[idx] == ABSENT_NUMERIC) 28162449Speter ? FAIL : cur_type->Numbers[idx]; 28250276Speter 28362449Speter case STRING: 28462449Speter return (cur_type->Strings[idx] != ABSENT_STRING) 28562449Speter ? (int) TRUE : FAIL; 28662449Speter } 28750276Speter 28862449Speter return (FALSE); /* pacify compiler */ 28950276Speter} 29050276Speter 291166124Srafanstatic void set_obsolete_termcaps(TERMTYPE *tp); 29250276Speter 29350276Speter/* is this the index of a function key string? */ 29450276Speter#define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268)) 29550276Speter 296166124Srafan/* 297166124Srafan * If we configure with a different Caps file, the offsets into the arrays 298166124Srafan * will change. So we use an address expression. 299166124Srafan */ 300184989Srafan#define BOOL_IDX(name) (PredType) (&(name) - &(CUR Booleans[0])) 301184989Srafan#define NUM_IDX(name) (PredType) (&(name) - &(CUR Numbers[0])) 302184989Srafan#define STR_IDX(name) (PredType) (&(name) - &(CUR Strings[0])) 303166124Srafan 30462449Speterstatic bool 305166124Srafanversion_filter(PredType type, PredIdx idx) 30650276Speter/* filter out capabilities we may want to suppress */ 30750276Speter{ 30862449Speter switch (tversion) { 30962449Speter case V_ALLCAPS: /* SVr4, XSI Curses */ 31062449Speter return (TRUE); 31150276Speter 31262449Speter case V_SVR1: /* System V Release 1, Ultrix */ 31362449Speter switch (type) { 31450276Speter case BOOLEAN: 315166124Srafan return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); 31650276Speter case NUMBER: 317166124Srafan return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE); 31850276Speter case STRING: 319166124Srafan return ((idx <= STR_IDX(prtr_non)) ? TRUE : FALSE); 32050276Speter } 32150276Speter break; 32250276Speter 32350276Speter case V_HPUX: /* Hewlett-Packard */ 32462449Speter switch (type) { 32550276Speter case BOOLEAN: 326166124Srafan return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); 32750276Speter case NUMBER: 328166124Srafan return ((idx <= NUM_IDX(label_width)) ? TRUE : FALSE); 32950276Speter case STRING: 330166124Srafan if (idx <= STR_IDX(prtr_non)) 33162449Speter return (TRUE); 33250276Speter else if (FNKEY(idx)) /* function keys */ 33362449Speter return (TRUE); 334166124Srafan else if (idx == STR_IDX(plab_norm) 335166124Srafan || idx == STR_IDX(label_on) 336166124Srafan || idx == STR_IDX(label_off)) 33762449Speter return (TRUE); 33850276Speter else 33962449Speter return (FALSE); 34050276Speter } 34150276Speter break; 34250276Speter 34350276Speter case V_AIX: /* AIX */ 34462449Speter switch (type) { 34550276Speter case BOOLEAN: 346166124Srafan return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); 34750276Speter case NUMBER: 348166124Srafan return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE); 34950276Speter case STRING: 350166124Srafan if (idx <= STR_IDX(prtr_non)) 35162449Speter return (TRUE); 35250276Speter else if (FNKEY(idx)) /* function keys */ 35362449Speter return (TRUE); 35450276Speter else 35562449Speter return (FALSE); 35650276Speter } 35750276Speter break; 35850276Speter 359184989Srafan#define is_termcap(type) (OkIndex(idx, type##_from_termcap) && \ 360174993Srafan type##_from_termcap[idx]) 361174993Srafan 36250276Speter case V_BSD: /* BSD */ 36362449Speter switch (type) { 36450276Speter case BOOLEAN: 365174993Srafan return is_termcap(bool); 36650276Speter case NUMBER: 367174993Srafan return is_termcap(num); 36850276Speter case STRING: 369174993Srafan return is_termcap(str); 37050276Speter } 37150276Speter break; 37250276Speter } 37350276Speter 37462449Speter return (FALSE); /* pacify the compiler */ 37550276Speter} 37650276Speter 37762449Speterstatic void 378166124Srafantrim_trailing(void) 379166124Srafan{ 380166124Srafan while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ') 381166124Srafan outbuf.text[--outbuf.used] = '\0'; 382166124Srafan} 383166124Srafan 384166124Srafanstatic void 38562449Speterforce_wrap(void) 38650276Speter{ 38762449Speter oldcol = column; 388166124Srafan trim_trailing(); 38962449Speter strcpy_DYN(&outbuf, trailer); 39062449Speter column = INDENT; 39150276Speter} 39250276Speter 39362449Speterstatic void 39462449Speterwrap_concat(const char *src) 39550276Speter{ 396184989Srafan unsigned need = strlen(src); 397184989Srafan unsigned want = strlen(separator) + need; 39850276Speter 39962449Speter if (column > INDENT 400184989Srafan && column + (int) want > width) { 40162449Speter force_wrap(); 40262449Speter } 40362449Speter strcpy_DYN(&outbuf, src); 40462449Speter strcpy_DYN(&outbuf, separator); 405184989Srafan column += (int) need; 40650276Speter} 40750276Speter 40850276Speter#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ 40950276Speter if ((size_t)(last - first) > sizeof(sep_trail)-1 \ 41050276Speter && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ 411184989Srafan first += sizeof(sep_trail)-2 41250276Speter 41350276Speter/* Returns the nominal length of the buffer assuming it is termcap format, 41450276Speter * i.e., the continuation sequence is treated as a single character ":". 41550276Speter * 41650276Speter * There are several implementations of termcap which read the text into a 41750276Speter * fixed-size buffer. Generally they strip the newlines from the text, but may 41850276Speter * not do it until after the buffer is read. Also, "tc=" resolution may be 41950276Speter * expanded in the same buffer. This function is useful for measuring the size 42050276Speter * of the best fixed-buffer implementation; the worst case may be much worse. 42150276Speter */ 42250276Speter#ifdef TEST_TERMCAP_LENGTH 42362449Speterstatic int 42462449Spetertermcap_length(const char *src) 42550276Speter{ 42662449Speter static const char pattern[] = ":\\\n\t:"; 42750276Speter 42862449Speter int len = 0; 42962449Speter const char *const t = src + strlen(src); 43050276Speter 43162449Speter while (*src != '\0') { 43262449Speter IGNORE_SEP_TRAIL(src, t, pattern); 43362449Speter src++; 43462449Speter len++; 43562449Speter } 43662449Speter return len; 43750276Speter} 43850276Speter#else 43950276Speter#define termcap_length(src) strlen(src) 44050276Speter#endif 44150276Speter 442166124Srafanstatic void 443166124Srafanindent_DYN(DYNBUF * buffer, int level) 444166124Srafan{ 445166124Srafan int n; 446166124Srafan 447166124Srafan for (n = 0; n < level; n++) 448166124Srafan strncpy_DYN(buffer, "\t", 1); 449166124Srafan} 450166124Srafan 451166124Srafanstatic bool 452166124Srafanhas_params(const char *src) 453166124Srafan{ 454166124Srafan bool result = FALSE; 455184989Srafan int len = (int) strlen(src); 456166124Srafan int n; 457166124Srafan bool ifthen = FALSE; 458166124Srafan bool params = FALSE; 459166124Srafan 460166124Srafan for (n = 0; n < len - 1; ++n) { 461166124Srafan if (!strncmp(src + n, "%p", 2)) { 462166124Srafan params = TRUE; 463166124Srafan } else if (!strncmp(src + n, "%;", 2)) { 464166124Srafan ifthen = TRUE; 465166124Srafan result = params; 466166124Srafan break; 467166124Srafan } 468166124Srafan } 469166124Srafan if (!ifthen) { 470166124Srafan result = ((len > 50) && params); 471166124Srafan } 472166124Srafan return result; 473166124Srafan} 474166124Srafan 47562449Speterstatic char * 47662449Speterfmt_complex(char *src, int level) 47750276Speter{ 478166124Srafan bool percent = FALSE; 479166124Srafan bool params = has_params(src); 48050276Speter 48162449Speter while (*src != '\0') { 48262449Speter switch (*src) { 48362449Speter case '\\': 484166124Srafan percent = FALSE; 48562449Speter strncpy_DYN(&tmpbuf, src++, 1); 48662449Speter break; 48762449Speter case '%': 488166124Srafan percent = TRUE; 48962449Speter break; 49062449Speter case '?': /* "if" */ 49162449Speter case 't': /* "then" */ 49262449Speter case 'e': /* "else" */ 49362449Speter if (percent) { 494166124Srafan percent = FALSE; 49562449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 496166124Srafan /* treat a "%e" as else-if, on the same level */ 497166124Srafan if (*src == 'e') { 498166124Srafan indent_DYN(&tmpbuf, level); 49962449Speter strncpy_DYN(&tmpbuf, "%", 1); 500166124Srafan strncpy_DYN(&tmpbuf, src, 1); 501166124Srafan src++; 502166124Srafan params = has_params(src); 503166124Srafan if (!params && *src != '\0' && *src != '%') { 504166124Srafan strncpy_DYN(&tmpbuf, "\n", 1); 505166124Srafan indent_DYN(&tmpbuf, level + 1); 506166124Srafan } 50762449Speter } else { 508166124Srafan indent_DYN(&tmpbuf, level + 1); 50962449Speter strncpy_DYN(&tmpbuf, "%", 1); 51062449Speter strncpy_DYN(&tmpbuf, src, 1); 51162449Speter if (*src++ == '?') { 51262449Speter src = fmt_complex(src, level + 1); 513166124Srafan if (*src != '\0' && *src != '%') { 514166124Srafan strncpy_DYN(&tmpbuf, "\n", 1); 515166124Srafan indent_DYN(&tmpbuf, level + 1); 516166124Srafan } 51762449Speter } else if (level == 1) { 51862449Speter _nc_warning("%%%c without %%?", *src); 51962449Speter } 52050276Speter } 52162449Speter continue; 52262449Speter } 52362449Speter break; 52462449Speter case ';': /* "endif" */ 52562449Speter if (percent) { 526166124Srafan percent = FALSE; 52762449Speter if (level > 1) { 52862449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 529166124Srafan indent_DYN(&tmpbuf, level); 53062449Speter strncpy_DYN(&tmpbuf, "%", 1); 53162449Speter strncpy_DYN(&tmpbuf, src++, 1); 53262449Speter return src; 53362449Speter } 53462449Speter _nc_warning("%%; without %%?"); 53562449Speter } 53662449Speter break; 53762449Speter case 'p': 53862449Speter if (percent && params) { 53962449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 540166124Srafan indent_DYN(&tmpbuf, level + 1); 54162449Speter strncpy_DYN(&tmpbuf, "%", 1); 54262449Speter } 543166124Srafan params = FALSE; 544166124Srafan percent = FALSE; 54562449Speter break; 546178866Srafan case ' ': 547178866Srafan strncpy_DYN(&tmpbuf, "\\s", 2); 548178866Srafan ++src; 549178866Srafan continue; 55062449Speter default: 551166124Srafan percent = FALSE; 55262449Speter break; 55350276Speter } 55462449Speter strncpy_DYN(&tmpbuf, src++, 1); 55562449Speter } 55662449Speter return src; 55750276Speter} 55850276Speter 559166124Srafan#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) 560184989Srafan#define EXTRA_CAP 20 561166124Srafan 56262449Speterint 563166124Srafanfmt_entry(TERMTYPE *tterm, 564166124Srafan PredFunc pred, 565166124Srafan bool content_only, 56698503Speter bool suppress_untranslatable, 56798503Speter bool infodump, 56898503Speter int numbers) 56950276Speter{ 570166124Srafan PredIdx i, j; 571184989Srafan char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; 572166124Srafan char *capability; 57362449Speter NCURSES_CONST char *name; 57462449Speter int predval, len; 575166124Srafan PredIdx num_bools = 0; 576166124Srafan PredIdx num_values = 0; 577166124Srafan PredIdx num_strings = 0; 57862449Speter bool outcount = 0; 57950276Speter 58050276Speter#define WRAP_CONCAT \ 58150276Speter wrap_concat(buffer); \ 58250276Speter outcount = TRUE 58350276Speter 58450276Speter len = 12; /* terminfo file-header */ 58550276Speter 58650276Speter if (pred == 0) { 58750276Speter cur_type = tterm; 58850276Speter pred = dump_predicate; 58950276Speter } 59050276Speter 59162449Speter strcpy_DYN(&outbuf, 0); 592166124Srafan if (content_only) { 593166124Srafan column = INDENT; /* FIXME: workaround to prevent empty lines */ 594166124Srafan } else { 595166124Srafan strcpy_DYN(&outbuf, tterm->term_names); 596166124Srafan strcpy_DYN(&outbuf, separator); 597184989Srafan column = (int) outbuf.used; 598166124Srafan force_wrap(); 599166124Srafan } 60050276Speter 60162449Speter for_each_boolean(j, tterm) { 60250276Speter i = BoolIndirect(j); 60362449Speter name = ExtBoolname(tterm, i, bool_names); 604184989Srafan assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); 60550276Speter 60650276Speter if (!version_filter(BOOLEAN, i)) 60750276Speter continue; 60862449Speter else if (isObsolete(outform, name)) 60950276Speter continue; 61050276Speter 61150276Speter predval = pred(BOOLEAN, i); 61250276Speter if (predval != FAIL) { 61350276Speter (void) strcpy(buffer, name); 61450276Speter if (predval <= 0) 61550276Speter (void) strcat(buffer, "@"); 61650276Speter else if (i + 1 > num_bools) 61750276Speter num_bools = i + 1; 61850276Speter WRAP_CONCAT; 61950276Speter } 62050276Speter } 62150276Speter 62250276Speter if (column != INDENT) 62350276Speter force_wrap(); 62450276Speter 62562449Speter for_each_number(j, tterm) { 62650276Speter i = NumIndirect(j); 62762449Speter name = ExtNumname(tterm, i, num_names); 628184989Srafan assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); 62950276Speter 63050276Speter if (!version_filter(NUMBER, i)) 63150276Speter continue; 63262449Speter else if (isObsolete(outform, name)) 63350276Speter continue; 63450276Speter 63550276Speter predval = pred(NUMBER, i); 63650276Speter if (predval != FAIL) { 63750276Speter if (tterm->Numbers[i] < 0) { 63850276Speter sprintf(buffer, "%s@", name); 63950276Speter } else { 64050276Speter sprintf(buffer, "%s#%d", name, tterm->Numbers[i]); 64150276Speter if (i + 1 > num_values) 64250276Speter num_values = i + 1; 64350276Speter } 64450276Speter WRAP_CONCAT; 64550276Speter } 64650276Speter } 64750276Speter 64850276Speter if (column != INDENT) 64950276Speter force_wrap(); 65050276Speter 651184989Srafan len += (int) (num_bools 652184989Srafan + num_values * 2 653184989Srafan + strlen(tterm->term_names) + 1); 65450276Speter if (len & 1) 65562449Speter len++; 65650276Speter 65762449Speter#undef CUR 65862449Speter#define CUR tterm-> 65962449Speter if (outform == F_TERMCAP) { 66062449Speter if (termcap_reset != ABSENT_STRING) { 66162449Speter if (init_3string != ABSENT_STRING 66262449Speter && !strcmp(init_3string, termcap_reset)) 66362449Speter DISCARD(init_3string); 66462449Speter 66562449Speter if (reset_2string != ABSENT_STRING 66662449Speter && !strcmp(reset_2string, termcap_reset)) 66762449Speter DISCARD(reset_2string); 66862449Speter } 66962449Speter } 67062449Speter 67150276Speter for_each_string(j, tterm) { 67250276Speter i = StrIndirect(j); 67362449Speter name = ExtStrname(tterm, i, str_names); 674184989Srafan assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); 675184989Srafan 676166124Srafan capability = tterm->Strings[i]; 67750276Speter 67850276Speter if (!version_filter(STRING, i)) 67950276Speter continue; 68062449Speter else if (isObsolete(outform, name)) 68150276Speter continue; 68250276Speter 683166124Srafan#if NCURSES_XNAMES 68450276Speter /* 685166124Srafan * Extended names can be longer than 2 characters, but termcap programs 686166124Srafan * cannot read those (filter them out). 68750276Speter */ 688166124Srafan if (outform == F_TERMCAP && (strlen(name) > 2)) 689166124Srafan continue; 690166124Srafan#endif 691166124Srafan 69262449Speter if (outform == F_TERMCAP) { 693166124Srafan /* 694166124Srafan * Some older versions of vi want rmir/smir to be defined 695166124Srafan * for ich/ich1 to work. If they're not defined, force 696166124Srafan * them to be output as defined and empty. 697166124Srafan */ 698166124Srafan if (PRESENT(insert_character) || PRESENT(parm_ich)) { 699166124Srafan if (SAME_CAP(i, enter_insert_mode) 70062449Speter && enter_insert_mode == ABSENT_STRING) { 70150276Speter (void) strcpy(buffer, "im="); 70262449Speter WRAP_CONCAT; 70362449Speter continue; 70450276Speter } 70550276Speter 706166124Srafan if (SAME_CAP(i, exit_insert_mode) 70762449Speter && exit_insert_mode == ABSENT_STRING) { 70850276Speter (void) strcpy(buffer, "ei="); 70962449Speter WRAP_CONCAT; 71062449Speter continue; 71150276Speter } 71250276Speter } 713166124Srafan /* 714166124Srafan * termcap applications such as screen will be confused if sgr0 715166124Srafan * is translated to a string containing rmacs. Filter that out. 716166124Srafan */ 717166124Srafan if (PRESENT(exit_attribute_mode)) { 718166124Srafan if (SAME_CAP(i, exit_attribute_mode)) { 719166124Srafan char *trimmed_sgr0; 720166124Srafan char *my_sgr = set_attributes; 721166124Srafan 722166124Srafan set_attributes = save_sgr; 723166124Srafan 724166124Srafan trimmed_sgr0 = _nc_trim_sgr0(tterm); 725166124Srafan if (strcmp(capability, trimmed_sgr0)) 726166124Srafan capability = trimmed_sgr0; 727166124Srafan 728166124Srafan set_attributes = my_sgr; 729166124Srafan } 730166124Srafan } 73150276Speter } 73250276Speter 73350276Speter predval = pred(STRING, i); 73450276Speter buffer[0] = '\0'; 73562449Speter 73650276Speter if (predval != FAIL) { 737166124Srafan if (capability != ABSENT_STRING 73862449Speter && i + 1 > num_strings) 73950276Speter num_strings = i + 1; 74062449Speter 741166124Srafan if (!VALID_STRING(capability)) { 74250276Speter sprintf(buffer, "%s@", name); 74362449Speter WRAP_CONCAT; 74462449Speter } else if (outform == F_TERMCAP || outform == F_TCONVERR) { 74598503Speter int params = ((i < (int) SIZEOF(parametrized)) 74698503Speter ? parametrized[i] 74798503Speter : 0); 748166124Srafan char *srccap = _nc_tic_expand(capability, TRUE, numbers); 74966963Speter char *cv = _nc_infotocap(name, srccap, params); 75050276Speter 75162449Speter if (cv == 0) { 75262449Speter if (outform == F_TCONVERR) { 75362449Speter sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", 75498503Speter name, srccap); 75562449Speter } else if (suppress_untranslatable) { 75650276Speter continue; 75762449Speter } else { 75862449Speter char *s = srccap, *d = buffer; 75962449Speter sprintf(d, "..%s=", name); 76062449Speter d += strlen(d); 76162449Speter while ((*d = *s++) != 0) { 76262449Speter if (*d == ':') { 76362449Speter *d++ = '\\'; 76462449Speter *d = ':'; 76562449Speter } else if (*d == '\\') { 76662449Speter *++d = *s++; 76762449Speter } 76862449Speter d++; 76962449Speter } 77062449Speter } 77162449Speter } else { 77262449Speter sprintf(buffer, "%s=%s", name, cv); 77350276Speter } 774184989Srafan len += (int) strlen(capability) + 1; 77562449Speter WRAP_CONCAT; 77662449Speter } else { 777166124Srafan char *src = _nc_tic_expand(capability, 77898503Speter outform == F_TERMINFO, numbers); 77962449Speter 78062449Speter strcpy_DYN(&tmpbuf, 0); 78162449Speter strcpy_DYN(&tmpbuf, name); 78262449Speter strcpy_DYN(&tmpbuf, "="); 78362449Speter if (pretty 78462449Speter && (outform == F_TERMINFO 78562449Speter || outform == F_VARIABLE)) { 78662449Speter fmt_complex(src, 1); 78762449Speter } else { 78862449Speter strcpy_DYN(&tmpbuf, src); 78962449Speter } 790184989Srafan len += (int) strlen(capability) + 1; 79162449Speter wrap_concat(tmpbuf.text); 79262449Speter outcount = TRUE; 79350276Speter } 79450276Speter } 795166124Srafan /* e.g., trimmed_sgr0 */ 796166124Srafan if (capability != tterm->Strings[i]) 797166124Srafan free(capability); 79850276Speter } 799184989Srafan len += (int) (num_strings * 2); 80050276Speter 80150276Speter /* 80250276Speter * This piece of code should be an effective inverse of the functions 803166124Srafan * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c. 80450276Speter * Much more work should be done on this to support dumping termcaps. 80550276Speter */ 80662449Speter if (tversion == V_HPUX) { 807174993Srafan if (VALID_STRING(memory_lock)) { 80850276Speter (void) sprintf(buffer, "meml=%s", memory_lock); 80950276Speter WRAP_CONCAT; 81050276Speter } 811174993Srafan if (VALID_STRING(memory_unlock)) { 81250276Speter (void) sprintf(buffer, "memu=%s", memory_unlock); 81350276Speter WRAP_CONCAT; 81450276Speter } 81562449Speter } else if (tversion == V_AIX) { 81662449Speter if (VALID_STRING(acs_chars)) { 81762449Speter bool box_ok = TRUE; 81862449Speter const char *acstrans = "lqkxjmwuvtn"; 81962449Speter const char *cp; 82062449Speter char *tp, *sp, boxchars[11]; 82150276Speter 82250276Speter tp = boxchars; 82362449Speter for (cp = acstrans; *cp; cp++) { 82450276Speter sp = strchr(acs_chars, *cp); 82550276Speter if (sp) 82650276Speter *tp++ = sp[1]; 82762449Speter else { 82850276Speter box_ok = FALSE; 82950276Speter break; 83050276Speter } 83150276Speter } 83250276Speter tp[0] = '\0'; 83350276Speter 83462449Speter if (box_ok) { 83550276Speter (void) strcpy(buffer, "box1="); 83662449Speter (void) strcat(buffer, _nc_tic_expand(boxchars, 83798503Speter outform == F_TERMINFO, numbers)); 83850276Speter WRAP_CONCAT; 83950276Speter } 84050276Speter } 84150276Speter } 84250276Speter 84350276Speter /* 84450276Speter * kludge: trim off trailer to avoid an extra blank line 84550276Speter * in infocmp -u output when there are no string differences 84650276Speter */ 84762449Speter if (outcount) { 84862449Speter bool trimmed = FALSE; 84962449Speter j = outbuf.used; 85050276Speter if (j >= 2 85162449Speter && outbuf.text[j - 1] == '\t' 85262449Speter && outbuf.text[j - 2] == '\n') { 85362449Speter outbuf.used -= 2; 85462449Speter trimmed = TRUE; 85550276Speter } else if (j >= 4 85698503Speter && outbuf.text[j - 1] == ':' 85798503Speter && outbuf.text[j - 2] == '\t' 85898503Speter && outbuf.text[j - 3] == '\n' 85998503Speter && outbuf.text[j - 4] == '\\') { 86062449Speter outbuf.used -= 4; 86162449Speter trimmed = TRUE; 86250276Speter } 86362449Speter if (trimmed) { 86462449Speter outbuf.text[outbuf.used] = '\0'; 86562449Speter column = oldcol; 866166124Srafan strcpy_DYN(&outbuf, " "); 86762449Speter } 86850276Speter } 86950276Speter#if 0 87050276Speter fprintf(stderr, "num_bools = %d\n", num_bools); 87150276Speter fprintf(stderr, "num_values = %d\n", num_values); 87250276Speter fprintf(stderr, "num_strings = %d\n", num_strings); 87350276Speter fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n", 87498503Speter tterm->term_names, len, outbuf.used, outbuf.text); 87550276Speter#endif 87650276Speter /* 87750276Speter * Here's where we use infodump to trigger a more stringent length check 87850276Speter * for termcap-translation purposes. 87950276Speter * Return the length of the raw entry, without tc= expansions, 88050276Speter * It gives an idea of which entries are deadly to even *scan past*, 88150276Speter * as opposed to *use*. 88250276Speter */ 88376726Speter return (infodump ? len : (int) termcap_length(outbuf.text)); 88450276Speter} 88550276Speter 88698503Speterstatic bool 887166124Srafankill_string(TERMTYPE *tterm, char *cap) 88898503Speter{ 889184989Srafan unsigned n; 890166124Srafan for (n = 0; n < NUM_STRINGS(tterm); ++n) { 89198503Speter if (cap == tterm->Strings[n]) { 89298503Speter tterm->Strings[n] = ABSENT_STRING; 89398503Speter return TRUE; 89498503Speter } 89598503Speter } 89698503Speter return FALSE; 89798503Speter} 89898503Speter 89998503Speterstatic char * 900166124Srafanfind_string(TERMTYPE *tterm, char *name) 90198503Speter{ 902166124Srafan PredIdx n; 903166124Srafan for (n = 0; n < NUM_STRINGS(tterm); ++n) { 90498503Speter if (version_filter(STRING, n) 90598503Speter && !strcmp(name, strnames[n])) { 90698503Speter char *cap = tterm->Strings[n]; 90798503Speter if (VALID_STRING(cap)) { 90898503Speter return cap; 90998503Speter } 91098503Speter break; 91198503Speter } 91298503Speter } 91398503Speter return ABSENT_STRING; 91498503Speter} 91598503Speter 91698503Speter/* 91798503Speter * This is used to remove function-key labels from a termcap entry to 91898503Speter * make it smaller. 91998503Speter */ 92098503Speterstatic int 921166124Srafankill_labels(TERMTYPE *tterm, int target) 92298503Speter{ 92398503Speter int n; 92498503Speter int result = 0; 92598503Speter char *cap; 92698503Speter char name[10]; 92798503Speter 92898503Speter for (n = 0; n <= 10; ++n) { 92998503Speter sprintf(name, "lf%d", n); 93098503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 93198503Speter && kill_string(tterm, cap)) { 932184989Srafan target -= (int) (strlen(cap) + 5); 93398503Speter ++result; 93498503Speter if (target < 0) 93598503Speter break; 93698503Speter } 93798503Speter } 93898503Speter return result; 93998503Speter} 94098503Speter 94198503Speter/* 94298503Speter * This is used to remove function-key definitions from a termcap entry to 94398503Speter * make it smaller. 94498503Speter */ 94598503Speterstatic int 946166124Srafankill_fkeys(TERMTYPE *tterm, int target) 94798503Speter{ 94898503Speter int n; 94998503Speter int result = 0; 95098503Speter char *cap; 95198503Speter char name[10]; 95298503Speter 95398503Speter for (n = 60; n >= 0; --n) { 95498503Speter sprintf(name, "kf%d", n); 95598503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 95698503Speter && kill_string(tterm, cap)) { 957184989Srafan target -= (int) (strlen(cap) + 5); 95898503Speter ++result; 95998503Speter if (target < 0) 96098503Speter break; 96198503Speter } 96298503Speter } 96398503Speter return result; 96498503Speter} 96598503Speter 966166124Srafan/* 967166124Srafan * Check if the given acsc string is a 1-1 mapping, i.e., just-like-vt100. 968166124Srafan * Also, since this is for termcap, we only care about the line-drawing map. 969166124Srafan */ 970166124Srafan#define isLine(c) (strchr("lmkjtuvwqxn", c) != 0) 971166124Srafan 972166124Srafanstatic bool 973166124Srafanone_one_mapping(const char *mapping) 974166124Srafan{ 975166124Srafan bool result = TRUE; 976166124Srafan 977166124Srafan if (mapping != ABSENT_STRING) { 978166124Srafan int n = 0; 979166124Srafan while (mapping[n] != '\0') { 980166124Srafan if (isLine(mapping[n]) && 981166124Srafan mapping[n] != mapping[n + 1]) { 982166124Srafan result = FALSE; 983166124Srafan break; 984166124Srafan } 985166124Srafan n += 2; 986166124Srafan } 987166124Srafan } 988166124Srafan return result; 989166124Srafan} 990166124Srafan 991166124Srafan#define FMT_ENTRY() \ 992166124Srafan fmt_entry(tterm, pred, \ 993166124Srafan 0, \ 994166124Srafan suppress_untranslatable, \ 995166124Srafan infodump, numbers) 996166124Srafan 997166124Srafan#define SHOW_WHY PRINTF 998166124Srafan 999166124Srafanstatic bool 1000166124Srafanpurged_acs(TERMTYPE *tterm) 1001166124Srafan{ 1002166124Srafan bool result = FALSE; 1003166124Srafan 1004166124Srafan if (VALID_STRING(acs_chars)) { 1005166124Srafan if (!one_one_mapping(acs_chars)) { 1006166124Srafan enter_alt_charset_mode = ABSENT_STRING; 1007166124Srafan exit_alt_charset_mode = ABSENT_STRING; 1008166124Srafan SHOW_WHY("# (rmacs/smacs removed for consistency)\n"); 1009166124Srafan } 1010166124Srafan result = TRUE; 1011166124Srafan } 1012166124Srafan return result; 1013166124Srafan} 1014166124Srafan 1015166124Srafan/* 1016166124Srafan * Dump a single entry. 1017166124Srafan */ 1018166124Srafanvoid 1019166124Srafandump_entry(TERMTYPE *tterm, 1020166124Srafan bool suppress_untranslatable, 102198503Speter bool limited, 102298503Speter int numbers, 1023166124Srafan PredFunc pred) 102450276Speter{ 1025166124Srafan TERMTYPE save_tterm; 102662449Speter int len, critlen; 102762449Speter const char *legend; 102862449Speter bool infodump; 102950276Speter 103062449Speter if (outform == F_TERMCAP || outform == F_TCONVERR) { 103150276Speter critlen = MAX_TERMCAP_LENGTH; 103250276Speter legend = "older termcap"; 103350276Speter infodump = FALSE; 103450276Speter set_obsolete_termcaps(tterm); 103562449Speter } else { 103650276Speter critlen = MAX_TERMINFO_LENGTH; 103750276Speter legend = "terminfo"; 103850276Speter infodump = TRUE; 103950276Speter } 104050276Speter 1041166124Srafan save_sgr = set_attributes; 1042166124Srafan 1043166124Srafan if (((len = FMT_ENTRY()) > critlen) 104462449Speter && limited) { 1045166124Srafan 1046166124Srafan save_tterm = *tterm; 1047166124Srafan if (!suppress_untranslatable) { 1048166124Srafan SHOW_WHY("# (untranslatable capabilities removed to fit entry within %d bytes)\n", 1049166124Srafan critlen); 1050166124Srafan suppress_untranslatable = TRUE; 1051166124Srafan } 1052166124Srafan if ((len = FMT_ENTRY()) > critlen) { 105350276Speter /* 105450276Speter * We pick on sgr because it's a nice long string capability that 105562449Speter * is really just an optimization hack. Another good candidate is 105662449Speter * acsc since it is both long and unused by BSD termcap. 105750276Speter */ 1058166124Srafan bool changed = FALSE; 1059166124Srafan 1060166124Srafan#if NCURSES_XNAMES 1061166124Srafan /* 1062166124Srafan * Extended names are most likely function-key definitions. Drop 1063166124Srafan * those first. 1064166124Srafan */ 1065184989Srafan unsigned n; 1066166124Srafan for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { 1067166124Srafan const char *name = ExtStrname(tterm, n, strnames); 1068166124Srafan 1069166124Srafan if (VALID_STRING(tterm->Strings[n])) { 1070166124Srafan set_attributes = ABSENT_STRING; 1071166124Srafan /* we remove long names anyway - only report the short */ 1072166124Srafan if (strlen(name) <= 2) { 1073166124Srafan SHOW_WHY("# (%s removed to fit entry within %d bytes)\n", 1074166124Srafan name, 1075166124Srafan critlen); 1076166124Srafan } 1077166124Srafan changed = TRUE; 1078166124Srafan if ((len = FMT_ENTRY()) <= critlen) 1079166124Srafan break; 1080166124Srafan } 108162449Speter } 1082166124Srafan#endif 1083166124Srafan if (VALID_STRING(set_attributes)) { 1084166124Srafan set_attributes = ABSENT_STRING; 1085166124Srafan SHOW_WHY("# (sgr removed to fit entry within %d bytes)\n", 1086166124Srafan critlen); 1087166124Srafan changed = TRUE; 1088166124Srafan } 1089166124Srafan if (!changed || ((len = FMT_ENTRY()) > critlen)) { 1090166124Srafan if (purged_acs(tterm)) { 1091166124Srafan acs_chars = ABSENT_STRING; 1092166124Srafan SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n", 1093166124Srafan critlen); 1094166124Srafan changed = TRUE; 1095166124Srafan } 1096166124Srafan } 1097166124Srafan if (!changed || ((len = FMT_ENTRY()) > critlen)) { 109850276Speter int oldversion = tversion; 109950276Speter 110050276Speter tversion = V_BSD; 1101166124Srafan SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", 1102166124Srafan critlen); 110350276Speter 1104166124Srafan len = FMT_ENTRY(); 110598503Speter if (len > critlen 110698503Speter && kill_labels(tterm, len - critlen)) { 1107166124Srafan SHOW_WHY("# (some labels capabilities suppressed to fit entry within %d bytes)\n", 1108166124Srafan critlen); 1109166124Srafan len = FMT_ENTRY(); 111098503Speter } 111198503Speter if (len > critlen 111298503Speter && kill_fkeys(tterm, len - critlen)) { 1113166124Srafan SHOW_WHY("# (some function-key capabilities suppressed to fit entry within %d bytes)\n", 1114166124Srafan critlen); 1115166124Srafan len = FMT_ENTRY(); 111698503Speter } 111798503Speter if (len > critlen) { 111850276Speter (void) fprintf(stderr, 111998503Speter "warning: %s entry is %d bytes long\n", 112098503Speter _nc_first_name(tterm->term_names), 112198503Speter len); 1122166124Srafan SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", 1123166124Srafan len, legend); 112450276Speter } 112550276Speter tversion = oldversion; 112650276Speter } 1127166124Srafan set_attributes = save_sgr; 1128166124Srafan *tterm = save_tterm; 112950276Speter } 1130166124Srafan } else if (!version_filter(STRING, STR_IDX(acs_chars))) { 1131166124Srafan save_tterm = *tterm; 1132166124Srafan if (purged_acs(tterm)) { 1133166124Srafan len = FMT_ENTRY(); 1134166124Srafan } 1135166124Srafan *tterm = save_tterm; 113650276Speter } 113750276Speter} 113850276Speter 1139166124Srafanvoid 114062449Speterdump_uses(const char *name, bool infodump) 114150276Speter/* dump "use=" clauses in the appropriate format */ 114250276Speter{ 114350276Speter char buffer[MAX_TERMINFO_LENGTH]; 114450276Speter 1145166124Srafan if (outform == F_TERMCAP || outform == F_TCONVERR) 1146166124Srafan trim_trailing(); 114762449Speter (void) sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name); 114850276Speter wrap_concat(buffer); 1149166124Srafan} 1150166124Srafan 1151166124Srafanint 1152166124Srafanshow_entry(void) 1153166124Srafan{ 1154166124Srafan trim_trailing(); 115562449Speter (void) fputs(outbuf.text, stdout); 1156166124Srafan putchar('\n'); 1157184989Srafan return (int) outbuf.used; 115850276Speter} 115950276Speter 116062449Spetervoid 1161166124Srafancompare_entry(void (*hook) (PredType t, PredIdx i, const char *name), 1162166124Srafan TERMTYPE *tp GCC_UNUSED, 1163166124Srafan bool quiet) 116450276Speter/* compare two entries */ 116550276Speter{ 1166166124Srafan PredIdx i, j; 116762449Speter NCURSES_CONST char *name; 116850276Speter 116962449Speter if (!quiet) 117062449Speter fputs(" comparing booleans.\n", stdout); 117162449Speter for_each_boolean(j, tp) { 117250276Speter i = BoolIndirect(j); 117362449Speter name = ExtBoolname(tp, i, bool_names); 117450276Speter 117562449Speter if (isObsolete(outform, name)) 117650276Speter continue; 117750276Speter 117862449Speter (*hook) (CMP_BOOLEAN, i, name); 117950276Speter } 118050276Speter 118162449Speter if (!quiet) 118262449Speter fputs(" comparing numbers.\n", stdout); 118362449Speter for_each_number(j, tp) { 118450276Speter i = NumIndirect(j); 118562449Speter name = ExtNumname(tp, i, num_names); 118650276Speter 118762449Speter if (isObsolete(outform, name)) 118850276Speter continue; 118950276Speter 119062449Speter (*hook) (CMP_NUMBER, i, name); 119150276Speter } 119250276Speter 119362449Speter if (!quiet) 119462449Speter fputs(" comparing strings.\n", stdout); 119562449Speter for_each_string(j, tp) { 119650276Speter i = StrIndirect(j); 119762449Speter name = ExtStrname(tp, i, str_names); 119850276Speter 119962449Speter if (isObsolete(outform, name)) 120050276Speter continue; 120150276Speter 120262449Speter (*hook) (CMP_STRING, i, name); 120350276Speter } 120462449Speter 120562449Speter /* (void) fputs(" comparing use entries.\n", stdout); */ 120662449Speter (*hook) (CMP_USE, 0, "use"); 120762449Speter 120850276Speter} 120950276Speter 121050276Speter#define NOTSET(s) ((s) == 0) 121150276Speter 121250276Speter/* 121350276Speter * This bit of legerdemain turns all the terminfo variable names into 121450276Speter * references to locations in the arrays Booleans, Numbers, and Strings --- 121550276Speter * precisely what's needed. 121650276Speter */ 121750276Speter#undef CUR 121850276Speter#define CUR tp-> 121950276Speter 122062449Speterstatic void 1221166124Srafanset_obsolete_termcaps(TERMTYPE *tp) 122250276Speter{ 122350276Speter#include "capdefaults.c" 122450276Speter} 122550276Speter 122650276Speter/* 122750276Speter * Convert an alternate-character-set string to canonical form: sorted and 122850276Speter * unique. 122950276Speter */ 123062449Spetervoid 1231166124Srafanrepair_acsc(TERMTYPE *tp) 123250276Speter{ 123362449Speter if (VALID_STRING(acs_chars)) { 123462449Speter size_t n, m; 123562449Speter char mapped[256]; 123662449Speter char extra = 0; 123762449Speter unsigned source; 123862449Speter unsigned target; 123962449Speter bool fix_needed = FALSE; 124050276Speter 124162449Speter for (n = 0, source = 0; acs_chars[n] != 0; n++) { 1242174993Srafan target = UChar(acs_chars[n]); 124362449Speter if (source >= target) { 124462449Speter fix_needed = TRUE; 124562449Speter break; 124662449Speter } 124762449Speter source = target; 124862449Speter if (acs_chars[n + 1]) 124962449Speter n++; 125062449Speter } 125162449Speter if (fix_needed) { 125262449Speter memset(mapped, 0, sizeof(mapped)); 125362449Speter for (n = 0; acs_chars[n] != 0; n++) { 1254174993Srafan source = UChar(acs_chars[n]); 125562449Speter if ((target = (unsigned char) acs_chars[n + 1]) != 0) { 1256184989Srafan mapped[source] = (char) target; 125762449Speter n++; 125862449Speter } else { 1259184989Srafan extra = (char) source; 126050276Speter } 126150276Speter } 126262449Speter for (n = m = 0; n < sizeof(mapped); n++) { 126362449Speter if (mapped[n]) { 1264184989Srafan acs_chars[m++] = (char) n; 126562449Speter acs_chars[m++] = mapped[n]; 126650276Speter } 126750276Speter } 126862449Speter if (extra) 126962449Speter acs_chars[m++] = extra; /* garbage in, garbage out */ 127062449Speter acs_chars[m] = 0; 127150276Speter } 127262449Speter } 127350276Speter} 1274