X-Git-Url: http://ncurses.scripts.mit.edu/?a=blobdiff_plain;f=progs%2Ftic.c;h=93a0b4916e269ffbd3648ebc137d5a5990044520;hb=2632b47fdcf4dcd101962c92acafaac69630388f;hp=a6281b32bbc11233a5cd440495e925db5beb3c59;hpb=643ec2bf782cd02efafe3ccdeaea8920a404645e;p=ncurses.git diff --git a/progs/tic.c b/progs/tic.c index a6281b32..93a0b491 100644 --- a/progs/tic.c +++ b/progs/tic.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 2018-2021,2022 Thomas E. Dickey * * Copyright 1998-2017,2018 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * @@ -49,7 +49,7 @@ #include #include -MODULE_ID("$Id: tic.c,v 1.302 2021/09/04 10:29:59 tom Exp $") +MODULE_ID("$Id: tic.c,v 1.320 2022/09/17 18:55:28 tom Exp $") #define STDIN_NAME "" @@ -312,9 +312,9 @@ put_translate(int c) if (used + 1 >= have) { have += 132; - if ((namebuf = typeRealloc(char, have, namebuf)) == 0) + if ((namebuf = typeRealloc(char, have, namebuf)) == NULL) failed("put_translate namebuf"); - if ((suffix = typeRealloc(char, have, suffix)) == 0) + if ((suffix = typeRealloc(char, have, suffix)) == NULL) failed("put_translate suffix"); } if (c == '\n' || c == '@') { @@ -413,12 +413,12 @@ copy_input(FILE *source, const char *filename, char *alt_file) FILE *target; int ch; - if (alt_file == 0) + if (alt_file == NULL) alt_file = my_altfile; - if (source == 0) { + if (source == NULL) { failed("copy_input (source)"); - } else if ((target = open_tempfile(alt_file)) == 0) { + } else if ((target = open_tempfile(alt_file)) == NULL) { failed("copy_input (target)"); } else { clearerr(source); @@ -468,7 +468,7 @@ open_input(const char *filename, char *alt_file) } else { fp = safe_fopen(filename, "r"); - if (fp == 0) { + if (fp == NULL) { fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename); ExitProgram(EXIT_FAILURE); } @@ -495,7 +495,7 @@ make_namelist(char *src) unsigned pass, n, nn; char buffer[BUFSIZ]; - if (src == 0) { + if (src == NULL) { /* EMPTY */ ; } else if (strchr(src, '/') != 0) { /* a filename */ FILE *fp = open_input(src, (char *) 0); @@ -512,7 +512,7 @@ make_namelist(char *src) } } if (pass == 1) { - if ((dst = typeCalloc(char *, nn + 1)) == 0) + if ((dst = typeCalloc(char *, nn + 1)) == NULL) failed("make_namelist"); rewind(fp); } @@ -536,7 +536,7 @@ make_namelist(char *src) break; } if (pass == 1) { - if ((dst = typeCalloc(char *, nn + 1)) == 0) + if ((dst = typeCalloc(char *, nn + 1)) == NULL) failed("make_namelist"); } } @@ -578,7 +578,7 @@ valid_db_path(const char *nominal) size_t need = strlen(nominal) + sizeof(suffix); char *result = malloc(need); - if (result == 0) + if (result == NULL) failed("valid_db_path"); _nc_STRCPY(result, nominal, need); if (strcmp(result + need - sizeof(suffix), suffix)) { @@ -643,8 +643,8 @@ show_databases(const char *outdir) char *result; const char *tried = 0; - if (outdir == 0) { - outdir = _nc_tic_dir(0); + if (outdir == NULL) { + outdir = _nc_tic_dir(NULL); } if ((result = valid_db_path(outdir)) != 0) { printf("%s\n", result); @@ -682,7 +682,6 @@ int main(int argc, char *argv[]) { char my_tmpname[PATH_MAX]; - char my_altfile[PATH_MAX]; int v_opt = -1; int smart_defaults = TRUE; char *termcap; @@ -723,7 +722,8 @@ main(int argc, char *argv[]) sortmode = S_TERMCAP; } #if NCURSES_XNAMES - use_extended_names(FALSE); + /* set this directly to avoid interaction with -v and -D options */ + _nc_user_definable = FALSE; #endif _nc_strict_bsd = 0; @@ -776,7 +776,7 @@ main(int argc, char *argv[]) break; case 'D': debug_level = VtoTrace(v_opt); - set_trace_level(debug_level); + use_verbosity(debug_level); show_databases(outdir); ExitProgram(EXIT_SUCCESS); break; @@ -854,7 +854,6 @@ main(int argc, char *argv[]) _nc_disable_period = TRUE; /* FALLTHRU */ case 'x': - use_extended_names(TRUE); using_extensions = TRUE; break; #endif @@ -864,8 +863,23 @@ main(int argc, char *argv[]) last_opt = this_opt; } + /* + * If the -v option is set, it may override the $NCURSES_TRACE environment + * variable, e.g., for -v3 and up. + */ debug_level = VtoTrace(v_opt); - set_trace_level(debug_level); + use_verbosity(debug_level); + + /* + * Do this after setting debug_level, since the function calls START_TRACE, + * which uses the $NCURSES_TRACE environment variable if _nc_tracing bits + * for tracing are zero. + */ +#if NCURSES_XNAMES + if (using_extensions) { + use_extended_names(TRUE); + } +#endif if (_nc_tracing) { save_check_termtype = _nc_check_termtype2; @@ -932,7 +946,8 @@ main(int argc, char *argv[]) } } - if (tmp_fp == 0) { + if (tmp_fp == NULL) { + char my_altfile[PATH_MAX]; tmp_fp = open_input(source_file, my_altfile); if (!strcmp(source_file, "-")) { source_file = STDIN_NAME; @@ -1081,7 +1096,7 @@ main(int argc, char *argv[]) if (total != 0) fprintf(log_fp, "%d entries written to %s\n", total, - _nc_tic_dir((char *) 0)); + _nc_tic_dir(NULL)); else fprintf(log_fp, "No entries written\n"); } @@ -1218,7 +1233,7 @@ check_colors(TERMTYPE2 *tp) char *value; if ((max_colors > 0) != (max_pairs > 0) - || ((max_colors > max_pairs) && (initialize_pair == 0))) + || ((max_colors > max_pairs) && !VALID_STRING(initialize_pair))) _nc_warning("inconsistent values for max_colors (%d) and max_pairs (%d)", max_colors, max_pairs); @@ -1338,7 +1353,7 @@ check_ansi_cursor(char *list[4]) if (j != k && !strcmp(list[j], list[k])) { char *value = _nc_tic_expand(list[k], TRUE, 0); - _nc_warning("repeated cursor control %s\n", value); + _nc_warning("repeated cursor control %s", value); repeated = TRUE; } } @@ -1367,19 +1382,19 @@ check_ansi_cursor(char *list[4]) continue; if (memcmp(list[j], up, prefix)) { char *value = _nc_tic_expand(list[j], TRUE, 0); - _nc_warning("inconsistent prefix for %s\n", value); + _nc_warning("inconsistent prefix for %s", value); continue; } if (strlen(list[j]) < suffix) { char *value = _nc_tic_expand(list[j], TRUE, 0); - _nc_warning("inconsistent length for %s, expected %d\n", + _nc_warning("inconsistent length for %s, expected %d", value, (int) suffix + 1); continue; } want = "BADC"[j]; if (list[j][suffix] != want) { char *value = _nc_tic_expand(list[j], TRUE, 0); - _nc_warning("inconsistent suffix for %s, expected %c, have %c\n", + _nc_warning("inconsistent suffix for %s, expected %c, have %c", value, want, list[j][suffix]); } } @@ -1412,7 +1427,7 @@ check_cursor(TERMTYPE2 *tp) check_noaddress(tp, "hard_copy"); } else if (generic_type) { check_noaddress(tp, "generic_type"); - } else if (strchr(tp->term_names, '+') == 0) { + } else if (strchr(tp->term_names, '+') == NULL) { int y = 0; int x = 0; if (PRESENT(column_address)) @@ -1669,20 +1684,10 @@ check_printer(TERMTYPE2 *tp) ANDMISSING(start_char_set_def, stop_char_set_def); #endif - /* if we have a parameterized form, then the non-parameterized is easy */ -#if defined(set_bottom_margin_parm) && defined(set_bottom_margin) - ANDMISSING(set_bottom_margin_parm, set_bottom_margin); -#endif -#if defined(set_left_margin_parm) && defined(set_left_margin) - ANDMISSING(set_left_margin_parm, set_left_margin); -#endif -#if defined(set_right_margin_parm) && defined(set_right_margin) - ANDMISSING(set_right_margin_parm, set_right_margin); -#endif -#if defined(set_top_margin_parm) && defined(set_top_margin) - ANDMISSING(set_top_margin_parm, set_top_margin); -#endif - + /* + * If we have a parameterized form, then the non-parameterized is easy. + * note: parameterized/non-parameterized margin settings are unrelated. + */ #if defined(parm_down_micro) && defined(micro_down) ANDMISSING(parm_down_micro, micro_down); #endif @@ -1721,7 +1726,7 @@ check_screen(TERMTYPE2 *tp) char *name = _nc_first_name(tp->term_names); bool is_screen = !strncmp(name, "screen", 6); bool screen_base = (is_screen - && strchr(name, '.') == 0); + && strchr(name, '.') == NULL); if (!VALID_BOOLEAN(have_bce)) { have_bce = FALSE; @@ -1751,6 +1756,8 @@ check_screen(TERMTYPE2 *tp) } else if (have_XT && screen_base) { _nc_warning("screen's \"screen\" entries should not have XT set"); } else if (have_XT) { + char *s; + if (!have_kmouse && is_screen) { if (VALID_STRING(key_mouse)) { _nc_warning("value of kmous inconsistent with screen's usage"); @@ -1766,12 +1773,14 @@ check_screen(TERMTYPE2 *tp) "to have 39/49 parameters", name_39_49); } } - if (VALID_STRING(to_status_line)) + if (VALID_STRING(to_status_line) + && (s = strchr(to_status_line, ';')) != NULL + && *++s == '\0') _nc_warning("\"tsl\" capability is redundant, given XT"); } else { if (have_kmouse && !have_XM - && !screen_base && strchr(name, '+') == 0) { + && !screen_base && strchr(name, '+') == NULL) { _nc_warning("expected XT to be set, given kmous"); } } @@ -1980,9 +1989,24 @@ check_params(TERMTYPE2 *tp, const char *name, const char *value, int extended) bool params[1 + NUM_PARM]; const char *s = value; +#ifdef set_left_margin_parm + if (!strcmp(name, "smgrp") + && !VALID_STRING(set_left_margin_parm)) + expected = 2; +#endif +#ifdef set_right_margin_parm + if (!strcmp(name, "smglp") + && !VALID_STRING(set_right_margin_parm)) + expected = 2; +#endif #ifdef set_top_margin_parm if (!strcmp(name, "smgbp") - && set_top_margin_parm == 0) + && !VALID_STRING(set_top_margin_parm)) + expected = 2; +#endif +#ifdef set_bottom_margin_parm + if (!strcmp(name, "smgtp") + && !VALID_STRING(set_bottom_margin_parm)) expected = 2; #endif @@ -2085,10 +2109,13 @@ check_params(TERMTYPE2 *tp, const char *name, const char *value, int extended) for (n = 0; n < limit; ++n) { _nc_reset_tparm(NULL); (void) TPARM_9(value, n, n, n, n, n, n, n, n, n); - if (_nc_tparm_err) + if (_nc_tparm_err) { _nc_warning("problem%s in tparm(%s, %d, ...)", (_nc_tparm_err == 1) ? "" : "s", name, n); + if (debug_level < 2) + break; + } } } } @@ -2136,7 +2163,7 @@ check_delays(TERMTYPE2 *tp, const char *name, const char *value) for (q = base; *q != '\0'; ++q) { if (*q == '>') { - if (mark == 0) + if (mark == NULL) mark = q; break; } else if (*q == '*' || *q == '/') { @@ -2144,7 +2171,7 @@ check_delays(TERMTYPE2 *tp, const char *name, const char *value) ++proportional; if (*q == '/') ++mandatory; - if (mark == 0) + if (mark == NULL) mark = q; } else if (!(isalnum(UChar(*q)) || strchr("+-.", *q) != 0)) { break; @@ -2166,7 +2193,7 @@ check_delays(TERMTYPE2 *tp, const char *name, const char *value) _nc_warning("non-line capability using proportional delay: %s", name); } else if (!xon_xoff && !mandatory && - strchr(_nc_first_name(tp->term_names), '+') == 0) { + strchr(_nc_first_name(tp->term_names), '+') == NULL) { _nc_warning("%s in %s is used since no xon/xoff", (proportional ? "proportional delay" @@ -2306,7 +2333,7 @@ parse_delay_value(const char *src, double *delays, int *always) } } while (*src == '*' || *src == '/') { - if (always == 0 && *src == '/') + if (always == NULL && *src == '/') break; if (*src++ == '*') { star = 1; @@ -2663,7 +2690,7 @@ get_fkey_list(TERMTYPE2 *tp) int used = 0; unsigned j; - if (result == 0) + if (result == NULL) failed("get_fkey_list"); for (j = 0; all_fkeys[j].code; j++) { @@ -2709,14 +2736,13 @@ show_fkey_name(NAME_VALUE * data) static void check_conflict(TERMTYPE2 *tp) { - bool conflict = FALSE; - if (!(_nc_syntax == SYN_TERMCAP && capdump)) { char *check = calloc((size_t) (NUM_STRINGS(tp) + 1), sizeof(char)); NAME_VALUE *given = get_fkey_list(tp); unsigned j, k; + bool conflict = FALSE; - if (check == 0) + if (check == NULL) failed("check_conflict"); for (j = 0; given[j].keycode; ++j) { @@ -2966,6 +2992,186 @@ check_user_capability_type(const char *name, int actual) } #endif +#define IN_DELAY "0123456789*/." + +static bool +check_ANSI_cap(const char *value, int nparams, char final) +{ + bool result = FALSE; + if (VALID_STRING(value) && csi_length(value) > 0) { + char *p_is_s[NUM_PARM]; + int popcount; + int analyzed = _nc_tparm_analyze(NULL, value, p_is_s, &popcount); + if (analyzed < popcount) { + analyzed = popcount; + } + if (analyzed == nparams) { + bool numbers = TRUE; + int p; + for (p = 0; p < nparams; ++p) { + if (p_is_s[p]) { + numbers = FALSE; + break; + } + } + if (numbers) { + int in_delay = 0; + p = (int) strlen(value); + while (p-- > 0) { + char ch = value[p]; + if (ch == final) { + result = TRUE; + break; + } + switch (in_delay) { + case 0: + if (ch == '>') + in_delay = 1; + break; + case 1: + if (strchr(IN_DELAY, value[p]) != NULL) + break; + if (ch != '<') + p = 0; + in_delay = 2; + break; + case 2: + if (ch != '$') + p = 0; + in_delay = 0; + break; + } + } + } + } + } + return result; +} + +static const char * +skip_Delay(const char *value) +{ + const char *result = value; + + if (*value == '$') { + ++result; + if (*result++ == '<') { + while (strchr(IN_DELAY, *result) != NULL) + ++result; + if (*result++ != '>') { + result = value; + } + } else { + result = value; + } + } + return result; +} + +static bool +isValidString(const char *value, const char *expect) +{ + bool result = FALSE; + if (VALID_STRING(value)) { + if (!strcmp(value, expect)) + result = TRUE; + } + return result; +} + +static bool +isValidEscape(const char *value, const char *expect) +{ + bool result = FALSE; + if (VALID_STRING(value)) { + if (*value == '\033') { + size_t need = strlen(expect); + size_t have = strlen(value) - 1; + if (have >= need && !strncmp(value + 1, expect, need)) { + if (*skip_Delay(value + need + 1) == '\0') { + result = TRUE; + } + } + } + } + return result; +} + +static int +guess_ANSI_VTxx(TERMTYPE2 *tp) +{ + int result = -1; + int checks = 0; + + /* VT100s have scrolling region, but ANSI (ECMA-48) does not specify */ + if (check_ANSI_cap(change_scroll_region, 2, 'r') && + (isValidEscape(scroll_forward, "D") || + isValidString(scroll_forward, "\n") || + isValidEscape(scroll_forward, "6")) && + (isValidEscape(scroll_reverse, "M") || + isValidEscape(scroll_reverse, "9"))) { + checks |= 2; + } + if (check_ANSI_cap(cursor_address, 2, 'H') && + check_ANSI_cap(cursor_up, 0, 'A') && + (check_ANSI_cap(cursor_down, 0, 'B') || + isValidString(cursor_down, "\n")) && + check_ANSI_cap(cursor_right, 0, 'C') && + (check_ANSI_cap(cursor_left, 0, 'D') || + isValidString(cursor_left, "\b")) && + check_ANSI_cap(clr_eos, 0, 'J') && + check_ANSI_cap(clr_bol, 0, 'K') && + check_ANSI_cap(clr_eol, 0, 'K')) { + checks |= 1; + } + if (checks == 3) + result = 1; + if (checks == 1) + result = 0; + return result; +} + +/* + * u6/u7 and u8/u9 are query/response extensions which most terminals support. + * In particular, any ECMA-48 terminal should support these, though the details + * for u9 are implementation dependent. + */ +static void +check_user_6789(TERMTYPE2 *tp) +{ + /* + * Check if the terminal is known to not + */ +#define NO_QUERY(longname,shortname) \ + if (PRESENT(longname)) _nc_warning(#shortname " is not supported") + if (tigetflag("NQ") > 0) { + NO_QUERY(user6, u6); + NO_QUERY(user7, u7); + NO_QUERY(user8, u8); + NO_QUERY(user9, u9); + return; + } + + PAIRED(user6, user7); + PAIRED(user8, user9); + + if (strchr(tp->term_names, '+') != NULL) + return; + + switch (guess_ANSI_VTxx(tp)) { + case 1: + if (!PRESENT(user8)) { + _nc_warning("expected u8/u9 for device-attributes"); + } + /* FALLTHRU */ + case 0: + if (!PRESENT(user6)) { + _nc_warning("expected u6/u7 for cursor-position"); + } + break; + } +} + /* other sanity-checks (things that we don't want in the normal * logic that reads a terminfo entry) */ @@ -3014,6 +3220,7 @@ check_termtype(TERMTYPE2 *tp, bool literal) check_keypad(tp); check_printer(tp); check_screen(tp); + check_user_6789(tp); /* * These are probably both or none. @@ -3079,7 +3286,7 @@ check_termtype(TERMTYPE2 *tp, bool literal) if (PRESENT(exit_attribute_mode)) { char *check_sgr0 = _nc_trim_sgr0(tp); - if (check_sgr0 == 0 || *check_sgr0 == '\0') { + if (check_sgr0 == NULL || *check_sgr0 == '\0') { _nc_warning("trimmed sgr0 is empty"); } else { show_where(2);