12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274 |
- /****************************************************************************
- * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. *
- * *
- * Permission is hereby granted, free of charge, to any person obtaining a *
- * copy of this software and associated documentation files (the *
- * "Software"), to deal in the Software without restriction, including *
- * without limitation the rights to use, copy, modify, merge, publish, *
- * distribute, distribute with modifications, sublicense, and/or sell *
- * copies of the Software, and to permit persons to whom the Software is *
- * furnished to do so, subject to the following conditions: *
- * *
- * The above copyright notice and this permission notice shall be included *
- * in all copies or substantial portions of the Software. *
- * *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
- * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
- * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
- * *
- * Except as contained in this notice, the name(s) of the above copyright *
- * holders shall not be used in advertising or otherwise to promote the *
- * sale, use or other dealings in this Software without prior written *
- * authorization. *
- ****************************************************************************/
- /****************************************************************************
- * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
- * and: Eric S. Raymond <esr@snark.thyrsus.com> *
- * and: Thomas E. Dickey 1996 on *
- ****************************************************************************/
- #define __INTERNAL_CAPS_VISIBLE
- #include <progs.priv.h>
- #include "dump_entry.h"
- #include "termsort.c" /* this C file is generated */
- #include <parametrized.h> /* so is this */
- MODULE_ID("$Id: dump_entry.c,v 1.88 2008/08/04 12:36:12 tom Exp $")
- #define INDENT 8
- #define DISCARD(string) string = ABSENT_STRING
- #define PRINTF (void) printf
- #define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array))
- typedef struct {
- char *text;
- size_t used;
- size_t size;
- } DYNBUF;
- static int tversion; /* terminfo version */
- static int outform; /* output format to use */
- static int sortmode; /* sort mode to use */
- static int width = 60; /* max line width for listings */
- static int column; /* current column, limited by 'width' */
- static int oldcol; /* last value of column before wrap */
- static bool pretty; /* true if we format if-then-else strings */
- static char *save_sgr;
- static DYNBUF outbuf;
- static DYNBUF tmpbuf;
- /* indirection pointers for implementing sort and display modes */
- static const PredIdx *bool_indirect, *num_indirect, *str_indirect;
- static NCURSES_CONST char *const *bool_names;
- static NCURSES_CONST char *const *num_names;
- static NCURSES_CONST char *const *str_names;
- static const char *separator, *trailer;
- /* cover various ports and variants of terminfo */
- #define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */
- #define V_SVR1 1 /* SVR1, Ultrix */
- #define V_HPUX 2 /* HP/UX */
- #define V_AIX 3 /* AIX */
- #define V_BSD 4 /* BSD */
- #if NCURSES_XNAMES
- #define OBSOLETE(n) (!_nc_user_definable && (n[0] == 'O' && n[1] == 'T'))
- #else
- #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T')
- #endif
- #define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n))
- #if NCURSES_XNAMES
- #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j]))
- #define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j]))
- #define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j]))
- #else
- #define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j])
- #define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j])
- #define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j])
- #endif
- static void
- strncpy_DYN(DYNBUF * dst, const char *src, size_t need)
- {
- size_t want = need + dst->used + 1;
- if (want > dst->size) {
- dst->size += (want + 1024); /* be generous */
- dst->text = typeRealloc(char, dst->size, dst->text);
- }
- (void) strncpy(dst->text + dst->used, src, need);
- dst->used += need;
- dst->text[dst->used] = 0;
- }
- static void
- strcpy_DYN(DYNBUF * dst, const char *src)
- {
- if (src == 0) {
- dst->used = 0;
- strcpy_DYN(dst, "");
- } else {
- strncpy_DYN(dst, src, strlen(src));
- }
- }
- #if NO_LEAKS
- static void
- free_DYN(DYNBUF * p)
- {
- if (p->text != 0)
- free(p->text);
- p->text = 0;
- p->size = 0;
- p->used = 0;
- }
- void
- _nc_leaks_dump_entry(void)
- {
- free_DYN(&outbuf);
- free_DYN(&tmpbuf);
- }
- #endif
- #define NameTrans(check,result) \
- if (OkIndex(np->nte_index, check) \
- && check[np->nte_index]) \
- return (result[np->nte_index])
- NCURSES_CONST char *
- nametrans(const char *name)
- /* translate a capability name from termcap to terminfo */
- {
- const struct name_table_entry *np;
- if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0)
- switch (np->nte_type) {
- case BOOLEAN:
- NameTrans(bool_from_termcap, boolcodes);
- break;
- case NUMBER:
- NameTrans(num_from_termcap, numcodes);
- break;
- case STRING:
- NameTrans(str_from_termcap, strcodes);
- break;
- }
- return (0);
- }
- void
- dump_init(const char *version, int mode, int sort, int twidth, int traceval,
- bool formatted)
- /* set up for entry display */
- {
- width = twidth;
- pretty = formatted;
- /* versions */
- if (version == 0)
- tversion = V_ALLCAPS;
- else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1")
- || !strcmp(version, "Ultrix"))
- tversion = V_SVR1;
- else if (!strcmp(version, "HP"))
- tversion = V_HPUX;
- else if (!strcmp(version, "AIX"))
- tversion = V_AIX;
- else if (!strcmp(version, "BSD"))
- tversion = V_BSD;
- else
- tversion = V_ALLCAPS;
- /* implement display modes */
- switch (outform = mode) {
- case F_LITERAL:
- case F_TERMINFO:
- bool_names = boolnames;
- num_names = numnames;
- str_names = strnames;
- separator = twidth ? ", " : ",";
- trailer = "\n\t";
- break;
- case F_VARIABLE:
- bool_names = boolfnames;
- num_names = numfnames;
- str_names = strfnames;
- separator = twidth ? ", " : ",";
- trailer = "\n\t";
- break;
- case F_TERMCAP:
- case F_TCONVERR:
- bool_names = boolcodes;
- num_names = numcodes;
- str_names = strcodes;
- separator = ":";
- trailer = "\\\n\t:";
- break;
- }
- /* implement sort modes */
- switch (sortmode = sort) {
- case S_NOSORT:
- if (traceval)
- (void) fprintf(stderr,
- "%s: sorting by term structure order\n", _nc_progname);
- break;
- case S_TERMINFO:
- if (traceval)
- (void) fprintf(stderr,
- "%s: sorting by terminfo name order\n", _nc_progname);
- bool_indirect = bool_terminfo_sort;
- num_indirect = num_terminfo_sort;
- str_indirect = str_terminfo_sort;
- break;
- case S_VARIABLE:
- if (traceval)
- (void) fprintf(stderr,
- "%s: sorting by C variable order\n", _nc_progname);
- bool_indirect = bool_variable_sort;
- num_indirect = num_variable_sort;
- str_indirect = str_variable_sort;
- break;
- case S_TERMCAP:
- if (traceval)
- (void) fprintf(stderr,
- "%s: sorting by termcap name order\n", _nc_progname);
- bool_indirect = bool_termcap_sort;
- num_indirect = num_termcap_sort;
- str_indirect = str_termcap_sort;
- break;
- }
- if (traceval)
- (void) fprintf(stderr,
- "%s: width = %d, tversion = %d, outform = %d\n",
- _nc_progname, width, tversion, outform);
- }
- static TERMTYPE *cur_type;
- static int
- dump_predicate(PredType type, PredIdx idx)
- /* predicate function to use for ordinary decompilation */
- {
- switch (type) {
- case BOOLEAN:
- return (cur_type->Booleans[idx] == FALSE)
- ? FAIL : cur_type->Booleans[idx];
- case NUMBER:
- return (cur_type->Numbers[idx] == ABSENT_NUMERIC)
- ? FAIL : cur_type->Numbers[idx];
- case STRING:
- return (cur_type->Strings[idx] != ABSENT_STRING)
- ? (int) TRUE : FAIL;
- }
- return (FALSE); /* pacify compiler */
- }
- static void set_obsolete_termcaps(TERMTYPE *tp);
- /* is this the index of a function key string? */
- #define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268))
- /*
- * If we configure with a different Caps file, the offsets into the arrays
- * will change. So we use an address expression.
- */
- #define BOOL_IDX(name) (PredType) (&(name) - &(CUR Booleans[0]))
- #define NUM_IDX(name) (PredType) (&(name) - &(CUR Numbers[0]))
- #define STR_IDX(name) (PredType) (&(name) - &(CUR Strings[0]))
- static bool
- version_filter(PredType type, PredIdx idx)
- /* filter out capabilities we may want to suppress */
- {
- switch (tversion) {
- case V_ALLCAPS: /* SVr4, XSI Curses */
- return (TRUE);
- case V_SVR1: /* System V Release 1, Ultrix */
- switch (type) {
- case BOOLEAN:
- return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
- case NUMBER:
- return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE);
- case STRING:
- return ((idx <= STR_IDX(prtr_non)) ? TRUE : FALSE);
- }
- break;
- case V_HPUX: /* Hewlett-Packard */
- switch (type) {
- case BOOLEAN:
- return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
- case NUMBER:
- return ((idx <= NUM_IDX(label_width)) ? TRUE : FALSE);
- case STRING:
- if (idx <= STR_IDX(prtr_non))
- return (TRUE);
- else if (FNKEY(idx)) /* function keys */
- return (TRUE);
- else if (idx == STR_IDX(plab_norm)
- || idx == STR_IDX(label_on)
- || idx == STR_IDX(label_off))
- return (TRUE);
- else
- return (FALSE);
- }
- break;
- case V_AIX: /* AIX */
- switch (type) {
- case BOOLEAN:
- return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE);
- case NUMBER:
- return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE);
- case STRING:
- if (idx <= STR_IDX(prtr_non))
- return (TRUE);
- else if (FNKEY(idx)) /* function keys */
- return (TRUE);
- else
- return (FALSE);
- }
- break;
- #define is_termcap(type) (OkIndex(idx, type##_from_termcap) && \
- type##_from_termcap[idx])
- case V_BSD: /* BSD */
- switch (type) {
- case BOOLEAN:
- return is_termcap(bool);
- case NUMBER:
- return is_termcap(num);
- case STRING:
- return is_termcap(str);
- }
- break;
- }
- return (FALSE); /* pacify the compiler */
- }
- static void
- trim_trailing(void)
- {
- while (outbuf.used > 0 && outbuf.text[outbuf.used - 1] == ' ')
- outbuf.text[--outbuf.used] = '\0';
- }
- static void
- force_wrap(void)
- {
- oldcol = column;
- trim_trailing();
- strcpy_DYN(&outbuf, trailer);
- column = INDENT;
- }
- static void
- wrap_concat(const char *src)
- {
- unsigned need = strlen(src);
- unsigned want = strlen(separator) + need;
- if (column > INDENT
- && column + (int) want > width) {
- force_wrap();
- }
- strcpy_DYN(&outbuf, src);
- strcpy_DYN(&outbuf, separator);
- column += (int) need;
- }
- #define IGNORE_SEP_TRAIL(first,last,sep_trail) \
- if ((size_t)(last - first) > sizeof(sep_trail)-1 \
- && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \
- first += sizeof(sep_trail)-2
- /* Returns the nominal length of the buffer assuming it is termcap format,
- * i.e., the continuation sequence is treated as a single character ":".
- *
- * There are several implementations of termcap which read the text into a
- * fixed-size buffer. Generally they strip the newlines from the text, but may
- * not do it until after the buffer is read. Also, "tc=" resolution may be
- * expanded in the same buffer. This function is useful for measuring the size
- * of the best fixed-buffer implementation; the worst case may be much worse.
- */
- #ifdef TEST_TERMCAP_LENGTH
- static int
- termcap_length(const char *src)
- {
- static const char pattern[] = ":\\\n\t:";
- int len = 0;
- const char *const t = src + strlen(src);
- while (*src != '\0') {
- IGNORE_SEP_TRAIL(src, t, pattern);
- src++;
- len++;
- }
- return len;
- }
- #else
- #define termcap_length(src) strlen(src)
- #endif
- static void
- indent_DYN(DYNBUF * buffer, int level)
- {
- int n;
- for (n = 0; n < level; n++)
- strncpy_DYN(buffer, "\t", 1);
- }
- static bool
- has_params(const char *src)
- {
- bool result = FALSE;
- int len = (int) strlen(src);
- int n;
- bool ifthen = FALSE;
- bool params = FALSE;
- for (n = 0; n < len - 1; ++n) {
- if (!strncmp(src + n, "%p", 2)) {
- params = TRUE;
- } else if (!strncmp(src + n, "%;", 2)) {
- ifthen = TRUE;
- result = params;
- break;
- }
- }
- if (!ifthen) {
- result = ((len > 50) && params);
- }
- return result;
- }
- static char *
- fmt_complex(char *src, int level)
- {
- bool percent = FALSE;
- bool params = has_params(src);
- while (*src != '\0') {
- switch (*src) {
- case '\\':
- percent = FALSE;
- strncpy_DYN(&tmpbuf, src++, 1);
- break;
- case '%':
- percent = TRUE;
- break;
- case '?': /* "if" */
- case 't': /* "then" */
- case 'e': /* "else" */
- if (percent) {
- percent = FALSE;
- tmpbuf.text[tmpbuf.used - 1] = '\n';
- /* treat a "%e" as else-if, on the same level */
- if (*src == 'e') {
- indent_DYN(&tmpbuf, level);
- strncpy_DYN(&tmpbuf, "%", 1);
- strncpy_DYN(&tmpbuf, src, 1);
- src++;
- params = has_params(src);
- if (!params && *src != '\0' && *src != '%') {
- strncpy_DYN(&tmpbuf, "\n", 1);
- indent_DYN(&tmpbuf, level + 1);
- }
- } else {
- indent_DYN(&tmpbuf, level + 1);
- strncpy_DYN(&tmpbuf, "%", 1);
- strncpy_DYN(&tmpbuf, src, 1);
- if (*src++ == '?') {
- src = fmt_complex(src, level + 1);
- if (*src != '\0' && *src != '%') {
- strncpy_DYN(&tmpbuf, "\n", 1);
- indent_DYN(&tmpbuf, level + 1);
- }
- } else if (level == 1) {
- _nc_warning("%%%c without %%?", *src);
- }
- }
- continue;
- }
- break;
- case ';': /* "endif" */
- if (percent) {
- percent = FALSE;
- if (level > 1) {
- tmpbuf.text[tmpbuf.used - 1] = '\n';
- indent_DYN(&tmpbuf, level);
- strncpy_DYN(&tmpbuf, "%", 1);
- strncpy_DYN(&tmpbuf, src++, 1);
- return src;
- }
- _nc_warning("%%; without %%?");
- }
- break;
- case 'p':
- if (percent && params) {
- tmpbuf.text[tmpbuf.used - 1] = '\n';
- indent_DYN(&tmpbuf, level + 1);
- strncpy_DYN(&tmpbuf, "%", 1);
- }
- params = FALSE;
- percent = FALSE;
- break;
- case ' ':
- strncpy_DYN(&tmpbuf, "\\s", 2);
- ++src;
- continue;
- default:
- percent = FALSE;
- break;
- }
- strncpy_DYN(&tmpbuf, src++, 1);
- }
- return src;
- }
- #define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap)
- #define EXTRA_CAP 20
- int
- fmt_entry(TERMTYPE *tterm,
- PredFunc pred,
- bool content_only,
- bool suppress_untranslatable,
- bool infodump,
- int numbers)
- {
- PredIdx i, j;
- char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP];
- char *capability;
- NCURSES_CONST char *name;
- int predval, len;
- PredIdx num_bools = 0;
- PredIdx num_values = 0;
- PredIdx num_strings = 0;
- bool outcount = 0;
- #define WRAP_CONCAT \
- wrap_concat(buffer); \
- outcount = TRUE
- len = 12; /* terminfo file-header */
- if (pred == 0) {
- cur_type = tterm;
- pred = dump_predicate;
- }
- strcpy_DYN(&outbuf, 0);
- if (content_only) {
- column = INDENT; /* FIXME: workaround to prevent empty lines */
- } else {
- strcpy_DYN(&outbuf, tterm->term_names);
- strcpy_DYN(&outbuf, separator);
- column = (int) outbuf.used;
- force_wrap();
- }
- for_each_boolean(j, tterm) {
- i = BoolIndirect(j);
- name = ExtBoolname(tterm, i, bool_names);
- assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
- if (!version_filter(BOOLEAN, i))
- continue;
- else if (isObsolete(outform, name))
- continue;
- predval = pred(BOOLEAN, i);
- if (predval != FAIL) {
- (void) strcpy(buffer, name);
- if (predval <= 0)
- (void) strcat(buffer, "@");
- else if (i + 1 > num_bools)
- num_bools = i + 1;
- WRAP_CONCAT;
- }
- }
- if (column != INDENT)
- force_wrap();
- for_each_number(j, tterm) {
- i = NumIndirect(j);
- name = ExtNumname(tterm, i, num_names);
- assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
- if (!version_filter(NUMBER, i))
- continue;
- else if (isObsolete(outform, name))
- continue;
- predval = pred(NUMBER, i);
- if (predval != FAIL) {
- if (tterm->Numbers[i] < 0) {
- sprintf(buffer, "%s@", name);
- } else {
- sprintf(buffer, "%s#%d", name, tterm->Numbers[i]);
- if (i + 1 > num_values)
- num_values = i + 1;
- }
- WRAP_CONCAT;
- }
- }
- if (column != INDENT)
- force_wrap();
- len += (int) (num_bools
- + num_values * 2
- + strlen(tterm->term_names) + 1);
- if (len & 1)
- len++;
- #undef CUR
- #define CUR tterm->
- if (outform == F_TERMCAP) {
- if (termcap_reset != ABSENT_STRING) {
- if (init_3string != ABSENT_STRING
- && !strcmp(init_3string, termcap_reset))
- DISCARD(init_3string);
- if (reset_2string != ABSENT_STRING
- && !strcmp(reset_2string, termcap_reset))
- DISCARD(reset_2string);
- }
- }
- for_each_string(j, tterm) {
- i = StrIndirect(j);
- name = ExtStrname(tterm, i, str_names);
- assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
- capability = tterm->Strings[i];
- if (!version_filter(STRING, i))
- continue;
- else if (isObsolete(outform, name))
- continue;
- #if NCURSES_XNAMES
- /*
- * Extended names can be longer than 2 characters, but termcap programs
- * cannot read those (filter them out).
- */
- if (outform == F_TERMCAP && (strlen(name) > 2))
- continue;
- #endif
- if (outform == F_TERMCAP) {
- /*
- * Some older versions of vi want rmir/smir to be defined
- * for ich/ich1 to work. If they're not defined, force
- * them to be output as defined and empty.
- */
- if (PRESENT(insert_character) || PRESENT(parm_ich)) {
- if (SAME_CAP(i, enter_insert_mode)
- && enter_insert_mode == ABSENT_STRING) {
- (void) strcpy(buffer, "im=");
- WRAP_CONCAT;
- continue;
- }
- if (SAME_CAP(i, exit_insert_mode)
- && exit_insert_mode == ABSENT_STRING) {
- (void) strcpy(buffer, "ei=");
- WRAP_CONCAT;
- continue;
- }
- }
- /*
- * termcap applications such as screen will be confused if sgr0
- * is translated to a string containing rmacs. Filter that out.
- */
- if (PRESENT(exit_attribute_mode)) {
- if (SAME_CAP(i, exit_attribute_mode)) {
- char *trimmed_sgr0;
- char *my_sgr = set_attributes;
- set_attributes = save_sgr;
- trimmed_sgr0 = _nc_trim_sgr0(tterm);
- if (strcmp(capability, trimmed_sgr0))
- capability = trimmed_sgr0;
- set_attributes = my_sgr;
- }
- }
- }
- predval = pred(STRING, i);
- buffer[0] = '\0';
- if (predval != FAIL) {
- if (capability != ABSENT_STRING
- && i + 1 > num_strings)
- num_strings = i + 1;
- if (!VALID_STRING(capability)) {
- sprintf(buffer, "%s@", name);
- WRAP_CONCAT;
- } else if (outform == F_TERMCAP || outform == F_TCONVERR) {
- int params = ((i < (int) SIZEOF(parametrized))
- ? parametrized[i]
- : 0);
- char *srccap = _nc_tic_expand(capability, TRUE, numbers);
- char *cv = _nc_infotocap(name, srccap, params);
- if (cv == 0) {
- if (outform == F_TCONVERR) {
- sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!",
- name, srccap);
- } else if (suppress_untranslatable) {
- continue;
- } else {
- char *s = srccap, *d = buffer;
- sprintf(d, "..%s=", name);
- d += strlen(d);
- while ((*d = *s++) != 0) {
- if (*d == ':') {
- *d++ = '\\';
- *d = ':';
- } else if (*d == '\\') {
- *++d = *s++;
- }
- d++;
- }
- }
- } else {
- sprintf(buffer, "%s=%s", name, cv);
- }
- len += (int) strlen(capability) + 1;
- WRAP_CONCAT;
- } else {
- char *src = _nc_tic_expand(capability,
- outform == F_TERMINFO, numbers);
- strcpy_DYN(&tmpbuf, 0);
- strcpy_DYN(&tmpbuf, name);
- strcpy_DYN(&tmpbuf, "=");
- if (pretty
- && (outform == F_TERMINFO
- || outform == F_VARIABLE)) {
- fmt_complex(src, 1);
- } else {
- strcpy_DYN(&tmpbuf, src);
- }
- len += (int) strlen(capability) + 1;
- wrap_concat(tmpbuf.text);
- outcount = TRUE;
- }
- }
- /* e.g., trimmed_sgr0 */
- if (capability != tterm->Strings[i])
- free(capability);
- }
- len += (int) (num_strings * 2);
- /*
- * This piece of code should be an effective inverse of the functions
- * postprocess_terminfo() and postprocess_terminfo() in parse_entry.c.
- * Much more work should be done on this to support dumping termcaps.
- */
- if (tversion == V_HPUX) {
- if (VALID_STRING(memory_lock)) {
- (void) sprintf(buffer, "meml=%s", memory_lock);
- WRAP_CONCAT;
- }
- if (VALID_STRING(memory_unlock)) {
- (void) sprintf(buffer, "memu=%s", memory_unlock);
- WRAP_CONCAT;
- }
- } else if (tversion == V_AIX) {
- if (VALID_STRING(acs_chars)) {
- bool box_ok = TRUE;
- const char *acstrans = "lqkxjmwuvtn";
- const char *cp;
- char *tp, *sp, boxchars[11];
- tp = boxchars;
- for (cp = acstrans; *cp; cp++) {
- sp = strchr(acs_chars, *cp);
- if (sp)
- *tp++ = sp[1];
- else {
- box_ok = FALSE;
- break;
- }
- }
- tp[0] = '\0';
- if (box_ok) {
- (void) strcpy(buffer, "box1=");
- (void) strcat(buffer, _nc_tic_expand(boxchars,
- outform == F_TERMINFO, numbers));
- WRAP_CONCAT;
- }
- }
- }
- /*
- * kludge: trim off trailer to avoid an extra blank line
- * in infocmp -u output when there are no string differences
- */
- if (outcount) {
- bool trimmed = FALSE;
- j = outbuf.used;
- if (j >= 2
- && outbuf.text[j - 1] == '\t'
- && outbuf.text[j - 2] == '\n') {
- outbuf.used -= 2;
- trimmed = TRUE;
- } else if (j >= 4
- && outbuf.text[j - 1] == ':'
- && outbuf.text[j - 2] == '\t'
- && outbuf.text[j - 3] == '\n'
- && outbuf.text[j - 4] == '\\') {
- outbuf.used -= 4;
- trimmed = TRUE;
- }
- if (trimmed) {
- outbuf.text[outbuf.used] = '\0';
- column = oldcol;
- strcpy_DYN(&outbuf, " ");
- }
- }
- #if 0
- fprintf(stderr, "num_bools = %d\n", num_bools);
- fprintf(stderr, "num_values = %d\n", num_values);
- fprintf(stderr, "num_strings = %d\n", num_strings);
- fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n",
- tterm->term_names, len, outbuf.used, outbuf.text);
- #endif
- /*
- * Here's where we use infodump to trigger a more stringent length check
- * for termcap-translation purposes.
- * Return the length of the raw entry, without tc= expansions,
- * It gives an idea of which entries are deadly to even *scan past*,
- * as opposed to *use*.
- */
- return (infodump ? len : (int) termcap_length(outbuf.text));
- }
- static bool
- kill_string(TERMTYPE *tterm, char *cap)
- {
- unsigned n;
- for (n = 0; n < NUM_STRINGS(tterm); ++n) {
- if (cap == tterm->Strings[n]) {
- tterm->Strings[n] = ABSENT_STRING;
- return TRUE;
- }
- }
- return FALSE;
- }
- static char *
- find_string(TERMTYPE *tterm, char *name)
- {
- PredIdx n;
- for (n = 0; n < NUM_STRINGS(tterm); ++n) {
- if (version_filter(STRING, n)
- && !strcmp(name, strnames[n])) {
- char *cap = tterm->Strings[n];
- if (VALID_STRING(cap)) {
- return cap;
- }
- break;
- }
- }
- return ABSENT_STRING;
- }
- /*
- * This is used to remove function-key labels from a termcap entry to
- * make it smaller.
- */
- static int
- kill_labels(TERMTYPE *tterm, int target)
- {
- int n;
- int result = 0;
- char *cap;
- char name[10];
- for (n = 0; n <= 10; ++n) {
- sprintf(name, "lf%d", n);
- if ((cap = find_string(tterm, name)) != ABSENT_STRING
- && kill_string(tterm, cap)) {
- target -= (int) (strlen(cap) + 5);
- ++result;
- if (target < 0)
- break;
- }
- }
- return result;
- }
- /*
- * This is used to remove function-key definitions from a termcap entry to
- * make it smaller.
- */
- static int
- kill_fkeys(TERMTYPE *tterm, int target)
- {
- int n;
- int result = 0;
- char *cap;
- char name[10];
- for (n = 60; n >= 0; --n) {
- sprintf(name, "kf%d", n);
- if ((cap = find_string(tterm, name)) != ABSENT_STRING
- && kill_string(tterm, cap)) {
- target -= (int) (strlen(cap) + 5);
- ++result;
- if (target < 0)
- break;
- }
- }
- return result;
- }
- /*
- * Check if the given acsc string is a 1-1 mapping, i.e., just-like-vt100.
- * Also, since this is for termcap, we only care about the line-drawing map.
- */
- #define isLine(c) (strchr("lmkjtuvwqxn", c) != 0)
- static bool
- one_one_mapping(const char *mapping)
- {
- bool result = TRUE;
- if (mapping != ABSENT_STRING) {
- int n = 0;
- while (mapping[n] != '\0') {
- if (isLine(mapping[n]) &&
- mapping[n] != mapping[n + 1]) {
- result = FALSE;
- break;
- }
- n += 2;
- }
- }
- return result;
- }
- #define FMT_ENTRY() \
- fmt_entry(tterm, pred, \
- 0, \
- suppress_untranslatable, \
- infodump, numbers)
- #define SHOW_WHY PRINTF
- static bool
- purged_acs(TERMTYPE *tterm)
- {
- bool result = FALSE;
- if (VALID_STRING(acs_chars)) {
- if (!one_one_mapping(acs_chars)) {
- enter_alt_charset_mode = ABSENT_STRING;
- exit_alt_charset_mode = ABSENT_STRING;
- SHOW_WHY("# (rmacs/smacs removed for consistency)\n");
- }
- result = TRUE;
- }
- return result;
- }
- /*
- * Dump a single entry.
- */
- void
- dump_entry(TERMTYPE *tterm,
- bool suppress_untranslatable,
- bool limited,
- int numbers,
- PredFunc pred)
- {
- TERMTYPE save_tterm;
- int len, critlen;
- const char *legend;
- bool infodump;
- if (outform == F_TERMCAP || outform == F_TCONVERR) {
- critlen = MAX_TERMCAP_LENGTH;
- legend = "older termcap";
- infodump = FALSE;
- set_obsolete_termcaps(tterm);
- } else {
- critlen = MAX_TERMINFO_LENGTH;
- legend = "terminfo";
- infodump = TRUE;
- }
- save_sgr = set_attributes;
- if (((len = FMT_ENTRY()) > critlen)
- && limited) {
- save_tterm = *tterm;
- if (!suppress_untranslatable) {
- SHOW_WHY("# (untranslatable capabilities removed to fit entry within %d bytes)\n",
- critlen);
- suppress_untranslatable = TRUE;
- }
- if ((len = FMT_ENTRY()) > critlen) {
- /*
- * We pick on sgr because it's a nice long string capability that
- * is really just an optimization hack. Another good candidate is
- * acsc since it is both long and unused by BSD termcap.
- */
- bool changed = FALSE;
- #if NCURSES_XNAMES
- /*
- * Extended names are most likely function-key definitions. Drop
- * those first.
- */
- unsigned n;
- for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) {
- const char *name = ExtStrname(tterm, n, strnames);
- if (VALID_STRING(tterm->Strings[n])) {
- set_attributes = ABSENT_STRING;
- /* we remove long names anyway - only report the short */
- if (strlen(name) <= 2) {
- SHOW_WHY("# (%s removed to fit entry within %d bytes)\n",
- name,
- critlen);
- }
- changed = TRUE;
- if ((len = FMT_ENTRY()) <= critlen)
- break;
- }
- }
- #endif
- if (VALID_STRING(set_attributes)) {
- set_attributes = ABSENT_STRING;
- SHOW_WHY("# (sgr removed to fit entry within %d bytes)\n",
- critlen);
- changed = TRUE;
- }
- if (!changed || ((len = FMT_ENTRY()) > critlen)) {
- if (purged_acs(tterm)) {
- acs_chars = ABSENT_STRING;
- SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n",
- critlen);
- changed = TRUE;
- }
- }
- if (!changed || ((len = FMT_ENTRY()) > critlen)) {
- int oldversion = tversion;
- tversion = V_BSD;
- SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n",
- critlen);
- len = FMT_ENTRY();
- if (len > critlen
- && kill_labels(tterm, len - critlen)) {
- SHOW_WHY("# (some labels capabilities suppressed to fit entry within %d bytes)\n",
- critlen);
- len = FMT_ENTRY();
- }
- if (len > critlen
- && kill_fkeys(tterm, len - critlen)) {
- SHOW_WHY("# (some function-key capabilities suppressed to fit entry within %d bytes)\n",
- critlen);
- len = FMT_ENTRY();
- }
- if (len > critlen) {
- (void) fprintf(stderr,
- "warning: %s entry is %d bytes long\n",
- _nc_first_name(tterm->term_names),
- len);
- SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n",
- len, legend);
- }
- tversion = oldversion;
- }
- set_attributes = save_sgr;
- *tterm = save_tterm;
- }
- } else if (!version_filter(STRING, STR_IDX(acs_chars))) {
- save_tterm = *tterm;
- if (purged_acs(tterm)) {
- len = FMT_ENTRY();
- }
- *tterm = save_tterm;
- }
- }
- void
- dump_uses(const char *name, bool infodump)
- /* dump "use=" clauses in the appropriate format */
- {
- char buffer[MAX_TERMINFO_LENGTH];
- if (outform == F_TERMCAP || outform == F_TCONVERR)
- trim_trailing();
- (void) sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name);
- wrap_concat(buffer);
- }
- int
- show_entry(void)
- {
- trim_trailing();
- (void) fputs(outbuf.text, stdout);
- putchar('\n');
- return (int) outbuf.used;
- }
- void
- compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
- TERMTYPE *tp GCC_UNUSED,
- bool quiet)
- /* compare two entries */
- {
- PredIdx i, j;
- NCURSES_CONST char *name;
- if (!quiet)
- fputs(" comparing booleans.\n", stdout);
- for_each_boolean(j, tp) {
- i = BoolIndirect(j);
- name = ExtBoolname(tp, i, bool_names);
- if (isObsolete(outform, name))
- continue;
- (*hook) (CMP_BOOLEAN, i, name);
- }
- if (!quiet)
- fputs(" comparing numbers.\n", stdout);
- for_each_number(j, tp) {
- i = NumIndirect(j);
- name = ExtNumname(tp, i, num_names);
- if (isObsolete(outform, name))
- continue;
- (*hook) (CMP_NUMBER, i, name);
- }
- if (!quiet)
- fputs(" comparing strings.\n", stdout);
- for_each_string(j, tp) {
- i = StrIndirect(j);
- name = ExtStrname(tp, i, str_names);
- if (isObsolete(outform, name))
- continue;
- (*hook) (CMP_STRING, i, name);
- }
- /* (void) fputs(" comparing use entries.\n", stdout); */
- (*hook) (CMP_USE, 0, "use");
- }
- #define NOTSET(s) ((s) == 0)
- /*
- * This bit of legerdemain turns all the terminfo variable names into
- * references to locations in the arrays Booleans, Numbers, and Strings ---
- * precisely what's needed.
- */
- #undef CUR
- #define CUR tp->
- static void
- set_obsolete_termcaps(TERMTYPE *tp)
- {
- #include "capdefaults.c"
- }
- /*
- * Convert an alternate-character-set string to canonical form: sorted and
- * unique.
- */
- void
- repair_acsc(TERMTYPE *tp)
- {
- if (VALID_STRING(acs_chars)) {
- size_t n, m;
- char mapped[256];
- char extra = 0;
- unsigned source;
- unsigned target;
- bool fix_needed = FALSE;
- for (n = 0, source = 0; acs_chars[n] != 0; n++) {
- target = UChar(acs_chars[n]);
- if (source >= target) {
- fix_needed = TRUE;
- break;
- }
- source = target;
- if (acs_chars[n + 1])
- n++;
- }
- if (fix_needed) {
- memset(mapped, 0, sizeof(mapped));
- for (n = 0; acs_chars[n] != 0; n++) {
- source = UChar(acs_chars[n]);
- if ((target = (unsigned char) acs_chars[n + 1]) != 0) {
- mapped[source] = (char) target;
- n++;
- } else {
- extra = (char) source;
- }
- }
- for (n = m = 0; n < sizeof(mapped); n++) {
- if (mapped[n]) {
- acs_chars[m++] = (char) n;
- acs_chars[m++] = mapped[n];
- }
- }
- if (extra)
- acs_chars[m++] = extra; /* garbage in, garbage out */
- acs_chars[m] = 0;
- }
- }
- }
|