dump_entry.c revision 178866
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> * 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 42178866SrafanMODULE_ID("$Id: dump_entry.c,v 1.82 2008/04/19 22:27:04 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 355174993Srafan#define is_termcap(type) (idx < (int) sizeof(type##_from_termcap) && \ 356174993Srafan type##_from_termcap[idx]) 357174993Srafan 35850276Speter case V_BSD: /* BSD */ 35962449Speter switch (type) { 36050276Speter case BOOLEAN: 361174993Srafan return is_termcap(bool); 36250276Speter case NUMBER: 363174993Srafan return is_termcap(num); 36450276Speter case STRING: 365174993Srafan return is_termcap(str); 36650276Speter } 36750276Speter break; 36850276Speter } 36950276Speter 37062449Speter return (FALSE); /* pacify the compiler */ 37150276Speter} 37250276Speter 37362449Speterstatic void 374166124Srafantrim_trailing(void) 375166124Srafan{ 376166124Srafan while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ') 377166124Srafan outbuf.text[--outbuf.used] = '\0'; 378166124Srafan} 379166124Srafan 380166124Srafanstatic void 38162449Speterforce_wrap(void) 38250276Speter{ 38362449Speter oldcol = column; 384166124Srafan trim_trailing(); 38562449Speter strcpy_DYN(&outbuf, trailer); 38662449Speter column = INDENT; 38750276Speter} 38850276Speter 38962449Speterstatic void 39062449Speterwrap_concat(const char *src) 39150276Speter{ 39262449Speter int need = strlen(src); 39362449Speter int want = strlen(separator) + need; 39450276Speter 39562449Speter if (column > INDENT 39662449Speter && column + want > width) { 39762449Speter force_wrap(); 39862449Speter } 39962449Speter strcpy_DYN(&outbuf, src); 40062449Speter strcpy_DYN(&outbuf, separator); 40162449Speter column += need; 40250276Speter} 40350276Speter 40450276Speter#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ 40550276Speter if ((size_t)(last - first) > sizeof(sep_trail)-1 \ 40650276Speter && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ 40750276Speter first += sizeof(sep_trail)-2 40850276Speter 40950276Speter/* Returns the nominal length of the buffer assuming it is termcap format, 41050276Speter * i.e., the continuation sequence is treated as a single character ":". 41150276Speter * 41250276Speter * There are several implementations of termcap which read the text into a 41350276Speter * fixed-size buffer. Generally they strip the newlines from the text, but may 41450276Speter * not do it until after the buffer is read. Also, "tc=" resolution may be 41550276Speter * expanded in the same buffer. This function is useful for measuring the size 41650276Speter * of the best fixed-buffer implementation; the worst case may be much worse. 41750276Speter */ 41850276Speter#ifdef TEST_TERMCAP_LENGTH 41962449Speterstatic int 42062449Spetertermcap_length(const char *src) 42150276Speter{ 42262449Speter static const char pattern[] = ":\\\n\t:"; 42350276Speter 42462449Speter int len = 0; 42562449Speter const char *const t = src + strlen(src); 42650276Speter 42762449Speter while (*src != '\0') { 42862449Speter IGNORE_SEP_TRAIL(src, t, pattern); 42962449Speter src++; 43062449Speter len++; 43162449Speter } 43262449Speter return len; 43350276Speter} 43450276Speter#else 43550276Speter#define termcap_length(src) strlen(src) 43650276Speter#endif 43750276Speter 438166124Srafanstatic void 439166124Srafanindent_DYN(DYNBUF * buffer, int level) 440166124Srafan{ 441166124Srafan int n; 442166124Srafan 443166124Srafan for (n = 0; n < level; n++) 444166124Srafan strncpy_DYN(buffer, "\t", 1); 445166124Srafan} 446166124Srafan 447166124Srafanstatic bool 448166124Srafanhas_params(const char *src) 449166124Srafan{ 450166124Srafan bool result = FALSE; 451166124Srafan int len = strlen(src); 452166124Srafan int n; 453166124Srafan bool ifthen = FALSE; 454166124Srafan bool params = FALSE; 455166124Srafan 456166124Srafan for (n = 0; n < len - 1; ++n) { 457166124Srafan if (!strncmp(src + n, "%p", 2)) { 458166124Srafan params = TRUE; 459166124Srafan } else if (!strncmp(src + n, "%;", 2)) { 460166124Srafan ifthen = TRUE; 461166124Srafan result = params; 462166124Srafan break; 463166124Srafan } 464166124Srafan } 465166124Srafan if (!ifthen) { 466166124Srafan result = ((len > 50) && params); 467166124Srafan } 468166124Srafan return result; 469166124Srafan} 470166124Srafan 47162449Speterstatic char * 47262449Speterfmt_complex(char *src, int level) 47350276Speter{ 474166124Srafan bool percent = FALSE; 475166124Srafan bool params = has_params(src); 47650276Speter 47762449Speter while (*src != '\0') { 47862449Speter switch (*src) { 47962449Speter case '\\': 480166124Srafan percent = FALSE; 48162449Speter strncpy_DYN(&tmpbuf, src++, 1); 48262449Speter break; 48362449Speter case '%': 484166124Srafan percent = TRUE; 48562449Speter break; 48662449Speter case '?': /* "if" */ 48762449Speter case 't': /* "then" */ 48862449Speter case 'e': /* "else" */ 48962449Speter if (percent) { 490166124Srafan percent = FALSE; 49162449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 492166124Srafan /* treat a "%e" as else-if, on the same level */ 493166124Srafan if (*src == 'e') { 494166124Srafan indent_DYN(&tmpbuf, level); 49562449Speter strncpy_DYN(&tmpbuf, "%", 1); 496166124Srafan strncpy_DYN(&tmpbuf, src, 1); 497166124Srafan src++; 498166124Srafan params = has_params(src); 499166124Srafan if (!params && *src != '\0' && *src != '%') { 500166124Srafan strncpy_DYN(&tmpbuf, "\n", 1); 501166124Srafan indent_DYN(&tmpbuf, level + 1); 502166124Srafan } 50362449Speter } else { 504166124Srafan indent_DYN(&tmpbuf, level + 1); 50562449Speter strncpy_DYN(&tmpbuf, "%", 1); 50662449Speter strncpy_DYN(&tmpbuf, src, 1); 50762449Speter if (*src++ == '?') { 50862449Speter src = fmt_complex(src, level + 1); 509166124Srafan if (*src != '\0' && *src != '%') { 510166124Srafan strncpy_DYN(&tmpbuf, "\n", 1); 511166124Srafan indent_DYN(&tmpbuf, level + 1); 512166124Srafan } 51362449Speter } else if (level == 1) { 51462449Speter _nc_warning("%%%c without %%?", *src); 51562449Speter } 51650276Speter } 51762449Speter continue; 51862449Speter } 51962449Speter break; 52062449Speter case ';': /* "endif" */ 52162449Speter if (percent) { 522166124Srafan percent = FALSE; 52362449Speter if (level > 1) { 52462449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 525166124Srafan indent_DYN(&tmpbuf, level); 52662449Speter strncpy_DYN(&tmpbuf, "%", 1); 52762449Speter strncpy_DYN(&tmpbuf, src++, 1); 52862449Speter return src; 52962449Speter } 53062449Speter _nc_warning("%%; without %%?"); 53162449Speter } 53262449Speter break; 53362449Speter case 'p': 53462449Speter if (percent && params) { 53562449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 536166124Srafan indent_DYN(&tmpbuf, level + 1); 53762449Speter strncpy_DYN(&tmpbuf, "%", 1); 53862449Speter } 539166124Srafan params = FALSE; 540166124Srafan percent = FALSE; 54162449Speter break; 542178866Srafan case ' ': 543178866Srafan strncpy_DYN(&tmpbuf, "\\s", 2); 544178866Srafan ++src; 545178866Srafan continue; 54662449Speter default: 547166124Srafan percent = FALSE; 54862449Speter break; 54950276Speter } 55062449Speter strncpy_DYN(&tmpbuf, src++, 1); 55162449Speter } 55262449Speter return src; 55350276Speter} 55450276Speter 555166124Srafan#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) 556166124Srafan 55762449Speterint 558166124Srafanfmt_entry(TERMTYPE *tterm, 559166124Srafan PredFunc pred, 560166124Srafan bool content_only, 56198503Speter bool suppress_untranslatable, 56298503Speter bool infodump, 56398503Speter int numbers) 56450276Speter{ 565166124Srafan PredIdx i, j; 56662449Speter char buffer[MAX_TERMINFO_LENGTH]; 567166124Srafan char *capability; 56862449Speter NCURSES_CONST char *name; 56962449Speter int predval, len; 570166124Srafan PredIdx num_bools = 0; 571166124Srafan PredIdx num_values = 0; 572166124Srafan PredIdx num_strings = 0; 57362449Speter bool outcount = 0; 57450276Speter 57550276Speter#define WRAP_CONCAT \ 57650276Speter wrap_concat(buffer); \ 57750276Speter outcount = TRUE 57850276Speter 57950276Speter len = 12; /* terminfo file-header */ 58050276Speter 58150276Speter if (pred == 0) { 58250276Speter cur_type = tterm; 58350276Speter pred = dump_predicate; 58450276Speter } 58550276Speter 58662449Speter strcpy_DYN(&outbuf, 0); 587166124Srafan if (content_only) { 588166124Srafan column = INDENT; /* FIXME: workaround to prevent empty lines */ 589166124Srafan } else { 590166124Srafan strcpy_DYN(&outbuf, tterm->term_names); 591166124Srafan strcpy_DYN(&outbuf, separator); 592166124Srafan column = outbuf.used; 593166124Srafan force_wrap(); 594166124Srafan } 59550276Speter 59662449Speter for_each_boolean(j, tterm) { 59750276Speter i = BoolIndirect(j); 59862449Speter name = ExtBoolname(tterm, i, bool_names); 59950276Speter 60050276Speter if (!version_filter(BOOLEAN, i)) 60150276Speter continue; 60262449Speter else if (isObsolete(outform, name)) 60350276Speter continue; 60450276Speter 60550276Speter predval = pred(BOOLEAN, i); 60650276Speter if (predval != FAIL) { 60750276Speter (void) strcpy(buffer, name); 60850276Speter if (predval <= 0) 60950276Speter (void) strcat(buffer, "@"); 61050276Speter else if (i + 1 > num_bools) 61150276Speter num_bools = i + 1; 61250276Speter WRAP_CONCAT; 61350276Speter } 61450276Speter } 61550276Speter 61650276Speter if (column != INDENT) 61750276Speter force_wrap(); 61850276Speter 61962449Speter for_each_number(j, tterm) { 62050276Speter i = NumIndirect(j); 62162449Speter name = ExtNumname(tterm, i, num_names); 62250276Speter 62350276Speter if (!version_filter(NUMBER, i)) 62450276Speter continue; 62562449Speter else if (isObsolete(outform, name)) 62650276Speter continue; 62750276Speter 62850276Speter predval = pred(NUMBER, i); 62950276Speter if (predval != FAIL) { 63050276Speter if (tterm->Numbers[i] < 0) { 63150276Speter sprintf(buffer, "%s@", name); 63250276Speter } else { 63350276Speter sprintf(buffer, "%s#%d", name, tterm->Numbers[i]); 63450276Speter if (i + 1 > num_values) 63550276Speter num_values = i + 1; 63650276Speter } 63750276Speter WRAP_CONCAT; 63850276Speter } 63950276Speter } 64050276Speter 64150276Speter if (column != INDENT) 64250276Speter force_wrap(); 64350276Speter 64450276Speter len += num_bools 64562449Speter + num_values * 2 64662449Speter + strlen(tterm->term_names) + 1; 64750276Speter if (len & 1) 64862449Speter len++; 64950276Speter 65062449Speter#undef CUR 65162449Speter#define CUR tterm-> 65262449Speter if (outform == F_TERMCAP) { 65362449Speter if (termcap_reset != ABSENT_STRING) { 65462449Speter if (init_3string != ABSENT_STRING 65562449Speter && !strcmp(init_3string, termcap_reset)) 65662449Speter DISCARD(init_3string); 65762449Speter 65862449Speter if (reset_2string != ABSENT_STRING 65962449Speter && !strcmp(reset_2string, termcap_reset)) 66062449Speter DISCARD(reset_2string); 66162449Speter } 66262449Speter } 66362449Speter 66450276Speter for_each_string(j, tterm) { 66550276Speter i = StrIndirect(j); 66662449Speter name = ExtStrname(tterm, i, str_names); 667166124Srafan capability = tterm->Strings[i]; 66850276Speter 66950276Speter if (!version_filter(STRING, i)) 67050276Speter continue; 67162449Speter else if (isObsolete(outform, name)) 67250276Speter continue; 67350276Speter 674166124Srafan#if NCURSES_XNAMES 67550276Speter /* 676166124Srafan * Extended names can be longer than 2 characters, but termcap programs 677166124Srafan * cannot read those (filter them out). 67850276Speter */ 679166124Srafan if (outform == F_TERMCAP && (strlen(name) > 2)) 680166124Srafan continue; 681166124Srafan#endif 682166124Srafan 68362449Speter if (outform == F_TERMCAP) { 684166124Srafan /* 685166124Srafan * Some older versions of vi want rmir/smir to be defined 686166124Srafan * for ich/ich1 to work. If they're not defined, force 687166124Srafan * them to be output as defined and empty. 688166124Srafan */ 689166124Srafan if (PRESENT(insert_character) || PRESENT(parm_ich)) { 690166124Srafan if (SAME_CAP(i, enter_insert_mode) 69162449Speter && enter_insert_mode == ABSENT_STRING) { 69250276Speter (void) strcpy(buffer, "im="); 69362449Speter WRAP_CONCAT; 69462449Speter continue; 69550276Speter } 69650276Speter 697166124Srafan if (SAME_CAP(i, exit_insert_mode) 69862449Speter && exit_insert_mode == ABSENT_STRING) { 69950276Speter (void) strcpy(buffer, "ei="); 70062449Speter WRAP_CONCAT; 70162449Speter continue; 70250276Speter } 70350276Speter } 704166124Srafan /* 705166124Srafan * termcap applications such as screen will be confused if sgr0 706166124Srafan * is translated to a string containing rmacs. Filter that out. 707166124Srafan */ 708166124Srafan if (PRESENT(exit_attribute_mode)) { 709166124Srafan if (SAME_CAP(i, exit_attribute_mode)) { 710166124Srafan char *trimmed_sgr0; 711166124Srafan char *my_sgr = set_attributes; 712166124Srafan 713166124Srafan set_attributes = save_sgr; 714166124Srafan 715166124Srafan trimmed_sgr0 = _nc_trim_sgr0(tterm); 716166124Srafan if (strcmp(capability, trimmed_sgr0)) 717166124Srafan capability = trimmed_sgr0; 718166124Srafan 719166124Srafan set_attributes = my_sgr; 720166124Srafan } 721166124Srafan } 72250276Speter } 72350276Speter 72450276Speter predval = pred(STRING, i); 72550276Speter buffer[0] = '\0'; 72662449Speter 72750276Speter if (predval != FAIL) { 728166124Srafan if (capability != ABSENT_STRING 72962449Speter && i + 1 > num_strings) 73050276Speter num_strings = i + 1; 73162449Speter 732166124Srafan if (!VALID_STRING(capability)) { 73350276Speter sprintf(buffer, "%s@", name); 73462449Speter WRAP_CONCAT; 73562449Speter } else if (outform == F_TERMCAP || outform == F_TCONVERR) { 73698503Speter int params = ((i < (int) SIZEOF(parametrized)) 73798503Speter ? parametrized[i] 73898503Speter : 0); 739166124Srafan char *srccap = _nc_tic_expand(capability, TRUE, numbers); 74066963Speter char *cv = _nc_infotocap(name, srccap, params); 74150276Speter 74262449Speter if (cv == 0) { 74362449Speter if (outform == F_TCONVERR) { 74462449Speter sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", 74598503Speter name, srccap); 74662449Speter } else if (suppress_untranslatable) { 74750276Speter continue; 74862449Speter } else { 74962449Speter char *s = srccap, *d = buffer; 75062449Speter sprintf(d, "..%s=", name); 75162449Speter d += strlen(d); 75262449Speter while ((*d = *s++) != 0) { 75362449Speter if (*d == ':') { 75462449Speter *d++ = '\\'; 75562449Speter *d = ':'; 75662449Speter } else if (*d == '\\') { 75762449Speter *++d = *s++; 75862449Speter } 75962449Speter d++; 76062449Speter } 76162449Speter } 76262449Speter } else { 76362449Speter sprintf(buffer, "%s=%s", name, cv); 76450276Speter } 765166124Srafan len += strlen(capability) + 1; 76662449Speter WRAP_CONCAT; 76762449Speter } else { 768166124Srafan char *src = _nc_tic_expand(capability, 76998503Speter outform == F_TERMINFO, numbers); 77062449Speter 77162449Speter strcpy_DYN(&tmpbuf, 0); 77262449Speter strcpy_DYN(&tmpbuf, name); 77362449Speter strcpy_DYN(&tmpbuf, "="); 77462449Speter if (pretty 77562449Speter && (outform == F_TERMINFO 77662449Speter || outform == F_VARIABLE)) { 77762449Speter fmt_complex(src, 1); 77862449Speter } else { 77962449Speter strcpy_DYN(&tmpbuf, src); 78062449Speter } 781166124Srafan len += strlen(capability) + 1; 78262449Speter wrap_concat(tmpbuf.text); 78362449Speter outcount = TRUE; 78450276Speter } 78550276Speter } 786166124Srafan /* e.g., trimmed_sgr0 */ 787166124Srafan if (capability != tterm->Strings[i]) 788166124Srafan free(capability); 78950276Speter } 79050276Speter len += num_strings * 2; 79150276Speter 79250276Speter /* 79350276Speter * This piece of code should be an effective inverse of the functions 794166124Srafan * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c. 79550276Speter * Much more work should be done on this to support dumping termcaps. 79650276Speter */ 79762449Speter if (tversion == V_HPUX) { 798174993Srafan if (VALID_STRING(memory_lock)) { 79950276Speter (void) sprintf(buffer, "meml=%s", memory_lock); 80050276Speter WRAP_CONCAT; 80150276Speter } 802174993Srafan if (VALID_STRING(memory_unlock)) { 80350276Speter (void) sprintf(buffer, "memu=%s", memory_unlock); 80450276Speter WRAP_CONCAT; 80550276Speter } 80662449Speter } else if (tversion == V_AIX) { 80762449Speter if (VALID_STRING(acs_chars)) { 80862449Speter bool box_ok = TRUE; 80962449Speter const char *acstrans = "lqkxjmwuvtn"; 81062449Speter const char *cp; 81162449Speter char *tp, *sp, boxchars[11]; 81250276Speter 81350276Speter tp = boxchars; 81462449Speter for (cp = acstrans; *cp; cp++) { 81550276Speter sp = strchr(acs_chars, *cp); 81650276Speter if (sp) 81750276Speter *tp++ = sp[1]; 81862449Speter else { 81950276Speter box_ok = FALSE; 82050276Speter break; 82150276Speter } 82250276Speter } 82350276Speter tp[0] = '\0'; 82450276Speter 82562449Speter if (box_ok) { 82650276Speter (void) strcpy(buffer, "box1="); 82762449Speter (void) strcat(buffer, _nc_tic_expand(boxchars, 82898503Speter outform == F_TERMINFO, numbers)); 82950276Speter WRAP_CONCAT; 83050276Speter } 83150276Speter } 83250276Speter } 83350276Speter 83450276Speter /* 83550276Speter * kludge: trim off trailer to avoid an extra blank line 83650276Speter * in infocmp -u output when there are no string differences 83750276Speter */ 83862449Speter if (outcount) { 83962449Speter bool trimmed = FALSE; 84062449Speter j = outbuf.used; 84150276Speter if (j >= 2 84262449Speter && outbuf.text[j - 1] == '\t' 84362449Speter && outbuf.text[j - 2] == '\n') { 84462449Speter outbuf.used -= 2; 84562449Speter trimmed = TRUE; 84650276Speter } else if (j >= 4 84798503Speter && outbuf.text[j - 1] == ':' 84898503Speter && outbuf.text[j - 2] == '\t' 84998503Speter && outbuf.text[j - 3] == '\n' 85098503Speter && outbuf.text[j - 4] == '\\') { 85162449Speter outbuf.used -= 4; 85262449Speter trimmed = TRUE; 85350276Speter } 85462449Speter if (trimmed) { 85562449Speter outbuf.text[outbuf.used] = '\0'; 85662449Speter column = oldcol; 857166124Srafan strcpy_DYN(&outbuf, " "); 85862449Speter } 85950276Speter } 86050276Speter#if 0 86150276Speter fprintf(stderr, "num_bools = %d\n", num_bools); 86250276Speter fprintf(stderr, "num_values = %d\n", num_values); 86350276Speter fprintf(stderr, "num_strings = %d\n", num_strings); 86450276Speter fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n", 86598503Speter tterm->term_names, len, outbuf.used, outbuf.text); 86650276Speter#endif 86750276Speter /* 86850276Speter * Here's where we use infodump to trigger a more stringent length check 86950276Speter * for termcap-translation purposes. 87050276Speter * Return the length of the raw entry, without tc= expansions, 87150276Speter * It gives an idea of which entries are deadly to even *scan past*, 87250276Speter * as opposed to *use*. 87350276Speter */ 87476726Speter return (infodump ? len : (int) termcap_length(outbuf.text)); 87550276Speter} 87650276Speter 87798503Speterstatic bool 878166124Srafankill_string(TERMTYPE *tterm, char *cap) 87998503Speter{ 88098503Speter int n; 881166124Srafan for (n = 0; n < NUM_STRINGS(tterm); ++n) { 88298503Speter if (cap == tterm->Strings[n]) { 88398503Speter tterm->Strings[n] = ABSENT_STRING; 88498503Speter return TRUE; 88598503Speter } 88698503Speter } 88798503Speter return FALSE; 88898503Speter} 88998503Speter 89098503Speterstatic char * 891166124Srafanfind_string(TERMTYPE *tterm, char *name) 89298503Speter{ 893166124Srafan PredIdx n; 894166124Srafan for (n = 0; n < NUM_STRINGS(tterm); ++n) { 89598503Speter if (version_filter(STRING, n) 89698503Speter && !strcmp(name, strnames[n])) { 89798503Speter char *cap = tterm->Strings[n]; 89898503Speter if (VALID_STRING(cap)) { 89998503Speter return cap; 90098503Speter } 90198503Speter break; 90298503Speter } 90398503Speter } 90498503Speter return ABSENT_STRING; 90598503Speter} 90698503Speter 90798503Speter/* 90898503Speter * This is used to remove function-key labels from a termcap entry to 90998503Speter * make it smaller. 91098503Speter */ 91198503Speterstatic int 912166124Srafankill_labels(TERMTYPE *tterm, int target) 91398503Speter{ 91498503Speter int n; 91598503Speter int result = 0; 91698503Speter char *cap; 91798503Speter char name[10]; 91898503Speter 91998503Speter for (n = 0; n <= 10; ++n) { 92098503Speter sprintf(name, "lf%d", n); 92198503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 92298503Speter && kill_string(tterm, cap)) { 92398503Speter target -= (strlen(cap) + 5); 92498503Speter ++result; 92598503Speter if (target < 0) 92698503Speter break; 92798503Speter } 92898503Speter } 92998503Speter return result; 93098503Speter} 93198503Speter 93298503Speter/* 93398503Speter * This is used to remove function-key definitions from a termcap entry to 93498503Speter * make it smaller. 93598503Speter */ 93698503Speterstatic int 937166124Srafankill_fkeys(TERMTYPE *tterm, int target) 93898503Speter{ 93998503Speter int n; 94098503Speter int result = 0; 94198503Speter char *cap; 94298503Speter char name[10]; 94398503Speter 94498503Speter for (n = 60; n >= 0; --n) { 94598503Speter sprintf(name, "kf%d", n); 94698503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 94798503Speter && kill_string(tterm, cap)) { 94898503Speter target -= (strlen(cap) + 5); 94998503Speter ++result; 95098503Speter if (target < 0) 95198503Speter break; 95298503Speter } 95398503Speter } 95498503Speter return result; 95598503Speter} 95698503Speter 957166124Srafan/* 958166124Srafan * Check if the given acsc string is a 1-1 mapping, i.e., just-like-vt100. 959166124Srafan * Also, since this is for termcap, we only care about the line-drawing map. 960166124Srafan */ 961166124Srafan#define isLine(c) (strchr("lmkjtuvwqxn", c) != 0) 962166124Srafan 963166124Srafanstatic bool 964166124Srafanone_one_mapping(const char *mapping) 965166124Srafan{ 966166124Srafan bool result = TRUE; 967166124Srafan 968166124Srafan if (mapping != ABSENT_STRING) { 969166124Srafan int n = 0; 970166124Srafan while (mapping[n] != '\0') { 971166124Srafan if (isLine(mapping[n]) && 972166124Srafan mapping[n] != mapping[n + 1]) { 973166124Srafan result = FALSE; 974166124Srafan break; 975166124Srafan } 976166124Srafan n += 2; 977166124Srafan } 978166124Srafan } 979166124Srafan return result; 980166124Srafan} 981166124Srafan 982166124Srafan#define FMT_ENTRY() \ 983166124Srafan fmt_entry(tterm, pred, \ 984166124Srafan 0, \ 985166124Srafan suppress_untranslatable, \ 986166124Srafan infodump, numbers) 987166124Srafan 988166124Srafan#define SHOW_WHY PRINTF 989166124Srafan 990166124Srafanstatic bool 991166124Srafanpurged_acs(TERMTYPE *tterm) 992166124Srafan{ 993166124Srafan bool result = FALSE; 994166124Srafan 995166124Srafan if (VALID_STRING(acs_chars)) { 996166124Srafan if (!one_one_mapping(acs_chars)) { 997166124Srafan enter_alt_charset_mode = ABSENT_STRING; 998166124Srafan exit_alt_charset_mode = ABSENT_STRING; 999166124Srafan SHOW_WHY("# (rmacs/smacs removed for consistency)\n"); 1000166124Srafan } 1001166124Srafan result = TRUE; 1002166124Srafan } 1003166124Srafan return result; 1004166124Srafan} 1005166124Srafan 1006166124Srafan/* 1007166124Srafan * Dump a single entry. 1008166124Srafan */ 1009166124Srafanvoid 1010166124Srafandump_entry(TERMTYPE *tterm, 1011166124Srafan bool suppress_untranslatable, 101298503Speter bool limited, 101398503Speter int numbers, 1014166124Srafan PredFunc pred) 101550276Speter{ 1016166124Srafan TERMTYPE save_tterm; 101762449Speter int len, critlen; 101862449Speter const char *legend; 101962449Speter bool infodump; 102050276Speter 102162449Speter if (outform == F_TERMCAP || outform == F_TCONVERR) { 102250276Speter critlen = MAX_TERMCAP_LENGTH; 102350276Speter legend = "older termcap"; 102450276Speter infodump = FALSE; 102550276Speter set_obsolete_termcaps(tterm); 102662449Speter } else { 102750276Speter critlen = MAX_TERMINFO_LENGTH; 102850276Speter legend = "terminfo"; 102950276Speter infodump = TRUE; 103050276Speter } 103150276Speter 1032166124Srafan save_sgr = set_attributes; 1033166124Srafan 1034166124Srafan if (((len = FMT_ENTRY()) > critlen) 103562449Speter && limited) { 1036166124Srafan 1037166124Srafan save_tterm = *tterm; 1038166124Srafan if (!suppress_untranslatable) { 1039166124Srafan SHOW_WHY("# (untranslatable capabilities removed to fit entry within %d bytes)\n", 1040166124Srafan critlen); 1041166124Srafan suppress_untranslatable = TRUE; 1042166124Srafan } 1043166124Srafan if ((len = FMT_ENTRY()) > critlen) { 104450276Speter /* 104550276Speter * We pick on sgr because it's a nice long string capability that 104662449Speter * is really just an optimization hack. Another good candidate is 104762449Speter * acsc since it is both long and unused by BSD termcap. 104850276Speter */ 1049166124Srafan bool changed = FALSE; 1050166124Srafan 1051166124Srafan#if NCURSES_XNAMES 1052166124Srafan /* 1053166124Srafan * Extended names are most likely function-key definitions. Drop 1054166124Srafan * those first. 1055166124Srafan */ 1056166124Srafan int n; 1057166124Srafan for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { 1058166124Srafan const char *name = ExtStrname(tterm, n, strnames); 1059166124Srafan 1060166124Srafan if (VALID_STRING(tterm->Strings[n])) { 1061166124Srafan set_attributes = ABSENT_STRING; 1062166124Srafan /* we remove long names anyway - only report the short */ 1063166124Srafan if (strlen(name) <= 2) { 1064166124Srafan SHOW_WHY("# (%s removed to fit entry within %d bytes)\n", 1065166124Srafan name, 1066166124Srafan critlen); 1067166124Srafan } 1068166124Srafan changed = TRUE; 1069166124Srafan if ((len = FMT_ENTRY()) <= critlen) 1070166124Srafan break; 1071166124Srafan } 107262449Speter } 1073166124Srafan#endif 1074166124Srafan if (VALID_STRING(set_attributes)) { 1075166124Srafan set_attributes = ABSENT_STRING; 1076166124Srafan SHOW_WHY("# (sgr removed to fit entry within %d bytes)\n", 1077166124Srafan critlen); 1078166124Srafan changed = TRUE; 1079166124Srafan } 1080166124Srafan if (!changed || ((len = FMT_ENTRY()) > critlen)) { 1081166124Srafan if (purged_acs(tterm)) { 1082166124Srafan acs_chars = ABSENT_STRING; 1083166124Srafan SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n", 1084166124Srafan critlen); 1085166124Srafan changed = TRUE; 1086166124Srafan } 1087166124Srafan } 1088166124Srafan if (!changed || ((len = FMT_ENTRY()) > critlen)) { 108950276Speter int oldversion = tversion; 109050276Speter 109150276Speter tversion = V_BSD; 1092166124Srafan SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", 1093166124Srafan critlen); 109450276Speter 1095166124Srafan len = FMT_ENTRY(); 109698503Speter if (len > critlen 109798503Speter && kill_labels(tterm, len - critlen)) { 1098166124Srafan SHOW_WHY("# (some labels capabilities suppressed to fit entry within %d bytes)\n", 1099166124Srafan critlen); 1100166124Srafan len = FMT_ENTRY(); 110198503Speter } 110298503Speter if (len > critlen 110398503Speter && kill_fkeys(tterm, len - critlen)) { 1104166124Srafan SHOW_WHY("# (some function-key capabilities suppressed to fit entry within %d bytes)\n", 1105166124Srafan critlen); 1106166124Srafan len = FMT_ENTRY(); 110798503Speter } 110898503Speter if (len > critlen) { 110950276Speter (void) fprintf(stderr, 111098503Speter "warning: %s entry is %d bytes long\n", 111198503Speter _nc_first_name(tterm->term_names), 111298503Speter len); 1113166124Srafan SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", 1114166124Srafan len, legend); 111550276Speter } 111650276Speter tversion = oldversion; 111750276Speter } 1118166124Srafan set_attributes = save_sgr; 1119166124Srafan *tterm = save_tterm; 112050276Speter } 1121166124Srafan } else if (!version_filter(STRING, STR_IDX(acs_chars))) { 1122166124Srafan save_tterm = *tterm; 1123166124Srafan if (purged_acs(tterm)) { 1124166124Srafan len = FMT_ENTRY(); 1125166124Srafan } 1126166124Srafan *tterm = save_tterm; 112750276Speter } 112850276Speter} 112950276Speter 1130166124Srafanvoid 113162449Speterdump_uses(const char *name, bool infodump) 113250276Speter/* dump "use=" clauses in the appropriate format */ 113350276Speter{ 113450276Speter char buffer[MAX_TERMINFO_LENGTH]; 113550276Speter 1136166124Srafan if (outform == F_TERMCAP || outform == F_TCONVERR) 1137166124Srafan trim_trailing(); 113862449Speter (void) sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name); 113950276Speter wrap_concat(buffer); 1140166124Srafan} 1141166124Srafan 1142166124Srafanint 1143166124Srafanshow_entry(void) 1144166124Srafan{ 1145166124Srafan trim_trailing(); 114662449Speter (void) fputs(outbuf.text, stdout); 1147166124Srafan putchar('\n'); 114862449Speter return outbuf.used; 114950276Speter} 115050276Speter 115162449Spetervoid 1152166124Srafancompare_entry(void (*hook) (PredType t, PredIdx i, const char *name), 1153166124Srafan TERMTYPE *tp GCC_UNUSED, 1154166124Srafan bool quiet) 115550276Speter/* compare two entries */ 115650276Speter{ 1157166124Srafan PredIdx i, j; 115862449Speter NCURSES_CONST char *name; 115950276Speter 116062449Speter if (!quiet) 116162449Speter fputs(" comparing booleans.\n", stdout); 116262449Speter for_each_boolean(j, tp) { 116350276Speter i = BoolIndirect(j); 116462449Speter name = ExtBoolname(tp, i, bool_names); 116550276Speter 116662449Speter if (isObsolete(outform, name)) 116750276Speter continue; 116850276Speter 116962449Speter (*hook) (CMP_BOOLEAN, i, name); 117050276Speter } 117150276Speter 117262449Speter if (!quiet) 117362449Speter fputs(" comparing numbers.\n", stdout); 117462449Speter for_each_number(j, tp) { 117550276Speter i = NumIndirect(j); 117662449Speter name = ExtNumname(tp, i, num_names); 117750276Speter 117862449Speter if (isObsolete(outform, name)) 117950276Speter continue; 118050276Speter 118162449Speter (*hook) (CMP_NUMBER, i, name); 118250276Speter } 118350276Speter 118462449Speter if (!quiet) 118562449Speter fputs(" comparing strings.\n", stdout); 118662449Speter for_each_string(j, tp) { 118750276Speter i = StrIndirect(j); 118862449Speter name = ExtStrname(tp, i, str_names); 118950276Speter 119062449Speter if (isObsolete(outform, name)) 119150276Speter continue; 119250276Speter 119362449Speter (*hook) (CMP_STRING, i, name); 119450276Speter } 119562449Speter 119662449Speter /* (void) fputs(" comparing use entries.\n", stdout); */ 119762449Speter (*hook) (CMP_USE, 0, "use"); 119862449Speter 119950276Speter} 120050276Speter 120150276Speter#define NOTSET(s) ((s) == 0) 120250276Speter 120350276Speter/* 120450276Speter * This bit of legerdemain turns all the terminfo variable names into 120550276Speter * references to locations in the arrays Booleans, Numbers, and Strings --- 120650276Speter * precisely what's needed. 120750276Speter */ 120850276Speter#undef CUR 120950276Speter#define CUR tp-> 121050276Speter 121162449Speterstatic void 1212166124Srafanset_obsolete_termcaps(TERMTYPE *tp) 121350276Speter{ 121450276Speter#include "capdefaults.c" 121550276Speter} 121650276Speter 121750276Speter/* 121850276Speter * Convert an alternate-character-set string to canonical form: sorted and 121950276Speter * unique. 122050276Speter */ 122162449Spetervoid 1222166124Srafanrepair_acsc(TERMTYPE *tp) 122350276Speter{ 122462449Speter if (VALID_STRING(acs_chars)) { 122562449Speter size_t n, m; 122662449Speter char mapped[256]; 122762449Speter char extra = 0; 122862449Speter unsigned source; 122962449Speter unsigned target; 123062449Speter bool fix_needed = FALSE; 123150276Speter 123262449Speter for (n = 0, source = 0; acs_chars[n] != 0; n++) { 1233174993Srafan target = UChar(acs_chars[n]); 123462449Speter if (source >= target) { 123562449Speter fix_needed = TRUE; 123662449Speter break; 123762449Speter } 123862449Speter source = target; 123962449Speter if (acs_chars[n + 1]) 124062449Speter n++; 124162449Speter } 124262449Speter if (fix_needed) { 124362449Speter memset(mapped, 0, sizeof(mapped)); 124462449Speter for (n = 0; acs_chars[n] != 0; n++) { 1245174993Srafan source = UChar(acs_chars[n]); 124662449Speter if ((target = (unsigned char) acs_chars[n + 1]) != 0) { 124762449Speter mapped[source] = target; 124862449Speter n++; 124962449Speter } else { 125062449Speter extra = source; 125150276Speter } 125250276Speter } 125362449Speter for (n = m = 0; n < sizeof(mapped); n++) { 125462449Speter if (mapped[n]) { 125562449Speter acs_chars[m++] = n; 125662449Speter acs_chars[m++] = mapped[n]; 125750276Speter } 125850276Speter } 125962449Speter if (extra) 126062449Speter acs_chars[m++] = extra; /* garbage in, garbage out */ 126162449Speter acs_chars[m] = 0; 126250276Speter } 126362449Speter } 126450276Speter} 1265