diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2010-01-12 23:22:15 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2010-01-12 23:22:15 +0000 |
commit | 6ee254699bf787d78835419be2b3241fb037d444 (patch) | |
tree | 07fe67dab517e4990f344fe2c00e65cef4d25b81 /usr.bin/tic | |
parent | 0b62f5dc36fc7203a74cdc812c4234ae188fdfd2 (diff) |
Update to ncurses 5.7, with local changes reapplied.
This is around eight years worth of changes (previously we were around ncurses
5.2), too many to list - many bug fixes and also a few new functions.
A major bump for libcurses, libpanel, libform and libmenu.
ok deraadt
Diffstat (limited to 'usr.bin/tic')
-rw-r--r-- | usr.bin/tic/MKtermsort.sh | 79 | ||||
-rw-r--r-- | usr.bin/tic/captoinfo.1tbl | 38 | ||||
-rw-r--r-- | usr.bin/tic/dump_entry.c | 646 | ||||
-rw-r--r-- | usr.bin/tic/dump_entry.h | 25 | ||||
-rw-r--r-- | usr.bin/tic/infotocap.1 | 14 | ||||
-rw-r--r-- | usr.bin/tic/progs.priv.h | 38 | ||||
-rw-r--r-- | usr.bin/tic/tic.1 | 173 | ||||
-rw-r--r-- | usr.bin/tic/tic.c | 753 |
8 files changed, 1309 insertions, 457 deletions
diff --git a/usr.bin/tic/MKtermsort.sh b/usr.bin/tic/MKtermsort.sh index 58694bd9a9b..43e1174cdb2 100644 --- a/usr.bin/tic/MKtermsort.sh +++ b/usr.bin/tic/MKtermsort.sh @@ -1,28 +1,63 @@ #!/bin/sh -# $OpenBSD: MKtermsort.sh,v 1.4 2000/03/10 01:35:06 millert Exp $ -# $From: MKtermsort.sh,v 1.6 2000/01/25 11:35:36 tom Exp $ +# $OpenBSD: MKtermsort.sh,v 1.5 2010/01/12 23:22:14 nicm Exp $ +# $Id: MKtermsort.sh,v 1.5 2010/01/12 23:22:14 nicm Exp $ # # MKtermsort.sh -- generate indirection vectors for the various sort methods # +############################################################################## +# Copyright (c) 1998-2003,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. # +############################################################################## +# # The output of this script is C source for nine arrays that list three sort # orders for each of the three different classes of terminfo capabilities. # # keep the order independent of locale: -LANGUAGE=C -LC_ALL=C -export LANGUAGE -export LC_ALL +if test "${LANGUAGE+set}" = set; then LANGUAGE=C; export LANGUAGE; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi +if test "${LC_COLLATE+set}" = set; then LC_COLLATE=C; export LC_COLLATE; fi # AWK=${1-awk} DATA=${2-../include/Caps} +data=data$$ +trap 'rm -f $data' 1 2 5 15 +sed -e 's/[ ][ ]*/ /g' < $DATA >$data +DATA=$data + echo "/*"; echo " * termsort.c --- sort order arrays for use by infocmp."; echo " *"; echo " * Note: this file is generated using MKtermsort.sh, do not edit by hand."; echo " */"; -echo "static const int bool_terminfo_sort[] = {"; +echo "static const PredIdx bool_terminfo_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -31,7 +66,7 @@ $3 == "bool" {printf("%s\t%d\n", $2, i++);} echo "};"; echo ""; -echo "static const int num_terminfo_sort[] = {"; +echo "static const PredIdx num_terminfo_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -40,7 +75,7 @@ $3 == "num" {printf("%s\t%d\n", $2, i++);} echo "};"; echo ""; -echo "static const int str_terminfo_sort[] = {"; +echo "static const PredIdx str_terminfo_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -49,7 +84,7 @@ $3 == "str" {printf("%s\t%d\n", $2, i++);} echo "};"; echo ""; -echo "static const int bool_variable_sort[] = {"; +echo "static const PredIdx bool_variable_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -58,7 +93,7 @@ $3 == "bool" {printf("%s\t%d\n", $1, i++);} echo "};"; echo ""; -echo "static const int num_variable_sort[] = {"; +echo "static const PredIdx num_variable_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -67,7 +102,7 @@ $3 == "num" {printf("%s\t%d\n", $1, i++);} echo "};"; echo ""; -echo "static const int str_variable_sort[] = {"; +echo "static const PredIdx str_variable_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -76,7 +111,7 @@ $3 == "str" {printf("%s\t%d\n", $1, i++);} echo "};"; echo ""; -echo "static const int bool_termcap_sort[] = {"; +echo "static const PredIdx bool_termcap_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -85,7 +120,7 @@ $3 == "bool" {printf("%s\t%d\n", $4, i++);} echo "};"; echo ""; -echo "static const int num_termcap_sort[] = {"; +echo "static const PredIdx num_termcap_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -94,7 +129,7 @@ $3 == "num" {printf("%s\t%d\n", $4, i++);} echo "};"; echo ""; -echo "static const int str_termcap_sort[] = {"; +echo "static const PredIdx str_termcap_sort[] = {"; $AWK <$DATA ' BEGIN {i = 0;} /^#/ {next;} @@ -105,24 +140,26 @@ echo ""; echo "static const bool bool_from_termcap[] = {"; $AWK <$DATA ' -$3 == "bool" && substr($5, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} -$3 == "bool" && substr($5, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} +$3 == "bool" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} +$3 == "bool" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} ' echo "};"; echo ""; echo "static const bool num_from_termcap[] = {"; $AWK <$DATA ' -$3 == "num" && substr($5, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} -$3 == "num" && substr($5, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} +$3 == "num" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} +$3 == "num" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} ' echo "};"; echo ""; echo "static const bool str_from_termcap[] = {"; $AWK <$DATA ' -$3 == "str" && substr($5, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} -$3 == "str" && substr($5, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} +$3 == "str" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} +$3 == "str" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} ' echo "};"; echo ""; + +rm -f $data diff --git a/usr.bin/tic/captoinfo.1tbl b/usr.bin/tic/captoinfo.1tbl index 6ca83a3945e..d412190e0cf 100644 --- a/usr.bin/tic/captoinfo.1tbl +++ b/usr.bin/tic/captoinfo.1tbl @@ -1,8 +1,6 @@ -'\" t -.\" $OpenBSD: captoinfo.1tbl,v 1.7 2000/10/08 22:47:09 millert Exp $ -.\" +.\" $OpenBSD: captoinfo.1tbl,v 1.8 2010/01/12 23:22:14 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 1998,2000 Free Software Foundation, Inc. * +.\" Copyright (c) 1998-2006,2007 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,10 +27,10 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $From: From: captoinfo.1m,v 1.16 2000/08/13 01:56:49 tom Exp $ +.\" $Id: captoinfo.1tbl,v 1.8 2010/01/12 23:22:14 nicm Exp $ .TH captoinfo 1 "" .ds n 5 -.ds d /usr/share/terminfo +.ds d /usr/share/misc/terminfo .SH NAME \fBcaptoinfo\fR - convert a \fItermcap\fR description into a \fIterminfo\fR description .SH SYNOPSIS @@ -42,7 +40,7 @@ one found, an equivalent \fBterminfo\fR description is written to standard output. Termcap \fBtc\fR capabilities are translated directly to terminfo \fBuse\fR capabilities. - +.PP If no \fIfile\fR is given, then the environment variable \fBTERMCAP\fR is used for the filename or entry. If \fBTERMCAP\fR is a full pathname to a file, only the terminal whose name is specified in the environment variable \fBTERM\fR is @@ -147,13 +145,12 @@ GG acs magic cookie count .TE .PP If the single-line capabilities occur in an entry, they will automatically -be composed into an \fBacsc\fR string. The double-line capabilities and +be composed into an \fIacsc\fR string. The double-line capabilities and \fBGG\fR are discarded with a warning message. .PP IBM's AIX has a terminfo facility descended from SVr1 terminfo but incompatible with the SVr4 format. The following AIX extensions are automatically translated: -.PP .TS c c l l. @@ -167,20 +164,25 @@ font2 s2ds font3 s3ds .TE .PP -Additionally, the AIX \fBbox1\fR capability will be automatically translated to -an \fBacsc\fR string. +Additionally, the AIX \fIbox1\fR capability will be automatically translated to +an \fIacsc\fR string. .PP Hewlett-Packard's terminfo library supports two nonstandard terminfo -capabilities \fBmeml\fR (memory lock) and \fBmemu\fR (memory unlock). +capabilities \fImeml\fR (memory lock) and \fImemu\fR (memory unlock). These will be discarded with a warning message. .SH NOTES -This utility is actually a link to \fItic\fR(1), running in \fI-I\fR mode. -You can use other \fItic\fR options such as \fB-f\fR and \fB-x\fR. - -The trace option isn't identical to SVr4's. Under SVr4, instead of following -the -v with a trace level n, you repeat it n times. +This utility is actually a link to \fBtic\fR(1), running in \fI-I\fR mode. +You can use other \fBtic\fR options such as \fB-f\fR and \fB-x\fR. +.PP +The trace option is not identical to SVr4's. Under SVr4, instead of following +the \fB-v\fR with a trace level n, you repeat it n times. .SH SEE ALSO -\fBcurses\fR(3), \fBtic\fR(1), \fBterminfo\fR(\*n) +\fBinfocmp\fR(1), +\fBcurses\fR(3), +\fBterminfo\fR(\*n) +.PP +This describes \fBncurses\fR +version 5.7. .SH AUTHOR Eric S. Raymond <esr@snark.thyrsus.com> .\"# diff --git a/usr.bin/tic/dump_entry.c b/usr.bin/tic/dump_entry.c index 923a2953d8b..ab6cc99d08f 100644 --- a/usr.bin/tic/dump_entry.c +++ b/usr.bin/tic/dump_entry.c @@ -1,7 +1,7 @@ -/* $OpenBSD: dump_entry.c,v 1.18 2003/04/06 21:12:07 millert Exp $ */ +/* $OpenBSD: dump_entry.c,v 1.19 2010/01/12 23:22:14 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000 Free Software Foundation, Inc. * + * 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 * @@ -31,21 +31,24 @@ /**************************************************************************** * 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 "termsort.c" /* this C file is generated */ #include <parametrized.h> /* so is this */ -MODULE_ID("$From: dump_entry.c,v 1.54 2000/10/01 01:34:06 tom Exp $") +MODULE_ID("$Id: dump_entry.c,v 1.19 2010/01/12 23:22:14 nicm 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; @@ -58,14 +61,15 @@ 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 int tracelevel; /* level of debug output */ 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 int *bool_indirect, *num_indirect, *str_indirect; +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; @@ -140,6 +144,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 */ @@ -149,18 +158,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,18 +175,17 @@ nametrans(const char *name) void dump_init(const char *version, int mode, int sort, int twidth, int traceval, - bool formatted) + bool formatted) /* set up for entry display */ { width = twidth; pretty = formatted; - tracelevel = traceval; /* versions */ if (version == 0) tversion = V_ALLCAPS; else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1") - || !strcmp(version, "Ultrix")) + || !strcmp(version, "Ultrix")) tversion = V_SVR1; else if (!strcmp(version, "HP")) tversion = V_HPUX; @@ -225,13 +230,13 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, case S_NOSORT: if (traceval) (void) fprintf(stderr, - "%s: sorting by term structure order\n", _nc_progname); + "%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); + "%s: sorting by terminfo name order\n", _nc_progname); bool_indirect = bool_terminfo_sort; num_indirect = num_terminfo_sort; str_indirect = str_terminfo_sort; @@ -240,7 +245,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, case S_VARIABLE: if (traceval) (void) fprintf(stderr, - "%s: sorting by C variable order\n", _nc_progname); + "%s: sorting by C variable order\n", _nc_progname); bool_indirect = bool_variable_sort; num_indirect = num_variable_sort; str_indirect = str_variable_sort; @@ -249,7 +254,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, case S_TERMCAP: if (traceval) (void) fprintf(stderr, - "%s: sorting by termcap name order\n", _nc_progname); + "%s: sorting by termcap name order\n", _nc_progname); bool_indirect = bool_termcap_sort; num_indirect = num_termcap_sort; str_indirect = str_termcap_sort; @@ -258,14 +263,14 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, if (traceval) (void) fprintf(stderr, - "%s: width = %d, tversion = %d, outform = %d\n", - _nc_progname, width, tversion, outform); + "%s: width = %d, tversion = %d, outform = %d\n", + _nc_progname, width, tversion, outform); } static TERMTYPE *cur_type; static int -dump_predicate(int type, int idx) +dump_predicate(PredType type, PredIdx idx) /* predicate function to use for ordinary decompilation */ { switch (type) { @@ -285,13 +290,21 @@ dump_predicate(int type, int idx) return (FALSE); /* pacify compiler */ } -static void set_obsolete_termcaps(TERMTYPE * tp); +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(int type, int idx) +version_filter(PredType type, PredIdx idx) /* filter out capabilities we may want to suppress */ { switch (tversion) { @@ -301,31 +314,28 @@ version_filter(int type, int idx) case V_SVR1: /* System V Release 1, Ultrix */ switch (type) { case BOOLEAN: - /* below and including xon_xoff */ - return ((idx <= 20) ? TRUE : FALSE); + return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); case NUMBER: - /* below and including width_status_line */ - return ((idx <= 7) ? TRUE : FALSE); + return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE); case STRING: - /* below and including prtr_non */ - return ((idx <= 144) ? TRUE : FALSE); + return ((idx <= STR_IDX(prtr_non)) ? TRUE : FALSE); } break; case V_HPUX: /* Hewlett-Packard */ switch (type) { case BOOLEAN: - /* below and including xon_xoff */ - return ((idx <= 20) ? TRUE : FALSE); + return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); case NUMBER: - /* below and including label_width */ - return ((idx <= 10) ? TRUE : FALSE); + return ((idx <= NUM_IDX(label_width)) ? TRUE : FALSE); case STRING: - if (idx <= 144) /* below and including prtr_non */ + if (idx <= STR_IDX(prtr_non)) return (TRUE); else if (FNKEY(idx)) /* function keys */ return (TRUE); - else if (idx == 147 || idx == 156 || idx == 157) /* plab_norm,label_on,label_off */ + else if (idx == STR_IDX(plab_norm) + || idx == STR_IDX(label_on) + || idx == STR_IDX(label_off)) return (TRUE); else return (FALSE); @@ -335,13 +345,11 @@ version_filter(int type, int idx) case V_AIX: /* AIX */ switch (type) { case BOOLEAN: - /* below and including xon_xoff */ - return ((idx <= 20) ? TRUE : FALSE); + return ((idx <= BOOL_IDX(xon_xoff)) ? TRUE : FALSE); case NUMBER: - /* below and including width_status_line */ - return ((idx <= 7) ? TRUE : FALSE); + return ((idx <= NUM_IDX(width_status_line)) ? TRUE : FALSE); case STRING: - if (idx <= 144) /* below and including prtr_non */ + if (idx <= STR_IDX(prtr_non)) return (TRUE); else if (FNKEY(idx)) /* function keys */ return (TRUE); @@ -350,14 +358,17 @@ version_filter(int type, int 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; } @@ -366,9 +377,17 @@ version_filter(int type, int idx) } 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; } @@ -376,22 +395,22 @@ force_wrap(void) static void wrap_concat(const char *src) { - int need = strlen(src); - int want = strlen(separator) + need; + unsigned need = strlen(src); + unsigned 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 ":". @@ -422,43 +441,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); } @@ -468,11 +525,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; @@ -483,14 +539,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); @@ -498,20 +558,25 @@ fmt_complex(char *src, int level) return src; } +#define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) +#define EXTRA_CAP 20 + int -fmt_entry(TERMTYPE * tterm, - int (*pred) (int type, int idx), - bool suppress_untranslatable, - bool infodump, - int numbers) +fmt_entry(TERMTYPE *tterm, + PredFunc pred, + bool content_only, + bool suppress_untranslatable, + bool infodump, + int numbers) { - int i, j; - char buffer[MAX_TERMINFO_LENGTH]; + PredIdx i, j; + char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; + char *capability; NCURSES_CONST char *name; int predval, len; - int num_bools = 0; - int num_values = 0; - int num_strings = 0; + PredIdx num_bools = 0; + PredIdx num_values = 0; + PredIdx num_strings = 0; bool outcount = 0; #define WRAP_CONCAT \ @@ -526,14 +591,19 @@ fmt_entry(TERMTYPE * tterm, } strcpy_DYN(&outbuf, 0); - strcpy_DYN(&outbuf, tterm->term_names); - strcpy_DYN(&outbuf, separator); - column = outbuf.used; - force_wrap(); + 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; @@ -557,6 +627,7 @@ fmt_entry(TERMTYPE * tterm, 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; @@ -579,9 +650,9 @@ fmt_entry(TERMTYPE * tterm, if (column != INDENT) 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++; @@ -602,63 +673,94 @@ fmt_entry(TERMTYPE * tterm, 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 /* - * 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. + * 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) { - if (insert_character || parm_ich) { - if (&tterm->Strings[i] == &enter_insert_mode + /* + * 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) strlcpy(buffer, "im=", sizeof buffer); + (void) strlcpy(buffer, "im=", sizeof(buffer)); WRAP_CONCAT; continue; } - if (&tterm->Strings[i] == &exit_insert_mode + if (SAME_CAP(i, exit_insert_mode) && exit_insert_mode == ABSENT_STRING) { - (void) strlcpy(buffer, "ei=", sizeof buffer); + (void) strlcpy(buffer, "ei=", sizeof(buffer)); 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 (tterm->Strings[i] != ABSENT_STRING + if (capability != ABSENT_STRING && i + 1 > num_strings) num_strings = i + 1; - if (!VALID_STRING(tterm->Strings[i])) { - snprintf(buffer, sizeof buffer, "%s@", name); + if (!VALID_STRING(capability)) { + snprintf(buffer, sizeof(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(tterm->Strings[i], TRUE, numbers); + 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) { - snprintf(buffer, sizeof buffer, - "%s=!!! %s WILL NOT CONVERT !!!", - name, srccap); + snprintf(buffer, sizeof(buffer), + "%s=!!! %s WILL NOT CONVERT !!!", name, srccap); } else if (suppress_untranslatable) { continue; } else { char *d, *s = srccap; - snprintf(buffer, sizeof buffer, "..%s=", name); + snprintf(buffer, sizeof(buffer), "..%s=", name); d = buffer + strlen(buffer); - while ((*d = *s++) != 0) { /* XXX overflow? */ + while ((*d = *s++) != 0) { /* XXX overflow */ if (*d == ':') { *d++ = '\\'; *d = ':'; @@ -671,11 +773,11 @@ fmt_entry(TERMTYPE * tterm, } else { snprintf(buffer, sizeof buffer, "%s=%s", name, cv); } - len += strlen(tterm->Strings[i]) + 1; + len += (int) strlen(capability) + 1; WRAP_CONCAT; } else { - char *src = _nc_tic_expand(tterm->Strings[i], - outform == F_TERMINFO, numbers); + char *src = _nc_tic_expand(capability, + outform == F_TERMINFO, numbers); strcpy_DYN(&tmpbuf, 0); strcpy_DYN(&tmpbuf, name); @@ -687,26 +789,29 @@ fmt_entry(TERMTYPE * tterm, } else { strcpy_DYN(&tmpbuf, src); } - len += strlen(tterm->Strings[i]) + 1; + len += (int) strlen(capability) + 1; wrap_concat(tmpbuf.text); outcount = TRUE; } } + /* e.g., trimmed_sgr0 */ + 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) { - (void) snprintf(buffer, sizeof buffer, "meml=%s", memory_lock); + if (VALID_STRING(memory_lock)) { + (void) snprintf(buffer, sizeof(buffer), "meml=%s", memory_lock); WRAP_CONCAT; } - if (memory_unlock) { - (void) snprintf(buffer, sizeof buffer, "memu=%s", memory_unlock); + if (VALID_STRING(memory_unlock)) { + (void) snprintf(buffer, sizeof(buffer), "memu=%s", memory_unlock); WRAP_CONCAT; } } else if (tversion == V_AIX) { @@ -729,9 +834,9 @@ fmt_entry(TERMTYPE * tterm, tp[0] = '\0'; if (box_ok) { - (void) strlcpy(buffer, "box1=", sizeof buffer); + (void) strlcpy(buffer, "box1=", sizeof(buffer)); (void) strlcat(buffer, _nc_tic_expand(boxchars, - outform == F_TERMINFO, numbers), sizeof buffer); + outform == F_TERMINFO, numbers), sizeof(buffer)); WRAP_CONCAT; } } @@ -750,16 +855,17 @@ fmt_entry(TERMTYPE * tterm, 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.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 @@ -767,7 +873,7 @@ fmt_entry(TERMTYPE * tterm, 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); + tterm->term_names, len, outbuf.used, outbuf.text); #endif /* * Here's where we use infodump to trigger a more stringent length check @@ -776,14 +882,149 @@ fmt_entry(TERMTYPE * tterm, * It gives an idea of which entries are deadly to even *scan past*, * as opposed to *use*. */ - return (infodump ? len : termcap_length(outbuf.text)); + return (infodump ? len : (int) termcap_length(outbuf.text)); } -int -dump_entry(TERMTYPE * tterm, bool limited, int numbers, int (*pred) (int - type, int idx)) -/* dump a single entry */ +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) { + snprintf(name, sizeof(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) { + snprintf(name, sizeof(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; @@ -799,74 +1040,133 @@ dump_entry(TERMTYPE * tterm, bool limited, int numbers, int (*pred) (int infodump = TRUE; } - if (((len = fmt_entry(tterm, pred, FALSE, infodump, numbers)) > critlen) + save_sgr = set_attributes; + + if (((len = FMT_ENTRY()) > critlen) && limited) { - PRINTF("# (untranslatable capabilities removed to fit entry within %d bytes)\n", - critlen); - if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) { + + 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. */ - char *oldsgr = set_attributes; - char *oldacsc = acs_chars; - set_attributes = ABSENT_STRING; - PRINTF("# (sgr removed to fit entry within %d bytes)\n", - critlen); - if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) { - acs_chars = ABSENT_STRING; - PRINTF("# (acsc removed to fit entry within %d bytes)\n", - critlen); + 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 ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) { + if (!changed || ((len = FMT_ENTRY()) > critlen)) { int oldversion = tversion; tversion = V_BSD; - PRINTF("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", - critlen); - - if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) - > critlen) { + 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); - PRINTF( - "# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", - len, legend); + "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 = oldsgr; - acs_chars = oldacsc; + 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) 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); - (void) snprintf(buffer, sizeof buffer, - "%s%s", infodump ? "use=" : "tc=", name); + if (outform == F_TERMCAP || outform == F_TCONVERR) + trim_trailing(); + (void) snprintf(buffer, sizeof(buffer), "%s%s", infodump ? "use=" : "tc=", + name); wrap_concat(buffer); +} + +int +show_entry(void) +{ + trim_trailing(); (void) fputs(outbuf.text, stdout); - return outbuf.used; + putchar('\n'); + return (int) outbuf.used; } void -compare_entry(void (*hook) (int t, int i, const char *name), TERMTYPE * tp - GCC_UNUSED, bool quiet) +compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), + TERMTYPE *tp GCC_UNUSED, + bool quiet) /* compare two entries */ { - int i, j; + PredIdx i, j; NCURSES_CONST char *name; if (!quiet) @@ -921,7 +1221,7 @@ compare_entry(void (*hook) (int t, int i, const char *name), TERMTYPE * tp #define CUR tp-> static void -set_obsolete_termcaps(TERMTYPE * tp) +set_obsolete_termcaps(TERMTYPE *tp) { #include "capdefaults.c" } @@ -931,7 +1231,7 @@ set_obsolete_termcaps(TERMTYPE * tp) * unique. */ void -repair_acsc(TERMTYPE * tp) +repair_acsc(TERMTYPE *tp) { if (VALID_STRING(acs_chars)) { size_t n, m; @@ -942,7 +1242,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; @@ -954,17 +1254,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]; } } diff --git a/usr.bin/tic/dump_entry.h b/usr.bin/tic/dump_entry.h index c088c550ef5..a1838120868 100644 --- a/usr.bin/tic/dump_entry.h +++ b/usr.bin/tic/dump_entry.h @@ -1,7 +1,7 @@ -/* $OpenBSD: dump_entry.h,v 1.5 2000/03/13 23:53:41 millert Exp $ */ +/* $OpenBSD: dump_entry.h,v 1.6 2010/01/12 23:22:14 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999 Free Software Foundation, Inc. * + * Copyright (c) 1998-2006,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 * @@ -31,13 +31,19 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* + * $Id: dump_entry.h,v 1.6 2010/01/12 23:22:14 nicm Exp $ + * * Dump control definitions and variables */ +#ifndef DUMP_ENTRY_H +#define DUMP_ENTRY_H 1 + /* capability output formats */ #define F_TERMINFO 0 /* use terminfo names */ #define F_VARIABLE 1 /* use C variable names */ @@ -58,12 +64,19 @@ #define CMP_STRING 2 /* comparison on strings */ #define CMP_USE 3 /* comparison on use capabilities */ +typedef unsigned PredType; +typedef unsigned PredIdx; +typedef int (*PredFunc)(PredType, PredIdx); + extern NCURSES_CONST char *nametrans(const char *); +extern int fmt_entry(TERMTYPE *, PredFunc, bool, bool, bool, int); +extern int show_entry(void); +extern void compare_entry(void (*)(PredType, PredIdx, const char *), TERMTYPE *, bool); +extern void dump_entry(TERMTYPE *, bool, bool, int, PredFunc); extern void dump_init(const char *, int, int, int, int, bool); -extern int fmt_entry(TERMTYPE *, int (*)(int, int), bool, bool, int); -extern int dump_entry(TERMTYPE *, bool, int, int (*)(int, int)); -extern int dump_uses(const char *, bool); -extern void compare_entry(void (*)(int, int, const char *), TERMTYPE *, bool); +extern void dump_uses(const char *, bool); extern void repair_acsc(TERMTYPE * tp); #define FAIL -1 + +#endif /* DUMP_ENTRY_H */ diff --git a/usr.bin/tic/infotocap.1 b/usr.bin/tic/infotocap.1 index e80f9531631..16e6d5b2abe 100644 --- a/usr.bin/tic/infotocap.1 +++ b/usr.bin/tic/infotocap.1 @@ -1,7 +1,6 @@ -'\" t -.\" $OpenBSD: infotocap.1,v 1.4 2008/08/27 20:20:13 jmc Exp $ +.\" $OpenBSD: infotocap.1,v 1.5 2010/01/12 23:22:14 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 1999,2000 Free Software Foundation, Inc. * +.\" Copyright (c) 1999-2004,2006 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 * @@ -28,10 +27,10 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $From: infotocap.1m,v 1.3 2000/08/13 01:56:03 tom Exp $ +.\" $Id: infotocap.1,v 1.5 2010/01/12 23:22:14 nicm Exp $ .TH infotocap 1 "" .ds n 5 -.ds d /usr/share/terminfo +.ds d /usr/share/misc/terminfo .SH NAME \fBinfotocap\fR - convert a \fIterminfo\fR description into a \fItermcap\fR description .SH SYNOPSIS @@ -60,13 +59,16 @@ change the output to \fIwidth\fR characters. \*d Compiled terminal description database. .SH NOTES -This utility is actually a link to \fItic\fR(1), running in \fI-C\fR mode. +This utility is actually a link to \fItic\fR, running in \fI-C\fR mode. You can use other \fItic\fR options such as \fB-f\fR and \fB-x\fR. .SH SEE ALSO \fBcurses\fR(3), \fBtic\fR(1), \fBinfocmp\fR(1), \fBterminfo\fR(\*n) +.PP +This describes \fBncurses\fR +version 5.7. .\"# .\"# The following sets edit modes for GNU EMACS .\"# Local Variables: diff --git a/usr.bin/tic/progs.priv.h b/usr.bin/tic/progs.priv.h index 3fb5a3e2828..0795db553e3 100644 --- a/usr.bin/tic/progs.priv.h +++ b/usr.bin/tic/progs.priv.h @@ -1,7 +1,7 @@ -/* $OpenBSD: progs.priv.h,v 1.8 2001/01/22 18:02:20 millert Exp $ */ +/* $OpenBSD: progs.priv.h,v 1.9 2010/01/12 23:22:14 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000 Free Software Foundation, Inc. * + * 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 * @@ -29,10 +29,10 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey <dickey@clark.net> 1997,1998 * + * Author: Thomas E. Dickey 1997-on * ****************************************************************************/ /* - * $From: progs.priv.h,v 1.26 2000/11/05 00:22:05 tom Exp $ + * $Id: progs.priv.h,v 1.9 2010/01/12 23:22:14 nicm Exp $ * * progs.priv.h * @@ -54,10 +54,6 @@ #if HAVE_UNISTD_H #include <unistd.h> -#else -# if HAVE_LIBC_H -# include <libc.h> -# endif #endif #if HAVE_SYS_BSDTYPES_H @@ -73,8 +69,17 @@ #if HAVE_DIRENT_H # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) +# if defined(_FILE_OFFSET_BITS) && defined(HAVE_STRUCT_DIRENT64) +# if !defined(_LP64) && (_FILE_OFFSET_BITS == 64) +# define DIRENT struct dirent64 +# else +# define DIRENT struct dirent +# endif +# else +# define DIRENT struct dirent +# endif #else -# define dirent direct +# define DIRENT struct direct # define NAMLEN(dirent) (dirent)->d_namlen # if HAVE_SYS_NDIR_H # include <sys/ndir.h> @@ -87,6 +92,7 @@ # endif #endif +#include <assert.h> #include <errno.h> #if DECL_ERRNO @@ -106,7 +112,17 @@ extern int optind; #include <curses.h> #include <term_entry.h> #include <tic.h> +#include <nc_tparm.h> + #include <nc_alloc.h> +#if HAVE_NC_FREEALL +#undef ExitProgram +#ifdef USE_LIBTINFO +#define ExitProgram(code) _nc_free_tinfo(code) +#else +#define ExitProgram(code) _nc_free_tic(code) +#endif +#endif /* usually in <unistd.h> */ #ifndef STDOUT_FILENO @@ -167,12 +183,12 @@ extern int optind; #if !HAVE_ISASCII # undef isascii # if ('z'-'a' == 25) && ('z' < 127) && ('Z'-'A' == 25) && ('Z' < 127) && ('9' < 127) -# define isascii(c) (CharOf(c) <= 127) +# define isascii(c) (UChar(c) <= 127) # else # define isascii(c) 1 /* not really ascii anyway */ # endif #endif -#define CharOf(c) ((unsigned char)(c)) +#define UChar(c) ((unsigned char)(c)) #define SIZEOF(v) (sizeof(v)/sizeof(v[0])) diff --git a/usr.bin/tic/tic.1 b/usr.bin/tic/tic.1 index de2230170dc..3cbda402779 100644 --- a/usr.bin/tic/tic.1 +++ b/usr.bin/tic/tic.1 @@ -1,7 +1,7 @@ -.\" $OpenBSD: tic.1,v 1.13 2003/04/03 06:47:59 jmc Exp $ +.\" $OpenBSD: tic.1,v 1.14 2010/01/12 23:22:14 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * +.\" Copyright (c) 1998-2005,2006 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 * @@ -28,31 +28,36 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $From: tic.1m,v 1.29 2000/08/19 18:51:05 tom Exp $ +.\" $Id: tic.1,v 1.14 2010/01/12 23:22:14 nicm Exp $ .TH tic 1 "" .ds n 5 -.ds d /usr/share/terminfo +.ds d /usr/share/misc/terminfo .SH NAME \fBtic\fR - the \fIterminfo\fR entry-description compiler .SH SYNOPSIS \fBtic\fR -[\fB\-\ +[\fB-\ 1\ C\ +G\ I\ +L\ N\ -R\ T\ +U\ V\ a\ c\ f\ +g\ r\ s\ +t\ x\ \fR] [\fB-e\fR \fInames\fR] [\fB-o\fR \fIdir\fR] +[\fB-R\fR \fIsubset\fR] [\fB-v\fR[\fIn\fR]] [\fB-w\fR[\fIn\fR]] \fIfile\fR @@ -60,7 +65,7 @@ x\ .SH DESCRIPTION The command \fBtic\fR translates a \fBterminfo\fR file from source format into compiled format. The compiled format is necessary for use with -the library routines in \fBcurses\fR(3). +the library routines in \fBncurses\fR(3X). .PP The results are normally placed in the system terminfo directory \fB\*d\fR. There are two ways to change this behavior. @@ -76,11 +81,23 @@ Libraries that read terminfo entries are expected to check for a TERMINFO directory first, look at \fI$HOME/.terminfo\fR if TERMINFO is not set, and finally look in \fI\*d\fR. .TP +\fB-1\fR +restricts the output to a single column +.TP \fB-a\fR tells \fBtic\fP to retain commented-out capabilities rather than discarding them. Capabilities are commented by prefixing them with a period. This sets the \fB-x\fR option, because it treats the commented-out entries as user-defined names. +If the source is termcap, accept the 2-character names required by version 6. +Otherwise these are ignored. +.TP +\fB-C\fR +Force source translation to termcap format. Note: this differs from the \fB-C\fR +option of \fBinfocmp\fR(1M) in that it does not merely translate capability +names, but also translates terminfo strings to termcap format. Capabilities +that are not translatable are left in the entry under their terminfo names +but commented out with two preceding dots. .TP \fB-c\fR tells \fBtic\fP to only check \fIfile\fR for errors, including syntax problems and @@ -90,35 +107,28 @@ will print warnings about entries which, after use resolution, are more than libraries (and a documented limit in terminfo), these entries may cause core dumps. .TP -\fB-v\fR\fIn\fR -specifies that (verbose) output be written to standard error trace -information showing \fBtic\fR's progress. The optional integer -\fIn\fR is a number from 1 to 10, inclusive, indicating the desired -level of detail of information. If \fIn\fR is omitted, the default -level is 1. If \fIn\fR is specified and greater than 1, the level of -detail is increased. -.TP -\fB-o\fR\fIdir\fR -Write compiled entries to given directory. Overrides the TERMINFO environment -variable. -.TP -\fB-w\fR\fIn\fR -specifies the width of the output. -.TP -\fB-1\fR -restricts the output to a single column +\fB-e \fR\fInames\fR +Limit writes and translations to the following comma-separated list of +terminals. +If any name or alias of a terminal matches one of the names in +the list, the entry will be written or translated as normal. +Otherwise no output will be generated for it. +The option value is interpreted as a file containing the list if it +contains a '/'. +(Note: depending on how tic was compiled, this option may require \fB-I\fR or \fB-C\fR.) .TP -\fB-C\fR -Force source translation to termcap format. Note: this differs from the -C -option of \fIinfocmp\fR(1) in that it does not merely translate capability -names, but also translates terminfo strings to termcap format. Capabilities -that are not translatable are left in the entry under their terminfo names -but commented out with two preceding dots. +\fB-f\fR +Display complex terminfo strings which contain if/then/else/endif expressions +indented for readability. .TP \fB-G\fR Display constant literals in decimal form rather than their character equivalents. .TP +\fB-g\fR +Display constant character literals in quoted form +rather than their decimal equivalents. +.TP \fB-I\fR Force source translation to terminfo format. .TP @@ -127,7 +137,7 @@ Force source translation to terminfo format using the long C variable names listed in <\fBterm.h\fR> .TP \fB-N\fR -Disable smart defaults. +Disable smart defaults. Normally, when translating from termcap to terminfo, the compiler makes a number of assumptions about the defaults of string capabilities \fBreset1_string\fR, \fBcarriage_return\fR, \fBcursor_left\fR, @@ -138,55 +148,67 @@ normally suppresses output of obsolete termcap capabilities such as \fBbs\fR. This option forces a more literal translation that also preserves the obsolete capabilities. .TP +\fB-o\fR\fIdir\fR +Write compiled entries to given directory. Overrides the TERMINFO environment +variable. +.TP \fB-R\fR\fIsubset\fR Restrict output to a given subset. This option is for use with archaic -versions of terminfo like those on SVr1, Ultrix, or HP-UX that don't support +versions of terminfo like those on SVr1, Ultrix, or HP-UX that do not support the full set of SVR4/XSI Curses terminfo; and outright broken ports like AIX 3.x that have their own extensions incompatible with SVr4/XSI. Available subsets are "SVr1", "Ultrix", "HP", "BSD" and "AIX"; see \fBterminfo\fR(\*n) for details. .TP +\fB-r\fR +Force entry resolution (so there are no remaining tc capabilities) even +when doing translation to termcap format. This may be needed if you are +preparing a termcap file for a termcap library (such as GNU termcap through +version 1.3 or BSD termcap through 4.3BSD) that does not handle multiple +tc capabilities per entry. +.TP +\fB-s\fR +Summarize the compile by showing the directory into which entries +are written, and the number of entries which are compiled. +.TP \fB-T\fR eliminates size-restrictions on the generated text. This is mainly useful for testing and analysis, since the compiled descriptions are limited (e.g., 1023 for termcap, 4096 for terminfo). .TP +\fB-t\fR +tells \fBtic\fP to discard commented-out capabilities. +Normally when translating from terminfo to termcap, +untranslatable capabilities are commented-out. +.TP 5 +\fB-U\fR +tells \fBtic\fP to not post-process the data after parsing the source file. +Normally, it infers data which is commonly missing in older terminfo data, +or in termcaps. +.TP \fB-V\fR reports the version of ncurses which was used in this program, and exits. .TP -\fB-r\fR -Force entry resolution (so there are no remaining tc capabilities) even -when doing translation to termcap format. This may be needed if you are -preparing a termcap file for a termcap library (such as GNU termcap up -to version 1.3 or BSD termcap up to 4.3BSD) that doesn't handle multiple -tc capabilities per entry. -.TP -\fB-e\fR -Limit writes and translations to the following comma-separated list of -terminals. -If any name or alias of a terminal matches one of the names in -the list, the entry will be written or translated as normal. -Otherwise no output will be generated for it. -The option value is interpreted as a file containing the list if it -contains a '/'. -(Note: depending on how tic was compiled, this option may require -I or -C.) -.TP -\fB-f\fR -Display complex terminfo strings which contain if/then/else/endif expressions -indented for readability. -.TP -\fB-g\fR -Display constant character literals in quoted form -rather than their decimal equivalents. +\fB-v\fR\fIn\fR +specifies that (verbose) output be written to standard error trace +information showing \fBtic\fR's progress. +The optional parameter \fIn\fR is a number from 1 to 10, inclusive, +indicating the desired level of detail of information. +If \fIn\fR is omitted, the default level is 1. +If \fIn\fR is specified and greater than 1, the level of +detail is increased. .TP -\fB-s\fR -Summarize the compile by showing the directory into which entries -are written, and the number of entries which are compiled. +\fB-w\fR\fIn\fR +specifies the width of the output. +The parameter is optional. +If it is omitted, it defaults to 60. .TP \fB-x\fR Treat unknown capabilities as user-defined. That is, if you supply a capability name which \fBtic\fP does not recognize, it will infer its type (boolean, number or string) from the syntax and make an extended table entry for that. +User-defined capability strings +whose name begins with ``k'' are treated as function keys. .TP \fIfile\fR contains one or more \fBterminfo\fR terminal descriptions in source @@ -216,11 +238,11 @@ List of tokens encountered by scanner 9 All values computed in construction of the hash table .LP -If n is not given, it is taken to be one. +If the debug level \fIn\fR is not given, it is taken to be one. .PP All but one of the capabilities recognized by \fBtic\fR are documented in \fBterminfo\fR(\*n). The exception is the \fBuse\fR capability. - +.PP When a \fBuse\fR=\fIentry\fR-\fIname\fR field is discovered in a terminal entry currently being compiled, \fBtic\fR reads in the binary from \fB\*d\fR to complete the entry. (Entries created from @@ -229,16 +251,16 @@ from \fB\*d\fR to complete the entry. (Entries created from \fB\*d\fR.) \fBtic\fR duplicates the capabilities in \fIentry\fR-\fIname\fR for the current entry, with the exception of those capabilities that explicitly are defined in the current entry. - +.PP When an entry, e.g., \fBentry_name_1\fR, contains a \fBuse=\fR\fIentry\fR_\fIname\fR_\fI2\fR field, any canceled capabilities in \fIentry\fR_\fIname\fR_\fI2\fR must also appear in \fBentry_name_1\fR before \fBuse=\fR for these capabilities to be canceled in \fBentry_name_1\fR. - +.PP If the environment variable \fBTERMINFO\fR is set, the compiled results are placed there instead of \fB\*d\fR. - +.PP Total compiled entries cannot exceed 4096 bytes. The name field cannot exceed 512 bytes. Terminal names exceeding the maximum alias length (32 characters on systems with long filenames, 14 characters otherwise) @@ -254,7 +276,7 @@ Unlike the stock SVr4 \fBtic\fR command, this implementation can actually compile termcap sources. In fact, entries in terminfo and termcap syntax can be mixed in a single source file. See \fBterminfo\fR(\*n) for the list of termcap names taken to be equivalent to terminfo names. - +.PP The SVr4 manual pages are not clear on the resolution rules for \fBuse\fR capabilities. This implementation of \fBtic\fR will find \fBuse\fR targets anywhere @@ -262,10 +284,10 @@ in the source file, or anywhere in the file tree rooted at \fBTERMINFO\fR (if \fBTERMINFO\fR is defined), or in the user's \fI$HOME/.terminfo\fR directory (if it exists), or (finally) anywhere in the system's file tree of compiled entries. - +.PP The error messages from this \fBtic\fR have the same format as GNU C error messages, and can be parsed by GNU Emacs's compile facility. - +.PP The \fB-C\fR, \fB-G\fR, @@ -280,12 +302,13 @@ The \fB-g\fR, \fB-o\fR, \fB-r\fR, -\fB-s\fR and +\fB-s\fR, +\fB-t\fR and \fB-x\fR options are not supported under SVr4. -The SVr4 -c mode does not report bad use links. - +The SVr4 \fB-c\fR mode does not report bad use links. +.PP System V does not compile entries to or read entries from your \fI$HOME/.terminfo\fR directory unless TERMINFO is explicitly set to it. .SH FILES @@ -293,8 +316,14 @@ System V does not compile entries to or read entries from your \fB\*d/?/*\fR Compiled terminal description database. .SH SEE ALSO -\fBcaptoinfo\fR(1), \fBinfocmp\fR(1), \fBinfotocap\fR(1), -\fBcurses\fR(3), \fBterminfo\fR(\*n). +\fBinfocmp\fR(1), +\fBcaptoinfo\fR(1), +\fBinfotocap\fR(1), +\fBcurses\fR(3), +\fBterminfo\fR(\*n). +.PP +This describes \fBncurses\fR +version 5.7. .\"# .\"# The following sets edit modes for GNU EMACS .\"# Local Variables: diff --git a/usr.bin/tic/tic.c b/usr.bin/tic/tic.c index 320f55e9ebe..2a7019fbe58 100644 --- a/usr.bin/tic/tic.c +++ b/usr.bin/tic/tic.c @@ -1,7 +1,7 @@ -/* $OpenBSD: tic.c,v 1.29 2006/10/10 21:38:16 cloder Exp $ */ +/* $OpenBSD: tic.c,v 1.30 2010/01/12 23:22:14 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * + * 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 * @@ -31,6 +31,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * * and: Eric S. Raymond <esr@snark.thyrsus.com> * + * and: Thomas E. Dickey 1996 on * ****************************************************************************/ /* @@ -43,26 +44,68 @@ #include <sys/stat.h> #include <dump_entry.h> -#include <term_entry.h> #include <transform.h> -MODULE_ID("$From: tic.c,v 1.85 2001/02/03 23:31:45 tom Exp $") +MODULE_ID("$Id: tic.c,v 1.30 2010/01/12 23:22:14 nicm Exp $") const char *_nc_progname = "tic"; static FILE *log_fp; static FILE *tmp_fp; +static bool capdump = FALSE; /* running as infotocap? */ +static bool infodump = FALSE; /* running as captoinfo? */ static bool showsummary = FALSE; static const char *to_remove; -static void (*save_check_termtype) (TERMTYPE *); -static void check_termtype(TERMTYPE * tt); - -static const char usage_string[] = "[-V] [-v[n]] [-e names] [-CILNRTcfrswx1] source-file\n"; +static void (*save_check_termtype) (TERMTYPE *, bool); +static void check_termtype(TERMTYPE *tt, bool); + +static const char usage_string[] = "\ +[-e names] \ +[-o dir] \ +[-R name] \ +[-v[n]] \ +[-V] \ +[-w[n]] \ +[-\ +1\ +a\ +C\ +c\ +f\ +G\ +g\ +I\ +L\ +N\ +r\ +s\ +T\ +t\ +U\ +x\ +] \ +source-file\n"; + +#if NO_LEAKS +static void +free_namelist(char **src) +{ + if (src != 0) { + int n; + for (n = 0; src[n] != 0; ++n) + free(src[n]); + free(src); + } +} +#endif static void -cleanup(void) +cleanup(char **namelst GCC_UNUSED) { +#if NO_LEAKS + free_namelist(namelst); +#endif if (tmp_fp != 0) fclose(tmp_fp); if (to_remove != 0) { @@ -78,8 +121,8 @@ static void failed(const char *msg) { perror(msg); - cleanup(); - exit(EXIT_FAILURE); + cleanup((char **) 0); + ExitProgram(EXIT_FAILURE); } static void @@ -89,24 +132,28 @@ usage(void) { "Options:", " -1 format translation output one capability per line", - " -C translate entries to termcap source form", - " -I translate entries to terminfo source form", - " -L translate entries to full terminfo source form", - " -N disable smart defaults for source translation", - " -R restrict translation to given terminfo/termcap version", - " -T remove size-restrictions on compiled description", - " -V print version", #if NCURSES_XNAMES " -a retain commented-out capabilities (sets -x also)", #endif + " -C translate entries to termcap source form", " -c check only, validate input without compiling or translating", + " -e<names> translate/compile only entries named by comma-separated list", " -f format complex strings for readability", " -G format %{number} to %'char'", " -g format %'char' to %{number}", - " -e<names> translate/compile only entries named by comma-separated list", + " -I translate entries to terminfo source form", + " -L translate entries to full terminfo source form", + " -N disable smart defaults for source translation", " -o<dir> set output directory for compiled entry writes", + " -R<name> restrict translation to given terminfo/termcap version", " -r force resolution of all use entries in source translation", " -s print summary statistics", + " -T remove size-restrictions on compiled description", +#if NCURSES_XNAMES + " -t suppress commented-out capabilities", +#endif + " -U suppress post-processing of entries", + " -V print version", " -v[n] set verbosity level", " -w[n] set format width for translation output", #if NCURSES_XNAMES @@ -123,7 +170,7 @@ usage(void) fputs(tbl[j], stderr); putc('\n', stderr); } - exit(EXIT_FAILURE); + ExitProgram(EXIT_FAILURE); } #define L_BRACE '{' @@ -149,7 +196,7 @@ write_it(ENTRY * ep) d = result; t = s; while ((ch = *t++) != 0) { - *d++ = ch; + *d++ = (char) ch; if (ch == '\\') { *d++ = *t++; } else if ((ch == '%') @@ -163,17 +210,17 @@ write_it(ENTRY * ep) && value < 127 && isprint((int) value)) { *d++ = S_QUOTE; - *d++ = (int) value; + *d++ = (char) value; *d++ = S_QUOTE; t = (v + 1); } } } *d = 0; - if (strlen(result) < strlen(s)) { - /* new string is same length as what is there, or shorter */ - strlcpy(s, result, strlen(s)); - } + if (strlen(result) < strlen(s)) { + /* new string is same length as what is there, or shorter */ + strlcpy(s, result, strlen(s)); + } } } @@ -253,7 +300,7 @@ put_translate(int c) putchar(c); in_name = FALSE; } else if (c != '>') { - namebuf[used++] = c; + namebuf[used++] = (char) c; } else { /* ah! candidate name! */ char *up; NCURSES_CONST char *tp; @@ -265,7 +312,7 @@ put_translate(int c) if ((up = strchr(namebuf, '#')) != 0 || (up = strchr(namebuf, '=')) != 0 || ((up = strchr(namebuf, '@')) != 0 && up[1] == '>')) { - (void) strlcpy(suffix, up, have); + (void) strlcpy(suffix, up, have); *up = '\0'; } @@ -296,16 +343,16 @@ put_translate(int c) static char * stripped(char *src) { - while (isspace(CharOf(*src))) + while (isspace(UChar(*src))) src++; if (*src != '\0') { char *dst; size_t len; if ((dst = strdup(src)) == NULL) - failed("strdup"); + failed("strdup"); len = strlen(dst); - while (--len != 0 && isspace(CharOf(dst[len]))) + while (--len != 0 && isspace(UChar(dst[len]))) dst[len] = '\0'; return dst; } @@ -320,21 +367,21 @@ open_input(const char *filename) if (fp == 0) { fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename); - exit(EXIT_FAILURE); + ExitProgram(EXIT_FAILURE); } if (fstat(fileno(fp), &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFREG) { fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename); - exit(EXIT_FAILURE); + ExitProgram(EXIT_FAILURE); } return fp; } /* Parse the "-e" option-value into a list of names */ -static const char ** +static char ** make_namelist(char *src) { - const char **dst = 0; + char **dst = 0; char *s, *base; unsigned pass, n, nn; @@ -351,11 +398,13 @@ make_namelist(char *src) if ((s = stripped(buffer)) != 0) { if (dst != 0) dst[nn] = s; + else + free(s); nn++; } } if (pass == 1) { - dst = typeCalloc(const char *, nn + 1); + dst = typeCalloc(char *, nn + 1); rewind(fp); } } @@ -378,19 +427,19 @@ make_namelist(char *src) break; } if (pass == 1) - dst = typeCalloc(const char *, nn + 1); + dst = typeCalloc(char *, nn + 1); } } - if (showsummary) { + if (showsummary && (dst != 0)) { fprintf(log_fp, "Entries that will be compiled:\n"); for (n = 0; dst[n] != 0; n++) - fprintf(log_fp, "%d:%s\n", n + 1, dst[n]); + fprintf(log_fp, "%u:%s\n", n + 1, dst[n]); } return dst; } static bool -matches(const char **needle, const char *haystack) +matches(char **needle, const char *haystack) /* does entry in needle list match |-separated field in haystack? */ { bool code = FALSE; @@ -439,20 +488,20 @@ main(int argc, char *argv[]) int width = 60; bool formatted = FALSE; /* reformat complex strings? */ + bool literal = FALSE; /* suppress post-processing? */ int numbers = 0; /* format "%'char'" to/from "%{number}" */ - bool infodump = FALSE; /* running as captoinfo? */ - bool capdump = FALSE; /* running as infotocap? */ bool forceresolve = FALSE; /* force resolution */ bool limited = TRUE; char *tversion = (char *) NULL; const char *source_file = "terminfo"; - const char **namelst = 0; + char **namelst = 0; char *outdir = (char *) NULL; bool check_only = FALSE; + bool suppress_untranslatable = FALSE; log_fp = stderr; - _nc_progname = _nc_basename(argv[0]); + _nc_progname = _nc_rootname(argv[0]); if ((infodump = (strcmp(_nc_progname, PROG_CAPTOINFO) == 0)) != FALSE) { outform = F_TERMINFO; @@ -472,7 +521,7 @@ main(int argc, char *argv[]) * be optional. */ while ((this_opt = getopt(argc, argv, - "0123456789CILNR:TVace:fGgo:rsvwx")) != -1) { + "0123456789CILNR:TUVace:fGgo:rstvwx")) != -1) { if (isdigit(this_opt)) { switch (last_opt) { case 'v': @@ -507,6 +556,7 @@ main(int argc, char *argv[]) break; case 'N': smart_defaults = FALSE; + literal = TRUE; break; case 'R': tversion = optarg; @@ -514,9 +564,13 @@ main(int argc, char *argv[]) case 'T': limited = FALSE; break; + case 'U': + literal = TRUE; + break; case 'V': puts(curses_version()); - return EXIT_SUCCESS; + cleanup(namelst); + ExitProgram(EXIT_SUCCESS); case 'c': check_only = TRUE; break; @@ -548,6 +602,10 @@ main(int argc, char *argv[]) width = 0; break; #if NCURSES_XNAMES + case 't': + _nc_disable_period = FALSE; + suppress_untranslatable = TRUE; + break; case 'a': _nc_disable_period = TRUE; /* FALLTHRU */ @@ -565,8 +623,8 @@ main(int argc, char *argv[]) set_trace_level(debug_level); if (_nc_tracing) { - save_check_termtype = _nc_check_termtype; - _nc_check_termtype = check_termtype; + save_check_termtype = _nc_check_termtype2; + _nc_check_termtype2 = check_termtype; } #if !HAVE_BIG_CORE /* @@ -582,8 +640,8 @@ main(int argc, char *argv[]) if (namelst && (!infodump && !capdump)) { (void) fprintf(stderr, "Sorry, -e can't be used without -I or -C\n"); - cleanup(); - return EXIT_FAILURE; + cleanup(namelst); + ExitProgram(EXIT_FAILURE); } #endif /* HAVE_BIG_CORE */ @@ -595,12 +653,12 @@ main(int argc, char *argv[]) _nc_progname, _nc_progname, usage_string); - return EXIT_FAILURE; + ExitProgram(EXIT_FAILURE); } } else { if (infodump == TRUE) { /* captoinfo's no-argument case */ - source_file = "/usr/share/misc/termcap"; + source_file = "/etc/termcap"; if ((termcap = getenv("TERMCAP")) != 0 && (namelst = make_namelist(getenv("TERM"))) != 0) { strlcpy(my_tmpname, "/tmp/XXXXXXXXXX", sizeof my_tmpname); @@ -614,7 +672,7 @@ main(int argc, char *argv[]) tmp_fp = open_input(source_file); to_remove = source_file; } else { - failed("mkstemp"); + failed("tmpnam"); } } } else { @@ -624,8 +682,8 @@ main(int argc, char *argv[]) _nc_progname, _nc_progname, usage_string); - cleanup(); - return EXIT_FAILURE; + cleanup(namelst); + ExitProgram(EXIT_FAILURE); } } @@ -650,14 +708,16 @@ main(int argc, char *argv[]) _nc_set_writedir(outdir); #endif /* HAVE_BIG_CORE */ _nc_read_entry_source(tmp_fp, (char *) NULL, - !smart_defaults, FALSE, - (check_only || infodump || capdump) ? NULLHOOK : immedhook); + !smart_defaults || literal, FALSE, + ((check_only || infodump || capdump) + ? NULLHOOK + : immedhook)); /* do use resolution */ if (check_only || (!infodump && !capdump) || forceresolve) { - if (!_nc_resolve_uses(TRUE) && !check_only) { - cleanup(); - return EXIT_FAILURE; + if (!_nc_resolve_uses2(TRUE, literal) && !check_only) { + cleanup(namelst); + ExitProgram(EXIT_FAILURE); } } @@ -665,7 +725,7 @@ main(int argc, char *argv[]) if (check_only && (capdump || infodump)) { for_entry_list(qp) { if (matches(namelst, qp->tterm.term_names)) { - int len = fmt_entry(&qp->tterm, NULL, TRUE, infodump, numbers); + int len = fmt_entry(&qp->tterm, NULL, FALSE, TRUE, infodump, numbers); if (len > (infodump ? MAX_TERMINFO_LENGTH : MAX_TERMCAP_LENGTH)) (void) fprintf(stderr, @@ -697,17 +757,18 @@ main(int argc, char *argv[]) _nc_set_type(_nc_first_name(qp->tterm.term_names)); (void) fseek(tmp_fp, qp->cstart, SEEK_SET); - while (j--) { + while (j-- > 0) { if (infodump) (void) putchar(fgetc(tmp_fp)); else put_translate(fgetc(tmp_fp)); } - len = dump_entry(&qp->tterm, limited, numbers, NULL); - for (j = 0; j < qp->nuses; j++) - len += dump_uses(qp->uses[j].name, !capdump); - (void) putchar('\n'); + dump_entry(&qp->tterm, suppress_untranslatable, + limited, numbers, NULL); + for (j = 0; j < (int) qp->nuses; j++) + dump_uses(qp->uses[j].name, !capdump); + len = show_entry(); if (debug_level != 0 && !limited) printf("# length=%d\n", len); } @@ -749,8 +810,8 @@ main(int argc, char *argv[]) else fprintf(log_fp, "No entries written\n"); } - cleanup(); - return (EXIT_SUCCESS); + cleanup(namelst); + ExitProgram(EXIT_SUCCESS); } /* @@ -758,23 +819,238 @@ main(int argc, char *argv[]) * references to locations in the arrays Booleans, Numbers, and Strings --- * precisely what's needed (see comp_parse.c). */ - -TERMINAL *cur_term; /* tweak to avoid linking lib_cur_term.c */ - #undef CUR #define CUR tp-> /* + * Check if the alternate character-set capabilities are consistent. + */ +static void +check_acs(TERMTYPE *tp) +{ + if (VALID_STRING(acs_chars)) { + const char *boxes = "lmkjtuvwqxn"; + char mapped[256]; + char missing[256]; + const char *p; + char *q; + + memset(mapped, 0, sizeof(mapped)); + for (p = acs_chars; *p != '\0'; p += 2) { + if (p[1] == '\0') { + _nc_warning("acsc has odd number of characters"); + break; + } + mapped[UChar(p[0])] = p[1]; + } + + if (mapped[UChar('I')] && !mapped[UChar('i')]) { + _nc_warning("acsc refers to 'I', which is probably an error"); + } + + for (p = boxes, q = missing; *p != '\0'; ++p) { + if (!mapped[UChar(p[0])]) { + *q++ = p[0]; + } + } + *q = '\0'; + + assert(strlen(missing) <= strlen(boxes)); + if (*missing != '\0' && strcmp(missing, boxes)) { + _nc_warning("acsc is missing some line-drawing mapping: %s", missing); + } + } +} + +/* + * Check if the color capabilities are consistent + */ +static void +check_colors(TERMTYPE *tp) +{ + if ((max_colors > 0) != (max_pairs > 0) + || ((max_colors > max_pairs) && (initialize_pair == 0))) + _nc_warning("inconsistent values for max_colors (%d) and max_pairs (%d)", + max_colors, max_pairs); + + PAIRED(set_foreground, set_background); + PAIRED(set_a_foreground, set_a_background); + PAIRED(set_color_pair, initialize_pair); + + if (VALID_STRING(set_foreground) + && VALID_STRING(set_a_foreground) + && !_nc_capcmp(set_foreground, set_a_foreground)) + _nc_warning("expected setf/setaf to be different"); + + if (VALID_STRING(set_background) + && VALID_STRING(set_a_background) + && !_nc_capcmp(set_background, set_a_background)) + _nc_warning("expected setb/setab to be different"); + + /* see: has_colors() */ + if (VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) + && (((set_foreground != NULL) + && (set_background != NULL)) + || ((set_a_foreground != NULL) + && (set_a_background != NULL)) + || set_color_pair)) { + if (!VALID_STRING(orig_pair) && !VALID_STRING(orig_colors)) + _nc_warning("expected either op/oc string for resetting colors"); + } +} + +static char +keypad_final(const char *string) +{ + char result = '\0'; + + if (VALID_STRING(string) + && *string++ == '\033' + && *string++ == 'O' + && strlen(string) == 1) { + result = *string; + } + + return result; +} + +static int +keypad_index(const char *string) +{ + char *test; + const char *list = "PQRSwxymtuvlqrsPpn"; /* app-keypad except "Enter" */ + int ch; + int result = -1; + + if ((ch = keypad_final(string)) != '\0') { + test = strchr(list, ch); + if (test != 0) + result = (test - list); + } + return result; +} + +#define MAX_KP 5 +/* + * Do a quick sanity-check for vt100-style keypads to see if the 5-key keypad + * is mapped inconsistently. + */ +static void +check_keypad(TERMTYPE *tp) +{ + char show[80]; + + if (VALID_STRING(key_a1) && + VALID_STRING(key_a3) && + VALID_STRING(key_b2) && + VALID_STRING(key_c1) && + VALID_STRING(key_c3)) { + char final[MAX_KP + 1]; + int list[MAX_KP]; + int increase = 0; + int j, k, kk; + int last; + int test; + + final[0] = keypad_final(key_a1); + final[1] = keypad_final(key_a3); + final[2] = keypad_final(key_b2); + final[3] = keypad_final(key_c1); + final[4] = keypad_final(key_c3); + final[5] = '\0'; + + /* special case: legacy coding using 1,2,3,0,. on the bottom */ + assert(strlen(final) <= MAX_KP); + if (!strcmp(final, "qsrpn")) + return; + + list[0] = keypad_index(key_a1); + list[1] = keypad_index(key_a3); + list[2] = keypad_index(key_b2); + list[3] = keypad_index(key_c1); + list[4] = keypad_index(key_c3); + + /* check that they're all vt100 keys */ + for (j = 0; j < MAX_KP; ++j) { + if (list[j] < 0) { + return; + } + } + + /* check if they're all in increasing order */ + for (j = 1; j < MAX_KP; ++j) { + if (list[j] > list[j - 1]) { + ++increase; + } + } + if (increase != (MAX_KP - 1)) { + show[0] = '\0'; + + for (j = 0, last = -1; j < MAX_KP; ++j) { + for (k = 0, kk = -1, test = 100; k < 5; ++k) { + if (list[k] > last && + list[k] < test) { + test = list[k]; + kk = k; + } + } + last = test; + assert(strlen(show) < (MAX_KP * 4)); + switch (kk) { + case 0: + strlcat(show, " ka1", sizeof(show)); + break; + case 1: + strlcat(show, " ka3", sizeof(show)); + break; + case 2: + strlcat(show, " kb2", sizeof(show)); + break; + case 3: + strlcat(show, " kc1", sizeof(show)); + break; + case 4: + strlcat(show, " kc3", sizeof(show)); + break; + } + } + + _nc_warning("vt100 keypad order inconsistent: %s", show); + } + + } else if (VALID_STRING(key_a1) || + VALID_STRING(key_a3) || + VALID_STRING(key_b2) || + VALID_STRING(key_c1) || + VALID_STRING(key_c3)) { + show[0] = '\0'; + if (keypad_index(key_a1) >= 0) + strlcat(show, " ka1", sizeof(show)); + if (keypad_index(key_a3) >= 0) + strlcat(show, " ka3", sizeof(show)); + if (keypad_index(key_b2) >= 0) + strlcat(show, " kb2", sizeof(show)); + if (keypad_index(key_c1) >= 0) + strlcat(show, " kc1", sizeof(show)); + if (keypad_index(key_c3) >= 0) + strlcat(show, " kc3", sizeof(show)); + if (*show != '\0') + _nc_warning("vt100 keypad map incomplete:%s", show); + } +} + +/* * Returns the expected number of parameters for the given capability. */ static int -expected_params(char *name) +expected_params(const char *name) { /* *INDENT-OFF* */ static const struct { const char *name; int count; } table[] = { + { "S0", 1 }, /* 'screen' extension */ { "birep", 2 }, { "chr", 1 }, { "colornm", 1 }, @@ -827,8 +1103,8 @@ expected_params(char *name) { "sgr1", 6 }, { "slength", 1 }, { "slines", 1 }, - { "smgbp", 2 }, - { "smglp", 2 }, + { "smgbp", 1 }, /* 2 if smgtp is not given */ + { "smglp", 1 }, { "smglr", 2 }, { "smgrp", 1 }, { "smgtb", 2 }, @@ -860,7 +1136,7 @@ expected_params(char *name) * markers. */ static void -check_params(TERMTYPE * tp, char *name, char *value) +check_params(TERMTYPE *tp, const char *name, char *value) { int expected = expected_params(name); int actual = 0; @@ -868,6 +1144,12 @@ check_params(TERMTYPE * tp, char *name, char *value) bool params[10]; char *s = value; +#ifdef set_top_margin_parm + if (!strcmp(name, "smgbp") + && set_top_margin_parm == 0) + expected = 2; +#endif + for (n = 0; n < 10; n++) params[n] = FALSE; @@ -906,6 +1188,51 @@ check_params(TERMTYPE * tp, char *name, char *value) } } +static char * +skip_delay(char *s) +{ + while (*s == '/' || isdigit(UChar(*s))) + ++s; + return s; +} + +/* + * Skip a delay altogether, e.g., when comparing a simple string to sgr, + * the latter may have a worst-case delay on the end. + */ +static char * +ignore_delays(char *s) +{ + int delaying = 0; + + do { + switch (*s) { + case '$': + if (delaying == 0) + delaying = 1; + break; + case '<': + if (delaying == 1) + delaying = 2; + break; + case '\0': + delaying = 0; + break; + default: + if (delaying) { + s = skip_delay(s); + if (*s == '>') + ++s; + delaying = 0; + } + break; + } + if (delaying) + ++s; + } while (delaying); + return s; +} + /* * An sgr string may contain several settings other than the one we're * interested in, essentially sgr0 + rmacs + whatever. As long as the @@ -913,54 +1240,131 @@ check_params(TERMTYPE * tp, char *name, char *value) * sanity check. */ static bool -similar_sgr(char *a, char *b) +similar_sgr(int num, char *a, char *b) { + static const char *names[] = + { + "none" + ,"standout" + ,"underline" + ,"reverse" + ,"blink" + ,"dim" + ,"bold" + ,"invis" + ,"protect" + ,"altcharset" + }; + char *base_a = a; + char *base_b = b; + int delaying = 0; + while (*b != 0) { while (*a != *b) { - if (*a == 0) + if (*a == 0) { + if (b[0] == '$' + && b[1] == '<') { + _nc_warning("Did not find delay %s", _nc_visbuf(b)); + } else { + _nc_warning("checking sgr(%s) %s\n\tcompare to %s\n\tunmatched %s", + names[num], _nc_visbuf2(1, base_a), + _nc_visbuf2(2, base_b), + _nc_visbuf2(3, b)); + } return FALSE; - a++; + } else if (delaying) { + a = skip_delay(a); + b = skip_delay(b); + } else { + a++; + } + } + switch (*a) { + case '$': + if (delaying == 0) + delaying = 1; + break; + case '<': + if (delaying == 1) + delaying = 2; + break; + default: + delaying = 0; + break; } a++; b++; } - return TRUE; + /* ignore delays on the end of the string */ + a = ignore_delays(a); + return ((num != 0) || (*a == 0)); } -static void -check_sgr(TERMTYPE * tp, char *zero, int num, char *cap, const char *name) +static char * +check_sgr(TERMTYPE *tp, char *zero, int num, char *cap, const char *name) { - char *test = tparm(set_attributes, - num == 1, - num == 2, - num == 3, - num == 4, - num == 5, - num == 6, - num == 7, - num == 8, - num == 9); + char *test; + + _nc_tparm_err = 0; + test = TPARM_9(set_attributes, + num == 1, + num == 2, + num == 3, + num == 4, + num == 5, + num == 6, + num == 7, + num == 8, + num == 9); if (test != 0) { if (PRESENT(cap)) { - if (!similar_sgr(test, cap)) { - _nc_warning("%s differs from sgr(%d): %s", name, num, - _nc_visbuf(test)); + if (!similar_sgr(num, test, cap)) { + _nc_warning("%s differs from sgr(%d)\n\t%s=%s\n\tsgr(%d)=%s", + name, num, + name, _nc_visbuf2(1, cap), + num, _nc_visbuf2(2, test)); } - } else if (strcmp(test, zero)) { + } else if (_nc_capcmp(test, zero)) { _nc_warning("sgr(%d) present, but not %s", num, name); } } else if (PRESENT(cap)) { _nc_warning("sgr(%d) missing, but %s present", num, name); } + if (_nc_tparm_err) + _nc_warning("stack error in sgr(%d) string", num); + return test; } #define CHECK_SGR(num,name) check_sgr(tp, zero, num, name, #name) +#ifdef TRACE +/* + * If tic is compiled with TRACE, we'll be able to see the output from the + * DEBUG() macro. But since it doesn't use traceon(), it always goes to + * the standard error. Use this function to make it simpler to follow the + * resulting debug traces. + */ +static void +show_where(unsigned level) +{ + if (_nc_tracing >= DEBUG_LEVEL(level)) { + char my_name[256]; + _nc_get_type(my_name); + fprintf(stderr, "\"%s\", line %d, '%s' ", + _nc_get_source(), + _nc_curr_line, my_name); + } +} + +#else +#define show_where(level) /* nothing */ +#endif + /* other sanity-checks (things that we don't want in the normal * logic that reads a terminfo entry) */ static void -check_termtype(TERMTYPE * tp) +check_termtype(TERMTYPE *tp, bool literal) { bool conflict = FALSE; unsigned j, k; @@ -971,37 +1375,39 @@ check_termtype(TERMTYPE * tp) * a given string (e.g., KEY_END and KEY_LL). But curses will only * return one (the last one assigned). */ - memset(fkeys, 0, sizeof(fkeys)); - for (j = 0; _nc_tinfo_fkeys[j].code; j++) { - char *a = tp->Strings[_nc_tinfo_fkeys[j].offset]; - 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]) + 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]; + bool first = TRUE; + if (!VALID_STRING(a)) continue; - if (!strcmp(a, b)) { - fkeys[j] = 1; - fkeys[k] = 1; - if (first) { - if (!conflict) { - _nc_warning("Conflicting key definitions (using the last)"); - conflict = TRUE; + 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]) + continue; + if (!_nc_capcmp(a, b)) { + fkeys[j] = 1; + fkeys[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)); + first = FALSE; + } else { + fprintf(stderr, ", %s", + keyname((int) _nc_tinfo_fkeys[k].code)); } - fprintf(stderr, "... %s is the same as %s", - keyname(_nc_tinfo_fkeys[j].code), - keyname(_nc_tinfo_fkeys[k].code)); - first = FALSE; - } else { - fprintf(stderr, ", %s", - keyname(_nc_tinfo_fkeys[k].code)); } } + if (!first) + fprintf(stderr, "\n"); } - if (!first) - fprintf(stderr, "\n"); } for (j = 0; j < NUM_STRINGS(tp); j++) { @@ -1010,16 +1416,9 @@ check_termtype(TERMTYPE * tp) check_params(tp, ExtStrname(tp, j, strnames), a); } - /* - * Quick check for color. We could also check if the ANSI versus - * non-ANSI strings are misused. - */ - if ((max_colors > 0) != (max_pairs > 0) - || (max_colors > max_pairs)) - _nc_warning("inconsistent values for max_colors and max_pairs"); - - PAIRED(set_foreground, set_background); - PAIRED(set_a_foreground, set_a_background); + check_acs(tp); + check_colors(tp); + check_keypad(tp); /* * These may be mismatched because the terminal description relies on @@ -1029,7 +1428,7 @@ check_termtype(TERMTYPE * tp) ANDMISSING(cursor_visible, cursor_normal); if (PRESENT(cursor_visible) && PRESENT(cursor_normal) - && !strcmp(cursor_visible, cursor_normal)) + && !_nc_capcmp(cursor_visible, cursor_normal)) _nc_warning("cursor_visible is same as cursor_normal"); /* @@ -1041,35 +1440,89 @@ check_termtype(TERMTYPE * tp) ANDMISSING(change_scroll_region, restore_cursor); if (PRESENT(set_attributes)) { - char *zero = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0); - - zero = strdup(zero); - CHECK_SGR(1, enter_standout_mode); - CHECK_SGR(2, enter_underline_mode); - CHECK_SGR(3, enter_reverse_mode); - CHECK_SGR(4, enter_blink_mode); - CHECK_SGR(5, enter_dim_mode); - CHECK_SGR(6, enter_bold_mode); - CHECK_SGR(7, enter_secure_mode); - CHECK_SGR(8, enter_protected_mode); - CHECK_SGR(9, enter_alt_charset_mode); - free(zero); + char *zero = 0; + + _nc_tparm_err = 0; + if (PRESENT(exit_attribute_mode)) { + zero = strdup(CHECK_SGR(0, exit_attribute_mode)); + } else { + zero = strdup(TPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + } + if (_nc_tparm_err) + _nc_warning("stack error in sgr(0) string"); + + if (zero != 0) { + CHECK_SGR(1, enter_standout_mode); + CHECK_SGR(2, enter_underline_mode); + CHECK_SGR(3, enter_reverse_mode); + CHECK_SGR(4, enter_blink_mode); + CHECK_SGR(5, enter_dim_mode); + CHECK_SGR(6, enter_bold_mode); + CHECK_SGR(7, enter_secure_mode); + CHECK_SGR(8, enter_protected_mode); + CHECK_SGR(9, enter_alt_charset_mode); + free(zero); + } else { + _nc_warning("sgr(0) did not return a value"); + } + } else if (PRESENT(exit_attribute_mode) && + set_attributes != CANCELLED_STRING) { + if (_nc_syntax == SYN_TERMINFO) + _nc_warning("missing sgr string"); } + if (PRESENT(exit_attribute_mode)) { + char *check_sgr0 = _nc_trim_sgr0(tp); + + if (check_sgr0 == 0 || *check_sgr0 == '\0') { + _nc_warning("trimmed sgr0 is empty"); + } else { + show_where(2); + if (check_sgr0 != exit_attribute_mode) { + DEBUG(2, + ("will trim sgr0\n\toriginal sgr0=%s\n\ttrimmed sgr0=%s", + _nc_visbuf2(1, exit_attribute_mode), + _nc_visbuf2(2, check_sgr0))); + free(check_sgr0); + } else { + DEBUG(2, + ("will not trim sgr0\n\toriginal sgr0=%s", + _nc_visbuf(exit_attribute_mode))); + } + } + } +#ifdef TRACE + show_where(2); + if (!auto_right_margin) { + DEBUG(2, + ("can write to lower-right directly")); + } else if (PRESENT(enter_am_mode) && PRESENT(exit_am_mode)) { + DEBUG(2, + ("can write to lower-right by suppressing automargin")); + } else if ((PRESENT(enter_insert_mode) && PRESENT(exit_insert_mode)) + || PRESENT(insert_character) || PRESENT(parm_ich)) { + DEBUG(2, + ("can write to lower-right by using inserts")); + } else { + DEBUG(2, + ("cannot write to lower-right")); + } +#endif + /* * Some standard applications (e.g., vi) and some non-curses - * applications (e.g., jove) get confused if we have both ich/ich1 and + * applications (e.g., jove) get confused if we have both ich1 and * smir/rmir. Let's be nice and warn about that, too, even though * ncurses handles it. */ if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode)) - && (PRESENT(insert_character) || PRESENT(parm_ich))) { - _nc_warning("non-curses applications may be confused by ich/ich1 with smir/rmir"); + && PRESENT(parm_ich)) { + _nc_warning("non-curses applications may be confused by ich1 with smir/rmir"); } /* * Finally, do the non-verbose checks */ if (save_check_termtype != 0) - save_check_termtype(tp); + save_check_termtype(tp, literal); } |