📄 dump_entry.c
字号:
/**************************************************************************** * Copyright (c) 1998-2004,2005 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.70 2005/07/23 20:03:30 tom Exp $")#define INDENT 8#define DISCARD(string) string = ABSENT_STRING#define PRINTF (void) printftypedef 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 char *save_acsc;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])#endifstatic voidstrncpy_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 voidstrcpy_DYN(DYNBUF * dst, const char *src){ if (src == 0) { dst->used = 0; strcpy_DYN(dst, ""); } else { strncpy_DYN(dst, src, strlen(src)); }}#if NO_LEAKSstatic voidfree_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);}#endifNCURSES_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: if (bool_from_termcap[np->nte_index]) return (boolcodes[np->nte_index]); break; case NUMBER: if (num_from_termcap[np->nte_index]) return (numcodes[np->nte_index]); break; case STRING: if (str_from_termcap[np->nte_index]) return (strcodes[np->nte_index]); break; } return (0);}voiddump_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 intdump_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) (&(name) - &(CUR Booleans[0]))#define NUM_IDX(name) (&(name) - &(CUR Numbers[0]))#define STR_IDX(name) (&(name) - &(CUR Strings[0]))static boolversion_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; case V_BSD: /* BSD */ switch (type) { case BOOLEAN: return bool_from_termcap[idx]; case NUMBER: return num_from_termcap[idx]; case STRING: return str_from_termcap[idx]; } break; } return (FALSE); /* pacify the compiler */}static voidforce_wrap(void){ oldcol = column; strcpy_DYN(&outbuf, trailer); column = INDENT;}static voidwrap_concat(const char *src){ int need = strlen(src); int want = strlen(separator) + need; if (column > INDENT && column + want > width) { force_wrap(); } strcpy_DYN(&outbuf, src); strcpy_DYN(&outbuf, separator); column += 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_LENGTHstatic inttermcap_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)#endifstatic char *fmt_complex(char *src, int level){ int percent = 0; int n; bool if_then = strstr(src, "%?") != 0; bool params = !if_then && (strlen(src) > 50) && (strstr(src, "%p") != 0); while (*src != '\0') { switch (*src) { case '\\': percent = 0; strncpy_DYN(&tmpbuf, src++, 1); break; case '%': percent = 1; break; case '?': /* "if" */ case 't': /* "then" */ case 'e': /* "else" */ if (percent) { percent = 0; tmpbuf.text[tmpbuf.used - 1] = '\n'; /* treat a "%e%?" as else-if, on the same level */ if (!strncmp(src, "e%?", 3)) { for (n = 0; n < level; n++) strncpy_DYN(&tmpbuf, "\t", 1); strncpy_DYN(&tmpbuf, "%", 1); strncpy_DYN(&tmpbuf, src, 3); src += 3; } else { for (n = 0; n <= level; n++) strncpy_DYN(&tmpbuf, "\t", 1); strncpy_DYN(&tmpbuf, "%", 1); strncpy_DYN(&tmpbuf, src, 1); if (*src++ == '?') { src = fmt_complex(src, level + 1); } else if (level == 1) { _nc_warning("%%%c without %%?", *src); } } continue; } break; case ';': /* "endif" */ if (percent) { percent = 0; if (level > 1) { tmpbuf.text[tmpbuf.used - 1] = '\n'; for (n = 0; n < level; n++) strncpy_DYN(&tmpbuf, "\t", 1); 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'; for (n = 0; n <= level; n++) strncpy_DYN(&tmpbuf, "\t", 1); strncpy_DYN(&tmpbuf, "%", 1); } percent = 0; break; default: percent = 0; break; } strncpy_DYN(&tmpbuf, src++, 1); } return src;}#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap)intfmt_entry(TERMTYPE *tterm, PredFunc pred, bool content_only, bool suppress_untranslatable, bool infodump, int numbers){ PredIdx i, j; char buffer[MAX_TERMINFO_LENGTH]; 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 = outbuf.used; force_wrap(); } for_each_boolean(j, tterm) { i = BoolIndirect(j); name = ExtBoolname(tterm, i, bool_names); 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); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -