X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=progs%2Ftic.c;h=717a1fb35126bbb79b2544b03907c2c810d0d933;hp=4881d655322b7e4674111430e854a253b4ada21e;hb=64f44b13d30e0a7bc2921a9d43755423f81564fd;hpb=70e1890695998ac225c5a2a3006500372e1987a1;ds=inline diff --git a/progs/tic.c b/progs/tic.c index 4881d655..717a1fb3 100644 --- a/progs/tic.c +++ b/progs/tic.c @@ -46,7 +46,7 @@ #include #include -MODULE_ID("$Id: tic.c,v 1.165 2012/03/24 22:07:10 tom Exp $") +MODULE_ID("$Id: tic.c,v 1.180 2012/12/08 22:17:22 tom Exp $") #define STDIN_NAME "" @@ -57,6 +57,7 @@ static FILE *tmp_fp; static bool capdump = FALSE; /* running as infotocap? */ static bool infodump = FALSE; /* running as captoinfo? */ static bool showsummary = FALSE; +static char **namelst = 0; static const char *to_remove; static void (*save_check_termtype) (TERMTYPE *, bool); @@ -105,8 +106,10 @@ free_namelist(char **src) #endif static void -cleanup(char **namelst GCC_UNUSED) +cleanup(void) { + int rc; + #if NO_LEAKS free_namelist(namelst); #endif @@ -114,10 +117,12 @@ cleanup(char **namelst GCC_UNUSED) fclose(tmp_fp); if (to_remove != 0) { #if HAVE_REMOVE - remove(to_remove); + rc = remove(to_remove); #else - unlink(to_remove); + rc = unlink(to_remove); #endif + if (rc != 0) + perror(to_remove); } } @@ -125,7 +130,6 @@ static void failed(const char *msg) { perror(msg); - cleanup((char **) 0); ExitProgram(EXIT_FAILURE); } @@ -294,8 +298,10 @@ put_translate(int c) if (in_name) { if (used + 1 >= have) { have += 132; - namebuf = typeRealloc(char, have, namebuf); - suffix = typeRealloc(char, have, suffix); + if ((namebuf = typeRealloc(char, have, namebuf)) == 0) + failed("put_translate namebuf"); + if ((suffix = typeRealloc(char, have, suffix)) == 0) + failed("put_translate suffix"); } if (c == '\n' || c == '@') { namebuf[used++] = '\0'; @@ -374,9 +380,11 @@ open_tempfile(char *filename) _nc_STRCPY(filename, "/tmp/XXXXXX", PATH_MAX); #if HAVE_MKSTEMP { + int oldmask = umask(077); int fd = mkstemp(filename); if (fd >= 0) result = fdopen(fd, "w"); + umask(oldmask); } #else if (tmpnam(filename) != 0) @@ -488,7 +496,8 @@ make_namelist(char *src) } } if (pass == 1) { - dst = typeCalloc(char *, nn + 1); + if ((dst = typeCalloc(char *, nn + 1)) == 0) + failed("make_namelist"); rewind(fp); } } @@ -510,8 +519,10 @@ make_namelist(char *src) if (mark == '\0') break; } - if (pass == 1) - dst = typeCalloc(char *, nn + 1); + if (pass == 1) { + if ((dst = typeCalloc(char *, nn + 1)) == 0) + failed("make_namelist"); + } } } if (showsummary && (dst != 0)) { @@ -550,6 +561,8 @@ valid_db_path(const char *nominal) size_t need = strlen(nominal) + sizeof(suffix); char *result = malloc(need); + if (result == 0) + failed("valid_db_path"); _nc_STRCPY(result, nominal, need); if (strcmp(result + need - sizeof(suffix), suffix)) { _nc_STRCAT(result, suffix, need); @@ -667,7 +680,6 @@ main(int argc, char *argv[]) bool limited = TRUE; char *tversion = (char *) NULL; const char *source_file = "terminfo"; - char **namelst = 0; char *outdir = (char *) NULL; bool check_only = FALSE; bool suppress_untranslatable = FALSE; @@ -675,6 +687,7 @@ main(int argc, char *argv[]) log_fp = stderr; _nc_progname = _nc_rootname(argv[0]); + atexit(cleanup); if ((infodump = same_program(_nc_progname, PROG_CAPTOINFO)) != FALSE) { outform = F_TERMINFO; @@ -764,7 +777,6 @@ main(int argc, char *argv[]) break; case 'V': puts(curses_version()); - cleanup(namelst); ExitProgram(EXIT_SUCCESS); case 'c': check_only = TRUE; @@ -836,7 +848,6 @@ main(int argc, char *argv[]) (void) fprintf(stderr, "%s: Sorry, -e can't be used without -I or -C\n", _nc_progname); - cleanup(namelst); ExitProgram(EXIT_FAILURE); } #endif /* HAVE_BIG_CORE */ @@ -879,7 +890,6 @@ main(int argc, char *argv[]) _nc_progname, _nc_progname, usage_string); - cleanup(namelst); ExitProgram(EXIT_FAILURE); } } @@ -918,7 +928,6 @@ main(int argc, char *argv[]) /* do use resolution */ if (check_only || (!infodump && !capdump) || forceresolve) { if (!_nc_resolve_uses2(TRUE, literal) && !check_only) { - cleanup(namelst); ExitProgram(EXIT_FAILURE); } } @@ -1013,7 +1022,6 @@ main(int argc, char *argv[]) else fprintf(log_fp, "No entries written\n"); } - cleanup(namelst); ExitProgram(EXIT_SUCCESS); } @@ -1217,13 +1225,18 @@ check_cursor(TERMTYPE *tp) int count; char *list[4]; + /* it is rare to have an insert-line feature without a matching delete */ + ANDMISSING(parm_insert_line, insert_line); + ANDMISSING(parm_delete_line, delete_line); + ANDMISSING(parm_insert_line, parm_delete_line); + /* if we have a parameterized form, then the non-parameterized is easy */ ANDMISSING(parm_down_cursor, cursor_down); ANDMISSING(parm_up_cursor, cursor_up); ANDMISSING(parm_left_cursor, cursor_left); ANDMISSING(parm_right_cursor, cursor_right); - /* Given any of a set of cursor movement, the whole set should be present. + /* Given any of a set of cursor movement, the whole set should be present. * Technically this is not true (we could use cursor_address to fill in * unsupported controls), but it is likely. */ @@ -1390,6 +1403,12 @@ check_keypad(TERMTYPE *tp) if (*show != '\0') _nc_warning("vt100 keypad map incomplete:%s", show); } + + /* + * These warnings are useful for consistency checks - it is possible that + * there are real terminals with mismatches in these + */ + ANDMISSING(key_ic, key_dc); } static void @@ -1418,6 +1437,72 @@ check_printer(TERMTYPE *tp) ANDMISSING(parm_up_micro, micro_up); } +static bool +uses_SGR_39_49(const char *value) +{ + return (strstr(value, "39;49") != 0 + || strstr(value, "49;39") != 0); +} + +/* + * Check consistency of termcap extensions related to "screen". + */ +static void +check_screen(TERMTYPE *tp) +{ + if (_nc_user_definable) { + int have_XT = tigetflag("XT"); + int have_XM = tigetflag("XM"); + int have_bce = back_color_erase; + bool have_kmouse = FALSE; + bool use_sgr_39_49 = FALSE; + char *name = _nc_first_name(tp->term_names); + + if (!VALID_BOOLEAN(have_bce)) { + have_bce = FALSE; + } + if (!VALID_BOOLEAN(have_XM)) { + have_XM = FALSE; + } + if (!VALID_BOOLEAN(have_XT)) { + have_XT = FALSE; + } + if (VALID_STRING(key_mouse)) { + have_kmouse = !strcmp("\033[M", key_mouse); + } + if (VALID_STRING(orig_colors)) { + use_sgr_39_49 = uses_SGR_39_49(orig_colors); + } else if (VALID_STRING(orig_pair)) { + use_sgr_39_49 = uses_SGR_39_49(orig_pair); + } + + if (have_XM && have_XT) { + _nc_warning("Screen's XT capability conflicts with XM"); + } else if (have_XT + && strstr(name, "screen") != 0 + && strchr(name, '.') != 0) { + _nc_warning("Screen's \"screen\" entries should not have XT set"); + } else if (have_XT) { + if (!have_kmouse && have_bce) { + if (VALID_STRING(key_mouse)) { + _nc_warning("Value of kmous inconsistent with screen's usage"); + } else { + _nc_warning("Expected kmous capability with XT"); + } + } + if (!have_bce && max_colors > 0) + _nc_warning("Expected bce capability with XT"); + if (!use_sgr_39_49 && have_bce && max_colors > 0) + _nc_warning("Expected orig_colors capability with XT to have 39/49 parameters"); + if (VALID_STRING(to_status_line)) + _nc_warning("\"tsl\" capability is redundant, given XT"); + } else { + if (have_kmouse && !have_XM) + _nc_warning("Expected XT to be set, given kmous"); + } + } +} + /* * Returns the expected number of parameters for the given capability. */ @@ -1729,7 +1814,7 @@ static void show_where(unsigned level) { if (_nc_tracing >= DEBUG_LEVEL(level)) { - char my_name[256]; + char my_name[MAX_NAME_SIZE]; _nc_get_type(my_name); _tracef("\"%s\", line %d, '%s'", _nc_get_source(), @@ -1741,6 +1826,58 @@ show_where(unsigned level) #define show_where(level) /* nothing */ #endif +typedef struct { + int keycode; + const char *name; + const char *value; +} NAME_VALUE; + +static NAME_VALUE * +get_fkey_list(TERMTYPE *tp) +{ + NAME_VALUE *result = typeMalloc(NAME_VALUE, NUM_STRINGS(tp) + 1); + const struct tinfo_fkeys *all_fkeys = _nc_tinfo_fkeys; + int used = 0; + int j; + + if (result == 0) + failed("get_fkey_list"); + + for (j = 0; all_fkeys[j].code; j++) { + char *a = tp->Strings[all_fkeys[j].offset]; + if (VALID_STRING(a)) { + result[used].keycode = (int) all_fkeys[j].code; + result[used].name = strnames[all_fkeys[j].offset]; + result[used].value = a; + ++used; + } + } +#if NCURSES_XNAMES + for (j = STRCOUNT; j < NUM_STRINGS(tp); ++j) { + const char *name = ExtStrname(tp, j, strnames); + if (*name == 'k') { + result[used].keycode = -1; + result[used].name = name; + result[used].value = tp->Strings[j]; + ++used; + } + } +#endif + result[used].keycode = 0; + return result; +} + +static void +show_fkey_name(NAME_VALUE * data) +{ + if (data->keycode > 0) { + fprintf(stderr, " %s", keyname(data->keycode)); + fprintf(stderr, " (capability \"%s\")", data->name); + } else { + fprintf(stderr, " capability \"%s\"", data->name); + } +} + /* other sanity-checks (things that we don't want in the normal * logic that reads a terminfo entry) */ @@ -1749,7 +1886,6 @@ check_termtype(TERMTYPE *tp, bool literal) { bool conflict = FALSE; unsigned j, k; - char fkeys[STRCOUNT]; /* * A terminal entry may contain more than one keycode assigned to @@ -1757,41 +1893,47 @@ check_termtype(TERMTYPE *tp, bool literal) * return one (the last one assigned). */ if (!(_nc_syntax == SYN_TERMCAP && capdump)) { - memset(fkeys, 0, sizeof(fkeys)); - for (j = 0; _nc_tinfo_fkeys[j].code; j++) { - char *a = tp->Strings[_nc_tinfo_fkeys[j].offset]; + char *check = calloc((size_t) (NUM_STRINGS(tp) + 1), sizeof(char)); + NAME_VALUE *given = get_fkey_list(tp); + + if (check == 0) + failed("check_termtype"); + + for (j = 0; given[j].keycode; ++j) { + const char *a = given[j].value; bool first = TRUE; - if (!VALID_STRING(a)) - continue; - for (k = j + 1; _nc_tinfo_fkeys[k].code; k++) { - char *b = tp->Strings[_nc_tinfo_fkeys[k].offset]; - if (!VALID_STRING(b) - || fkeys[k]) + + for (k = j + 1; given[k].keycode; k++) { + const char *b = given[k].value; + if (check[k]) continue; if (!_nc_capcmp(a, b)) { - fkeys[j] = 1; - fkeys[k] = 1; + check[j] = 1; + check[k] = 1; if (first) { if (!conflict) { _nc_warning("Conflicting key definitions (using the last)"); conflict = TRUE; } - fprintf(stderr, "... %s is the same as %s", - keyname((int) _nc_tinfo_fkeys[j].code), - keyname((int) _nc_tinfo_fkeys[k].code)); + fprintf(stderr, "..."); + show_fkey_name(given + j); + fprintf(stderr, " is the same as"); + show_fkey_name(given + k); first = FALSE; } else { - fprintf(stderr, ", %s", - keyname((int) _nc_tinfo_fkeys[k].code)); + fprintf(stderr, ", "); + show_fkey_name(given + k); } } } if (!first) fprintf(stderr, "\n"); } + free(given); + free(check); } - for (j = 0; j < NUM_STRINGS(tp); j++) { + for_each_string(j, tp) { char *a = tp->Strings[j]; if (VALID_STRING(a)) check_params(tp, ExtStrname(tp, (int) j, strnames), a); @@ -1802,6 +1944,7 @@ check_termtype(TERMTYPE *tp, bool literal) check_cursor(tp); check_keypad(tp); check_printer(tp); + check_screen(tp); /* * These may be mismatched because the terminal description relies on