X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=progs%2Fdump_entry.c;h=12bef2c279f2038b0750ef02091876681e2aaf27;hp=6187d5b13084e76c8364d1dbba14c171149d569d;hb=03f728e5bb3630a54fffc4a2ff2f8dbfcce9088e;hpb=55ccd2b959766810cf7db8d1c4462f338ce0afc8 diff --git a/progs/dump_entry.c b/progs/dump_entry.c index 6187d5b1..12bef2c2 100644 --- a/progs/dump_entry.c +++ b/progs/dump_entry.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright (c) 1998-2010,2011 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 * @@ -29,7 +29,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996 on * + * and: Thomas E. Dickey 1996 on * ****************************************************************************/ #define __INTERNAL_CAPS_VISIBLE @@ -39,12 +39,14 @@ #include "termsort.c" /* this C file is generated */ #include /* so is this */ -MODULE_ID("$Id: dump_entry.c,v 1.70 2005/07/23 20:03:30 tom Exp $") +MODULE_ID("$Id: dump_entry.c,v 1.95 2011/08/07 22:10:17 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; @@ -55,12 +57,12 @@ 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 height = 65535; /* max number of lines 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; @@ -141,6 +143,11 @@ _nc_leaks_dump_entry(void) } #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 */ @@ -150,18 +157,15 @@ nametrans(const char *name) 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]); + NameTrans(bool_from_termcap, boolcodes); break; case NUMBER: - if (num_from_termcap[np->nte_index]) - return (numcodes[np->nte_index]); + NameTrans(num_from_termcap, numcodes); break; case STRING: - if (str_from_termcap[np->nte_index]) - return (strcodes[np->nte_index]); + NameTrans(str_from_termcap, strcodes); break; } @@ -169,11 +173,17 @@ nametrans(const char *name) } void -dump_init(const char *version, int mode, int sort, int twidth, int traceval, +dump_init(const char *version, + int mode, + int sort, + int twidth, + int theight, + unsigned traceval, bool formatted) /* set up for entry display */ { width = twidth; + height = theight; pretty = formatted; /* versions */ @@ -198,7 +208,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool_names = boolnames; num_names = numnames; str_names = strnames; - separator = twidth ? ", " : ","; + separator = (twidth > 0 && theight > 1) ? ", " : ","; trailer = "\n\t"; break; @@ -206,7 +216,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool_names = boolfnames; num_names = numfnames; str_names = strfnames; - separator = twidth ? ", " : ","; + separator = (twidth > 0 && theight > 1) ? ", " : ","; trailer = "\n\t"; break; @@ -294,9 +304,9 @@ static void set_obsolete_termcaps(TERMTYPE *tp); * 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])) +#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) @@ -353,14 +363,17 @@ version_filter(PredType type, PredIdx idx) } break; +#define is_termcap(type) (OkIndex(idx, type##_from_termcap) && \ + type##_from_termcap[idx]) + case V_BSD: /* BSD */ switch (type) { case BOOLEAN: - return bool_from_termcap[idx]; + return is_termcap(bool); case NUMBER: - return num_from_termcap[idx]; + return is_termcap(num); case STRING: - return str_from_termcap[idx]; + return is_termcap(str); } break; } @@ -368,10 +381,18 @@ version_filter(PredType type, PredIdx idx) 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; } @@ -379,22 +400,22 @@ force_wrap(void) static void wrap_concat(const char *src) { - int need = strlen(src); - int want = strlen(separator) + need; + size_t need = strlen(src); + size_t want = strlen(separator) + need; if (column > INDENT - && column + want > width) { + && column + (int) want > width) { force_wrap(); } strcpy_DYN(&outbuf, src); strcpy_DYN(&outbuf, separator); - column += need; + 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 + 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 ":". @@ -425,43 +446,81 @@ termcap_length(const char *src) #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) { - int percent = 0; - int n; - bool if_then = strstr(src, "%?") != 0; - bool params = !if_then && (strlen(src) > 50) && (strstr(src, "%p") != 0); + bool percent = FALSE; + bool params = has_params(src); while (*src != '\0') { switch (*src) { case '\\': - percent = 0; + percent = FALSE; strncpy_DYN(&tmpbuf, src++, 1); break; case '%': - percent = 1; + percent = TRUE; break; case '?': /* "if" */ case 't': /* "then" */ case 'e': /* "else" */ if (percent) { - percent = 0; + percent = FALSE; 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); + /* 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, 3); - src += 3; + 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 { - for (n = 0; n <= level; n++) - strncpy_DYN(&tmpbuf, "\t", 1); + 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); } @@ -471,11 +530,10 @@ fmt_complex(char *src, int level) break; case ';': /* "endif" */ if (percent) { - percent = 0; + percent = FALSE; if (level > 1) { tmpbuf.text[tmpbuf.used - 1] = '\n'; - for (n = 0; n < level; n++) - strncpy_DYN(&tmpbuf, "\t", 1); + indent_DYN(&tmpbuf, level); strncpy_DYN(&tmpbuf, "%", 1); strncpy_DYN(&tmpbuf, src++, 1); return src; @@ -486,14 +544,18 @@ fmt_complex(char *src, int level) case 'p': if (percent && params) { tmpbuf.text[tmpbuf.used - 1] = '\n'; - for (n = 0; n <= level; n++) - strncpy_DYN(&tmpbuf, "\t", 1); + indent_DYN(&tmpbuf, level + 1); strncpy_DYN(&tmpbuf, "%", 1); } - percent = 0; + params = FALSE; + percent = FALSE; break; + case ' ': + strncpy_DYN(&tmpbuf, "\\s", 2); + ++src; + continue; default: - percent = 0; + percent = FALSE; break; } strncpy_DYN(&tmpbuf, src++, 1); @@ -502,6 +564,7 @@ fmt_complex(char *src, int level) } #define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) +#define EXTRA_CAP 20 int fmt_entry(TERMTYPE *tterm, @@ -512,7 +575,7 @@ fmt_entry(TERMTYPE *tterm, int numbers) { PredIdx i, j; - char buffer[MAX_TERMINFO_LENGTH]; + char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; char *capability; NCURSES_CONST char *name; int predval, len; @@ -537,14 +600,29 @@ fmt_entry(TERMTYPE *tterm, column = INDENT; /* FIXME: workaround to prevent empty lines */ } else { strcpy_DYN(&outbuf, tterm->term_names); + + /* + * Colon is legal in terminfo descriptions, but not in termcap. + */ + if (!infodump) { + char *p = outbuf.text; + while (*p) { + if (*p == ':') { + *p = '='; + } + ++p; + } + } strcpy_DYN(&outbuf, separator); - column = outbuf.used; - force_wrap(); + column = (int) outbuf.used; + if (height > 1) + force_wrap(); } for_each_boolean(j, tterm) { i = BoolIndirect(j); - name = ExtBoolname(tterm, i, bool_names); + name = ExtBoolname(tterm, (int) i, bool_names); + assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); if (!version_filter(BOOLEAN, i)) continue; @@ -562,12 +640,13 @@ fmt_entry(TERMTYPE *tterm, } } - if (column != INDENT) + if (column != INDENT && height > 1) force_wrap(); for_each_number(j, tterm) { i = NumIndirect(j); - name = ExtNumname(tterm, i, num_names); + name = ExtNumname(tterm, (int) i, num_names); + assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); if (!version_filter(NUMBER, i)) continue; @@ -587,12 +666,12 @@ fmt_entry(TERMTYPE *tterm, } } - if (column != INDENT) + if (column != INDENT && height > 1) force_wrap(); - len += num_bools - + num_values * 2 - + strlen(tterm->term_names) + 1; + len += (int) (num_bools + + num_values * 2 + + strlen(tterm->term_names) + 1); if (len & 1) len++; @@ -612,7 +691,9 @@ fmt_entry(TERMTYPE *tterm, for_each_string(j, tterm) { i = StrIndirect(j); - name = ExtStrname(tterm, i, str_names); + name = ExtStrname(tterm, (int) i, str_names); + assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); + capability = tterm->Strings[i]; if (!version_filter(STRING, i)) @@ -711,7 +792,7 @@ fmt_entry(TERMTYPE *tterm, } else { sprintf(buffer, "%s=%s", name, cv); } - len += strlen(capability) + 1; + len += (int) strlen(capability) + 1; WRAP_CONCAT; } else { char *src = _nc_tic_expand(capability, @@ -727,7 +808,7 @@ fmt_entry(TERMTYPE *tterm, } else { strcpy_DYN(&tmpbuf, src); } - len += strlen(capability) + 1; + len += (int) strlen(capability) + 1; wrap_concat(tmpbuf.text); outcount = TRUE; } @@ -736,19 +817,19 @@ fmt_entry(TERMTYPE *tterm, if (capability != tterm->Strings[i]) free(capability); } - len += num_strings * 2; + 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. + * 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 (memory_lock) { + if (VALID_STRING(memory_lock)) { (void) sprintf(buffer, "meml=%s", memory_lock); WRAP_CONCAT; } - if (memory_unlock) { + if (VALID_STRING(memory_unlock)) { (void) sprintf(buffer, "memu=%s", memory_unlock); WRAP_CONCAT; } @@ -786,7 +867,7 @@ fmt_entry(TERMTYPE *tterm, */ if (outcount) { bool trimmed = FALSE; - j = outbuf.used; + j = (PredIdx) outbuf.used; if (j >= 2 && outbuf.text[j - 1] == '\t' && outbuf.text[j - 2] == '\n') { @@ -803,6 +884,7 @@ fmt_entry(TERMTYPE *tterm, if (trimmed) { outbuf.text[outbuf.used] = '\0'; column = oldcol; + strcpy_DYN(&outbuf, " "); } } #if 0 @@ -825,7 +907,7 @@ fmt_entry(TERMTYPE *tterm, static bool kill_string(TERMTYPE *tterm, char *cap) { - int n; + unsigned n; for (n = 0; n < NUM_STRINGS(tterm); ++n) { if (cap == tterm->Strings[n]) { tterm->Strings[n] = ABSENT_STRING; @@ -868,7 +950,7 @@ kill_labels(TERMTYPE *tterm, int target) sprintf(name, "lf%d", n); if ((cap = find_string(tterm, name)) != ABSENT_STRING && kill_string(tterm, cap)) { - target -= (strlen(cap) + 5); + target -= (int) (strlen(cap) + 5); ++result; if (target < 0) break; @@ -893,7 +975,7 @@ kill_fkeys(TERMTYPE *tterm, int target) sprintf(name, "kf%d", n); if ((cap = find_string(tterm, name)) != ABSENT_STRING && kill_string(tterm, cap)) { - target -= (strlen(cap) + 5); + target -= (int) (strlen(cap) + 5); ++result; if (target < 0) break; @@ -902,23 +984,66 @@ kill_fkeys(TERMTYPE *tterm, int target) 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, \ - (already_used > 0), \ + 0, \ suppress_untranslatable, \ infodump, numbers) -#define SHOW_WHY if (!already_used) PRINTF +#define SHOW_WHY PRINTF -int +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 already_used, int numbers, PredFunc pred) -/* dump a single entry */ { + TERMTYPE save_tterm; int len, critlen; const char *legend; bool infodump; @@ -933,19 +1058,19 @@ dump_entry(TERMTYPE *tterm, legend = "terminfo"; infodump = TRUE; } - critlen -= already_used; save_sgr = set_attributes; - save_acsc = acs_chars; - if (((len = FMT_ENTRY()) > critlen) + if ((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) { + if (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 @@ -958,9 +1083,9 @@ dump_entry(TERMTYPE *tterm, * Extended names are most likely function-key definitions. Drop * those first. */ - int n; + unsigned n; for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { - char *name = ExtStrname(tterm, n, strnames); + const char *name = ExtStrname(tterm, (int) n, strnames); if (VALID_STRING(tterm->Strings[n])) { set_attributes = ABSENT_STRING; @@ -971,7 +1096,7 @@ dump_entry(TERMTYPE *tterm, critlen); } changed = TRUE; - if ((len = FMT_ENTRY()) <= critlen) + if (FMT_ENTRY() <= critlen) break; } } @@ -982,15 +1107,15 @@ dump_entry(TERMTYPE *tterm, critlen); changed = TRUE; } - if (!changed || ((len = FMT_ENTRY()) > critlen)) { - if (VALID_STRING(acs_chars)) { + if (!changed || (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)) { + if (!changed || (FMT_ENTRY() > critlen)) { int oldversion = tversion; tversion = V_BSD; @@ -1010,40 +1135,74 @@ dump_entry(TERMTYPE *tterm, critlen); len = FMT_ENTRY(); } - if (len > critlen && !already_used) { + 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", - already_used + len, legend); + len, legend); } tversion = oldversion; } set_attributes = save_sgr; - acs_chars = save_acsc; + *tterm = save_tterm; + } + } else if (!version_filter(STRING, STR_IDX(acs_chars))) { + save_tterm = *tterm; + if (purged_acs(tterm)) { + (void) FMT_ENTRY(); } + *tterm = save_tterm; } - - (void) fputs(outbuf.text, stdout); - return len; } -int +void dump_uses(const char *name, bool infodump) /* dump "use=" clauses in the appropriate format */ { char buffer[MAX_TERMINFO_LENGTH]; - strcpy_DYN(&outbuf, 0); + 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 any remaining whitespace. + */ + if (outbuf.used != 0) { + bool infodump = (outform != F_TERMCAP && outform != F_TCONVERR); + char delim = infodump ? ',' : ':'; + int j; + + for (j = (int) outbuf.used - 1; j > 0; --j) { + char ch = outbuf.text[j]; + if (ch == '\n') { + ; + } else if (isspace(UChar(ch))) { + outbuf.used = j; + } else if (!infodump && ch == '\\') { + outbuf.used = j; + } else if (ch == delim && (j == 0 || outbuf.text[j - 1] != '\\')) { + outbuf.used = (j + 1); + } else { + break; + } + } + outbuf.text[outbuf.used] = '\0'; + } (void) fputs(outbuf.text, stdout); - return outbuf.used; + putchar('\n'); + return (int) outbuf.used; } void -compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), +compare_entry(PredHook hook, TERMTYPE *tp GCC_UNUSED, bool quiet) /* compare two entries */ @@ -1055,7 +1214,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), fputs(" comparing booleans.\n", stdout); for_each_boolean(j, tp) { i = BoolIndirect(j); - name = ExtBoolname(tp, i, bool_names); + name = ExtBoolname(tp, (int) i, bool_names); if (isObsolete(outform, name)) continue; @@ -1067,7 +1226,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), fputs(" comparing numbers.\n", stdout); for_each_number(j, tp) { i = NumIndirect(j); - name = ExtNumname(tp, i, num_names); + name = ExtNumname(tp, (int) i, num_names); if (isObsolete(outform, name)) continue; @@ -1079,7 +1238,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), fputs(" comparing strings.\n", stdout); for_each_string(j, tp) { i = StrIndirect(j); - name = ExtStrname(tp, i, str_names); + name = ExtStrname(tp, (int) i, str_names); if (isObsolete(outform, name)) continue; @@ -1124,7 +1283,7 @@ repair_acsc(TERMTYPE *tp) bool fix_needed = FALSE; for (n = 0, source = 0; acs_chars[n] != 0; n++) { - target = acs_chars[n]; + target = UChar(acs_chars[n]); if (source >= target) { fix_needed = TRUE; break; @@ -1136,17 +1295,17 @@ repair_acsc(TERMTYPE *tp) if (fix_needed) { memset(mapped, 0, sizeof(mapped)); for (n = 0; acs_chars[n] != 0; n++) { - source = acs_chars[n]; + source = UChar(acs_chars[n]); if ((target = (unsigned char) acs_chars[n + 1]) != 0) { - mapped[source] = target; + mapped[source] = (char) target; n++; } else { - extra = source; + extra = (char) source; } } for (n = m = 0; n < sizeof(mapped); n++) { if (mapped[n]) { - acs_chars[m++] = n; + acs_chars[m++] = (char) n; acs_chars[m++] = mapped[n]; } }