dump_entry.c revision 98503
150276Speter/**************************************************************************** 298503Speter * Copyright (c) 1998-2001,2002 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 4298503SpeterMODULE_ID("$Id: dump_entry.c,v 1.58 2002/06/01 22:58:11 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 6262449Speterstatic DYNBUF outbuf; 6362449Speterstatic DYNBUF tmpbuf; 6450276Speter 6550276Speter/* indirection pointers for implementing sort and display modes */ 6650276Speterstatic const int *bool_indirect, *num_indirect, *str_indirect; 6762449Speterstatic NCURSES_CONST char *const *bool_names; 6862449Speterstatic NCURSES_CONST char *const *num_names; 6962449Speterstatic NCURSES_CONST char *const *str_names; 7050276Speter 7150276Speterstatic const char *separator, *trailer; 7250276Speter 7350276Speter/* cover various ports and variants of terminfo */ 7450276Speter#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ 7550276Speter#define V_SVR1 1 /* SVR1, Ultrix */ 7650276Speter#define V_HPUX 2 /* HP/UX */ 7750276Speter#define V_AIX 3 /* AIX */ 7850276Speter#define V_BSD 4 /* BSD */ 7950276Speter 8062449Speter#if NCURSES_XNAMES 8162449Speter#define OBSOLETE(n) (!_nc_user_definable && (n[0] == 'O' && n[1] == 'T')) 8262449Speter#else 8350276Speter#define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') 8462449Speter#endif 8550276Speter 8662449Speter#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n)) 8762449Speter 8850276Speter#if NCURSES_XNAMES 8950276Speter#define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) 9050276Speter#define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j])) 9150276Speter#define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j])) 9250276Speter#else 9350276Speter#define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j]) 9450276Speter#define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j]) 9550276Speter#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) 9650276Speter#endif 9750276Speter 9862449Speterstatic void 9962449Speterstrncpy_DYN(DYNBUF * dst, const char *src, size_t need) 10062449Speter{ 10162449Speter size_t want = need + dst->used + 1; 10262449Speter if (want > dst->size) { 10362449Speter dst->size += (want + 1024); /* be generous */ 10462449Speter dst->text = typeRealloc(char, dst->size, dst->text); 10562449Speter } 10662449Speter (void) strncpy(dst->text + dst->used, src, need); 10762449Speter dst->used += need; 10862449Speter dst->text[dst->used] = 0; 10962449Speter} 11062449Speter 11162449Speterstatic void 11262449Speterstrcpy_DYN(DYNBUF * dst, const char *src) 11362449Speter{ 11462449Speter if (src == 0) { 11562449Speter dst->used = 0; 11662449Speter strcpy_DYN(dst, ""); 11762449Speter } else { 11862449Speter strncpy_DYN(dst, src, strlen(src)); 11962449Speter } 12062449Speter} 12162449Speter 12250276Speter#if NO_LEAKS 12362449Speterstatic void 12462449Speterfree_DYN(DYNBUF * p) 12550276Speter{ 12662449Speter if (p->text != 0) 12762449Speter free(p->text); 12862449Speter p->text = 0; 12962449Speter p->size = 0; 13062449Speter p->used = 0; 13150276Speter} 13262449Speter 13362449Spetervoid 13462449Speter_nc_leaks_dump_entry(void) 13562449Speter{ 13662449Speter free_DYN(&outbuf); 13762449Speter free_DYN(&tmpbuf); 13862449Speter} 13950276Speter#endif 14050276Speter 14162449SpeterNCURSES_CONST char * 14262449Speternametrans(const char *name) 14350276Speter/* translate a capability name from termcap to terminfo */ 14450276Speter{ 14562449Speter const struct name_table_entry *np; 14650276Speter 14750276Speter if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) 14862449Speter switch (np->nte_type) { 14950276Speter case BOOLEAN: 15050276Speter if (bool_from_termcap[np->nte_index]) 15162449Speter return (boolcodes[np->nte_index]); 15250276Speter break; 15350276Speter 15450276Speter case NUMBER: 15550276Speter if (num_from_termcap[np->nte_index]) 15662449Speter return (numcodes[np->nte_index]); 15750276Speter break; 15850276Speter 15950276Speter case STRING: 16050276Speter if (str_from_termcap[np->nte_index]) 16162449Speter return (strcodes[np->nte_index]); 16250276Speter break; 16350276Speter } 16450276Speter 16562449Speter return (0); 16650276Speter} 16750276Speter 16862449Spetervoid 16962449Speterdump_init(const char *version, int mode, int sort, int twidth, int traceval, 17098503Speter bool formatted) 17150276Speter/* set up for entry display */ 17250276Speter{ 17350276Speter width = twidth; 17450276Speter pretty = formatted; 17550276Speter 17650276Speter /* versions */ 17750276Speter if (version == 0) 17850276Speter tversion = V_ALLCAPS; 17950276Speter else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1") 18098503Speter || !strcmp(version, "Ultrix")) 18150276Speter tversion = V_SVR1; 18250276Speter else if (!strcmp(version, "HP")) 18350276Speter tversion = V_HPUX; 18450276Speter else if (!strcmp(version, "AIX")) 18550276Speter tversion = V_AIX; 18650276Speter else if (!strcmp(version, "BSD")) 18750276Speter tversion = V_BSD; 18850276Speter else 18950276Speter tversion = V_ALLCAPS; 19050276Speter 19150276Speter /* implement display modes */ 19262449Speter switch (outform = mode) { 19350276Speter case F_LITERAL: 19450276Speter case F_TERMINFO: 19550276Speter bool_names = boolnames; 19650276Speter num_names = numnames; 19750276Speter str_names = strnames; 19850276Speter separator = twidth ? ", " : ","; 19950276Speter trailer = "\n\t"; 20050276Speter break; 20150276Speter 20250276Speter case F_VARIABLE: 20350276Speter bool_names = boolfnames; 20450276Speter num_names = numfnames; 20550276Speter str_names = strfnames; 20650276Speter separator = twidth ? ", " : ","; 20750276Speter trailer = "\n\t"; 20850276Speter break; 20950276Speter 21050276Speter case F_TERMCAP: 21150276Speter case F_TCONVERR: 21250276Speter bool_names = boolcodes; 21350276Speter num_names = numcodes; 21450276Speter str_names = strcodes; 21550276Speter separator = ":"; 21650276Speter trailer = "\\\n\t:"; 21750276Speter break; 21850276Speter } 21950276Speter 22050276Speter /* implement sort modes */ 22162449Speter switch (sortmode = sort) { 22250276Speter case S_NOSORT: 22350276Speter if (traceval) 22450276Speter (void) fprintf(stderr, 22598503Speter "%s: sorting by term structure order\n", _nc_progname); 22650276Speter break; 22750276Speter 22850276Speter case S_TERMINFO: 22950276Speter if (traceval) 23050276Speter (void) fprintf(stderr, 23198503Speter "%s: sorting by terminfo name order\n", _nc_progname); 23250276Speter bool_indirect = bool_terminfo_sort; 23350276Speter num_indirect = num_terminfo_sort; 23450276Speter str_indirect = str_terminfo_sort; 23550276Speter break; 23650276Speter 23750276Speter case S_VARIABLE: 23850276Speter if (traceval) 23950276Speter (void) fprintf(stderr, 24098503Speter "%s: sorting by C variable order\n", _nc_progname); 24150276Speter bool_indirect = bool_variable_sort; 24250276Speter num_indirect = num_variable_sort; 24350276Speter str_indirect = str_variable_sort; 24450276Speter break; 24550276Speter 24650276Speter case S_TERMCAP: 24750276Speter if (traceval) 24850276Speter (void) fprintf(stderr, 24998503Speter "%s: sorting by termcap name order\n", _nc_progname); 25050276Speter bool_indirect = bool_termcap_sort; 25150276Speter num_indirect = num_termcap_sort; 25250276Speter str_indirect = str_termcap_sort; 25350276Speter break; 25450276Speter } 25550276Speter 25650276Speter if (traceval) 25750276Speter (void) fprintf(stderr, 25898503Speter "%s: width = %d, tversion = %d, outform = %d\n", 25998503Speter _nc_progname, width, tversion, outform); 26050276Speter} 26150276Speter 26262449Speterstatic TERMTYPE *cur_type; 26350276Speter 26462449Speterstatic int 26562449Speterdump_predicate(int type, int idx) 26650276Speter/* predicate function to use for ordinary decompilation */ 26750276Speter{ 26862449Speter switch (type) { 26962449Speter case BOOLEAN: 27062449Speter return (cur_type->Booleans[idx] == FALSE) 27162449Speter ? FAIL : cur_type->Booleans[idx]; 27250276Speter 27362449Speter case NUMBER: 27462449Speter return (cur_type->Numbers[idx] == ABSENT_NUMERIC) 27562449Speter ? FAIL : cur_type->Numbers[idx]; 27650276Speter 27762449Speter case STRING: 27862449Speter return (cur_type->Strings[idx] != ABSENT_STRING) 27962449Speter ? (int) TRUE : FAIL; 28062449Speter } 28150276Speter 28262449Speter return (FALSE); /* pacify compiler */ 28350276Speter} 28450276Speter 28562449Speterstatic void set_obsolete_termcaps(TERMTYPE * tp); 28650276Speter 28750276Speter/* is this the index of a function key string? */ 28850276Speter#define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268)) 28950276Speter 29062449Speterstatic bool 29162449Speterversion_filter(int type, int idx) 29250276Speter/* filter out capabilities we may want to suppress */ 29350276Speter{ 29462449Speter switch (tversion) { 29562449Speter case V_ALLCAPS: /* SVr4, XSI Curses */ 29662449Speter return (TRUE); 29750276Speter 29862449Speter case V_SVR1: /* System V Release 1, Ultrix */ 29962449Speter switch (type) { 30050276Speter case BOOLEAN: 30150276Speter /* below and including xon_xoff */ 30250276Speter return ((idx <= 20) ? TRUE : FALSE); 30350276Speter case NUMBER: 30450276Speter /* below and including width_status_line */ 30550276Speter return ((idx <= 7) ? TRUE : FALSE); 30650276Speter case STRING: 30750276Speter /* below and including prtr_non */ 30850276Speter return ((idx <= 144) ? TRUE : FALSE); 30950276Speter } 31050276Speter break; 31150276Speter 31250276Speter case V_HPUX: /* Hewlett-Packard */ 31362449Speter switch (type) { 31450276Speter case BOOLEAN: 31550276Speter /* below and including xon_xoff */ 31650276Speter return ((idx <= 20) ? TRUE : FALSE); 31750276Speter case NUMBER: 31850276Speter /* below and including label_width */ 31950276Speter return ((idx <= 10) ? TRUE : FALSE); 32050276Speter case STRING: 32150276Speter if (idx <= 144) /* below and including prtr_non */ 32262449Speter return (TRUE); 32350276Speter else if (FNKEY(idx)) /* function keys */ 32462449Speter return (TRUE); 32562449Speter else if (idx == 147 || idx == 156 || idx == 157) /* plab_norm,label_on,label_off */ 32662449Speter return (TRUE); 32750276Speter else 32862449Speter return (FALSE); 32950276Speter } 33050276Speter break; 33150276Speter 33250276Speter case V_AIX: /* AIX */ 33362449Speter switch (type) { 33450276Speter case BOOLEAN: 33550276Speter /* below and including xon_xoff */ 33650276Speter return ((idx <= 20) ? TRUE : FALSE); 33750276Speter case NUMBER: 33850276Speter /* below and including width_status_line */ 33950276Speter return ((idx <= 7) ? TRUE : FALSE); 34050276Speter case STRING: 34150276Speter if (idx <= 144) /* below and including prtr_non */ 34262449Speter return (TRUE); 34350276Speter else if (FNKEY(idx)) /* function keys */ 34462449Speter return (TRUE); 34550276Speter else 34662449Speter return (FALSE); 34750276Speter } 34850276Speter break; 34950276Speter 35050276Speter case V_BSD: /* BSD */ 35162449Speter switch (type) { 35250276Speter case BOOLEAN: 35350276Speter return bool_from_termcap[idx]; 35450276Speter case NUMBER: 35550276Speter return num_from_termcap[idx]; 35650276Speter case STRING: 35750276Speter return str_from_termcap[idx]; 35850276Speter } 35950276Speter break; 36050276Speter } 36150276Speter 36262449Speter return (FALSE); /* pacify the compiler */ 36350276Speter} 36450276Speter 36562449Speterstatic void 36662449Speterforce_wrap(void) 36750276Speter{ 36862449Speter oldcol = column; 36962449Speter strcpy_DYN(&outbuf, trailer); 37062449Speter column = INDENT; 37150276Speter} 37250276Speter 37362449Speterstatic void 37462449Speterwrap_concat(const char *src) 37550276Speter{ 37662449Speter int need = strlen(src); 37762449Speter int want = strlen(separator) + need; 37850276Speter 37962449Speter if (column > INDENT 38062449Speter && column + want > width) { 38162449Speter force_wrap(); 38262449Speter } 38362449Speter strcpy_DYN(&outbuf, src); 38462449Speter strcpy_DYN(&outbuf, separator); 38562449Speter column += need; 38650276Speter} 38750276Speter 38850276Speter#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ 38950276Speter if ((size_t)(last - first) > sizeof(sep_trail)-1 \ 39050276Speter && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ 39150276Speter first += sizeof(sep_trail)-2 39250276Speter 39350276Speter/* Returns the nominal length of the buffer assuming it is termcap format, 39450276Speter * i.e., the continuation sequence is treated as a single character ":". 39550276Speter * 39650276Speter * There are several implementations of termcap which read the text into a 39750276Speter * fixed-size buffer. Generally they strip the newlines from the text, but may 39850276Speter * not do it until after the buffer is read. Also, "tc=" resolution may be 39950276Speter * expanded in the same buffer. This function is useful for measuring the size 40050276Speter * of the best fixed-buffer implementation; the worst case may be much worse. 40150276Speter */ 40250276Speter#ifdef TEST_TERMCAP_LENGTH 40362449Speterstatic int 40462449Spetertermcap_length(const char *src) 40550276Speter{ 40662449Speter static const char pattern[] = ":\\\n\t:"; 40750276Speter 40862449Speter int len = 0; 40962449Speter const char *const t = src + strlen(src); 41050276Speter 41162449Speter while (*src != '\0') { 41262449Speter IGNORE_SEP_TRAIL(src, t, pattern); 41362449Speter src++; 41462449Speter len++; 41562449Speter } 41662449Speter return len; 41750276Speter} 41850276Speter#else 41950276Speter#define termcap_length(src) strlen(src) 42050276Speter#endif 42150276Speter 42262449Speterstatic char * 42362449Speterfmt_complex(char *src, int level) 42450276Speter{ 42562449Speter int percent = 0; 42662449Speter int n; 42762449Speter bool if_then = strstr(src, "%?") != 0; 42862449Speter bool params = !if_then && (strlen(src) > 50) && (strstr(src, "%p") != 0); 42950276Speter 43062449Speter while (*src != '\0') { 43162449Speter switch (*src) { 43262449Speter case '\\': 43362449Speter percent = 0; 43462449Speter strncpy_DYN(&tmpbuf, src++, 1); 43562449Speter break; 43662449Speter case '%': 43762449Speter percent = 1; 43862449Speter break; 43962449Speter case '?': /* "if" */ 44062449Speter case 't': /* "then" */ 44162449Speter case 'e': /* "else" */ 44262449Speter if (percent) { 44362449Speter percent = 0; 44462449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 44562449Speter /* treat a "%e%?" as else-if, on the same level */ 44662449Speter if (!strncmp(src, "e%?", 3)) { 44762449Speter for (n = 0; n < level; n++) 44862449Speter strncpy_DYN(&tmpbuf, "\t", 1); 44962449Speter strncpy_DYN(&tmpbuf, "%", 1); 45062449Speter strncpy_DYN(&tmpbuf, src, 3); 45162449Speter src += 3; 45262449Speter } else { 45362449Speter for (n = 0; n <= level; n++) 45462449Speter strncpy_DYN(&tmpbuf, "\t", 1); 45562449Speter strncpy_DYN(&tmpbuf, "%", 1); 45662449Speter strncpy_DYN(&tmpbuf, src, 1); 45762449Speter if (*src++ == '?') { 45862449Speter src = fmt_complex(src, level + 1); 45962449Speter } else if (level == 1) { 46062449Speter _nc_warning("%%%c without %%?", *src); 46162449Speter } 46250276Speter } 46362449Speter continue; 46462449Speter } 46562449Speter break; 46662449Speter case ';': /* "endif" */ 46762449Speter if (percent) { 46862449Speter percent = 0; 46962449Speter if (level > 1) { 47062449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 47162449Speter for (n = 0; n < level; n++) 47262449Speter strncpy_DYN(&tmpbuf, "\t", 1); 47362449Speter strncpy_DYN(&tmpbuf, "%", 1); 47462449Speter strncpy_DYN(&tmpbuf, src++, 1); 47562449Speter return src; 47662449Speter } 47762449Speter _nc_warning("%%; without %%?"); 47862449Speter } 47962449Speter break; 48062449Speter case 'p': 48162449Speter if (percent && params) { 48262449Speter tmpbuf.text[tmpbuf.used - 1] = '\n'; 48362449Speter for (n = 0; n <= level; n++) 48462449Speter strncpy_DYN(&tmpbuf, "\t", 1); 48562449Speter strncpy_DYN(&tmpbuf, "%", 1); 48662449Speter } 48762449Speter percent = 0; 48862449Speter break; 48962449Speter default: 49062449Speter percent = 0; 49162449Speter break; 49250276Speter } 49362449Speter strncpy_DYN(&tmpbuf, src++, 1); 49462449Speter } 49562449Speter return src; 49650276Speter} 49750276Speter 49862449Speterint 49962449Speterfmt_entry(TERMTYPE * tterm, 50098503Speter int (*pred) (int type, int idx), 50198503Speter bool suppress_untranslatable, 50298503Speter bool infodump, 50398503Speter int numbers) 50450276Speter{ 50562449Speter int i, j; 50662449Speter char buffer[MAX_TERMINFO_LENGTH]; 50762449Speter NCURSES_CONST char *name; 50862449Speter int predval, len; 50962449Speter int num_bools = 0; 51062449Speter int num_values = 0; 51162449Speter int num_strings = 0; 51262449Speter bool outcount = 0; 51350276Speter 51450276Speter#define WRAP_CONCAT \ 51550276Speter wrap_concat(buffer); \ 51650276Speter outcount = TRUE 51750276Speter 51850276Speter len = 12; /* terminfo file-header */ 51950276Speter 52050276Speter if (pred == 0) { 52150276Speter cur_type = tterm; 52250276Speter pred = dump_predicate; 52350276Speter } 52450276Speter 52562449Speter strcpy_DYN(&outbuf, 0); 52662449Speter strcpy_DYN(&outbuf, tterm->term_names); 52762449Speter strcpy_DYN(&outbuf, separator); 52862449Speter column = outbuf.used; 52950276Speter force_wrap(); 53050276Speter 53162449Speter for_each_boolean(j, tterm) { 53250276Speter i = BoolIndirect(j); 53362449Speter name = ExtBoolname(tterm, i, bool_names); 53450276Speter 53550276Speter if (!version_filter(BOOLEAN, i)) 53650276Speter continue; 53762449Speter else if (isObsolete(outform, name)) 53850276Speter continue; 53950276Speter 54050276Speter predval = pred(BOOLEAN, i); 54150276Speter if (predval != FAIL) { 54250276Speter (void) strcpy(buffer, name); 54350276Speter if (predval <= 0) 54450276Speter (void) strcat(buffer, "@"); 54550276Speter else if (i + 1 > num_bools) 54650276Speter num_bools = i + 1; 54750276Speter WRAP_CONCAT; 54850276Speter } 54950276Speter } 55050276Speter 55150276Speter if (column != INDENT) 55250276Speter force_wrap(); 55350276Speter 55462449Speter for_each_number(j, tterm) { 55550276Speter i = NumIndirect(j); 55662449Speter name = ExtNumname(tterm, i, num_names); 55750276Speter 55850276Speter if (!version_filter(NUMBER, i)) 55950276Speter continue; 56062449Speter else if (isObsolete(outform, name)) 56150276Speter continue; 56250276Speter 56350276Speter predval = pred(NUMBER, i); 56450276Speter if (predval != FAIL) { 56550276Speter if (tterm->Numbers[i] < 0) { 56650276Speter sprintf(buffer, "%s@", name); 56750276Speter } else { 56850276Speter sprintf(buffer, "%s#%d", name, tterm->Numbers[i]); 56950276Speter if (i + 1 > num_values) 57050276Speter num_values = i + 1; 57150276Speter } 57250276Speter WRAP_CONCAT; 57350276Speter } 57450276Speter } 57550276Speter 57650276Speter if (column != INDENT) 57750276Speter force_wrap(); 57850276Speter 57950276Speter len += num_bools 58062449Speter + num_values * 2 58162449Speter + strlen(tterm->term_names) + 1; 58250276Speter if (len & 1) 58362449Speter len++; 58450276Speter 58562449Speter#undef CUR 58662449Speter#define CUR tterm-> 58762449Speter if (outform == F_TERMCAP) { 58862449Speter if (termcap_reset != ABSENT_STRING) { 58962449Speter if (init_3string != ABSENT_STRING 59062449Speter && !strcmp(init_3string, termcap_reset)) 59162449Speter DISCARD(init_3string); 59262449Speter 59362449Speter if (reset_2string != ABSENT_STRING 59462449Speter && !strcmp(reset_2string, termcap_reset)) 59562449Speter DISCARD(reset_2string); 59662449Speter } 59762449Speter } 59862449Speter 59950276Speter for_each_string(j, tterm) { 60050276Speter i = StrIndirect(j); 60162449Speter name = ExtStrname(tterm, i, str_names); 60250276Speter 60350276Speter if (!version_filter(STRING, i)) 60450276Speter continue; 60562449Speter else if (isObsolete(outform, name)) 60650276Speter continue; 60750276Speter 60850276Speter /* 60950276Speter * Some older versions of vi want rmir/smir to be defined 61050276Speter * for ich/ich1 to work. If they're not defined, force 61150276Speter * them to be output as defined and empty. 61250276Speter */ 61362449Speter if (outform == F_TERMCAP) { 61462449Speter if (insert_character || parm_ich) { 61550276Speter if (&tterm->Strings[i] == &enter_insert_mode 61662449Speter && enter_insert_mode == ABSENT_STRING) { 61750276Speter (void) strcpy(buffer, "im="); 61862449Speter WRAP_CONCAT; 61962449Speter continue; 62050276Speter } 62150276Speter 62250276Speter if (&tterm->Strings[i] == &exit_insert_mode 62362449Speter && exit_insert_mode == ABSENT_STRING) { 62450276Speter (void) strcpy(buffer, "ei="); 62562449Speter WRAP_CONCAT; 62662449Speter continue; 62750276Speter } 62850276Speter } 62950276Speter } 63050276Speter 63150276Speter predval = pred(STRING, i); 63250276Speter buffer[0] = '\0'; 63362449Speter 63450276Speter if (predval != FAIL) { 63550276Speter if (tterm->Strings[i] != ABSENT_STRING 63662449Speter && i + 1 > num_strings) 63750276Speter num_strings = i + 1; 63862449Speter 63962449Speter if (!VALID_STRING(tterm->Strings[i])) { 64050276Speter sprintf(buffer, "%s@", name); 64162449Speter WRAP_CONCAT; 64262449Speter } else if (outform == F_TERMCAP || outform == F_TCONVERR) { 64398503Speter int params = ((i < (int) SIZEOF(parametrized)) 64498503Speter ? parametrized[i] 64598503Speter : 0); 64662449Speter char *srccap = _nc_tic_expand(tterm->Strings[i], TRUE, numbers); 64766963Speter char *cv = _nc_infotocap(name, srccap, params); 64850276Speter 64962449Speter if (cv == 0) { 65062449Speter if (outform == F_TCONVERR) { 65162449Speter sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", 65298503Speter name, srccap); 65362449Speter } else if (suppress_untranslatable) { 65450276Speter continue; 65562449Speter } else { 65662449Speter char *s = srccap, *d = buffer; 65762449Speter sprintf(d, "..%s=", name); 65862449Speter d += strlen(d); 65962449Speter while ((*d = *s++) != 0) { 66062449Speter if (*d == ':') { 66162449Speter *d++ = '\\'; 66262449Speter *d = ':'; 66362449Speter } else if (*d == '\\') { 66462449Speter *++d = *s++; 66562449Speter } 66662449Speter d++; 66762449Speter } 66862449Speter } 66962449Speter } else { 67062449Speter sprintf(buffer, "%s=%s", name, cv); 67150276Speter } 67250276Speter len += strlen(tterm->Strings[i]) + 1; 67362449Speter WRAP_CONCAT; 67462449Speter } else { 67562449Speter char *src = _nc_tic_expand(tterm->Strings[i], 67698503Speter outform == F_TERMINFO, numbers); 67762449Speter 67862449Speter strcpy_DYN(&tmpbuf, 0); 67962449Speter strcpy_DYN(&tmpbuf, name); 68062449Speter strcpy_DYN(&tmpbuf, "="); 68162449Speter if (pretty 68262449Speter && (outform == F_TERMINFO 68362449Speter || outform == F_VARIABLE)) { 68462449Speter fmt_complex(src, 1); 68562449Speter } else { 68662449Speter strcpy_DYN(&tmpbuf, src); 68762449Speter } 68850276Speter len += strlen(tterm->Strings[i]) + 1; 68962449Speter wrap_concat(tmpbuf.text); 69062449Speter outcount = TRUE; 69150276Speter } 69250276Speter } 69350276Speter } 69450276Speter len += num_strings * 2; 69550276Speter 69650276Speter /* 69750276Speter * This piece of code should be an effective inverse of the functions 69850276Speter * postprocess_terminfo and postprocess_terminfo in parse_entry.c. 69950276Speter * Much more work should be done on this to support dumping termcaps. 70050276Speter */ 70162449Speter if (tversion == V_HPUX) { 70262449Speter if (memory_lock) { 70350276Speter (void) sprintf(buffer, "meml=%s", memory_lock); 70450276Speter WRAP_CONCAT; 70550276Speter } 70662449Speter if (memory_unlock) { 70750276Speter (void) sprintf(buffer, "memu=%s", memory_unlock); 70850276Speter WRAP_CONCAT; 70950276Speter } 71062449Speter } else if (tversion == V_AIX) { 71162449Speter if (VALID_STRING(acs_chars)) { 71262449Speter bool box_ok = TRUE; 71362449Speter const char *acstrans = "lqkxjmwuvtn"; 71462449Speter const char *cp; 71562449Speter char *tp, *sp, boxchars[11]; 71650276Speter 71750276Speter tp = boxchars; 71862449Speter for (cp = acstrans; *cp; cp++) { 71950276Speter sp = strchr(acs_chars, *cp); 72050276Speter if (sp) 72150276Speter *tp++ = sp[1]; 72262449Speter else { 72350276Speter box_ok = FALSE; 72450276Speter break; 72550276Speter } 72650276Speter } 72750276Speter tp[0] = '\0'; 72850276Speter 72962449Speter if (box_ok) { 73050276Speter (void) strcpy(buffer, "box1="); 73162449Speter (void) strcat(buffer, _nc_tic_expand(boxchars, 73298503Speter outform == F_TERMINFO, numbers)); 73350276Speter WRAP_CONCAT; 73450276Speter } 73550276Speter } 73650276Speter } 73750276Speter 73850276Speter /* 73950276Speter * kludge: trim off trailer to avoid an extra blank line 74050276Speter * in infocmp -u output when there are no string differences 74150276Speter */ 74262449Speter if (outcount) { 74362449Speter bool trimmed = FALSE; 74462449Speter j = outbuf.used; 74550276Speter if (j >= 2 74662449Speter && outbuf.text[j - 1] == '\t' 74762449Speter && outbuf.text[j - 2] == '\n') { 74862449Speter outbuf.used -= 2; 74962449Speter trimmed = TRUE; 75050276Speter } else if (j >= 4 75198503Speter && outbuf.text[j - 1] == ':' 75298503Speter && outbuf.text[j - 2] == '\t' 75398503Speter && outbuf.text[j - 3] == '\n' 75498503Speter && outbuf.text[j - 4] == '\\') { 75562449Speter outbuf.used -= 4; 75662449Speter trimmed = TRUE; 75750276Speter } 75862449Speter if (trimmed) { 75962449Speter outbuf.text[outbuf.used] = '\0'; 76062449Speter column = oldcol; 76162449Speter } 76250276Speter } 76350276Speter#if 0 76450276Speter fprintf(stderr, "num_bools = %d\n", num_bools); 76550276Speter fprintf(stderr, "num_values = %d\n", num_values); 76650276Speter fprintf(stderr, "num_strings = %d\n", num_strings); 76750276Speter fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n", 76898503Speter tterm->term_names, len, outbuf.used, outbuf.text); 76950276Speter#endif 77050276Speter /* 77150276Speter * Here's where we use infodump to trigger a more stringent length check 77250276Speter * for termcap-translation purposes. 77350276Speter * Return the length of the raw entry, without tc= expansions, 77450276Speter * It gives an idea of which entries are deadly to even *scan past*, 77550276Speter * as opposed to *use*. 77650276Speter */ 77776726Speter return (infodump ? len : (int) termcap_length(outbuf.text)); 77850276Speter} 77950276Speter 78098503Speterstatic bool 78198503Speterkill_string(TERMTYPE * tterm, char *cap) 78298503Speter{ 78398503Speter int n; 78498503Speter for (n = 0; n < tterm->num_Strings; ++n) { 78598503Speter if (cap == tterm->Strings[n]) { 78698503Speter tterm->Strings[n] = ABSENT_STRING; 78798503Speter return TRUE; 78898503Speter } 78998503Speter } 79098503Speter return FALSE; 79198503Speter} 79298503Speter 79398503Speterstatic char * 79498503Speterfind_string(TERMTYPE * tterm, char *name) 79598503Speter{ 79698503Speter int n; 79798503Speter for (n = 0; n < tterm->num_Strings; ++n) { 79898503Speter if (version_filter(STRING, n) 79998503Speter && !strcmp(name, strnames[n])) { 80098503Speter char *cap = tterm->Strings[n]; 80198503Speter if (VALID_STRING(cap)) { 80298503Speter return cap; 80398503Speter } 80498503Speter break; 80598503Speter } 80698503Speter } 80798503Speter return ABSENT_STRING; 80898503Speter} 80998503Speter 81098503Speter/* 81198503Speter * This is used to remove function-key labels from a termcap entry to 81298503Speter * make it smaller. 81398503Speter */ 81498503Speterstatic int 81598503Speterkill_labels(TERMTYPE * tterm, int target) 81698503Speter{ 81798503Speter int n; 81898503Speter int result = 0; 81998503Speter char *cap; 82098503Speter char name[10]; 82198503Speter 82298503Speter for (n = 0; n <= 10; ++n) { 82398503Speter sprintf(name, "lf%d", n); 82498503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 82598503Speter && kill_string(tterm, cap)) { 82698503Speter target -= (strlen(cap) + 5); 82798503Speter ++result; 82898503Speter if (target < 0) 82998503Speter break; 83098503Speter } 83198503Speter } 83298503Speter return result; 83398503Speter} 83498503Speter 83598503Speter/* 83698503Speter * This is used to remove function-key definitions from a termcap entry to 83798503Speter * make it smaller. 83898503Speter */ 83998503Speterstatic int 84098503Speterkill_fkeys(TERMTYPE * tterm, int target) 84198503Speter{ 84298503Speter int n; 84398503Speter int result = 0; 84498503Speter char *cap; 84598503Speter char name[10]; 84698503Speter 84798503Speter for (n = 60; n >= 0; --n) { 84898503Speter sprintf(name, "kf%d", n); 84998503Speter if ((cap = find_string(tterm, name)) != ABSENT_STRING 85098503Speter && kill_string(tterm, cap)) { 85198503Speter target -= (strlen(cap) + 5); 85298503Speter ++result; 85398503Speter if (target < 0) 85498503Speter break; 85598503Speter } 85698503Speter } 85798503Speter return result; 85898503Speter} 85998503Speter 86062449Speterint 86198503Speterdump_entry(TERMTYPE * tterm, 86298503Speter bool limited, 86398503Speter int numbers, 86498503Speter int (*pred) (int type, int idx)) 86550276Speter/* dump a single entry */ 86650276Speter{ 86762449Speter int len, critlen; 86862449Speter const char *legend; 86962449Speter bool infodump; 87050276Speter 87162449Speter if (outform == F_TERMCAP || outform == F_TCONVERR) { 87250276Speter critlen = MAX_TERMCAP_LENGTH; 87350276Speter legend = "older termcap"; 87450276Speter infodump = FALSE; 87550276Speter set_obsolete_termcaps(tterm); 87662449Speter } else { 87750276Speter critlen = MAX_TERMINFO_LENGTH; 87850276Speter legend = "terminfo"; 87950276Speter infodump = TRUE; 88050276Speter } 88150276Speter 88262449Speter if (((len = fmt_entry(tterm, pred, FALSE, infodump, numbers)) > critlen) 88362449Speter && limited) { 88462449Speter PRINTF("# (untranslatable capabilities removed to fit entry within %d bytes)\n", 88598503Speter critlen); 88662449Speter if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) { 88750276Speter /* 88850276Speter * We pick on sgr because it's a nice long string capability that 88962449Speter * is really just an optimization hack. Another good candidate is 89062449Speter * acsc since it is both long and unused by BSD termcap. 89150276Speter */ 89250276Speter char *oldsgr = set_attributes; 89362449Speter char *oldacsc = acs_chars; 89450276Speter set_attributes = ABSENT_STRING; 89562449Speter PRINTF("# (sgr removed to fit entry within %d bytes)\n", 89698503Speter critlen); 89762449Speter if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) { 89862449Speter acs_chars = ABSENT_STRING; 89962449Speter PRINTF("# (acsc removed to fit entry within %d bytes)\n", 90098503Speter critlen); 90162449Speter } 90262449Speter if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) { 90350276Speter int oldversion = tversion; 90450276Speter 90550276Speter tversion = V_BSD; 90662449Speter PRINTF("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", 90798503Speter critlen); 90850276Speter 90998503Speter len = fmt_entry(tterm, pred, TRUE, infodump, numbers); 91098503Speter if (len > critlen 91198503Speter && kill_labels(tterm, len - critlen)) { 91298503Speter PRINTF("# (some labels capabilities suppressed to fit entry within %d bytes)\n", 91398503Speter critlen); 91498503Speter len = fmt_entry(tterm, pred, TRUE, infodump, numbers); 91598503Speter } 91698503Speter if (len > critlen 91798503Speter && kill_fkeys(tterm, len - critlen)) { 91898503Speter PRINTF("# (some function-key capabilities suppressed to fit entry within %d bytes)\n", 91998503Speter critlen); 92098503Speter len = fmt_entry(tterm, pred, TRUE, infodump, numbers); 92198503Speter } 92298503Speter if (len > critlen) { 92350276Speter (void) fprintf(stderr, 92498503Speter "warning: %s entry is %d bytes long\n", 92598503Speter _nc_first_name(tterm->term_names), 92698503Speter len); 92762449Speter PRINTF( 92898503Speter "# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", 92998503Speter len, legend); 93050276Speter } 93150276Speter tversion = oldversion; 93250276Speter } 93350276Speter set_attributes = oldsgr; 93462449Speter acs_chars = oldacsc; 93550276Speter } 93650276Speter } 93750276Speter 93862449Speter (void) fputs(outbuf.text, stdout); 93950276Speter return len; 94050276Speter} 94150276Speter 94262449Speterint 94362449Speterdump_uses(const char *name, bool infodump) 94450276Speter/* dump "use=" clauses in the appropriate format */ 94550276Speter{ 94650276Speter char buffer[MAX_TERMINFO_LENGTH]; 94750276Speter 94862449Speter strcpy_DYN(&outbuf, 0); 94962449Speter (void) sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name); 95050276Speter wrap_concat(buffer); 95162449Speter (void) fputs(outbuf.text, stdout); 95262449Speter return outbuf.used; 95350276Speter} 95450276Speter 95562449Spetervoid 95662449Spetercompare_entry(void (*hook) (int t, int i, const char *name), TERMTYPE * tp 95798503Speter GCC_UNUSED, bool quiet) 95850276Speter/* compare two entries */ 95950276Speter{ 96062449Speter int i, j; 96162449Speter NCURSES_CONST char *name; 96250276Speter 96362449Speter if (!quiet) 96462449Speter fputs(" comparing booleans.\n", stdout); 96562449Speter for_each_boolean(j, tp) { 96650276Speter i = BoolIndirect(j); 96762449Speter name = ExtBoolname(tp, i, bool_names); 96850276Speter 96962449Speter if (isObsolete(outform, name)) 97050276Speter continue; 97150276Speter 97262449Speter (*hook) (CMP_BOOLEAN, i, name); 97350276Speter } 97450276Speter 97562449Speter if (!quiet) 97662449Speter fputs(" comparing numbers.\n", stdout); 97762449Speter for_each_number(j, tp) { 97850276Speter i = NumIndirect(j); 97962449Speter name = ExtNumname(tp, i, num_names); 98050276Speter 98162449Speter if (isObsolete(outform, name)) 98250276Speter continue; 98350276Speter 98462449Speter (*hook) (CMP_NUMBER, i, name); 98550276Speter } 98650276Speter 98762449Speter if (!quiet) 98862449Speter fputs(" comparing strings.\n", stdout); 98962449Speter for_each_string(j, tp) { 99050276Speter i = StrIndirect(j); 99162449Speter name = ExtStrname(tp, i, str_names); 99250276Speter 99362449Speter if (isObsolete(outform, name)) 99450276Speter continue; 99550276Speter 99662449Speter (*hook) (CMP_STRING, i, name); 99750276Speter } 99862449Speter 99962449Speter /* (void) fputs(" comparing use entries.\n", stdout); */ 100062449Speter (*hook) (CMP_USE, 0, "use"); 100162449Speter 100250276Speter} 100350276Speter 100450276Speter#define NOTSET(s) ((s) == 0) 100550276Speter 100650276Speter/* 100750276Speter * This bit of legerdemain turns all the terminfo variable names into 100850276Speter * references to locations in the arrays Booleans, Numbers, and Strings --- 100950276Speter * precisely what's needed. 101050276Speter */ 101150276Speter#undef CUR 101250276Speter#define CUR tp-> 101350276Speter 101462449Speterstatic void 101562449Speterset_obsolete_termcaps(TERMTYPE * tp) 101650276Speter{ 101750276Speter#include "capdefaults.c" 101850276Speter} 101950276Speter 102050276Speter/* 102150276Speter * Convert an alternate-character-set string to canonical form: sorted and 102250276Speter * unique. 102350276Speter */ 102462449Spetervoid 102562449Speterrepair_acsc(TERMTYPE * tp) 102650276Speter{ 102762449Speter if (VALID_STRING(acs_chars)) { 102862449Speter size_t n, m; 102962449Speter char mapped[256]; 103062449Speter char extra = 0; 103162449Speter unsigned source; 103262449Speter unsigned target; 103362449Speter bool fix_needed = FALSE; 103450276Speter 103562449Speter for (n = 0, source = 0; acs_chars[n] != 0; n++) { 103662449Speter target = acs_chars[n]; 103762449Speter if (source >= target) { 103862449Speter fix_needed = TRUE; 103962449Speter break; 104062449Speter } 104162449Speter source = target; 104262449Speter if (acs_chars[n + 1]) 104362449Speter n++; 104462449Speter } 104562449Speter if (fix_needed) { 104662449Speter memset(mapped, 0, sizeof(mapped)); 104762449Speter for (n = 0; acs_chars[n] != 0; n++) { 104862449Speter source = acs_chars[n]; 104962449Speter if ((target = (unsigned char) acs_chars[n + 1]) != 0) { 105062449Speter mapped[source] = target; 105162449Speter n++; 105262449Speter } else { 105362449Speter extra = source; 105450276Speter } 105550276Speter } 105662449Speter for (n = m = 0; n < sizeof(mapped); n++) { 105762449Speter if (mapped[n]) { 105862449Speter acs_chars[m++] = n; 105962449Speter acs_chars[m++] = mapped[n]; 106050276Speter } 106150276Speter } 106262449Speter if (extra) 106362449Speter acs_chars[m++] = extra; /* garbage in, garbage out */ 106462449Speter acs_chars[m] = 0; 106550276Speter } 106662449Speter } 106750276Speter} 1068