summaryrefslogtreecommitdiff
path: root/progs
diff options
context:
space:
mode:
Diffstat (limited to 'progs')
-rw-r--r--progs/Makefile.in40
-rwxr-xr-xprogs/capconvert24
-rw-r--r--progs/clear.c12
-rw-r--r--progs/dump_entry.c258
-rw-r--r--progs/dump_entry.h19
-rw-r--r--progs/infocmp.c492
-rw-r--r--progs/modules9
-rw-r--r--progs/progs.priv.h27
-rw-r--r--progs/tabs.c146
-rw-r--r--progs/tic.c890
-rw-r--r--progs/toe.c456
-rw-r--r--progs/tparm_type.c68
-rw-r--r--progs/tparm_type.h52
-rw-r--r--progs/tput.c56
-rw-r--r--progs/transform.c16
-rw-r--r--progs/tset.c121
16 files changed, 2040 insertions, 646 deletions
diff --git a/progs/Makefile.in b/progs/Makefile.in
index bdb8a0f..5a74634 100644
--- a/progs/Makefile.in
+++ b/progs/Makefile.in
@@ -1,6 +1,6 @@
-# $Id: Makefile.in,v 1.85 2010/11/27 21:45:27 tom Exp $
+# $Id: Makefile.in,v 1.93 2014/11/15 00:34:28 tom Exp $
##############################################################################
-# Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. #
+# Copyright (c) 1998-2013,2014 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"), #
@@ -61,9 +61,16 @@ exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
+datarootdir = @datarootdir@
datadir = @datadir@
+includesubdir = @includesubdir@
+
+INCLUDEDIR = $(DESTDIR)$(includedir)$(includesubdir)
+
+PACKAGE = @PACKAGE@
LIBTOOL = @LIBTOOL@
+LIBTOOL_OPTS = @LIBTOOL_OPTS@
LIBTOOL_CLEAN = @LIB_CLEAN@
LIBTOOL_COMPILE = @LIB_COMPILE@
LIBTOOL_LINK = @LIB_LINK@
@@ -85,7 +92,7 @@ CPP = @CPP@
CFLAGS = @CFLAGS@
INCDIR = $(top_srcdir)/include
-CPPFLAGS = -I../progs -I$(srcdir) -DHAVE_CONFIG_H @CPPFLAGS@
+CPPFLAGS = -DHAVE_CONFIG_H @CPPFLAGS@
CCFLAGS = $(CPPFLAGS) $(CFLAGS)
@@ -104,20 +111,21 @@ LOCAL_LIBDIR = @top_builddir@/lib
LD = @LD@
LINK = @LINK_PROGS@ $(LIBTOOL_LINK)
LDFLAGS = @EXTRA_LDFLAGS@ @LDFLAGS@
+RPATH_LIST = @RPATH_LIST@
LDFLAGS_LIBTOOL = $(LDFLAGS) $(CFLAGS_LIBTOOL)
LDFLAGS_NORMAL = $(LDFLAGS) $(CFLAGS_NORMAL)
LDFLAGS_DEBUG = $(LDFLAGS) $(CFLAGS_DEBUG)
-LDFLAGS_PROFILE = $(LDFLAGS) $(CFLAGS_PROFILE)
+LDFLAGS_PROFILE = $(LDFLAGS) $(CFLAGS_PROFILE)
LDFLAGS_SHARED = $(LDFLAGS) $(CFLAGS_SHARED) @LD_SHARED_OPTS@
LDFLAGS_DEFAULT = $(LDFLAGS_@DFT_UPR_MODEL@)
-LIBS_TIC = @LDFLAGS_STATIC@ @TICS_ARGS@ @TINFO_ARGS@ @LDFLAGS_SHARED@ @LD_MODEL@ @LIBS@
-LDFLAGS_TIC = $(LDFLAGS_@DFT_UPR_MODEL@) $(LIBS_TIC)
+LIBS_TIC = @TINFO_LDFLAGS@ @LDFLAGS_STATIC@ @TICS_LIBS@ @TINFO_LIBS@ @LDFLAGS_SHARED@ @LD_MODEL@ @LIBS@
+LDFLAGS_TIC = @TICS_LDFLAGS@ $(LDFLAGS_@DFT_UPR_MODEL@) $(LIBS_TIC)
-LIBS_TINFO = @LDFLAGS_STATIC@ @TINFO_ARGS@ @LDFLAGS_SHARED@ @LD_MODEL@ @LIBS@
-LDFLAGS_TINFO = $(LDFLAGS_@DFT_UPR_MODEL@) $(LIBS_TINFO)
+LIBS_TINFO = @LDFLAGS_STATIC@ @TINFO_LIBS@ @LDFLAGS_SHARED@ @LD_MODEL@ @LIBS@
+LDFLAGS_TINFO = @TINFO_LDFLAGS@ $(LDFLAGS_@DFT_UPR_MODEL@) $(LIBS_TINFO)
LINT = @LINT@
LINT_OPTS = @LINT_OPTS@
@@ -227,49 +235,51 @@ $(DESTDIR)$(bindir) :
DEPS_TIC = \
$(MODEL)/tic$o \
$(MODEL)/dump_entry$o \
+ $(MODEL)/tparm_type$o \
$(MODEL)/transform$o
tic$x: $(DEPS_TIC) $(DEPS_CURSES) transform.h
- @ECHO_LINK@ $(LINK) $(DEPS_TIC) $(LDFLAGS_TIC) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_TIC) $(LDFLAGS_TIC) -o $@
DEPS_TOE = \
$(MODEL)/toe$o
toe$x: $(DEPS_TOE) $(DEPS_CURSES)
- @ECHO_LINK@ $(LINK) $(DEPS_TOE) $(LDFLAGS_TIC) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_TOE) $(LDFLAGS_TIC) -o $@
DEPS_CLEAR = \
$(MODEL)/clear$o
clear$x: $(DEPS_CLEAR) $(DEPS_CURSES)
- @ECHO_LINK@ $(LINK) $(DEPS_CLEAR) $(LDFLAGS_TINFO) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_CLEAR) $(LDFLAGS_TINFO) -o $@
DEPS_TABS = \
$(MODEL)/tabs$o
tabs$x: $(DEPS_TABS) $(DEPS_TABS)
- @ECHO_LINK@ $(LINK) $(DEPS_TABS) $(LDFLAGS_TINFO) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_TABS) $(LDFLAGS_TINFO) -o $@
DEPS_TPUT = \
$(MODEL)/tput$o \
+ $(MODEL)/tparm_type$o \
$(MODEL)/transform$o
tput$x: $(DEPS_TPUT) $(DEPS_CURSES) transform.h
- @ECHO_LINK@ $(LINK) $(DEPS_TPUT) $(LDFLAGS_TINFO) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_TPUT) $(LDFLAGS_TINFO) -o $@
DEPS_INFOCMP = \
$(MODEL)/infocmp$o \
$(MODEL)/dump_entry$o
infocmp$x: $(DEPS_INFOCMP) $(DEPS_CURSES)
- @ECHO_LINK@ $(LINK) $(DEPS_INFOCMP) $(LDFLAGS_TIC) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_INFOCMP) $(LDFLAGS_TIC) -o $@
DEPS_TSET = \
$(MODEL)/tset$o \
$(MODEL)/transform$o
tset$x: $(DEPS_TSET) $(DEPS_CURSES) transform.h
- @ECHO_LINK@ $(LINK) $(DEPS_TSET) $(LDFLAGS_TINFO) -o $@
+ @ECHO_LD@ $(LINK) $(DEPS_TSET) $(LDFLAGS_TINFO) -o $@
termsort.c: $(srcdir)/MKtermsort.sh
sh $(srcdir)/MKtermsort.sh $(AWK) $(srcdir)/../include/@TERMINFO_CAPS@ >$@
diff --git a/progs/capconvert b/progs/capconvert
index 8199bbf..eb382e0 100755
--- a/progs/capconvert
+++ b/progs/capconvert
@@ -1,6 +1,6 @@
#!/bin/sh
##############################################################################
-# Copyright (c) 1998,2006 Free Software Foundation, Inc. #
+# Copyright (c) 1998-2006,2011 Free Software Foundation, Inc. #
# #
# Permission is hereby granted, free of charge, to any person obtaining a #
# copy of this software and associated documentation files (the "Software"), #
@@ -26,7 +26,7 @@
# use or other dealings in this Software without prior written #
# authorization. #
##############################################################################
-# $Id: capconvert,v 1.4 2006/04/22 21:46:17 tom Exp $
+# $Id: capconvert,v 1.5 2011/11/12 23:28:07 Robert.Millan Exp $
#
# capconvert -- automated conversion from termcap to terminfo
#
@@ -77,16 +77,18 @@ then
# Assumes the terminfo master covers all canned terminal types
exit;
fi
- if test "$TERM" = "xterm"
- then
+ case $TERM in
+ xterm | xterm-*)
echo "You are running xterm, which usually sets TERMCAP itself."
echo "We can ignore this, because terminfo knows about xterm."
echo "So you will just use the system-wide terminfo tree."
- exit;
- else
+ exit
+ ;;
+ *)
echo "We will have to make a local one for you anyway, to capture the effect"
echo "of your TERMCAP variable."
- fi
+ ;;
+ esac
else
echo "No system-wide terminfo tree. We will make you a local one."
fi
@@ -109,7 +111,7 @@ IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:"
for x in $PATH .
do
if test $OPT $x/tic
- then
+ then
TIC=$x/tic
break
fi
@@ -141,7 +143,7 @@ if test -d $HOME/.terminfo
then
echo "It appears you already have a private terminfo directory"
echo "at $HOME/.terminfo; this seems odd, because TERMINFO"
- echo "is not defined. I am not going to second-guess this -- if you"
+ echo "is not defined. I am not going to second-guess this -- if you"
echo "really want me to try auto-configuring for you, remove or"
echo "rename $HOME/terminfo and run me again."
exit;
@@ -214,7 +216,7 @@ trap 0 1 2 5 15
#
echo "You now have a private tree under $HOME/.terminfo;"
echo "the ncurses library will automatically read from it,"
-echo "and ncurses tic will automatically compile entries to it."
+echo "and ncurses tic will automatically compile entries to it."
# We're done unless user has a .termcap file or equivalent named by TERMCAP
if test -z "$TERMCAP"
@@ -235,7 +237,7 @@ then
echo "Done."
echo "Note that editing $HOME/.termcap will no longer change the data curses sees."
elif test -f "$TERMCAP"
-then
+then
echo "Your TERMCAP names the file $TERMCAP. I will compile that."
eval $TIC $TERMCAP
echo "Done."
diff --git a/progs/clear.c b/progs/clear.c
index 9f5a543..4ac503e 100644
--- a/progs/clear.c
+++ b/progs/clear.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2007,2013 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 *
@@ -39,7 +39,7 @@
#define USE_LIBTINFO
#include <progs.priv.h>
-MODULE_ID("$Id: clear.c,v 1.11 2007/10/13 22:16:02 tom Exp $")
+MODULE_ID("$Id: clear.c,v 1.13 2013/06/22 22:20:54 tom Exp $")
static int
putch(int c)
@@ -52,7 +52,15 @@ main(
int argc GCC_UNUSED,
char *argv[]GCC_UNUSED)
{
+ char *E3;
+
setupterm((char *) 0, STDOUT_FILENO, (int *) 0);
+
+ /* Clear the scrollback buffer if possible. */
+ E3 = tigetstr("E3");
+ if (E3)
+ (void) tputs(E3, lines > 0 ? lines : 1, putch);
+
ExitProgram((tputs(clear_screen, lines > 0 ? lines : 1, putch) == ERR)
? EXIT_FAILURE
: EXIT_SUCCESS);
diff --git a/progs/dump_entry.c b/progs/dump_entry.c
index 485bbbd..0f6a8b0 100644
--- a/progs/dump_entry.c
+++ b/progs/dump_entry.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2008,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2013,2014 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 *
@@ -39,7 +39,7 @@
#include "termsort.c" /* this C file is generated */
#include <parametrized.h> /* so is this */
-MODULE_ID("$Id: dump_entry.c,v 1.89 2010/05/01 22:04:08 tom Exp $")
+MODULE_ID("$Id: dump_entry.c,v 1.114 2014/10/18 09:32:54 tom Exp $")
#define INDENT 8
#define DISCARD(string) string = ABSENT_STRING
@@ -57,6 +57,7 @@ static int tversion; /* terminfo version */
static int outform; /* output format to use */
static int sortmode; /* sort mode to use */
static int width = 60; /* max line width for listings */
+static int height = 65535; /* max number of lines for listings */
static int column; /* current column, limited by 'width' */
static int oldcol; /* last value of column before wrap */
static bool pretty; /* true if we format if-then-else strings */
@@ -72,7 +73,7 @@ static NCURSES_CONST char *const *bool_names;
static NCURSES_CONST char *const *num_names;
static NCURSES_CONST char *const *str_names;
-static const char *separator, *trailer;
+static const char *separator = "", *trailer = "";
/* cover various ports and variants of terminfo */
#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */
@@ -99,6 +100,15 @@ static const char *separator, *trailer;
#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j])
#endif
+static void failed(const char *) GCC_NORETURN;
+
+static void
+failed(const char *s)
+{
+ perror(s);
+ ExitProgram(EXIT_FAILURE);
+}
+
static void
strncpy_DYN(DYNBUF * dst, const char *src, size_t need)
{
@@ -106,6 +116,8 @@ strncpy_DYN(DYNBUF * dst, const char *src, size_t need)
if (want > dst->size) {
dst->size += (want + 1024); /* be generous */
dst->text = typeRealloc(char, dst->size, dst->text);
+ if (dst->text == 0)
+ failed("strncpy_DYN");
}
(void) strncpy(dst->text + dst->used, src, need);
dst->used += need;
@@ -172,11 +184,17 @@ nametrans(const char *name)
}
void
-dump_init(const char *version, int mode, int sort, int twidth, int traceval,
+dump_init(const char *version,
+ int mode,
+ int sort,
+ int twidth,
+ int theight,
+ unsigned traceval,
bool formatted)
/* set up for entry display */
{
width = twidth;
+ height = theight;
pretty = formatted;
/* versions */
@@ -201,7 +219,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval,
bool_names = boolnames;
num_names = numnames;
str_names = strnames;
- separator = twidth ? ", " : ",";
+ separator = (twidth > 0 && theight > 1) ? ", " : ",";
trailer = "\n\t";
break;
@@ -209,7 +227,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval,
bool_names = boolfnames;
num_names = numfnames;
str_names = strfnames;
- separator = twidth ? ", " : ",";
+ separator = (twidth > 0 && theight > 1) ? ", " : ",";
trailer = "\n\t";
break;
@@ -291,7 +309,11 @@ dump_predicate(PredType type, PredIdx idx)
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))
+#define FNKEY(i) \
+ (((i) >= STR_IDX(key_f0) && \
+ (i) <= STR_IDX(key_f9)) || \
+ ((i) >= STR_IDX(key_f11) && \
+ (i) <= STR_IDX(key_f63)))
/*
* If we configure with a different Caps file, the offsets into the arrays
@@ -393,8 +415,8 @@ force_wrap(void)
static void
wrap_concat(const char *src)
{
- unsigned need = strlen(src);
- unsigned want = strlen(separator) + need;
+ size_t need = strlen(src);
+ size_t want = strlen(separator) + need;
if (column > INDENT
&& column + (int) want > width) {
@@ -445,10 +467,10 @@ indent_DYN(DYNBUF * buffer, int level)
int n;
for (n = 0; n < level; n++)
- strncpy_DYN(buffer, "\t", 1);
+ strncpy_DYN(buffer, "\t", (size_t) 1);
}
-static bool
+bool
has_params(const char *src)
{
bool result = FALSE;
@@ -458,9 +480,9 @@ has_params(const char *src)
bool params = FALSE;
for (n = 0; n < len - 1; ++n) {
- if (!strncmp(src + n, "%p", 2)) {
+ if (!strncmp(src + n, "%p", (size_t) 2)) {
params = TRUE;
- } else if (!strncmp(src + n, "%;", 2)) {
+ } else if (!strncmp(src + n, "%;", (size_t) 2)) {
ifthen = TRUE;
result = params;
break;
@@ -473,7 +495,7 @@ has_params(const char *src)
}
static char *
-fmt_complex(char *src, int level)
+fmt_complex(TERMTYPE *tterm, const char *capability, char *src, int level)
{
bool percent = FALSE;
bool params = has_params(src);
@@ -482,7 +504,7 @@ fmt_complex(char *src, int level)
switch (*src) {
case '\\':
percent = FALSE;
- strncpy_DYN(&tmpbuf, src++, 1);
+ strncpy_DYN(&tmpbuf, src++, (size_t) 1);
break;
case '%':
percent = TRUE;
@@ -496,26 +518,28 @@ fmt_complex(char *src, int level)
/* 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, 1);
+ strncpy_DYN(&tmpbuf, "%", (size_t) 1);
+ strncpy_DYN(&tmpbuf, src, (size_t) 1);
src++;
params = has_params(src);
if (!params && *src != '\0' && *src != '%') {
- strncpy_DYN(&tmpbuf, "\n", 1);
+ strncpy_DYN(&tmpbuf, "\n", (size_t) 1);
indent_DYN(&tmpbuf, level + 1);
}
} else {
indent_DYN(&tmpbuf, level + 1);
- strncpy_DYN(&tmpbuf, "%", 1);
- strncpy_DYN(&tmpbuf, src, 1);
+ strncpy_DYN(&tmpbuf, "%", (size_t) 1);
+ strncpy_DYN(&tmpbuf, src, (size_t) 1);
if (*src++ == '?') {
- src = fmt_complex(src, level + 1);
+ src = fmt_complex(tterm, capability, src, level + 1);
if (*src != '\0' && *src != '%') {
- strncpy_DYN(&tmpbuf, "\n", 1);
+ strncpy_DYN(&tmpbuf, "\n", (size_t) 1);
indent_DYN(&tmpbuf, level + 1);
}
} else if (level == 1) {
- _nc_warning("%%%c without %%?", *src);
+ _nc_warning("%s: %%%c without %%? in %s",
+ _nc_first_name(tterm->term_names),
+ *src, capability);
}
}
continue;
@@ -527,31 +551,39 @@ fmt_complex(char *src, int level)
if (level > 1) {
tmpbuf.text[tmpbuf.used - 1] = '\n';
indent_DYN(&tmpbuf, level);
- strncpy_DYN(&tmpbuf, "%", 1);
- strncpy_DYN(&tmpbuf, src++, 1);
+ strncpy_DYN(&tmpbuf, "%", (size_t) 1);
+ strncpy_DYN(&tmpbuf, src++, (size_t) 1);
+ if (src[0] == '%'
+ && src[1] != '\0'
+ && (strchr("?e;", src[1])) == 0) {
+ tmpbuf.text[tmpbuf.used++] = '\n';
+ indent_DYN(&tmpbuf, level);
+ }
return src;
}
- _nc_warning("%%; without %%?");
+ _nc_warning("%s: %%; without %%? in %s",
+ _nc_first_name(tterm->term_names),
+ capability);
}
break;
case 'p':
if (percent && params) {
tmpbuf.text[tmpbuf.used - 1] = '\n';
indent_DYN(&tmpbuf, level + 1);
- strncpy_DYN(&tmpbuf, "%", 1);
+ strncpy_DYN(&tmpbuf, "%", (size_t) 1);
}
params = FALSE;
percent = FALSE;
break;
case ' ':
- strncpy_DYN(&tmpbuf, "\\s", 2);
+ strncpy_DYN(&tmpbuf, "\\s", (size_t) 2);
++src;
continue;
default:
percent = FALSE;
break;
}
- strncpy_DYN(&tmpbuf, src++, 1);
+ strncpy_DYN(&tmpbuf, src++, (size_t) 1);
}
return src;
}
@@ -562,9 +594,9 @@ fmt_complex(char *src, int level)
int
fmt_entry(TERMTYPE *tterm,
PredFunc pred,
- bool content_only,
- bool suppress_untranslatable,
- bool infodump,
+ int content_only,
+ int suppress_untranslatable,
+ int infodump,
int numbers)
{
PredIdx i, j;
@@ -593,14 +625,28 @@ fmt_entry(TERMTYPE *tterm,
column = INDENT; /* FIXME: workaround to prevent empty lines */
} else {
strcpy_DYN(&outbuf, tterm->term_names);
+
+ /*
+ * Colon is legal in terminfo descriptions, but not in termcap.
+ */
+ if (!infodump) {
+ char *p = outbuf.text;
+ while (*p) {
+ if (*p == ':') {
+ *p = '=';
+ }
+ ++p;
+ }
+ }
strcpy_DYN(&outbuf, separator);
column = (int) outbuf.used;
- force_wrap();
+ if (height > 1)
+ force_wrap();
}
for_each_boolean(j, tterm) {
i = BoolIndirect(j);
- name = ExtBoolname(tterm, i, bool_names);
+ name = ExtBoolname(tterm, (int) i, bool_names);
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
if (!version_filter(BOOLEAN, i))
@@ -610,21 +656,21 @@ fmt_entry(TERMTYPE *tterm,
predval = pred(BOOLEAN, i);
if (predval != FAIL) {
- (void) strcpy(buffer, name);
+ _nc_STRCPY(buffer, name, sizeof(buffer));
if (predval <= 0)
- (void) strcat(buffer, "@");
+ _nc_STRCAT(buffer, "@", sizeof(buffer));
else if (i + 1 > num_bools)
num_bools = i + 1;
WRAP_CONCAT;
}
}
- if (column != INDENT)
+ if (column != INDENT && height > 1)
force_wrap();
for_each_number(j, tterm) {
i = NumIndirect(j);
- name = ExtNumname(tterm, i, num_names);
+ name = ExtNumname(tterm, (int) i, num_names);
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
if (!version_filter(NUMBER, i))
@@ -635,9 +681,11 @@ fmt_entry(TERMTYPE *tterm,
predval = pred(NUMBER, i);
if (predval != FAIL) {
if (tterm->Numbers[i] < 0) {
- sprintf(buffer, "%s@", name);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "%s@", name);
} else {
- sprintf(buffer, "%s#%d", name, tterm->Numbers[i]);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "%s#%d", name, tterm->Numbers[i]);
if (i + 1 > num_values)
num_values = i + 1;
}
@@ -645,7 +693,7 @@ fmt_entry(TERMTYPE *tterm,
}
}
- if (column != INDENT)
+ if (column != INDENT && height > 1)
force_wrap();
len += (int) (num_bools
@@ -670,7 +718,7 @@ fmt_entry(TERMTYPE *tterm,
for_each_string(j, tterm) {
i = StrIndirect(j);
- name = ExtStrname(tterm, i, str_names);
+ name = ExtStrname(tterm, (int) i, str_names);
assert(strlen(name) < sizeof(buffer) - EXTRA_CAP);
capability = tterm->Strings[i];
@@ -698,14 +746,14 @@ fmt_entry(TERMTYPE *tterm,
if (PRESENT(insert_character) || PRESENT(parm_ich)) {
if (SAME_CAP(i, enter_insert_mode)
&& enter_insert_mode == ABSENT_STRING) {
- (void) strcpy(buffer, "im=");
+ _nc_STRCPY(buffer, "im=", sizeof(buffer));
WRAP_CONCAT;
continue;
}
if (SAME_CAP(i, exit_insert_mode)
&& exit_insert_mode == ABSENT_STRING) {
- (void) strcpy(buffer, "ei=");
+ _nc_STRCPY(buffer, "ei=", sizeof(buffer));
WRAP_CONCAT;
continue;
}
@@ -739,24 +787,29 @@ fmt_entry(TERMTYPE *tterm,
num_strings = i + 1;
if (!VALID_STRING(capability)) {
- sprintf(buffer, "%s@", name);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(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(capability, TRUE, numbers);
+ int params = (((i < (int) SIZEOF(parametrized)) &&
+ (i < STRCOUNT))
+ ? parametrized[i]
+ : ((*srccap == 'k')
+ ? 0
+ : has_params(srccap)));
char *cv = _nc_infotocap(name, srccap, params);
if (cv == 0) {
if (outform == F_TCONVERR) {
- sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!",
- name, srccap);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "%s=!!! %s WILL NOT CONVERT !!!",
+ name, srccap);
} else if (suppress_untranslatable) {
continue;
} else {
char *s = srccap, *d = buffer;
- sprintf(d, "..%s=", name);
+ _nc_SPRINTF(d, _nc_SLIMIT(sizeof(buffer)) "..%s=", name);
d += strlen(d);
while ((*d = *s++) != 0) {
if (*d == ':') {
@@ -769,7 +822,8 @@ fmt_entry(TERMTYPE *tterm,
}
}
} else {
- sprintf(buffer, "%s=%s", name, cv);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "%s=%s", name, cv);
}
len += (int) strlen(capability) + 1;
WRAP_CONCAT;
@@ -783,7 +837,7 @@ fmt_entry(TERMTYPE *tterm,
if (pretty
&& (outform == F_TERMINFO
|| outform == F_VARIABLE)) {
- fmt_complex(src, 1);
+ fmt_complex(tterm, name, src, 1);
} else {
strcpy_DYN(&tmpbuf, src);
}
@@ -793,7 +847,9 @@ fmt_entry(TERMTYPE *tterm,
}
}
/* e.g., trimmed_sgr0 */
- if (capability != tterm->Strings[i])
+ if (capability != ABSENT_STRING &&
+ capability != CANCELLED_STRING &&
+ capability != tterm->Strings[i])
free(capability);
}
len += (int) (num_strings * 2);
@@ -805,11 +861,13 @@ fmt_entry(TERMTYPE *tterm,
*/
if (tversion == V_HPUX) {
if (VALID_STRING(memory_lock)) {
- (void) sprintf(buffer, "meml=%s", memory_lock);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "meml=%s", memory_lock);
WRAP_CONCAT;
}
if (VALID_STRING(memory_unlock)) {
- (void) sprintf(buffer, "memu=%s", memory_unlock);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "memu=%s", memory_unlock);
WRAP_CONCAT;
}
} else if (tversion == V_AIX) {
@@ -821,7 +879,7 @@ fmt_entry(TERMTYPE *tterm,
tp = boxchars;
for (cp = acstrans; *cp; cp++) {
- sp = strchr(acs_chars, *cp);
+ sp = (strchr) (acs_chars, *cp);
if (sp)
*tp++ = sp[1];
else {
@@ -832,9 +890,41 @@ fmt_entry(TERMTYPE *tterm,
tp[0] = '\0';
if (box_ok) {
- (void) strcpy(buffer, "box1=");
- (void) strcat(buffer, _nc_tic_expand(boxchars,
- outform == F_TERMINFO, numbers));
+ char *tmp = _nc_tic_expand(boxchars,
+ (outform == F_TERMINFO),
+ numbers);
+ _nc_STRCPY(buffer, "box1=", sizeof(buffer));
+ while (*tmp != '\0') {
+ size_t have = strlen(buffer);
+ size_t next = strlen(tmp);
+ size_t want = have + next + 1;
+ size_t last = next;
+ char save = '\0';
+
+ /*
+ * If the expanded string is too long for the buffer,
+ * chop it off and save the location where we chopped it.
+ */
+ if (want >= sizeof(buffer)) {
+ save = tmp[last];
+ tmp[last] = '\0';
+ }
+ _nc_STRCAT(buffer, tmp, sizeof(buffer));
+
+ /*
+ * If we chopped the buffer, replace the missing piece and
+ * shift everything to append the remainder.
+ */
+ if (save != '\0') {
+ next = 0;
+ tmp[last] = save;
+ while ((tmp[next] = tmp[last + next]) != '\0') {
+ ++next;
+ }
+ } else {
+ break;
+ }
+ }
WRAP_CONCAT;
}
}
@@ -846,7 +936,7 @@ fmt_entry(TERMTYPE *tterm,
*/
if (outcount) {
bool trimmed = FALSE;
- j = outbuf.used;
+ j = (PredIdx) outbuf.used;
if (j >= 2
&& outbuf.text[j - 1] == '\t'
&& outbuf.text[j - 2] == '\n') {
@@ -926,7 +1016,7 @@ kill_labels(TERMTYPE *tterm, int target)
char name[10];
for (n = 0; n <= 10; ++n) {
- sprintf(name, "lf%d", n);
+ _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n);
if ((cap = find_string(tterm, name)) != ABSENT_STRING
&& kill_string(tterm, cap)) {
target -= (int) (strlen(cap) + 5);
@@ -951,7 +1041,7 @@ kill_fkeys(TERMTYPE *tterm, int target)
char name[10];
for (n = 60; n >= 0; --n) {
- sprintf(name, "kf%d", n);
+ _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n);
if ((cap = find_string(tterm, name)) != ABSENT_STRING
&& kill_string(tterm, cap)) {
target -= (int) (strlen(cap) + 5);
@@ -1017,8 +1107,8 @@ purged_acs(TERMTYPE *tterm)
*/
void
dump_entry(TERMTYPE *tterm,
- bool suppress_untranslatable,
- bool limited,
+ int suppress_untranslatable,
+ int limited,
int numbers,
PredFunc pred)
{
@@ -1064,7 +1154,7 @@ dump_entry(TERMTYPE *tterm,
*/
unsigned n;
for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) {
- const char *name = ExtStrname(tterm, n, strnames);
+ const char *name = ExtStrname(tterm, (int) n, strnames);
if (VALID_STRING(tterm->Strings[n])) {
set_attributes = ABSENT_STRING;
@@ -1144,21 +1234,45 @@ dump_uses(const char *name, bool infodump)
if (outform == F_TERMCAP || outform == F_TCONVERR)
trim_trailing();
- (void) sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name);
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "%s%s", infodump ? "use=" : "tc=", name);
wrap_concat(buffer);
}
int
show_entry(void)
{
- trim_trailing();
+ /*
+ * Trim any remaining whitespace.
+ */
+ if (outbuf.used != 0) {
+ bool infodump = (outform != F_TERMCAP && outform != F_TCONVERR);
+ char delim = (char) (infodump ? ',' : ':');
+ int j;
+
+ for (j = (int) outbuf.used - 1; j > 0; --j) {
+ char ch = outbuf.text[j];
+ if (ch == '\n') {
+ ;
+ } else if (isspace(UChar(ch))) {
+ outbuf.used = (size_t) j;
+ } else if (!infodump && ch == '\\') {
+ outbuf.used = (size_t) j;
+ } else if (ch == delim && (j == 0 || outbuf.text[j - 1] != '\\')) {
+ outbuf.used = (size_t) (j + 1);
+ } else {
+ break;
+ }
+ }
+ outbuf.text[outbuf.used] = '\0';
+ }
(void) fputs(outbuf.text, stdout);
putchar('\n');
return (int) outbuf.used;
}
void
-compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
+compare_entry(PredHook hook,
TERMTYPE *tp GCC_UNUSED,
bool quiet)
/* compare two entries */
@@ -1170,7 +1284,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
fputs(" comparing booleans.\n", stdout);
for_each_boolean(j, tp) {
i = BoolIndirect(j);
- name = ExtBoolname(tp, i, bool_names);
+ name = ExtBoolname(tp, (int) i, bool_names);
if (isObsolete(outform, name))
continue;
@@ -1182,7 +1296,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
fputs(" comparing numbers.\n", stdout);
for_each_number(j, tp) {
i = NumIndirect(j);
- name = ExtNumname(tp, i, num_names);
+ name = ExtNumname(tp, (int) i, num_names);
if (isObsolete(outform, name))
continue;
@@ -1194,7 +1308,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name),
fputs(" comparing strings.\n", stdout);
for_each_string(j, tp) {
i = StrIndirect(j);
- name = ExtStrname(tp, i, str_names);
+ name = ExtStrname(tp, (int) i, str_names);
if (isObsolete(outform, name))
continue;
diff --git a/progs/dump_entry.h b/progs/dump_entry.h
index b99a37a..8b61808 100644
--- a/progs/dump_entry.h
+++ b/progs/dump_entry.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2013,2014 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 *
@@ -32,9 +32,8 @@
* and: Thomas E. Dickey 1996-on *
****************************************************************************/
-
/*
- * $Id: dump_entry.h,v 1.30 2008/07/12 20:23:03 tom Exp $
+ * $Id: dump_entry.h,v 1.34 2014/10/18 09:34:15 tom Exp $
*
* Dump control definitions and variables
*/
@@ -64,16 +63,18 @@
typedef unsigned PredType;
typedef unsigned PredIdx;
-typedef int (*PredFunc)(PredType, PredIdx);
+typedef int (*PredFunc) (PredType, PredIdx);
+typedef void (*PredHook) (PredType, PredIdx, const char *);
extern NCURSES_CONST char *nametrans(const char *);
-extern int fmt_entry(TERMTYPE *, PredFunc, bool, bool, bool, int);
+extern bool has_params(const char *src);
+extern int fmt_entry(TERMTYPE *, PredFunc, int, int, int, 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 void compare_entry(PredHook, TERMTYPE *, bool);
+extern void dump_entry(TERMTYPE *, int, int, int, PredFunc);
+extern void dump_init(const char *, int, int, int, int, unsigned, bool);
extern void dump_uses(const char *, bool);
-extern void repair_acsc(TERMTYPE * tp);
+extern void repair_acsc(TERMTYPE *tp);
#define FAIL -1
diff --git a/progs/infocmp.c b/progs/infocmp.c
index 2af9cb5..587cbc3 100644
--- a/progs/infocmp.c
+++ b/progs/infocmp.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2013,2014 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 *
@@ -42,7 +42,7 @@
#include <dump_entry.h>
-MODULE_ID("$Id: infocmp.c,v 1.105 2010/05/01 22:04:08 tom Exp $")
+MODULE_ID("$Id: infocmp.c,v 1.129 2014/02/01 22:11:03 tom Exp $")
#define L_CURL "{"
#define R_CURL "}"
@@ -70,8 +70,9 @@ static const char *bool_sep = ":";
static const char *s_absent = "NULL";
static const char *s_cancel = "NULL";
static const char *tversion; /* terminfo version selected */
-static int itrace; /* trace flag for debugging */
+static unsigned itrace; /* trace flag for debugging */
static int mwidth = 60;
+static int mheight = 65535;
static int numbers = 0; /* format "%'char'" to/from "%{number}" */
static int outform = F_TERMINFO; /* output format */
static int sortmode; /* sort_mode */
@@ -86,27 +87,52 @@ static int compare;
static bool ignorepads; /* ignore pad prefixes when diffing */
#if NO_LEAKS
+
+typedef struct {
+ ENTRY *head;
+ ENTRY *tail;
+} ENTERED;
+
+static ENTERED *entered;
+
#undef ExitProgram
static void ExitProgram(int code) GCC_NORETURN;
/* prototype is to get gcc to accept the noreturn attribute */
static void
ExitProgram(int code)
{
- while (termcount-- > 0)
- _nc_free_termtype(&entries[termcount].tterm);
+ int n;
+
+ for (n = 0; n < termcount; ++n) {
+ ENTRY *new_head = _nc_head;
+ ENTRY *new_tail = _nc_tail;
+ _nc_head = entered[n].head;
+ _nc_tail = entered[n].tail;
+ _nc_free_entries(entered[n].head);
+ _nc_head = new_head;
+ _nc_tail = new_tail;
+ }
_nc_leaks_dump_entry();
free(entries);
+ free(entered);
_nc_free_tic(code);
}
#endif
+static void
+failed(const char *s)
+{
+ perror(s);
+ ExitProgram(EXIT_FAILURE);
+}
+
static char *
canonical_name(char *ptr, char *buf)
/* extract the terminal type's primary name */
{
char *bp;
- (void) strcpy(buf, ptr);
+ _nc_STRCPY(buf, ptr, NAMESIZE);
if ((bp = strchr(buf, '|')) != 0)
*bp = '\0';
@@ -307,13 +333,13 @@ dump_numeric(int val, char *buf)
{
switch (val) {
case ABSENT_NUMERIC:
- strcpy(buf, s_absent);
+ _nc_STRCPY(buf, s_absent, MAX_STRING);
break;
case CANCELLED_NUMERIC:
- strcpy(buf, s_cancel);
+ _nc_STRCPY(buf, s_cancel, MAX_STRING);
break;
default:
- sprintf(buf, "%d", val);
+ _nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING) "%d", val);
break;
}
}
@@ -323,31 +349,94 @@ dump_string(char *val, char *buf)
/* display the value of a string capability */
{
if (val == ABSENT_STRING)
- strcpy(buf, s_absent);
+ _nc_STRCPY(buf, s_absent, MAX_STRING);
else if (val == CANCELLED_STRING)
- strcpy(buf, s_cancel);
+ _nc_STRCPY(buf, s_cancel, MAX_STRING);
else {
- sprintf(buf, "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val));
+ _nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING)
+ "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val));
}
}
+/*
+ * Show "comparing..." message for the given terminal names.
+ */
+static void
+show_comparing(char **names)
+{
+ if (itrace) {
+ switch (compare) {
+ case C_DIFFERENCE:
+ (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname);
+ break;
+
+ case C_COMMON:
+ (void) fprintf(stderr, "%s: dumping common capabilities\n", _nc_progname);
+ break;
+
+ case C_NAND:
+ (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname);
+ break;
+ }
+ }
+ if (*names) {
+ printf("comparing %s", *names++);
+ if (*names) {
+ printf(" to %s", *names++);
+ while (*names) {
+ printf(", %s", *names++);
+ }
+ }
+ printf(".\n");
+ }
+}
+
+/*
+ * ncurses stores two types of non-standard capabilities:
+ * a) capabilities listed past the "STOP-HERE" comment in the Caps file.
+ * These are used in the terminfo source file to provide data for termcaps,
+ * e.g., when there is no equivalent capability in terminfo, as well as for
+ * widely-used non-standard capabilities.
+ * b) user-definable capabilities, via "tic -x".
+ *
+ * However, if "-x" is omitted from the tic command, both types of
+ * non-standard capability are not loaded into the terminfo database. This
+ * macro is used for limit-checks against the symbols that tic uses to omit
+ * the two types of non-standard entry.
+ */
+#if NCURSES_XNAMES
+#define check_user_definable(n,limit) if (!_nc_user_definable && (n) > (limit)) break
+#else
+#define check_user_definable(n,limit) if ((n) > (limit)) break
+#endif
+
+/*
+ * Use these macros to simplify loops on C_COMMON and C_NAND:
+ */
+#define for_each_entry() while (entries[extra].tterm.term_names)
+#define next_entry (&(entries[extra++].tterm))
+
static void
compare_predicate(PredType type, PredIdx idx, const char *name)
/* predicate function to use for entry difference reports */
{
- register ENTRY *e1 = &entries[0];
- register ENTRY *e2 = &entries[1];
- char buf1[MAX_STRING], buf2[MAX_STRING];
+ ENTRY *e1 = &entries[0];
+ ENTRY *e2 = &entries[1];
+ char buf1[MAX_STRING];
+ char buf2[MAX_STRING];
int b1, b2;
int n1, n2;
char *s1, *s2;
+ bool found;
+ int extra = 1;
switch (type) {
case CMP_BOOLEAN:
+ check_user_definable(idx, BOOLWRITE);
b1 = e1->tterm.Booleans[idx];
- b2 = e2->tterm.Booleans[idx];
switch (compare) {
case C_DIFFERENCE:
+ b2 = next_entry->Booleans[idx];
if (!(b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) && b1 != b2)
(void) printf("\t%s: %s%s%s.\n",
name,
@@ -357,45 +446,93 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
break;
case C_COMMON:
- if (b1 == b2 && b1 != ABSENT_BOOLEAN)
- (void) printf("\t%s= %s.\n", name, dump_boolean(b1));
+ if (b1 != ABSENT_BOOLEAN) {
+ found = TRUE;
+ for_each_entry() {
+ b2 = next_entry->Booleans[idx];
+ if (b1 != b2) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) printf("\t%s= %s.\n", name, dump_boolean(b1));
+ }
+ }
break;
case C_NAND:
- if (b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN)
- (void) printf("\t!%s.\n", name);
+ if (b1 == ABSENT_BOOLEAN) {
+ found = TRUE;
+ for_each_entry() {
+ b2 = next_entry->Booleans[idx];
+ if (b1 != b2) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) printf("\t!%s.\n", name);
+ }
+ }
break;
}
break;
case CMP_NUMBER:
+ check_user_definable(idx, NUMWRITE);
n1 = e1->tterm.Numbers[idx];
- n2 = e2->tterm.Numbers[idx];
- dump_numeric(n1, buf1);
- dump_numeric(n2, buf2);
switch (compare) {
case C_DIFFERENCE:
- if (!((n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)) && n1 != n2)
+ n2 = next_entry->Numbers[idx];
+ if (!((n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)) && n1 != n2) {
+ dump_numeric(n1, buf1);
+ dump_numeric(n2, buf2);
(void) printf("\t%s: %s, %s.\n", name, buf1, buf2);
+ }
break;
case C_COMMON:
- if (n1 != ABSENT_NUMERIC && n2 != ABSENT_NUMERIC && n1 == n2)
- (void) printf("\t%s= %s.\n", name, buf1);
+ if (n1 != ABSENT_NUMERIC) {
+ found = TRUE;
+ for_each_entry() {
+ n2 = next_entry->Numbers[idx];
+ if (n1 != n2) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ dump_numeric(n1, buf1);
+ (void) printf("\t%s= %s.\n", name, buf1);
+ }
+ }
break;
case C_NAND:
- if (n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)
- (void) printf("\t!%s.\n", name);
+ if (n1 == ABSENT_NUMERIC) {
+ found = TRUE;
+ for_each_entry() {
+ n2 = next_entry->Numbers[idx];
+ if (n1 != n2) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) printf("\t!%s.\n", name);
+ }
+ }
break;
}
break;
case CMP_STRING:
+ check_user_definable(idx, STRWRITE);
s1 = e1->tterm.Strings[idx];
- s2 = e2->tterm.Strings[idx];
switch (compare) {
case C_DIFFERENCE:
+ s2 = next_entry->Strings[idx];
if (capcmp(idx, s1, s2)) {
dump_string(s1, buf1);
dump_string(s2, buf2);
@@ -405,13 +542,35 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
break;
case C_COMMON:
- if (s1 && s2 && !capcmp(idx, s1, s2))
- (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1));
+ if (s1 != ABSENT_STRING) {
+ found = TRUE;
+ for_each_entry() {
+ s2 = next_entry->Strings[idx];
+ if (capcmp(idx, s1, s2) != 0) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1));
+ }
+ }
break;
case C_NAND:
- if (!s1 && !s2)
- (void) printf("\t!%s.\n", name);
+ if (s1 == ABSENT_STRING) {
+ found = TRUE;
+ for_each_entry() {
+ s2 = next_entry->Strings[idx];
+ if (s2 != s1) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) printf("\t!%s.\n", name);
+ }
+ }
break;
}
break;
@@ -430,16 +589,37 @@ compare_predicate(PredType type, PredIdx idx, const char *name)
break;
case C_COMMON:
- if (e1->nuses && e2->nuses && useeq(e1, e2)) {
- (void) fputs("\tuse: ", stdout);
- print_uses(e1, stdout);
- fputs(".\n", stdout);
+ if (e1->nuses) {
+ found = TRUE;
+ for_each_entry() {
+ e2 = &entries[extra++];
+ if (e2->nuses != e1->nuses || !useeq(e1, e2)) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) fputs("\tuse: ", stdout);
+ print_uses(e1, stdout);
+ fputs(".\n", stdout);
+ }
}
break;
case C_NAND:
- if (!e1->nuses && !e2->nuses)
- (void) printf("\t!use.\n");
+ if (!e1->nuses) {
+ found = TRUE;
+ for_each_entry() {
+ e2 = &entries[extra++];
+ if (e2->nuses != e1->nuses) {
+ found = FALSE;
+ break;
+ }
+ }
+ if (found) {
+ (void) printf("\t!use.\n");
+ }
+ }
break;
}
}
@@ -556,7 +736,7 @@ skip_csi(const char *cap)
}
static bool
-same_param(const char *table, const char *param, unsigned length)
+same_param(const char *table, const char *param, size_t length)
{
bool result = FALSE;
if (strncmp(table, param, length) == 0) {
@@ -581,15 +761,15 @@ lookup_params(const assoc * table, char *dst, char *src)
size_t tlen = strlen(ap->from);
if (same_param(ap->from, ep, tlen)) {
- (void) strcat(dst, ap->to);
+ _nc_STRCAT(dst, ap->to, MAX_TERMINFO_LENGTH);
found = TRUE;
break;
}
}
if (!found)
- (void) strcat(dst, ep);
- (void) strcat(dst, ";");
+ _nc_STRCAT(dst, ep, MAX_TERMINFO_LENGTH);
+ _nc_STRCAT(dst, ";", MAX_TERMINFO_LENGTH);
} while
((ep = strtok((char *) 0, ";")));
@@ -608,7 +788,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
const assoc *ap;
int tp_lines = tp->Numbers[2];
- if (cap == ABSENT_STRING || cap == CANCELLED_STRING)
+ if (!VALID_STRING(cap))
return;
(void) printf("%s: ", name);
@@ -624,12 +804,13 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
for (i = 0; i < STRCOUNT; i++) {
char *cp = tp->Strings[i];
- /* don't use soft-key capabilities */
- if (strnames[i][0] == 'k' && strnames[i][0] == 'f')
+ /* don't use function-key capabilities */
+ if (strnames[i][0] == 'k' && strnames[i][1] == 'f')
continue;
- if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp
- != cap) {
+ if (VALID_STRING(cp) &&
+ cp[0] != '\0' &&
+ cp != cap) {
len = strlen(cp);
(void) strncpy(buf2, sp, len);
buf2[len] = '\0';
@@ -637,7 +818,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
if (_nc_capcmp(cp, buf2))
continue;
-#define ISRS(s) (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2))
+#define ISRS(s) (!strncmp((s), "is", (size_t) 2) || !strncmp((s), "rs", (size_t) 2))
/*
* Theoretically we just passed the test for translation
* (equality once the padding is stripped). However, there
@@ -677,12 +858,16 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
/* now check for standard-mode sequences */
if (!expansion
&& (csi = skip_csi(sp)) != 0
- && (len = strspn(sp + csi, "0123456789;"))
+ && (len = (strspn) (sp + csi, "0123456789;"))
&& (len < sizeof(buf3))
&& (next = (size_t) csi + len)
&& ((sp[next] == 'h') || (sp[next] == 'l'))) {
- (void) strcpy(buf2, (sp[next] == 'h') ? "ECMA+" : "ECMA-");
+ _nc_STRCPY(buf2,
+ ((sp[next] == 'h')
+ ? "ECMA+"
+ : "ECMA-"),
+ sizeof(buf2));
(void) strncpy(buf3, sp + csi, len);
buf3[len] = '\0';
len += (size_t) csi + 1;
@@ -694,12 +879,16 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
if (!expansion
&& (csi = skip_csi(sp)) != 0
&& sp[csi] == '?'
- && (len = strspn(sp + csi + 1, "0123456789;"))
+ && (len = (strspn) (sp + csi + 1, "0123456789;"))
&& (len < sizeof(buf3))
&& (next = (size_t) csi + 1 + len)
&& ((sp[next] == 'h') || (sp[next] == 'l'))) {
- (void) strcpy(buf2, (sp[next] == 'h') ? "DEC+" : "DEC-");
+ _nc_STRCPY(buf2,
+ ((sp[next] == 'h')
+ ? "DEC+"
+ : "DEC-"),
+ sizeof(buf2));
(void) strncpy(buf3, sp + csi + 1, len);
buf3[len] = '\0';
len += (size_t) csi + 2;
@@ -710,12 +899,12 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
/* now check for ECMA highlight sequences */
if (!expansion
&& (csi = skip_csi(sp)) != 0
- && (len = strspn(sp + csi, "0123456789;")) != 0
+ && (len = (strspn) (sp + csi, "0123456789;")) != 0
&& (len < sizeof(buf3))
&& (next = (size_t) csi + len)
&& sp[next] == 'm') {
- (void) strcpy(buf2, "SGR:");
+ _nc_STRCPY(buf2, "SGR:", sizeof(buf2));
(void) strncpy(buf3, sp + csi, len);
buf3[len] = '\0';
len += (size_t) csi + 1;
@@ -727,8 +916,8 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
&& (csi = skip_csi(sp)) != 0
&& sp[csi] == 'm') {
len = (size_t) csi + 1;
- (void) strcpy(buf2, "SGR:");
- strcat(buf2, ecma_highlights[0].to);
+ _nc_STRCPY(buf2, "SGR:", sizeof(buf2));
+ _nc_STRCAT(buf2, ecma_highlights[0].to, sizeof(buf2));
expansion = buf2;
}
@@ -739,7 +928,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
expansion = "RSR";
len = 1;
} else {
- (void) sprintf(buf2, "1;%dr", tp_lines);
+ _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "1;%dr", tp_lines);
len = strlen(buf2);
if (strncmp(buf2, sp + csi, len) == 0)
expansion = "RSR";
@@ -750,12 +939,12 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp)
/* now check for home-down */
if (!expansion
&& (csi = skip_csi(sp)) != 0) {
- (void) sprintf(buf2, "%d;1H", tp_lines);
+ _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "%d;1H", tp_lines);
len = strlen(buf2);
if (strncmp(buf2, sp + csi, len) == 0) {
expansion = "LL";
} else {
- (void) sprintf(buf2, "%dH", tp_lines);
+ _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "%dH", tp_lines);
len = strlen(buf2);
if (strncmp(buf2, sp + csi, len) == 0) {
expansion = "LL";
@@ -795,12 +984,16 @@ file_comparison(int argc, char *argv[])
int i, n;
memset(heads, 0, sizeof(heads));
- dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, itrace, FALSE);
+ dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, 65535, itrace, FALSE);
for (n = 0; n < argc && n < MAXCOMPARE; n++) {
if (freopen(argv[n], "r", stdin) == 0)
_nc_err_abort("Can't open %s", argv[n]);
+#if NO_LEAKS
+ entered[n].head = _nc_head;
+ entered[n].tail = _nc_tail;
+#endif
_nc_head = _nc_tail = 0;
/* parse entries out of the source file */
@@ -925,6 +1118,11 @@ file_comparison(int argc, char *argv[])
#endif
if (!(entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp))) {
char name1[NAMESIZE], name2[NAMESIZE];
+ char *names[3];
+
+ names[0] = name1;
+ names[1] = name2;
+ names[2] = 0;
entries[0] = *qp;
entries[1] = *rp;
@@ -934,29 +1132,17 @@ file_comparison(int argc, char *argv[])
switch (compare) {
case C_DIFFERENCE:
- if (itrace)
- (void) fprintf(stderr,
- "%s: dumping differences\n",
- _nc_progname);
- (void) printf("comparing %s to %s.\n", name1, name2);
+ show_comparing(names);
compare_entry(compare_predicate, &entries->tterm, quiet);
break;
case C_COMMON:
- if (itrace)
- (void) fprintf(stderr,
- "%s: dumping common capabilities\n",
- _nc_progname);
- (void) printf("comparing %s to %s.\n", name1, name2);
+ show_comparing(names);
compare_entry(compare_predicate, &entries->tterm, quiet);
break;
case C_NAND:
- if (itrace)
- (void) fprintf(stderr,
- "%s: dumping differences\n",
- _nc_progname);
- (void) printf("comparing %s to %s.\n", name1, name2);
+ show_comparing(names);
compare_entry(compare_predicate, &entries->tterm, quiet);
break;
@@ -974,7 +1160,9 @@ usage(void)
"Usage: infocmp [options] [-A directory] [-B directory] [termname...]"
,""
,"Options:"
+ ," -0 print single-row"
," -1 print single-column"
+ ," -K use termcap-names and BSD syntax"
," -C use termcap-names"
," -F compare terminfo-files"
," -I use terminfo-names"
@@ -982,6 +1170,7 @@ usage(void)
," -R subset (see manpage)"
," -T eliminate size limits (test)"
," -U eliminate post-processing of entries"
+ ," -D print database locations"
," -V print version"
#if NCURSES_XNAMES
," -a with -F, list commented-out caps"
@@ -1030,19 +1219,25 @@ static char *
any_initializer(const char *fmt, const char *type)
{
static char *initializer;
+ static size_t need;
char *s;
- if (initializer == 0)
- initializer = (char *) malloc(strlen(entries->tterm.term_names) +
- strlen(type) + strlen(fmt));
+ if (initializer == 0) {
+ need = (strlen(entries->tterm.term_names)
+ + strlen(type)
+ + strlen(fmt));
+ initializer = (char *) malloc(need + 1);
+ if (initializer == 0)
+ failed("any_initializer");
+ }
- (void) strcpy(initializer, entries->tterm.term_names);
+ _nc_STRCPY(initializer, entries->tterm.term_names, need);
for (s = initializer; *s != 0 && *s != '|'; s++) {
if (!isalnum(UChar(*s)))
*s = '_';
}
*s = 0;
- (void) sprintf(s, fmt, type);
+ _nc_SPRINTF(s, _nc_SLIMIT(need) fmt, type);
return initializer;
}
@@ -1073,9 +1268,10 @@ dump_initializers(TERMTYPE *term)
if (VALID_STRING(term->Strings[n])) {
tp = buf;
+#define TP_LIMIT ((MAX_STRING - 5) - (size_t)(tp - buf))
*tp++ = '"';
for (sp = term->Strings[n];
- *sp != 0 && (tp - buf) < MAX_STRING - 6;
+ *sp != 0 && TP_LIMIT > 2;
sp++) {
if (isascii(UChar(*sp))
&& isprint(UChar(*sp))
@@ -1083,14 +1279,15 @@ dump_initializers(TERMTYPE *term)
&& *sp != '"')
*tp++ = *sp;
else {
- (void) sprintf(tp, "\\%03o", UChar(*sp));
+ _nc_SPRINTF(tp, _nc_SLIMIT(TP_LIMIT) "\\%03o", UChar(*sp));
tp += 4;
}
}
*tp++ = '"';
*tp = '\0';
(void) printf("static char %-20s[] = %s;\n",
- string_variable(ExtStrname(term, n, strnames)), buf);
+ string_variable(ExtStrname(term, (int) n, strnames)),
+ buf);
}
}
printf("\n");
@@ -1116,7 +1313,7 @@ dump_initializers(TERMTYPE *term)
break;
}
(void) printf("\t/* %3u: %-8s */\t%s,\n",
- n, ExtBoolname(term, n, boolnames), str);
+ n, ExtBoolname(term, (int) n, boolnames), str);
}
(void) printf("%s;\n", R_CURL);
@@ -1132,12 +1329,12 @@ dump_initializers(TERMTYPE *term)
str = "CANCELLED_NUMERIC";
break;
default:
- sprintf(buf, "%d", term->Numbers[n]);
+ _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) "%d", term->Numbers[n]);
str = buf;
break;
}
(void) printf("\t/* %3u: %-8s */\t%s,\n", n,
- ExtNumname(term, n, numnames), str);
+ ExtNumname(term, (int) n, numnames), str);
}
(void) printf("%s;\n", R_CURL);
@@ -1150,10 +1347,10 @@ dump_initializers(TERMTYPE *term)
else if (term->Strings[n] == CANCELLED_STRING)
str = "CANCELLED_STRING";
else {
- str = string_variable(ExtStrname(term, n, strnames));
+ str = string_variable(ExtStrname(term, (int) n, strnames));
}
(void) printf("\t/* %3u: %-8s */\t%s,\n", n,
- ExtStrname(term, n, strnames), str);
+ ExtStrname(term, (int) n, strnames), str);
}
(void) printf("%s;\n", R_CURL);
@@ -1165,15 +1362,15 @@ dump_initializers(TERMTYPE *term)
name_initializer("string_ext"), L_CURL);
for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) {
(void) printf("\t/* %3u: bool */\t\"%s\",\n",
- n, ExtBoolname(term, n, boolnames));
+ n, ExtBoolname(term, (int) n, boolnames));
}
for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) {
(void) printf("\t/* %3u: num */\t\"%s\",\n",
- n, ExtNumname(term, n, numnames));
+ n, ExtNumname(term, (int) n, numnames));
}
for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) {
(void) printf("\t/* %3u: str */\t\"%s\",\n",
- n, ExtStrname(term, n, strnames));
+ n, ExtStrname(term, (int) n, strnames));
}
(void) printf("%s;\n", R_CURL);
}
@@ -1247,6 +1444,23 @@ terminal_env(void)
return terminal;
}
+/*
+ * Show the databases that infocmp knows about. The location to which it writes is
+ */
+static void
+show_databases(void)
+{
+ DBDIRS state;
+ int offset;
+ const char *path2;
+
+ _nc_first_db(&state, &offset);
+ while ((path2 = _nc_next_db(&state, &offset)) != 0) {
+ printf("%s\n", path2);
+ }
+ _nc_last_db();
+}
+
/***************************************************************************
*
* Main sequence
@@ -1269,7 +1483,7 @@ main(int argc, char *argv[])
/* Also avoid overflowing smaller stacks on systems like AmigaOS */
path *tfile = 0;
char **tname = 0;
- int maxterms;
+ size_t maxterms;
char **myargv;
@@ -1287,18 +1501,27 @@ main(int argc, char *argv[])
#if NCURSES_XNAMES
use_extended_names(FALSE);
#endif
+ _nc_strict_bsd = 0;
_nc_progname = _nc_rootname(argv[0]);
/* make sure we have enough space to add two terminal entries */
myargv = typeCalloc(char *, (size_t) (argc + 3));
+ if (myargv == 0)
+ failed("myargv");
+
memcpy(myargv, argv, (sizeof(char *) * (size_t) argc));
argv = myargv;
while ((c = getopt(argc,
argv,
- "1A:aB:CcdEeFfGgIiLlnpqR:rs:TtUuVv:w:x")) != -1) {
+ "01A:aB:CcDdEeFfGgIiKLlnpqR:rs:TtUuVv:w:x")) != -1) {
switch (c) {
+ case '0':
+ mwidth = 65535;
+ mheight = 1;
+ break;
+
case '1':
mwidth = 0;
break;
@@ -1317,6 +1540,9 @@ main(int argc, char *argv[])
restdir = optarg;
break;
+ case 'K':
+ _nc_strict_bsd = 1;
+ /* FALLTHRU */
case 'C':
outform = F_TERMCAP;
tversion = "BSD";
@@ -1324,6 +1550,11 @@ main(int argc, char *argv[])
sortmode = S_TERMCAP;
break;
+ case 'D':
+ show_databases();
+ ExitProgram(EXIT_SUCCESS);
+ break;
+
case 'c':
compare = C_COMMON;
break;
@@ -1441,7 +1672,7 @@ main(int argc, char *argv[])
ExitProgram(EXIT_SUCCESS);
case 'v':
- itrace = optarg_to_number();
+ itrace = (unsigned) optarg_to_number();
set_trace_level(itrace);
break;
@@ -1460,10 +1691,17 @@ main(int argc, char *argv[])
}
}
- maxterms = (argc + 2 - optind);
- tfile = typeMalloc(path, maxterms);
- tname = typeCalloc(char *, maxterms);
- entries = typeCalloc(ENTRY, maxterms);
+ maxterms = (size_t) (argc + 2 - optind);
+ if ((tfile = typeMalloc(path, maxterms)) == 0)
+ failed("tfile");
+ if ((tname = typeCalloc(char *, maxterms)) == 0)
+ failed("tname");
+ if ((entries = typeCalloc(ENTRY, maxterms)) == 0)
+ failed("entries");
+#if NO_LEAKS
+ if ((entered = typeCalloc(ENTERED, maxterms)) == 0)
+ failed("entered");
+#endif
if (tfile == 0
|| tname == 0
@@ -1476,9 +1714,6 @@ main(int argc, char *argv[])
if (sortmode == S_DEFAULT)
sortmode = S_TERMINFO;
- /* set up for display */
- dump_init(tversion, outform, sortmode, mwidth, itrace, formatted);
-
/* make sure we have at least one terminal name to work with */
if (optind >= argc)
argv[argc++] = terminal_env();
@@ -1487,9 +1722,23 @@ main(int argc, char *argv[])
if (compare != C_DEFAULT && optind >= argc - 1)
argv[argc++] = terminal_env();
+ /* exactly one terminal name with no options means display it */
/* exactly two terminal names with no options means do -d */
- if (argc - optind == 2 && compare == C_DEFAULT)
- compare = C_DIFFERENCE;
+ if (compare == C_DEFAULT) {
+ switch (argc - optind) {
+ default:
+ fprintf(stderr, "%s: too many names to compare\n", _nc_progname);
+ ExitProgram(EXIT_FAILURE);
+ case 1:
+ break;
+ case 2:
+ compare = C_DIFFERENCE;
+ break;
+ }
+ }
+
+ /* set up for display */
+ dump_init(tversion, outform, sortmode, mwidth, mheight, itrace, formatted);
if (!filecompare) {
/* grab the entries */
@@ -1501,15 +1750,17 @@ main(int argc, char *argv[])
tname[termcount] = argv[optind];
if (directory) {
-#if USE_DATABASE
+#if NCURSES_USE_DATABASE
#if MIXEDCASE_FILENAMES
#define LEAF_FMT "%c"
#else
#define LEAF_FMT "%02x"
#endif
- (void) sprintf(tfile[termcount], "%s/" LEAF_FMT "/%s",
- directory,
- UChar(*argv[optind]), argv[optind]);
+ _nc_SPRINTF(tfile[termcount],
+ _nc_SLIMIT(sizeof(path))
+ "%s/" LEAF_FMT "/%s",
+ directory,
+ UChar(*argv[optind]), argv[optind]);
if (itrace)
(void) fprintf(stderr,
"%s: reading entry %s from file %s\n",
@@ -1599,27 +1850,17 @@ main(int argc, char *argv[])
break;
case C_DIFFERENCE:
- if (itrace)
- (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname);
- (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
+ show_comparing(tname);
compare_entry(compare_predicate, &entries->tterm, quiet);
break;
case C_COMMON:
- if (itrace)
- (void) fprintf(stderr,
- "%s: dumping common capabilities\n",
- _nc_progname);
- (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
+ show_comparing(tname);
compare_entry(compare_predicate, &entries->tterm, quiet);
break;
case C_NAND:
- if (itrace)
- (void) fprintf(stderr,
- "%s: dumping differences\n",
- _nc_progname);
- (void) printf("comparing %s to %s.\n", tname[0], tname[1]);
+ show_comparing(tname);
compare_entry(compare_predicate, &entries->tterm, quiet);
break;
@@ -1640,15 +1881,16 @@ main(int argc, char *argv[])
break;
}
}
- } else if (compare == C_USEALL)
+ } else if (compare == C_USEALL) {
(void) fprintf(stderr, "Sorry, -u doesn't work with -F\n");
- else if (compare == C_DEFAULT)
+ } else if (compare == C_DEFAULT) {
(void) fprintf(stderr, "Use `tic -[CI] <file>' for this.\n");
- else if (argc - optind != 2)
+ } else if (argc - optind != 2) {
(void) fprintf(stderr,
"File comparison needs exactly two file arguments.\n");
- else
+ } else {
file_comparison(argc - optind, argv + optind);
+ }
MAIN_LEAKS();
ExitProgram(EXIT_SUCCESS);
diff --git a/progs/modules b/progs/modules
index 55d7a9f..c09d2a6 100644
--- a/progs/modules
+++ b/progs/modules
@@ -1,7 +1,7 @@
-# $Id: modules,v 1.17 2010/01/23 17:47:23 tom Exp $
+# $Id: modules,v 1.18 2014/05/21 17:01:28 tom Exp $
# Program modules (some are in ncurses lib!)
##############################################################################
-# Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. #
+# Copyright (c) 1998-2010,2014 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"), #
@@ -33,12 +33,13 @@
@ base
clear progs $(srcdir) $(HEADER_DEPS)
-tic progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h
+tic progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h $(srcdir)/tparm_type.h
toe progs $(srcdir) $(HEADER_DEPS) $(INCDIR)/hashed_db.h
dump_entry progs $(srcdir) $(HEADER_DEPS) $(srcdir)/dump_entry.h ../include/parametrized.h $(INCDIR)/capdefaults.c termsort.c
infocmp progs $(srcdir) $(HEADER_DEPS) $(srcdir)/dump_entry.h
tabs progs $(srcdir) $(HEADER_DEPS)
-tput progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h termsort.c
+tparm_type progs $(srcdir) $(HEADER_DEPS) $(srcdir)/tparm_type.h
+tput progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h $(srcdir)/tparm_type.h termsort.c
tset progs $(srcdir) $(HEADER_DEPS) transform.h $(srcdir)/dump_entry.h ../include/termcap.h
transform progs $(srcdir) $(HEADER_DEPS) transform.h
diff --git a/progs/progs.priv.h b/progs/progs.priv.h
index f0ea460..c1cc1e6 100644
--- a/progs/progs.priv.h
+++ b/progs/progs.priv.h
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2012,2014 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 *
@@ -30,19 +30,22 @@
* Author: Thomas E. Dickey 1997-on *
****************************************************************************/
/*
- * $Id: progs.priv.h,v 1.34 2008/08/03 17:43:05 tom Exp $
+ * $Id: progs.priv.h,v 1.40 2014/05/21 17:00:19 tom Exp $
*
* progs.priv.h
*
* Header file for curses utility programs
*/
+#ifndef PROGS_PRIV_H
+#define PROGS_PRIV_H 1
+
#include <ncurses_cfg.h>
#if USE_RCS_IDS
#define MODULE_ID(id) static const char Ident[] = id;
#else
-#define MODULE_ID(id) /*nothing*/
+#define MODULE_ID(id) /*nothing */
#endif
#include <stdlib.h>
@@ -90,6 +93,14 @@
# endif
#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+
#include <assert.h>
#include <errno.h>
@@ -99,7 +110,7 @@ extern int errno;
#if HAVE_GETOPT_H
#include <getopt.h>
-#else
+#elif !defined(HAVE_GETOPT_HEADER)
/* 'getopt()' may be prototyped in <stdlib.h>, but declaring its
* variables doesn't hurt.
*/
@@ -109,9 +120,11 @@ extern int optind;
#include <curses.h>
#include <term_entry.h>
+#include <nc_termios.h>
#include <tic.h>
#include <nc_tparm.h>
+#include <nc_string.h>
#include <nc_alloc.h>
#if HAVE_NC_FREEALL
#undef ExitProgram
@@ -171,7 +184,7 @@ extern int optind;
# elif defined(MAXPATHLEN)
# define PATH_MAX MAXPATHLEN
# else
-# define PATH_MAX 255 /* the Posix minimum pathsize */
+# define PATH_MAX 255 /* the Posix minimum pathsize */
# endif
#endif
@@ -183,10 +196,12 @@ extern int optind;
# if ('z'-'a' == 25) && ('z' < 127) && ('Z'-'A' == 25) && ('Z' < 127) && ('9' < 127)
# define isascii(c) (UChar(c) <= 127)
# else
-# define isascii(c) 1 /* not really ascii anyway */
+# define isascii(c) 1 /* not really ascii anyway */
# endif
#endif
#define UChar(c) ((unsigned char)(c))
#define SIZEOF(v) (sizeof(v)/sizeof(v[0]))
+
+#endif /* PROGS_PRIV_H */
diff --git a/progs/tabs.c b/progs/tabs.c
index b59c908..7ed3007 100644
--- a/progs/tabs.c
+++ b/progs/tabs.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 2008-2009,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 2008-2012,2013 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 *
@@ -37,12 +37,20 @@
#define USE_LIBTINFO
#include <progs.priv.h>
-MODULE_ID("$Id: tabs.c,v 1.19 2010/10/23 22:26:01 tom Exp $")
+MODULE_ID("$Id: tabs.c,v 1.34 2013/06/11 08:18:27 tom Exp $")
static void usage(void) GCC_NORETURN;
+static char *prg_name;
static int max_cols;
+static void
+failed(const char *s)
+{
+ perror(s);
+ ExitProgram(EXIT_FAILURE);
+}
+
static int
putch(int c)
{
@@ -83,28 +91,29 @@ decode_tabs(const char *tab_list)
int prior = 0;
int ch;
- if (result != 0) {
- while ((ch = *tab_list++) != '\0') {
- if (isdigit(UChar(ch))) {
- value *= 10;
- value += (ch - '0');
- } else if (ch == ',') {
- result[n] = value + prior;
- if (n > 0 && result[n] <= result[n - 1]) {
- fprintf(stderr,
- "tab-stops are not in increasing order: %d %d\n",
- value, result[n - 1]);
- free(result);
- result = 0;
- break;
- }
- ++n;
- value = 0;
- prior = 0;
- } else if (ch == '+') {
- if (n)
- prior = result[n - 1];
+ if (result == 0)
+ failed("decode_tabs");
+
+ while ((ch = *tab_list++) != '\0') {
+ if (isdigit(UChar(ch))) {
+ value *= 10;
+ value += (ch - '0');
+ } else if (ch == ',') {
+ result[n] = value + prior;
+ if (n > 0 && result[n] <= result[n - 1]) {
+ fprintf(stderr,
+ "%s: tab-stops are not in increasing order: %d %d\n",
+ prg_name, value, result[n - 1]);
+ free(result);
+ result = 0;
+ break;
}
+ ++n;
+ value = 0;
+ prior = 0;
+ } else if (ch == '+') {
+ if (n)
+ prior = result[n - 1];
}
}
@@ -114,6 +123,7 @@ decode_tabs(const char *tab_list)
*/
if ((n == 0) && (value > 0)) {
int step = value;
+ value = 1;
while (n < max_cols - 1) {
result[n++] = value;
value += step;
@@ -126,6 +136,7 @@ decode_tabs(const char *tab_list)
result[n++] = value + prior;
result[n] = 0;
}
+
return result;
}
@@ -140,10 +151,11 @@ print_ruler(int *tab_list)
for (n = 0; n < max_cols; n += 10) {
int ch = 1 + (n / 10);
char buffer[20];
- sprintf(buffer, "----+----%c",
- ((ch < 10)
- ? (ch + '0')
- : (ch + 'A' - 10)));
+ _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer))
+ "----+----%c",
+ ((ch < 10)
+ ? (ch + '0')
+ : (ch + 'A' - 10)));
printf("%.*s", ((max_cols - n) > 10) ? 10 : (max_cols - n), buffer);
}
putchar('\n');
@@ -227,7 +239,7 @@ comma_is_needed(const char *source)
bool result = FALSE;
if (source != 0) {
- unsigned len = strlen(source);
+ size_t len = strlen(source);
if (len != 0)
result = (source[len - 1] != ',');
} else {
@@ -251,7 +263,7 @@ add_to_tab_list(char **append, const char *value)
if (copied != 0 && *copied != '\0') {
const char *comma = ",";
- unsigned need = 1 + strlen(copied);
+ size_t need = 1 + strlen(copied);
if (*copied == ',')
comma = "";
@@ -263,15 +275,16 @@ add_to_tab_list(char **append, const char *value)
need += strlen(*append);
result = malloc(need);
- if (result != 0) {
- *result = '\0';
- if (*append != 0) {
- strcpy(result, *append);
- free(*append);
- }
- strcat(result, comma);
- strcat(result, copied);
+ if (result == 0)
+ failed("add_to_tab_list");
+
+ *result = '\0';
+ if (*append != 0) {
+ _nc_STRCPY(result, *append, need);
+ free(*append);
}
+ _nc_STRCAT(result, comma, need);
+ _nc_STRCAT(result, copied, need);
*append = result;
}
@@ -282,7 +295,7 @@ add_to_tab_list(char **append, const char *value)
* Check for illegal characters in the tab-list.
*/
static bool
-legal_tab_list(const char *program, const char *tab_list)
+legal_tab_list(const char *tab_list)
{
bool result = TRUE;
@@ -294,22 +307,34 @@ legal_tab_list(const char *program, const char *tab_list)
if (!(isdigit(ch) || ch == ',' || ch == '+')) {
fprintf(stderr,
"%s: unexpected character found '%c'\n",
- program, ch);
+ prg_name, ch);
result = FALSE;
break;
}
}
} else {
- fprintf(stderr, "%s: trailing comma found '%s'\n", program, tab_list);
+ fprintf(stderr, "%s: trailing comma found '%s'\n", prg_name, tab_list);
result = FALSE;
}
} else {
- fprintf(stderr, "%s: no tab-list given\n", program);
+ fprintf(stderr, "%s: no tab-list given\n", prg_name);
result = FALSE;
}
return result;
}
+static char *
+skip_list(char *value)
+{
+ while (*value != '\0' &&
+ (isdigit(UChar(*value)) ||
+ isspace(UChar(*value)) ||
+ strchr("+,", UChar(*value)) != 0)) {
+ ++value;
+ }
+ return value;
+}
+
static void
usage(void)
{
@@ -332,6 +357,7 @@ usage(void)
," -s SNOBOL"
," -u UNIVAC 1100 Assembler"
," -T name use terminal type 'name'"
+ ," -V print version"
,""
,"A tabstop-list is an ordered list of column numbers, e.g., 1,11,21"
,"or 1,+10,+10 which is the same."
@@ -353,10 +379,11 @@ main(int argc, char *argv[])
bool no_op = FALSE;
int n, ch;
NCURSES_CONST char *term_name = 0;
- const char *mar_list = 0; /* ignored */
char *append = 0;
const char *tab_list = 0;
+ prg_name = _nc_rootname(argv[0]);
+
if ((term_name = getenv("TERM")) == 0)
term_name = "ansi+tabs";
@@ -368,23 +395,25 @@ main(int argc, char *argv[])
while ((ch = *++option) != '\0') {
switch (ch) {
case 'a':
- switch (*option) {
+ switch (*++option) {
+ default:
case '\0':
tab_list = "1,10,16,36,72";
+ option--;
/* Assembler, IBM S/370, first format */
break;
case '2':
tab_list = "1,10,16,40,72";
/* Assembler, IBM S/370, second format */
break;
- default:
- usage();
}
break;
case 'c':
- switch (*option) {
+ switch (*++option) {
+ default:
case '\0':
tab_list = "1,8,12,16,20,55";
+ option--;
/* COBOL, normal format */
break;
case '2':
@@ -395,8 +424,6 @@ main(int argc, char *argv[])
tab_list = "1,6,10,14,18,22,26,30,34,38,42,46,50,54,58,62,67";
/* COBOL compact format extended */
break;
- default:
- usage();
}
break;
case 'd': /* ncurses extension */
@@ -427,17 +454,22 @@ main(int argc, char *argv[])
term_name = option;
} else {
term_name = argv[n++];
+ option--;
}
option += ((int) strlen(option)) - 1;
continue;
+ case 'V':
+ puts(curses_version());
+ ExitProgram(EXIT_SUCCESS);
default:
if (isdigit(UChar(*option))) {
- tab_list = option;
- ++n;
+ char *copy = strdup(option);
+ *skip_list(copy) = '\0';
+ tab_list = copy;
+ option = skip_list(option) - 1;
} else {
usage();
}
- option += ((int) strlen(option)) - 1;
break;
}
}
@@ -446,7 +478,11 @@ main(int argc, char *argv[])
while ((ch = *++option) != '\0') {
switch (ch) {
case 'm':
- mar_list = option;
+ /*
+ * The "+mXXX" option is unimplemented because only the long-obsolete
+ * att510d implements smgl, which is needed to support
+ * this option.
+ */
break;
default:
/* special case of relative stops separated by spaces? */
@@ -477,12 +513,12 @@ main(int argc, char *argv[])
if (!VALID_STRING(clear_all_tabs)) {
fprintf(stderr,
"%s: terminal type '%s' cannot reset tabs\n",
- argv[0], term_name);
+ prg_name, term_name);
} else if (!VALID_STRING(set_tab)) {
fprintf(stderr,
"%s: terminal type '%s' cannot set tabs\n",
- argv[0], term_name);
- } else if (legal_tab_list(argv[0], tab_list)) {
+ prg_name, term_name);
+ } else if (legal_tab_list(tab_list)) {
int *list = decode_tabs(tab_list);
if (!no_op)
diff --git a/progs/tic.c b/progs/tic.c
index 8e89095..763c2b7 100644
--- a/progs/tic.c
+++ b/progs/tic.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2013,2014 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 *
@@ -35,6 +35,7 @@
/*
* tic.c --- Main program for terminfo compiler
* by Eric S. Raymond
+ * and Thomas E Dickey
*
*/
@@ -42,9 +43,14 @@
#include <sys/stat.h>
#include <dump_entry.h>
+#include <tparm_type.h>
+#include <hashed_db.h>
+#include <parametrized.h>
#include <transform.h>
-MODULE_ID("$Id: tic.c,v 1.147 2011/02/12 18:39:08 tom Exp $")
+MODULE_ID("$Id: tic.c,v 1.208 2014/10/18 09:34:29 tom Exp $")
+
+#define STDIN_NAME "<stdin>"
const char *_nc_progname = "tic";
@@ -53,6 +59,7 @@ static FILE *tmp_fp;
static bool capdump = FALSE; /* running as infotocap? */
static bool infodump = FALSE; /* running as captoinfo? */
static bool showsummary = FALSE;
+static char **namelst = 0;
static const char *to_remove;
static void (*save_check_termtype) (TERMTYPE *, bool);
@@ -69,11 +76,13 @@ static const char usage_string[] = "\
1\
a\
C\
+D\
c\
f\
G\
g\
I\
+K\
L\
N\
r\
@@ -99,8 +108,10 @@ free_namelist(char **src)
#endif
static void
-cleanup(char **namelst GCC_UNUSED)
+cleanup(void)
{
+ int rc;
+
#if NO_LEAKS
free_namelist(namelst);
#endif
@@ -108,10 +119,12 @@ cleanup(char **namelst GCC_UNUSED)
fclose(tmp_fp);
if (to_remove != 0) {
#if HAVE_REMOVE
- remove(to_remove);
+ rc = remove(to_remove);
#else
- unlink(to_remove);
+ rc = unlink(to_remove);
#endif
+ if (rc != 0)
+ perror(to_remove);
}
}
@@ -119,7 +132,6 @@ static void
failed(const char *msg)
{
perror(msg);
- cleanup((char **) 0);
ExitProgram(EXIT_FAILURE);
}
@@ -134,12 +146,14 @@ usage(void)
" -a retain commented-out capabilities (sets -x also)",
#endif
" -C translate entries to termcap source form",
+ " -D print list of tic's database locations (first must be writable)",
" -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}",
" -I translate entries to terminfo source form",
+ " -K translate entries to termcap source form with BSD syntax",
" -L translate entries to full terminfo source form",
" -N disable smart defaults for source translation",
" -o<dir> set output directory for compiled entry writes",
@@ -173,7 +187,7 @@ usage(void)
#define L_BRACE '{'
#define R_BRACE '}'
-#define S_QUOTE '\'';
+#define S_QUOTE '\''
static void
write_it(ENTRY * ep)
@@ -216,12 +230,12 @@ write_it(ENTRY * ep)
}
*d = 0;
if (strlen(result) < strlen(s))
- strcpy(s, result);
+ _nc_STRCPY(s, result, strlen(s) + 1);
}
}
_nc_set_type(_nc_first_name(ep->tterm.term_names));
- _nc_curr_line = ep->startline;
+ _nc_curr_line = (int) ep->startline;
_nc_write_entry(&ep->tterm);
}
@@ -286,8 +300,10 @@ put_translate(int c)
if (in_name) {
if (used + 1 >= have) {
have += 132;
- namebuf = typeRealloc(char, have, namebuf);
- suffix = typeRealloc(char, have, suffix);
+ if ((namebuf = typeRealloc(char, have, namebuf)) == 0)
+ failed("put_translate namebuf");
+ if ((suffix = typeRealloc(char, have, suffix)) == 0)
+ failed("put_translate suffix");
}
if (c == '\n' || c == '@') {
namebuf[used++] = '\0';
@@ -308,7 +324,7 @@ put_translate(int c)
if ((up = strchr(namebuf, '#')) != 0
|| (up = strchr(namebuf, '=')) != 0
|| ((up = strchr(namebuf, '@')) != 0 && up[1] == '>')) {
- (void) strcpy(suffix, up);
+ _nc_STRCPY(suffix, up, have);
*up = '\0';
}
@@ -339,39 +355,122 @@ put_translate(int c)
static char *
stripped(char *src)
{
+ char *dst = 0;
+
while (isspace(UChar(*src)))
src++;
+
if (*src != '\0') {
- char *dst;
size_t len;
- if ((dst = strdup(src)) == NULL)
+ if ((dst = strdup(src)) == NULL) {
failed("strdup");
+ } else {
+ len = strlen(dst);
+ while (--len != 0 && isspace(UChar(dst[len])))
+ dst[len] = '\0';
+ }
+ }
+ return dst;
+}
- assert(dst != 0);
+static FILE *
+open_tempfile(char *filename)
+{
+ FILE *result = 0;
- len = strlen(dst);
- while (--len != 0 && isspace(UChar(dst[len])))
- dst[len] = '\0';
- return dst;
+ _nc_STRCPY(filename, "/tmp/XXXXXX", PATH_MAX);
+#if HAVE_MKSTEMP
+ {
+ int oldmask = (int) umask(077);
+ int fd = mkstemp(filename);
+ if (fd >= 0)
+ result = fdopen(fd, "w");
+ umask((mode_t) oldmask);
}
- return 0;
+#else
+ if (tmpnam(filename) != 0)
+ result = fopen(filename, "w");
+#endif
+ return result;
}
static FILE *
-open_input(const char *filename)
+copy_input(FILE *source, const char *filename, char *alt_file)
{
- FILE *fp = fopen(filename, "r");
+ char my_altfile[PATH_MAX];
+ FILE *result = 0;
+ FILE *target = 0;
+ int ch;
+
+ if (alt_file == 0)
+ alt_file = my_altfile;
+
+ if (source == 0) {
+ failed("copy_input (source)");
+ } else if ((target = open_tempfile(alt_file)) == 0) {
+ failed("copy_input (target)");
+ } else {
+ clearerr(source);
+ for (;;) {
+ ch = fgetc(source);
+ if (feof(source)) {
+ break;
+ } else if (ferror(source)) {
+ failed(filename);
+ } else if (ch == 0) {
+ /* don't loop in case someone wants to convert /dev/zero */
+ fprintf(stderr, "%s: %s is not a text-file\n", _nc_progname, filename);
+ ExitProgram(EXIT_FAILURE);
+ }
+ fputc(ch, target);
+ }
+ fclose(source);
+ /*
+ * rewind() does not force the target file's data to disk (not does
+ * fflush()...). So open a second stream on the data and then close
+ * the one that we were writing on before starting to read from the
+ * second stream.
+ */
+ result = fopen(alt_file, "r+");
+ fclose(target);
+ to_remove = strdup(alt_file);
+ }
+ return result;
+}
+
+static FILE *
+open_input(const char *filename, char *alt_file)
+{
+ FILE *fp;
struct stat sb;
+ int mode;
- if (fp == 0) {
- fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename);
+ if (!strcmp(filename, "-")) {
+ fp = copy_input(stdin, STDIN_NAME, alt_file);
+ } else if (stat(filename, &sb) < 0) {
+ fprintf(stderr, "%s: %s %s\n", _nc_progname, filename, strerror(errno));
ExitProgram(EXIT_FAILURE);
- }
- if (fstat(fileno(fp), &sb) < 0
- || (sb.st_mode & S_IFMT) != S_IFREG) {
+ } else if ((mode = (sb.st_mode & S_IFMT)) == S_IFDIR
+ || (mode != S_IFREG && mode != S_IFCHR && mode != S_IFIFO)) {
fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename);
ExitProgram(EXIT_FAILURE);
+ } else {
+ fp = fopen(filename, "r");
+
+ if (fp == 0) {
+ fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename);
+ ExitProgram(EXIT_FAILURE);
+ }
+ if (mode != S_IFREG) {
+ if (alt_file != 0) {
+ FILE *fp2 = copy_input(fp, filename, alt_file);
+ fp = fp2;
+ } else {
+ fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename);
+ ExitProgram(EXIT_FAILURE);
+ }
+ }
}
return fp;
}
@@ -389,7 +488,7 @@ make_namelist(char *src)
if (src == 0) {
/* EMPTY */ ;
} else if (strchr(src, '/') != 0) { /* a filename */
- FILE *fp = open_input(src);
+ FILE *fp = open_input(src, (char *) 0);
for (pass = 1; pass <= 2; pass++) {
nn = 0;
@@ -403,7 +502,8 @@ make_namelist(char *src)
}
}
if (pass == 1) {
- dst = typeCalloc(char *, nn + 1);
+ if ((dst = typeCalloc(char *, nn + 1)) == 0)
+ failed("make_namelist");
rewind(fp);
}
}
@@ -425,8 +525,10 @@ make_namelist(char *src)
if (mark == '\0')
break;
}
- if (pass == 1)
- dst = typeCalloc(char *, nn + 1);
+ if (pass == 1) {
+ if ((dst = typeCalloc(char *, nn + 1)) == 0)
+ failed("make_namelist");
+ }
}
}
if (showsummary && (dst != 0)) {
@@ -456,26 +558,118 @@ matches(char **needle, const char *haystack)
return (code);
}
-static FILE *
-open_tempfile(char *name)
+static char *
+valid_db_path(const char *nominal)
{
- FILE *result = 0;
-#if HAVE_MKSTEMP
- int fd = mkstemp(name);
- if (fd >= 0)
- result = fdopen(fd, "w");
+ struct stat sb;
+#if USE_HASHED_DB
+ char suffix[] = DBM_SUFFIX;
+ size_t need = strlen(nominal) + sizeof(suffix);
+ char *result = malloc(need);
+
+ if (result == 0)
+ failed("valid_db_path");
+ _nc_STRCPY(result, nominal, need);
+ if (strcmp(result + need - sizeof(suffix), suffix)) {
+ _nc_STRCAT(result, suffix, need);
+ }
#else
- if (tmpnam(name) != 0)
- result = fopen(name, "w");
+ char *result = strdup(nominal);
+#endif
+
+ DEBUG(1, ("** stat(%s)", result));
+ if (stat(result, &sb) >= 0) {
+#if USE_HASHED_DB
+ if (!S_ISREG(sb.st_mode)
+ || access(result, R_OK | W_OK) != 0) {
+ DEBUG(1, ("...not a writable file"));
+ free(result);
+ result = 0;
+ }
+#else
+ if (!S_ISDIR(sb.st_mode)
+ || access(result, R_OK | W_OK | X_OK) != 0) {
+ DEBUG(1, ("...not a writable directory"));
+ free(result);
+ result = 0;
+ }
#endif
+ } else {
+ /* check if parent is directory and is writable */
+ unsigned leaf = _nc_pathlast(result);
+
+ DEBUG(1, ("...not found"));
+ if (leaf) {
+ char save = result[leaf];
+ result[leaf] = 0;
+ if (stat(result, &sb) >= 0
+ && S_ISDIR(sb.st_mode)
+ && access(result, R_OK | W_OK | X_OK) == 0) {
+ result[leaf] = save;
+ } else {
+ DEBUG(1, ("...parent directory %s is not writable", result));
+ free(result);
+ result = 0;
+ }
+ } else {
+ DEBUG(1, ("... no parent directory"));
+ free(result);
+ result = 0;
+ }
+ }
return result;
}
+/*
+ * Show the databases to which tic could write. The location to which it
+ * writes is always the first one. If none are writable, print an error
+ * message.
+ */
+static void
+show_databases(const char *outdir)
+{
+ bool specific = (outdir != 0) || getenv("TERMINFO") != 0;
+ char *result;
+ const char *tried = 0;
+
+ if (outdir == 0) {
+ outdir = _nc_tic_dir(0);
+ }
+ if ((result = valid_db_path(outdir)) != 0) {
+ printf("%s\n", result);
+ free(result);
+ } else {
+ tried = outdir;
+ }
+
+ if ((outdir = _nc_home_terminfo())) {
+ if ((result = valid_db_path(outdir)) != 0) {
+ printf("%s\n", result);
+ free(result);
+ } else if (!specific) {
+ tried = outdir;
+ }
+ }
+
+ /*
+ * If we can write in neither location, give an error message.
+ */
+ if (tried) {
+ fflush(stdout);
+ fprintf(stderr, "%s: %s (no permission)\n", _nc_progname, tried);
+ ExitProgram(EXIT_FAILURE);
+ }
+}
+
+#define VtoTrace(opt) (unsigned) ((opt > 0) ? opt : (opt == 0))
+
int
main(int argc, char *argv[])
{
char my_tmpname[PATH_MAX];
- int v_opt = -1, debug_level;
+ char my_altfile[PATH_MAX];
+ int v_opt = -1;
+ unsigned debug_level;
int smart_defaults = TRUE;
char *termcap;
ENTRY *qp;
@@ -486,6 +680,7 @@ main(int argc, char *argv[])
int sortmode = S_TERMINFO; /* sort_mode */
int width = 60;
+ int height = 65535;
bool formatted = FALSE; /* reformat complex strings? */
bool literal = FALSE; /* suppress post-processing? */
int numbers = 0; /* format "%'char'" to/from "%{number}" */
@@ -493,7 +688,6 @@ main(int argc, char *argv[])
bool limited = TRUE;
char *tversion = (char *) NULL;
const char *source_file = "terminfo";
- char **namelst = 0;
char *outdir = (char *) NULL;
bool check_only = FALSE;
bool suppress_untranslatable = FALSE;
@@ -501,6 +695,7 @@ main(int argc, char *argv[])
log_fp = stderr;
_nc_progname = _nc_rootname(argv[0]);
+ atexit(cleanup);
if ((infodump = same_program(_nc_progname, PROG_CAPTOINFO)) != FALSE) {
outform = F_TERMINFO;
@@ -513,6 +708,7 @@ main(int argc, char *argv[])
#if NCURSES_XNAMES
use_extended_names(FALSE);
#endif
+ _nc_strict_bsd = 0;
/*
* Processing arguments is a little complicated, since someone made a
@@ -520,7 +716,7 @@ main(int argc, char *argv[])
* be optional.
*/
while ((this_opt = getopt(argc, argv,
- "0123456789CILNR:TUVace:fGgo:rstvwx")) != -1) {
+ "0123456789CDIKLNR:TUVace:fGgo:rstvwx")) != -1) {
if (isdigit(this_opt)) {
switch (last_opt) {
case 'v':
@@ -530,19 +726,40 @@ main(int argc, char *argv[])
width = (width * 10) + (this_opt - '0');
break;
default:
- if (this_opt != '1')
+ switch (this_opt) {
+ case '0':
+ last_opt = this_opt;
+ width = 65535;
+ height = 1;
+ break;
+ case '1':
+ last_opt = this_opt;
+ width = 0;
+ break;
+ default:
usage();
- last_opt = this_opt;
- width = 0;
+ }
}
continue;
}
switch (this_opt) {
+ case 'K':
+ _nc_strict_bsd = 1;
+ /* the initial version of -K in 20110730 fell-thru here, but the
+ * same flag is useful when reading sources -TD
+ */
+ break;
case 'C':
capdump = TRUE;
outform = F_TERMCAP;
sortmode = S_TERMCAP;
break;
+ case 'D':
+ debug_level = VtoTrace(v_opt);
+ set_trace_level(debug_level);
+ show_databases(outdir);
+ ExitProgram(EXIT_SUCCESS);
+ break;
case 'I':
infodump = TRUE;
outform = F_TERMINFO;
@@ -568,7 +785,6 @@ main(int argc, char *argv[])
break;
case 'V':
puts(curses_version());
- cleanup(namelst);
ExitProgram(EXIT_SUCCESS);
case 'c':
check_only = TRUE;
@@ -618,7 +834,7 @@ main(int argc, char *argv[])
last_opt = this_opt;
}
- debug_level = (v_opt > 0) ? v_opt : (v_opt == 0);
+ debug_level = VtoTrace(v_opt);
set_trace_level(debug_level);
if (_nc_tracing) {
@@ -638,8 +854,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(namelst);
+ "%s: Sorry, -e can't be used without -I or -C\n",
+ _nc_progname);
ExitProgram(EXIT_FAILURE);
}
#endif /* HAVE_BIG_CORE */
@@ -663,16 +879,16 @@ main(int argc, char *argv[])
if (access(termcap, F_OK) == 0) {
/* file exists */
source_file = termcap;
- } else if ((tmp_fp = open_tempfile(strcpy(my_tmpname,
- "/tmp/XXXXXX")))
- != 0) {
- source_file = my_tmpname;
- fprintf(tmp_fp, "%s\n", termcap);
- fclose(tmp_fp);
- tmp_fp = open_input(source_file);
- to_remove = source_file;
} else {
- failed("tmpnam");
+ if ((tmp_fp = open_tempfile(my_tmpname)) != 0) {
+ source_file = my_tmpname;
+ fprintf(tmp_fp, "%s\n", termcap);
+ fclose(tmp_fp);
+ tmp_fp = open_input(source_file, (char *) 0);
+ to_remove = source_file;
+ } else {
+ failed("tmpnam");
+ }
}
}
} else {
@@ -682,24 +898,28 @@ main(int argc, char *argv[])
_nc_progname,
_nc_progname,
usage_string);
- cleanup(namelst);
ExitProgram(EXIT_FAILURE);
}
}
- if (tmp_fp == 0)
- tmp_fp = open_input(source_file);
+ if (tmp_fp == 0) {
+ tmp_fp = open_input(source_file, my_altfile);
+ if (!strcmp(source_file, "-")) {
+ source_file = STDIN_NAME;
+ }
+ }
- if (infodump)
+ if (infodump) {
dump_init(tversion,
smart_defaults
? outform
: F_LITERAL,
- sortmode, width, debug_level, formatted);
- else if (capdump)
+ sortmode, width, height, debug_level, formatted);
+ } else if (capdump) {
dump_init(tversion,
outform,
- sortmode, width, debug_level, FALSE);
+ sortmode, width, height, debug_level, FALSE);
+ }
/* parse entries out of the source file */
_nc_set_source(source_file);
@@ -716,13 +936,12 @@ main(int argc, char *argv[])
/* do use resolution */
if (check_only || (!infodump && !capdump) || forceresolve) {
if (!_nc_resolve_uses2(TRUE, literal) && !check_only) {
- cleanup(namelst);
ExitProgram(EXIT_FAILURE);
}
}
/* length check */
- if (check_only && (capdump || infodump)) {
+ if (check_only && limited && (capdump || infodump)) {
for_entry_list(qp) {
if (matches(namelst, qp->tterm.term_names)) {
int len = fmt_entry(&qp->tterm, NULL, FALSE, TRUE, infodump, numbers);
@@ -750,7 +969,7 @@ main(int argc, char *argv[])
for_entry_list(qp) {
if (matches(namelst, qp->tterm.term_names)) {
- int j = qp->cend - qp->cstart;
+ long j = qp->cend - qp->cstart;
int len = 0;
/* this is in case infotocap() generates warnings */
@@ -767,7 +986,7 @@ main(int argc, char *argv[])
repair_acsc(&qp->tterm);
dump_entry(&qp->tterm, suppress_untranslatable,
limited, numbers, NULL);
- for (j = 0; j < (int) qp->nuses; j++)
+ for (j = 0; j < (long) qp->nuses; j++)
dump_uses(qp->uses[j].name, !capdump);
len = show_entry();
if (debug_level != 0 && !limited)
@@ -811,7 +1030,6 @@ main(int argc, char *argv[])
else
fprintf(log_fp, "No entries written\n");
}
- cleanup(namelst);
ExitProgram(EXIT_SUCCESS);
}
@@ -898,6 +1116,17 @@ check_colors(TERMTYPE *tp)
if (!VALID_STRING(orig_pair) && !VALID_STRING(orig_colors))
_nc_warning("expected either op/oc string for resetting colors");
}
+ if (can_change) {
+ if (!VALID_STRING(initialize_pair) &&
+ !VALID_STRING(initialize_color)) {
+ _nc_warning("expected initc or initp because ccc is given");
+ }
+ } else {
+ if (VALID_STRING(initialize_pair) ||
+ VALID_STRING(initialize_color)) {
+ _nc_warning("expected ccc because initc is given");
+ }
+ }
}
static char
@@ -915,18 +1144,18 @@ keypad_final(const char *string)
return result;
}
-static int
+static long
keypad_index(const char *string)
{
char *test;
const char *list = "PQRSwxymtuvlqrsPpn"; /* app-keypad except "Enter" */
int ch;
- int result = -1;
+ long result = -1;
if ((ch = keypad_final(string)) != '\0') {
- test = strchr(list, ch);
+ test = (strchr) (list, ch);
if (test != 0)
- result = (test - list);
+ result = (long) (test - list);
}
return result;
}
@@ -1008,6 +1237,19 @@ check_ansi_cursor(char *list[4])
}
#define EXPECTED(name) if (!PRESENT(name)) _nc_warning("expected " #name)
+#define UNEXPECTED(name) if (PRESENT(name)) _nc_warning("unexpected " #name ", for %s", why)
+
+static void
+check_noaddress(TERMTYPE *tp, const char *why)
+{
+ UNEXPECTED(column_address);
+ UNEXPECTED(cursor_address);
+ UNEXPECTED(cursor_home);
+ UNEXPECTED(cursor_mem_address);
+ UNEXPECTED(cursor_to_ll);
+ UNEXPECTED(row_address);
+ UNEXPECTED(row_address);
+}
static void
check_cursor(TERMTYPE *tp)
@@ -1015,13 +1257,55 @@ check_cursor(TERMTYPE *tp)
int count;
char *list[4];
+ if (hard_copy) {
+ check_noaddress(tp, "hard_copy");
+ } else if (generic_type) {
+ check_noaddress(tp, "generic_type");
+ } else if (strchr(tp->term_names, '+') == 0) {
+ int y = 0;
+ int x = 0;
+ if (PRESENT(column_address))
+ ++y;
+ if (PRESENT(cursor_address))
+ y = x = 10;
+ if (PRESENT(cursor_home))
+ ++y, ++x;
+ if (PRESENT(cursor_mem_address))
+ y = x = 10;
+ if (PRESENT(cursor_to_ll))
+ ++y, ++x;
+ if (PRESENT(row_address))
+ ++x;
+ if (PRESENT(cursor_down))
+ ++y;
+ if (PRESENT(cursor_up))
+ ++y;
+ if (PRESENT(cursor_left))
+ ++x;
+ if (PRESENT(cursor_right))
+ ++x;
+ if (x < 2 && y < 2) {
+ _nc_warning("terminal lacks cursor addressing");
+ } else {
+ if (x < 2)
+ _nc_warning("terminal lacks cursor column-addressing");
+ if (y < 2)
+ _nc_warning("terminal lacks cursor row-addressing");
+ }
+ }
+
+ /* it is rare to have an insert-line feature without a matching delete */
+ ANDMISSING(parm_insert_line, insert_line);
+ ANDMISSING(parm_delete_line, delete_line);
+ ANDMISSING(parm_insert_line, parm_delete_line);
+
/* if we have a parameterized form, then the non-parameterized is easy */
ANDMISSING(parm_down_cursor, cursor_down);
ANDMISSING(parm_up_cursor, cursor_up);
ANDMISSING(parm_left_cursor, cursor_left);
ANDMISSING(parm_right_cursor, cursor_right);
- /* Given any of a set of cursor movement, the whole set should be present.
+ /* Given any of a set of cursor movement, the whole set should be present.
* Technically this is not true (we could use cursor_address to fill in
* unsupported controls), but it is likely.
*/
@@ -1097,11 +1381,11 @@ check_keypad(TERMTYPE *tp)
VALID_STRING(key_c1) &&
VALID_STRING(key_c3)) {
char final[MAX_KP + 1];
- int list[MAX_KP];
+ long list[MAX_KP];
int increase = 0;
int j, k, kk;
- int last;
- int test;
+ long last;
+ long test;
final[0] = keypad_final(key_a1);
final[1] = keypad_final(key_a3);
@@ -1149,19 +1433,19 @@ check_keypad(TERMTYPE *tp)
assert(strlen(show) < (MAX_KP * 4));
switch (kk) {
case 0:
- strcat(show, " ka1");
+ _nc_STRCAT(show, " ka1", sizeof(show));
break;
case 1:
- strcat(show, " ka3");
+ _nc_STRCAT(show, " ka3", sizeof(show));
break;
case 2:
- strcat(show, " kb2");
+ _nc_STRCAT(show, " kb2", sizeof(show));
break;
case 3:
- strcat(show, " kc1");
+ _nc_STRCAT(show, " kc1", sizeof(show));
break;
case 4:
- strcat(show, " kc3");
+ _nc_STRCAT(show, " kc3", sizeof(show));
break;
}
}
@@ -1176,18 +1460,24 @@ check_keypad(TERMTYPE *tp)
VALID_STRING(key_c3)) {
show[0] = '\0';
if (keypad_index(key_a1) >= 0)
- strcat(show, " ka1");
+ _nc_STRCAT(show, " ka1", sizeof(show));
if (keypad_index(key_a3) >= 0)
- strcat(show, " ka3");
+ _nc_STRCAT(show, " ka3", sizeof(show));
if (keypad_index(key_b2) >= 0)
- strcat(show, " kb2");
+ _nc_STRCAT(show, " kb2", sizeof(show));
if (keypad_index(key_c1) >= 0)
- strcat(show, " kc1");
+ _nc_STRCAT(show, " kc1", sizeof(show));
if (keypad_index(key_c3) >= 0)
- strcat(show, " kc3");
+ _nc_STRCAT(show, " kc3", sizeof(show));
if (*show != '\0')
_nc_warning("vt100 keypad map incomplete:%s", show);
}
+
+ /*
+ * These warnings are useful for consistency checks - it is possible that
+ * there are real terminals with mismatches in these
+ */
+ ANDMISSING(key_ic, key_dc);
}
static void
@@ -1216,6 +1506,74 @@ check_printer(TERMTYPE *tp)
ANDMISSING(parm_up_micro, micro_up);
}
+static bool
+uses_SGR_39_49(const char *value)
+{
+ return (strstr(value, "39;49") != 0
+ || strstr(value, "49;39") != 0);
+}
+
+/*
+ * Check consistency of termcap extensions related to "screen".
+ */
+static void
+check_screen(TERMTYPE *tp)
+{
+#if NCURSES_XNAMES
+ if (_nc_user_definable) {
+ int have_XT = tigetflag("XT");
+ int have_XM = tigetflag("XM");
+ int have_bce = back_color_erase;
+ bool have_kmouse = FALSE;
+ bool use_sgr_39_49 = FALSE;
+ char *name = _nc_first_name(tp->term_names);
+
+ if (!VALID_BOOLEAN(have_bce)) {
+ have_bce = FALSE;
+ }
+ if (!VALID_BOOLEAN(have_XM)) {
+ have_XM = FALSE;
+ }
+ if (!VALID_BOOLEAN(have_XT)) {
+ have_XT = FALSE;
+ }
+ if (VALID_STRING(key_mouse)) {
+ have_kmouse = !strcmp("\033[M", key_mouse);
+ }
+ if (VALID_STRING(orig_colors)) {
+ use_sgr_39_49 = uses_SGR_39_49(orig_colors);
+ } else if (VALID_STRING(orig_pair)) {
+ use_sgr_39_49 = uses_SGR_39_49(orig_pair);
+ }
+
+ if (have_XM && have_XT) {
+ _nc_warning("Screen's XT capability conflicts with XM");
+ } else if (have_XT
+ && strstr(name, "screen") != 0
+ && strchr(name, '.') != 0) {
+ _nc_warning("Screen's \"screen\" entries should not have XT set");
+ } else if (have_XT) {
+ if (!have_kmouse && have_bce) {
+ if (VALID_STRING(key_mouse)) {
+ _nc_warning("Value of kmous inconsistent with screen's usage");
+ } else {
+ _nc_warning("Expected kmous capability with XT");
+ }
+ }
+ if (!have_bce && max_colors > 0)
+ _nc_warning("Expected bce capability with XT");
+ if (!use_sgr_39_49 && have_bce && max_colors > 0)
+ _nc_warning("Expected orig_colors capability with XT to have 39/49 parameters");
+ if (VALID_STRING(to_status_line))
+ _nc_warning("\"tsl\" capability is redundant, given XT");
+ } else {
+ if (have_kmouse && !have_XM)
+ _nc_warning("Expected XT to be set, given kmous");
+ }
+ }
+#endif
+}
+
/*
* Returns the expected number of parameters for the given capability.
*/
@@ -1318,7 +1676,7 @@ check_params(TERMTYPE *tp, const char *name, char *value)
int expected = expected_params(name);
int actual = 0;
int n;
- bool params[10];
+ bool params[NUM_PARM];
char *s = value;
#ifdef set_top_margin_parm
@@ -1327,7 +1685,7 @@ check_params(TERMTYPE *tp, const char *name, char *value)
expected = 2;
#endif
- for (n = 0; n < 10; n++)
+ for (n = 0; n < NUM_PARM; n++)
params[n] = FALSE;
while (*s != 0) {
@@ -1366,6 +1724,228 @@ check_params(TERMTYPE *tp, const char *name, char *value)
}
static char *
+check_1_infotocap(const char *name, NCURSES_CONST char *value, int count)
+{
+ int k;
+ int ignored;
+ long numbers[1 + NUM_PARM];
+ char *strings[1 + NUM_PARM];
+ char *p_is_s[NUM_PARM];
+ char *result;
+ char blob[NUM_PARM * 10];
+ char *next = blob;
+
+ *next++ = '\0';
+ for (k = 1; k <= NUM_PARM; k++) {
+ numbers[k] = count;
+ sprintf(next, "XYZ%d", count);
+ strings[k] = next;
+ next += strlen(next) + 1;
+ }
+
+ switch (tparm_type(name)) {
+ case Num_Str:
+ result = TPARM_2(value, numbers[1], strings[2]);
+ break;
+ case Num_Str_Str:
+ result = TPARM_3(value, numbers[1], strings[2], strings[3]);
+ break;
+ case Numbers:
+ default:
+ (void) _nc_tparm_analyze(value, p_is_s, &ignored);
+#define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n])
+ result = TPARM_9(value,
+ myParam(1),
+ myParam(2),
+ myParam(3),
+ myParam(4),
+ myParam(5),
+ myParam(6),
+ myParam(7),
+ myParam(8),
+ myParam(9));
+ break;
+ }
+ return result;
+}
+
+#define IsDelay(ch) ((ch) == '.' || isdigit(UChar(ch)))
+
+static const char *
+parse_delay_value(const char *src, double *delays, int *always)
+{
+ int star = 0;
+
+ *delays = 0.0;
+ if (always)
+ *always = 0;
+
+ while (isdigit(UChar(*src))) {
+ (*delays) = (*delays) * 10 + (*src++ - '0');
+ }
+ if (*src == '.') {
+ int gotdot = 1;
+
+ ++src;
+ while (isdigit(UChar(*src))) {
+ gotdot *= 10;
+ (*delays) += (*src++ - '0') / gotdot;
+ }
+ }
+ while (*src == '*' || *src == '/') {
+ if (always == 0 && *src == '/')
+ break;
+ if (*src++ == '*') {
+ star = 1;
+ } else {
+ *always = 1;
+ }
+ }
+ if (star)
+ *delays = -(*delays);
+ return src;
+}
+
+static const char *
+parse_ti_delay(const char *ti, double *delays)
+{
+ *delays = 0.0;
+ while (*ti != '\0') {
+ if (*ti == '\\') {
+ ++ti;
+ }
+ if (ti[0] == '$'
+ && ti[1] == '<'
+ && IsDelay(UChar(ti[2]))) {
+ int ignored;
+ const char *last = parse_delay_value(ti + 2, delays, &ignored);
+ if (*last == '>') {
+ ti = last;
+ }
+ } else {
+ ++ti;
+ }
+ }
+ return ti;
+}
+
+static const char *
+parse_tc_delay(const char *tc, double *delays)
+{
+ return parse_delay_value(tc, delays, (int *) 0);
+}
+
+/*
+ * Compare terminfo- and termcap-strings, factoring out delays.
+ */
+static bool
+same_ti_tc(const char *ti, const char *tc, bool * embedded)
+{
+ bool same = TRUE;
+ double ti_delay = 0.0;
+ double tc_delay = 0.0;
+ const char *ti_last;
+
+ *embedded = FALSE;
+ ti_last = parse_ti_delay(ti, &ti_delay);
+ tc = parse_tc_delay(tc, &tc_delay);
+
+ while ((ti < ti_last) && *tc) {
+ if (*ti == '\\' && ispunct(UChar(ti[1]))) {
+ ++ti;
+ if ((*ti == '^') && !strncmp(tc, "\\136", 4)) {
+ ti += 1;
+ tc += 4;
+ continue;
+ }
+ } else if (ti[0] == '$' && ti[1] == '<') {
+ double no_delay;
+ const char *ss = parse_ti_delay(ti, &no_delay);
+ if (ss != ti) {
+ *embedded = TRUE;
+ ti = ss;
+ continue;
+ }
+ }
+ if (*tc == '\\' && ispunct(UChar(tc[1]))) {
+ ++tc;
+ }
+ if (*ti++ != *tc++) {
+ same = FALSE;
+ break;
+ }
+ }
+
+ if (*embedded) {
+ if (same) {
+ same = FALSE;
+ } else {
+ *embedded = FALSE; /* report only one problem */
+ }
+ }
+
+ return same;
+}
+
+/*
+ * Check terminfo to termcap translation.
+ */
+static void
+check_infotocap(TERMTYPE *tp, int i, const char *value)
+{
+ const char *name = ExtStrname(tp, i, strnames);
+ int params = (((i < (int) SIZEOF(parametrized)) &&
+ (i < STRCOUNT))
+ ? parametrized[i]
+ : ((*value == 'k')
+ ? 0
+ : has_params(value)));
+ int to_char = 0;
+ char *ti_value;
+ char *tc_value;
+ bool embedded;
+
+ if ((ti_value = _nc_tic_expand(value, TRUE, to_char)) == ABSENT_STRING) {
+ _nc_warning("tic-expansion of %s failed", name);
+ } else if ((tc_value = _nc_infotocap(name, ti_value, params)) == ABSENT_STRING) {
+ _nc_warning("tic-conversion of %s failed", name);
+ } else if (params > 0) {
+ int limit = 5;
+ int count;
+ bool first = TRUE;
+
+ if (!strcmp(name, "setf")
+ || !strcmp(name, "setb")
+ || !strcmp(name, "setaf")
+ || !strcmp(name, "setab")) {
+ limit = max_colors;
+ }
+ for (count = 0; count < limit; ++count) {
+ char *ti_check = check_1_infotocap(name, ti_value, count);
+ char *tc_check = check_1_infotocap(name, tc_value, count);
+
+ if (strcmp(ti_check, tc_check)) {
+ if (first) {
+ fprintf(stderr, "check_infotocap(%s)\n", name);
+ fprintf(stderr, "...ti '%s'\n", ti_value);
+ fprintf(stderr, "...tc '%s'\n", tc_value);
+ first = FALSE;
+ }
+ _nc_warning("tparm-conversion of %s(%d) differs between\n\tterminfo %s\n\ttermcap %s",
+ name, count, ti_check, tc_check);
+ }
+ }
+ } else if (params == 0 && !same_ti_tc(ti_value, tc_value, &embedded)) {
+ if (embedded) {
+ _nc_warning("termcap equivalent of %s cannot use embedded delay", name);
+ } else {
+ _nc_warning("tic-conversion of %s changed value\n\tfrom %s\n\tto %s",
+ name, ti_value, tc_value);
+ }
+ }
+}
+
+static char *
skip_delay(char *s)
{
while (*s == '/' || isdigit(UChar(*s)))
@@ -1527,7 +2107,7 @@ static void
show_where(unsigned level)
{
if (_nc_tracing >= DEBUG_LEVEL(level)) {
- char my_name[256];
+ char my_name[MAX_NAME_SIZE];
_nc_get_type(my_name);
_tracef("\"%s\", line %d, '%s'",
_nc_get_source(),
@@ -1539,60 +2119,129 @@ show_where(unsigned level)
#define show_where(level) /* nothing */
#endif
-/* other sanity-checks (things that we don't want in the normal
- * logic that reads a terminfo entry)
+typedef struct {
+ int keycode;
+ const char *name;
+ const char *value;
+} NAME_VALUE;
+
+static NAME_VALUE *
+get_fkey_list(TERMTYPE *tp)
+{
+ NAME_VALUE *result = typeMalloc(NAME_VALUE, NUM_STRINGS(tp) + 1);
+ const struct tinfo_fkeys *all_fkeys = _nc_tinfo_fkeys;
+ int used = 0;
+ int j;
+
+ if (result == 0)
+ failed("get_fkey_list");
+
+ for (j = 0; all_fkeys[j].code; j++) {
+ char *a = tp->Strings[all_fkeys[j].offset];
+ if (VALID_STRING(a)) {
+ result[used].keycode = (int) all_fkeys[j].code;
+ result[used].name = strnames[all_fkeys[j].offset];
+ result[used].value = a;
+ ++used;
+ }
+ }
+#if NCURSES_XNAMES
+ for (j = STRCOUNT; j < NUM_STRINGS(tp); ++j) {
+ const char *name = ExtStrname(tp, j, strnames);
+ if (*name == 'k') {
+ result[used].keycode = -1;
+ result[used].name = name;
+ result[used].value = tp->Strings[j];
+ ++used;
+ }
+ }
+#endif
+ result[used].keycode = 0;
+ return result;
+}
+
+static void
+show_fkey_name(NAME_VALUE * data)
+{
+ if (data->keycode > 0) {
+ fprintf(stderr, " %s", keyname(data->keycode));
+ fprintf(stderr, " (capability \"%s\")", data->name);
+ } else {
+ fprintf(stderr, " capability \"%s\"", data->name);
+ }
+}
+
+/*
+ * A terminal entry may contain more than one keycode assigned to a given
+ * string (e.g., KEY_END and KEY_LL). But curses will only return one (the
+ * last one assigned).
*/
static void
-check_termtype(TERMTYPE *tp, bool literal)
+check_conflict(TERMTYPE *tp)
{
bool conflict = FALSE;
unsigned j, k;
- char fkeys[STRCOUNT];
- /*
- * A terminal entry may contain more than one keycode assigned to
- * a given string (e.g., KEY_END and KEY_LL). But curses will only
- * return one (the last one assigned).
- */
if (!(_nc_syntax == SYN_TERMCAP && capdump)) {
- memset(fkeys, 0, sizeof(fkeys));
- for (j = 0; _nc_tinfo_fkeys[j].code; j++) {
- char *a = tp->Strings[_nc_tinfo_fkeys[j].offset];
+ char *check = calloc((size_t) (NUM_STRINGS(tp) + 1), sizeof(char));
+ NAME_VALUE *given = get_fkey_list(tp);
+
+ if (check == 0)
+ failed("check_termtype");
+
+ for (j = 0; given[j].keycode; ++j) {
+ const char *a = given[j].value;
bool first = TRUE;
- if (!VALID_STRING(a))
- continue;
- for (k = j + 1; _nc_tinfo_fkeys[k].code; k++) {
- char *b = tp->Strings[_nc_tinfo_fkeys[k].offset];
- if (!VALID_STRING(b)
- || fkeys[k])
+
+ for (k = j + 1; given[k].keycode; k++) {
+ const char *b = given[k].value;
+ if (check[k])
continue;
if (!_nc_capcmp(a, b)) {
- fkeys[j] = 1;
- fkeys[k] = 1;
+ check[j] = 1;
+ check[k] = 1;
if (first) {
if (!conflict) {
_nc_warning("Conflicting key definitions (using the last)");
conflict = TRUE;
}
- fprintf(stderr, "... %s is the same as %s",
- keyname((int) _nc_tinfo_fkeys[j].code),
- keyname((int) _nc_tinfo_fkeys[k].code));
+ fprintf(stderr, "...");
+ show_fkey_name(given + j);
+ fprintf(stderr, " is the same as");
+ show_fkey_name(given + k);
first = FALSE;
} else {
- fprintf(stderr, ", %s",
- keyname((int) _nc_tinfo_fkeys[k].code));
+ fprintf(stderr, ", ");
+ show_fkey_name(given + k);
}
}
}
if (!first)
fprintf(stderr, "\n");
}
+ free(given);
+ free(check);
}
+}
+
+/* other sanity-checks (things that we don't want in the normal
+ * logic that reads a terminfo entry)
+ */
+static void
+check_termtype(TERMTYPE *tp, bool literal)
+{
+ unsigned j;
- for (j = 0; j < NUM_STRINGS(tp); j++) {
+ check_conflict(tp);
+
+ for_each_string(j, tp) {
char *a = tp->Strings[j];
- if (VALID_STRING(a))
- check_params(tp, ExtStrname(tp, j, strnames), a);
+ if (VALID_STRING(a)) {
+ check_params(tp, ExtStrname(tp, (int) j, strnames), a);
+ if (capdump) {
+ check_infotocap(tp, (int) j, a);
+ }
+ }
}
check_acs(tp);
@@ -1600,6 +2249,7 @@ check_termtype(TERMTYPE *tp, bool literal)
check_cursor(tp);
check_keypad(tp);
check_printer(tp);
+ check_screen(tp);
/*
* These may be mismatched because the terminal description relies on
diff --git a/progs/toe.c b/progs/toe.c
index 6f45992..0d299b4 100644
--- a/progs/toe.c
+++ b/progs/toe.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2008,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2012,2013 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 *
@@ -44,12 +44,23 @@
#include <hashed_db.h>
#endif
-MODULE_ID("$Id: toe.c,v 1.52 2010/05/01 22:04:08 tom Exp $")
+MODULE_ID("$Id: toe.c,v 1.74 2013/12/15 01:08:28 tom Exp $")
#define isDotname(name) (!strcmp(name, ".") || !strcmp(name, ".."))
+typedef struct {
+ int db_index;
+ unsigned long checksum;
+ char *term_name;
+ char *description;
+} TERMDATA;
+
const char *_nc_progname;
+static TERMDATA *ptr_termdata; /* array of terminal data */
+static size_t use_termdata; /* actual usage in ptr_termdata[] */
+static size_t len_termdata; /* allocated size of ptr_termdata[] */
+
#if NO_LEAKS
#undef ExitProgram
static void ExitProgram(int code) GCC_NORETURN;
@@ -61,6 +72,8 @@ ExitProgram(int code)
}
#endif
+static void failed(const char *) GCC_NORETURN;
+
static void
failed(const char *msg)
{
@@ -68,6 +81,150 @@ failed(const char *msg)
ExitProgram(EXIT_FAILURE);
}
+static char *
+strmalloc(const char *value)
+{
+ char *result = strdup(value);
+ if (result == 0) {
+ failed("strmalloc");
+ }
+ return result;
+}
+
+static TERMDATA *
+new_termdata(void)
+{
+ size_t want = use_termdata + 1;
+
+ if (want >= len_termdata) {
+ len_termdata = (2 * want) + 10;
+ ptr_termdata = typeRealloc(TERMDATA, len_termdata, ptr_termdata);
+ if (ptr_termdata == 0)
+ failed("ptr_termdata");
+ }
+
+ return ptr_termdata + use_termdata++;
+}
+
+static int
+compare_termdata(const void *a, const void *b)
+{
+ const TERMDATA *p = (const TERMDATA *) a;
+ const TERMDATA *q = (const TERMDATA *) b;
+ int result = strcmp(p->term_name, q->term_name);
+
+ if (result == 0) {
+ result = (p->db_index - q->db_index);
+ }
+ return result;
+}
+
+/*
+ * Sort the array of TERMDATA and print it. If more than one database is being
+ * reported, add a column to show which database has a given entry.
+ */
+static void
+show_termdata(int eargc, char **eargv)
+{
+ int j, k;
+ size_t n;
+
+ if (use_termdata) {
+ if (eargc > 1) {
+ for (j = 0; j < eargc; ++j) {
+ for (k = 0; k <= j; ++k) {
+ printf("--");
+ }
+ printf("> ");
+ printf("%s\n", eargv[j]);
+ }
+ }
+ if (use_termdata > 1)
+ qsort(ptr_termdata, use_termdata, sizeof(TERMDATA), compare_termdata);
+ for (n = 0; n < use_termdata; ++n) {
+
+ /*
+ * If there is more than one database, show how they differ.
+ */
+ if (eargc > 1) {
+ unsigned long check = 0;
+ k = 0;
+ for (;;) {
+ for (; k < ptr_termdata[n].db_index; ++k) {
+ printf("--");
+ }
+
+ /*
+ * If this is the first entry, or its checksum differs
+ * from the first entry's checksum, print "*". Otherwise
+ * it looks enough like a duplicate to print "+".
+ */
+ printf("%c-", ((check == 0
+ || (check != ptr_termdata[n].checksum))
+ ? '*'
+ : '+'));
+ check = ptr_termdata[n].checksum;
+
+ ++k;
+ if ((n + 1) >= use_termdata
+ || strcmp(ptr_termdata[n].term_name,
+ ptr_termdata[n + 1].term_name)) {
+ break;
+ }
+ ++n;
+ }
+ for (; k < eargc; ++k) {
+ printf("--");
+ }
+ printf(":\t");
+ }
+
+ (void) printf("%-10s\t%s\n",
+ ptr_termdata[n].term_name,
+ ptr_termdata[n].description);
+ }
+ }
+}
+
+static void
+free_termdata(void)
+{
+ if (ptr_termdata != 0) {
+ while (use_termdata != 0) {
+ --use_termdata;
+ free(ptr_termdata[use_termdata].term_name);
+ free(ptr_termdata[use_termdata].description);
+ }
+ free(ptr_termdata);
+ ptr_termdata = 0;
+ }
+ use_termdata = 0;
+ len_termdata = 0;
+}
+
+static char **
+allocArgv(size_t count)
+{
+ char **result = typeCalloc(char *, count + 1);
+ if (result == 0)
+ failed("realloc eargv");
+
+ assert(result != 0);
+ return result;
+}
+
+static void
+freeArgv(char **argv)
+{
+ if (argv) {
+ int count = 0;
+ while (argv[count]) {
+ free(argv[count++]);
+ }
+ free(argv);
+ }
+}
+
#if USE_HASHED_DB
static bool
make_db_name(char *dst, const char *src, unsigned limit)
@@ -75,67 +232,100 @@ make_db_name(char *dst, const char *src, unsigned limit)
static const char suffix[] = DBM_SUFFIX;
bool result = FALSE;
- unsigned lens = sizeof(suffix) - 1;
- unsigned size = strlen(src);
- unsigned need = lens + size;
+ size_t lens = sizeof(suffix) - 1;
+ size_t size = strlen(src);
+ size_t need = lens + size;
if (need <= limit) {
if (size >= lens
- && !strcmp(src + size - lens, suffix))
- (void) strcpy(dst, src);
- else
- (void) sprintf(dst, "%s%s", src, suffix);
+ && !strcmp(src + size - lens, suffix)) {
+ _nc_STRCPY(dst, src, PATH_MAX);
+ } else {
+ _nc_SPRINTF(dst, _nc_SLIMIT(PATH_MAX) "%s%s", src, suffix);
+ }
result = TRUE;
}
return result;
}
#endif
-static bool
-is_database(const char *path)
+typedef void (DescHook) (int /* db_index */ ,
+ int /* db_limit */ ,
+ const char * /* term_name */ ,
+ TERMTYPE * /* term */ );
+
+static const char *
+term_description(TERMTYPE *tp)
{
- bool result = FALSE;
-#if USE_DATABASE
- if (_nc_is_dir_path(path) && access(path, R_OK | X_OK) == 0) {
- result = TRUE;
- }
-#endif
-#if USE_TERMCAP
- if (_nc_is_file_path(path) && access(path, R_OK) == 0) {
- result = TRUE;
+ const char *desc;
+
+ if (tp->term_names == 0
+ || (desc = strrchr(tp->term_names, '|')) == 0
+ || (*++desc == '\0')) {
+ desc = "(No description)";
}
-#endif
-#if USE_HASHED_DB
- if (!result) {
- char filename[PATH_MAX];
- if (_nc_is_file_path(path) && access(path, R_OK) == 0) {
- result = TRUE;
- } else if (make_db_name(filename, path, sizeof(filename))) {
- if (_nc_is_file_path(filename) && access(filename, R_OK) == 0) {
- result = TRUE;
- }
+
+ return desc;
+}
+
+/* display a description for the type */
+static void
+deschook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
+{
+ (void) db_index;
+ (void) db_limit;
+ (void) printf("%-10s\t%s\n", term_name, term_description(tp));
+}
+
+static unsigned long
+string_sum(const char *value)
+{
+ unsigned long result = 0;
+
+ if ((intptr_t) value == (intptr_t) (-1)) {
+ result = ~result;
+ } else if (value) {
+ while (*value) {
+ result += UChar(*value);
+ ++value;
}
}
-#endif
return result;
}
-static void
-deschook(const char *cn, TERMTYPE *tp)
-/* display a description for the type */
+static unsigned long
+checksum_of(TERMTYPE *tp)
{
- const char *desc;
+ unsigned long result = string_sum(tp->term_names);
+ unsigned i;
- if ((desc = strrchr(tp->term_names, '|')) == 0 || *++desc == '\0')
- desc = "(No description)";
+ for (i = 0; i < NUM_BOOLEANS(tp); i++) {
+ result += (unsigned long) (tp->Booleans[i]);
+ }
+ for (i = 0; i < NUM_NUMBERS(tp); i++) {
+ result += (unsigned long) (tp->Numbers[i]);
+ }
+ for (i = 0; i < NUM_STRINGS(tp); i++) {
+ result += string_sum(tp->Strings[i]);
+ }
+ return result;
+}
+
+/* collect data, to sort before display */
+static void
+sorthook(int db_index, int db_limit, const char *term_name, TERMTYPE *tp)
+{
+ TERMDATA *data = new_termdata();
- (void) printf("%-10s\t%s\n", cn, desc);
+ data->db_index = db_index;
+ data->checksum = ((db_limit > 1) ? checksum_of(tp) : 0);
+ data->term_name = strmalloc(term_name);
+ data->description = strmalloc(term_description(tp));
}
-#if USE_TERMCAP
+#if NCURSES_USE_TERMCAP
static void
-show_termcap(char *buffer,
- void (*hook) (const char *, TERMTYPE *tp))
+show_termcap(int db_index, int db_limit, char *buffer, DescHook hook)
{
TERMTYPE data;
char *next = strchr(buffer, ':');
@@ -149,26 +339,42 @@ show_termcap(char *buffer,
if (last)
++last;
- data.term_names = strdup(buffer);
+ memset(&data, 0, sizeof(data));
+ data.term_names = strmalloc(buffer);
while ((next = strtok(list, "|")) != 0) {
if (next != last)
- hook(next, &data);
+ hook(db_index, db_limit, next, &data);
list = 0;
}
free(data.term_names);
}
#endif
+#if NCURSES_USE_DATABASE
+static char *
+copy_entryname(DIRENT * src)
+{
+ size_t len = NAMLEN(src);
+ char *result = malloc(len + 1);
+ if (result == 0)
+ failed("copy entryname");
+ memcpy(result, src->d_name, len);
+ result[len] = '\0';
+
+ return result;
+}
+#endif
+
static int
typelist(int eargc, char *eargv[],
- bool verbosity,
- void (*hook) (const char *, TERMTYPE *tp))
+ int verbosity,
+ DescHook hook)
/* apply a function to each entry in given terminfo directories */
{
int i;
for (i = 0; i < eargc; i++) {
-#if USE_DATABASE
+#if NCURSES_USE_DATABASE
if (_nc_is_dir_path(eargv[i])) {
char *cwd_buf = 0;
DIR *termdir;
@@ -179,28 +385,35 @@ typelist(int eargc, char *eargv[],
(void) fprintf(stderr,
"%s: can't open terminfo directory %s\n",
_nc_progname, eargv[i]);
- return (EXIT_FAILURE);
- } else if (verbosity)
+ continue;
+ }
+
+ if (verbosity)
(void) printf("#\n#%s:\n#\n", eargv[i]);
while ((subdir = readdir(termdir)) != 0) {
- size_t len = NAMLEN(subdir);
- size_t cwd_len = len + strlen(eargv[i]) + 3;
- char name_1[PATH_MAX];
+ size_t cwd_len;
+ char *name_1;
DIR *entrydir;
DIRENT *entry;
+ name_1 = copy_entryname(subdir);
+ if (isDotname(name_1)) {
+ free(name_1);
+ continue;
+ }
+
+ cwd_len = NAMLEN(subdir) + strlen(eargv[i]) + 3;
cwd_buf = typeRealloc(char, cwd_len, cwd_buf);
if (cwd_buf == 0)
failed("realloc cwd_buf");
assert(cwd_buf != 0);
- strncpy(name_1, subdir->d_name, len)[len] = '\0';
- if (isDotname(name_1))
- continue;
+ _nc_SPRINTF(cwd_buf, _nc_SLIMIT(cwd_len)
+ "%s/%s/", eargv[i], name_1);
+ free(name_1);
- (void) sprintf(cwd_buf, "%s/%.*s/", eargv[i], (int) len, name_1);
if (chdir(cwd_buf) != 0)
continue;
@@ -210,15 +423,16 @@ typelist(int eargc, char *eargv[],
continue;
}
while ((entry = readdir(entrydir)) != 0) {
- char name_2[PATH_MAX];
+ char *name_2;
TERMTYPE lterm;
char *cn;
int status;
- len = NAMLEN(entry);
- strncpy(name_2, entry->d_name, len)[len] = '\0';
- if (isDotname(name_2) || !_nc_is_file_path(name_2))
+ name_2 = copy_entryname(entry);
+ if (isDotname(name_2) || !_nc_is_file_path(name_2)) {
+ free(name_2);
continue;
+ }
status = _nc_read_file_entry(name_2, &lterm);
if (status <= 0) {
@@ -226,6 +440,10 @@ typelist(int eargc, char *eargv[],
(void) fprintf(stderr,
"%s: couldn't open terminfo file %s.\n",
_nc_progname, name_2);
+ free(cwd_buf);
+ free(name_2);
+ closedir(entrydir);
+ closedir(termdir);
return (EXIT_FAILURE);
}
@@ -233,21 +451,26 @@ typelist(int eargc, char *eargv[],
cn = _nc_first_name(lterm.term_names);
if (!strcmp(cn, name_2)) {
/* apply the selected hook function */
- (*hook) (cn, &lterm);
+ hook(i, eargc, cn, &lterm);
}
_nc_free_termtype(&lterm);
+ free(name_2);
}
closedir(entrydir);
}
closedir(termdir);
if (cwd_buf != 0)
free(cwd_buf);
+ continue;
}
#if USE_HASHED_DB
else {
DB *capdbp;
char filename[PATH_MAX];
+ if (verbosity)
+ (void) printf("#\n#%s:\n#\n", eargv[i]);
+
if (make_db_name(filename, eargv[i], sizeof(filename))) {
if ((capdbp = _nc_db_open(filename, FALSE)) != 0) {
DBT key, data;
@@ -265,7 +488,7 @@ typelist(int eargc, char *eargv[],
/* only visit things once, by primary name */
cn = _nc_first_name(lterm.term_names);
/* apply the selected hook function */
- (*hook) (cn, &lterm);
+ hook(i, eargc, cn, &lterm);
_nc_free_termtype(&lterm);
}
}
@@ -273,44 +496,51 @@ typelist(int eargc, char *eargv[],
}
_nc_db_close(capdbp);
+ continue;
}
}
}
#endif
#endif
-#if USE_TERMCAP
+#if NCURSES_USE_TERMCAP
#if HAVE_BSD_CGETENT
- char *db_array[2];
- char *buffer = 0;
+ {
+ CGETENT_CONST char *db_array[2];
+ char *buffer = 0;
- if (verbosity)
- (void) printf("#\n#%s:\n#\n", eargv[i]);
+ if (verbosity)
+ (void) printf("#\n#%s:\n#\n", eargv[i]);
- db_array[0] = eargv[i];
- db_array[1] = 0;
+ db_array[0] = eargv[i];
+ db_array[1] = 0;
- if (cgetfirst(&buffer, db_array)) {
- show_termcap(buffer, hook);
- free(buffer);
- while (cgetnext(&buffer, db_array)) {
- show_termcap(buffer, hook);
+ if (cgetfirst(&buffer, db_array) > 0) {
+ show_termcap(i, eargc, buffer, hook);
free(buffer);
+ while (cgetnext(&buffer, db_array) > 0) {
+ show_termcap(i, eargc, buffer, hook);
+ free(buffer);
+ }
+ cgetclose();
+ continue;
}
}
- cgetclose();
#else
/* scan termcap text-file only */
if (_nc_is_file_path(eargv[i])) {
char buffer[2048];
FILE *fp;
+ if (verbosity)
+ (void) printf("#\n#%s:\n#\n", eargv[i]);
+
if ((fp = fopen(eargv[i], "r")) != 0) {
while (fgets(buffer, sizeof(buffer), fp) != 0) {
if (*buffer == '#')
continue;
if (isspace(*buffer))
continue;
- show_termcap(buffer, hook);
+ show_termcap(i, eargc, buffer, hook);
}
fclose(fp);
}
@@ -319,13 +549,18 @@ typelist(int eargc, char *eargv[],
#endif
}
+ if (hook == sorthook) {
+ show_termdata(eargc, eargv);
+ free_termdata();
+ }
+
return (EXIT_SUCCESS);
}
static void
usage(void)
{
- (void) fprintf(stderr, "usage: %s [-ahuUV] [-v n] [file...]\n", _nc_progname);
+ (void) fprintf(stderr, "usage: %s [-ahsuUV] [-v n] [file...]\n", _nc_progname);
ExitProgram(EXIT_FAILURE);
}
@@ -340,23 +575,24 @@ main(int argc, char *argv[])
unsigned i;
int code;
int this_opt, last_opt = '?';
- int v_opt = 0;
+ unsigned v_opt = 0;
+ DescHook *hook = deschook;
_nc_progname = _nc_rootname(argv[0]);
- while ((this_opt = getopt(argc, argv, "0123456789ahu:vU:V")) != -1) {
+ while ((this_opt = getopt(argc, argv, "0123456789ahsu:vU:V")) != -1) {
/* handle optional parameter */
if (isdigit(this_opt)) {
switch (last_opt) {
case 'v':
- v_opt = (this_opt - '0');
+ v_opt = (unsigned) (this_opt - '0');
break;
default:
if (isdigit(last_opt))
v_opt *= 10;
else
v_opt = 0;
- v_opt += (this_opt - '0');
+ v_opt += (unsigned) (this_opt - '0');
last_opt = this_opt;
}
continue;
@@ -368,6 +604,9 @@ main(int argc, char *argv[])
case 'h':
header = TRUE;
break;
+ case 's':
+ hook = sorthook;
+ break;
case 'u':
direct_dependencies = TRUE;
report_file = optarg;
@@ -450,7 +689,7 @@ main(int argc, char *argv[])
* If we get this far, user wants a simple terminal type listing.
*/
if (optind < argc) {
- code = typelist(argc - optind, argv + optind, header, deschook);
+ code = typelist(argc - optind, argv + optind, header, hook);
} else if (all_dirs) {
DBDIRS state;
int offset;
@@ -460,64 +699,41 @@ main(int argc, char *argv[])
code = EXIT_FAILURE;
for (pass = 0; pass < 2; ++pass) {
- unsigned count = 0;
+ size_t count = 0;
_nc_first_db(&state, &offset);
while ((path = _nc_next_db(&state, &offset)) != 0) {
- if (!is_database(path)) {
- ;
- } else if (eargv != 0) {
- unsigned n;
- int found = FALSE;
-
- /* eliminate duplicates */
- for (n = 0; n < count; ++n) {
- if (!strcmp(path, eargv[n])) {
- found = TRUE;
- break;
- }
- }
- if (!found) {
- eargv[count] = strdup(path);
- ++count;
- }
- } else {
- ++count;
+ if (pass) {
+ eargv[count] = strmalloc(path);
}
+ ++count;
}
if (!pass) {
- eargv = typeCalloc(char *, count + 1);
+ eargv = allocArgv(count);
if (eargv == 0)
- failed("realloc eargv");
-
- assert(eargv != 0);
+ failed("eargv");
} else {
- code = typelist((int) count, eargv, header, deschook);
- while (count-- > 0)
- free(eargv[count]);
- free(eargv);
+ code = typelist((int) count, eargv, header, hook);
+ freeArgv(eargv);
}
}
} else {
DBDIRS state;
int offset;
const char *path;
- char *eargv[3];
- int count = 0;
+ char **eargv = allocArgv((size_t) 2);
+ size_t count = 0;
+ if (eargv == 0)
+ failed("eargv");
_nc_first_db(&state, &offset);
- while ((path = _nc_next_db(&state, &offset)) != 0) {
- if (is_database(path)) {
- eargv[count++] = strdup(path);
- break;
- }
+ if ((path = _nc_next_db(&state, &offset)) != 0) {
+ eargv[count++] = strmalloc(path);
}
- eargv[count] = 0;
- code = typelist(count, eargv, header, deschook);
+ code = typelist((int) count, eargv, header, hook);
- while (count-- > 0)
- free(eargv[count]);
+ freeArgv(eargv);
}
_nc_last_db();
diff --git a/progs/tparm_type.c b/progs/tparm_type.c
new file mode 100644
index 0000000..26eee69
--- /dev/null
+++ b/progs/tparm_type.c
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Author: Thomas E. Dickey *
+ ****************************************************************************/
+
+#include <tparm_type.h>
+
+MODULE_ID("$Id: tparm_type.c,v 1.1 2014/05/21 16:50:57 tom Exp $")
+
+/*
+ * Lookup the type of call we should make to tparm(). This ignores the actual
+ * terminfo capability (bad, because it is not extensible), but makes this
+ * code portable to platforms where sizeof(int) != sizeof(char *).
+ */
+TParams
+tparm_type(const char *name)
+{
+#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc}
+ TParams result = Numbers;
+ /* *INDENT-OFF* */
+ static const struct {
+ TParams code;
+ const char *name;
+ } table[] = {
+ TD(Num_Str, "pkey_key", "pfkey", "pk"),
+ TD(Num_Str, "pkey_local", "pfloc", "pl"),
+ TD(Num_Str, "pkey_xmit", "pfx", "px"),
+ TD(Num_Str, "plab_norm", "pln", "pn"),
+ TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"),
+ };
+ /* *INDENT-ON* */
+
+ unsigned n;
+ for (n = 0; n < SIZEOF(table); n++) {
+ if (!strcmp(name, table[n].name)) {
+ result = table[n].code;
+ break;
+ }
+ }
+ return result;
+}
diff --git a/progs/tparm_type.h b/progs/tparm_type.h
new file mode 100644
index 0000000..d143168
--- /dev/null
+++ b/progs/tparm_type.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+ * Copyright (c) 2014 Free Software Foundation, Inc. *
+ * *
+ * Permission is hereby granted, free of charge, to any person obtaining a *
+ * copy of this software and associated documentation files (the *
+ * "Software"), to deal in the Software without restriction, including *
+ * without limitation the rights to use, copy, modify, merge, publish, *
+ * distribute, distribute with modifications, sublicense, and/or sell *
+ * copies of the Software, and to permit persons to whom the Software is *
+ * furnished to do so, subject to the following conditions: *
+ * *
+ * The above copyright notice and this permission notice shall be included *
+ * in all copies or substantial portions of the Software. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
+ * *
+ * Except as contained in this notice, the name(s) of the above copyright *
+ * holders shall not be used in advertising or otherwise to promote the *
+ * sale, use or other dealings in this Software without prior written *
+ * authorization. *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Author: Thomas E. Dickey *
+ ****************************************************************************/
+
+/*
+ * $Id: tparm_type.h,v 1.1 2014/05/21 16:57:56 tom Exp $
+ *
+ * determine expected/actual number of parameters to setup for tparm
+ */
+#ifndef TPARM_TYPE_H
+#define TPARM_TYPE_H 1
+
+#define USE_LIBTINFO
+#include <progs.priv.h>
+
+typedef enum {
+ Numbers = 0
+ ,Num_Str
+ ,Num_Str_Str
+} TParams;
+
+extern TParams tparm_type(const char *name);
+
+#endif /* TPARM_TYPE_H */
diff --git a/progs/tput.c b/progs/tput.c
index 2e67cfe..5069a5c 100644
--- a/progs/tput.c
+++ b/progs/tput.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2013,2014 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,6 +29,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 *
****************************************************************************/
/*
@@ -38,8 +39,7 @@
* Ross Ridge's mytinfo package.
*/
-#define USE_LIBTINFO
-#include <progs.priv.h>
+#include <tparm_type.h>
#if !PURE_TERMINFO
#include <dump_entry.h>
@@ -47,18 +47,12 @@
#endif
#include <transform.h>
-MODULE_ID("$Id: tput.c,v 1.46 2010/01/09 16:53:24 tom Exp $")
+MODULE_ID("$Id: tput.c,v 1.50 2014/05/21 16:57:16 tom Exp $")
#define PUTS(s) fputs(s, stdout)
#define PUTCHAR(c) putchar(c)
#define FLUSH fflush(stdout)
-typedef enum {
- Numbers = 0
- ,Num_Str
- ,Num_Str_Str
-} TParams;
-
static char *prg_name;
static bool is_init = FALSE;
static bool is_reset = FALSE;
@@ -90,42 +84,6 @@ check_aliases(const char *name)
is_reset = same_program(name, PROG_RESET);
}
-/*
- * Lookup the type of call we should make to tparm(). This ignores the actual
- * terminfo capability (bad, because it is not extensible), but makes this
- * code portable to platforms where sizeof(int) != sizeof(char *).
- *
- * FIXME: If we want extensibility, analyze the capability string as we do
- * in tparm() to decide how to parse the varargs list.
- */
-static TParams
-tparm_type(const char *name)
-{
-#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc}
- TParams result = Numbers;
- /* *INDENT-OFF* */
- static const struct {
- TParams code;
- const char *name;
- } table[] = {
- TD(Num_Str, "pkey_key", "pfkey", "pk"),
- TD(Num_Str, "pkey_local", "pfloc", "pl"),
- TD(Num_Str, "pkey_xmit", "pfx", "px"),
- TD(Num_Str, "plab_norm", "pln", "pn"),
- TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"),
- };
- /* *INDENT-ON* */
-
- unsigned n;
- for (n = 0; n < SIZEOF(table); n++) {
- if (!strcmp(name, table[n].name)) {
- result = table[n].code;
- break;
- }
- }
- return result;
-}
-
static int
exit_code(int token, int value)
{
@@ -306,7 +264,7 @@ tput(int argc, char *argv[])
} else if (s != ABSENT_STRING) {
if (argc > 1) {
int k;
- int popcount;
+ int ignored;
long numbers[1 + NUM_PARM];
char *strings[1 + NUM_PARM];
char *p_is_s[NUM_PARM];
@@ -337,8 +295,8 @@ tput(int argc, char *argv[])
break;
case Numbers:
default:
- (void) _nc_tparm_analyze(s, p_is_s, &popcount);
-#define myParam(n) (p_is_s[n - 1] != 0 ? ((long) strings[n]) : numbers[n])
+ (void) _nc_tparm_analyze(s, p_is_s, &ignored);
+#define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n])
s = TPARM_9(s,
myParam(1),
myParam(2),
diff --git a/progs/transform.c b/progs/transform.c
index 75f4573..c0557f0 100644
--- a/progs/transform.c
+++ b/progs/transform.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 2009,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 2009-2010,2011 Free Software Foundation, Inc. *
* *
* Permission is hereby granted, free of charge, to any person obtaining a *
* copy of this software and associated documentation files (the *
@@ -34,21 +34,21 @@
#include <transform.h>
-MODULE_ID("$Id: transform.c,v 1.2 2010/09/04 21:16:17 tom Exp $")
+MODULE_ID("$Id: transform.c,v 1.3 2011/05/14 22:41:17 tom Exp $")
#ifdef SUFFIX_IGNORED
static void
-trim_suffix(const char *a, unsigned *len)
+trim_suffix(const char *a, size_t *len)
{
const char ignore[] = SUFFIX_IGNORED;
if (sizeof(ignore) != 0) {
bool trim = FALSE;
- unsigned need = (sizeof(ignore) - 1);
+ size_t need = (sizeof(ignore) - 1);
if (*len > need) {
- unsigned first = *len - need;
- unsigned n;
+ size_t first = *len - need;
+ size_t n;
trim = TRUE;
for (n = first; n < *len; ++n) {
if (tolower(UChar(a[n])) != tolower(UChar(ignore[n - first]))) {
@@ -69,8 +69,8 @@ trim_suffix(const char *a, unsigned *len)
bool
same_program(const char *a, const char *b)
{
- unsigned len_a = strlen(a);
- unsigned len_b = strlen(b);
+ size_t len_a = strlen(a);
+ size_t len_b = strlen(b);
trim_suffix(a, &len_a);
trim_suffix(b, &len_b);
diff --git a/progs/tset.c b/progs/tset.c
index 084e41d..f01acd7 100644
--- a/progs/tset.c
+++ b/progs/tset.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2012,2013 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 *
@@ -119,7 +119,7 @@ char *ttyname(int fd);
#include <dump_entry.h>
#include <transform.h>
-MODULE_ID("$Id: tset.c,v 1.82 2010/05/01 21:42:46 tom Exp $")
+MODULE_ID("$Id: tset.c,v 1.93 2013/12/15 01:05:56 tom Exp $")
/*
* SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS,
@@ -148,6 +148,10 @@ extern char **environ;
#undef CTRL
#define CTRL(x) ((x) & 0x1f)
+static void failed(const char *) GCC_NORETURN;
+static void exit_error(void) GCC_NORETURN;
+static void err(const char *,...) GCC_NORETURN;
+
const char *_nc_progname = "tset";
static TTY mode, oldmode, original;
@@ -160,7 +164,10 @@ static bool isreset = FALSE; /* invoked as reset */
static int terasechar = -1; /* new erase character */
static int intrchar = -1; /* new interrupt character */
static int tkillchar = -1; /* new kill character */
+
+#if HAVE_SIZECHANGE
static int tlines, tcolumns; /* window size */
+#endif
#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
@@ -203,13 +210,13 @@ static void
failed(const char *msg)
{
char temp[BUFSIZ];
- unsigned len = strlen(_nc_progname) + 2;
+ size_t len = strlen(_nc_progname) + 2;
if ((int) len < (int) sizeof(temp) - 12) {
- strcpy(temp, _nc_progname);
- strcat(temp, ": ");
+ _nc_STRCPY(temp, _nc_progname, sizeof(temp));
+ _nc_STRCAT(temp, ": ", sizeof(temp));
} else {
- strcpy(temp, "tset: ");
+ _nc_STRCPY(temp, "tset: ", sizeof(temp));
}
perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2));
exit_error();
@@ -467,9 +474,6 @@ add_mapping(const char *port, char *arg)
mapp->speed = tbaudrate(p);
}
- if (arg == (char *) 0) /* Non-optional type. */
- goto badmopt;
-
mapp->type = arg;
/* Terminate porttype, if specified. */
@@ -527,19 +531,19 @@ mapped(const char *type)
match = TRUE;
break;
case EQ:
- match = (ospeed == mapp->speed);
+ match = ((int) ospeed == mapp->speed);
break;
case GE:
- match = (ospeed >= mapp->speed);
+ match = ((int) ospeed >= mapp->speed);
break;
case GT:
- match = (ospeed > mapp->speed);
+ match = ((int) ospeed > mapp->speed);
break;
case LE:
- match = (ospeed <= mapp->speed);
+ match = ((int) ospeed <= mapp->speed);
break;
case LT:
- match = (ospeed < mapp->speed);
+ match = ((int) ospeed < mapp->speed);
break;
default:
match = FALSE;
@@ -631,13 +635,14 @@ get_termcap_entry(char *userarg)
* real entry from /etc/termcap. This prevents us from being fooled
* by out of date stuff in the environment.
*/
- found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
+ found:
+ if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
/* 'unsetenv("TERMCAP")' is not portable.
* The 'environ' array is better.
*/
int n;
for (n = 0; environ[n] != 0; n++) {
- if (!strncmp("TERMCAP=", environ[n], 8)) {
+ if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
while ((environ[n] = environ[n + 1]) != 0) {
n++;
}
@@ -788,14 +793,14 @@ reset_mode(void)
mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
#endif
- mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
+ mode.c_iflag &= ~((unsigned) (IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
#ifdef IUCLC
- | IUCLC
+ | IUCLC
#endif
#ifdef IXANY
- | IXANY
+ | IXANY
#endif
- | IXOFF);
+ | IXOFF));
mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
#ifdef IMAXBEL
@@ -803,44 +808,44 @@ reset_mode(void)
#endif
);
- mode.c_oflag &= ~(0
+ mode.c_oflag &= ~((unsigned) (0
#ifdef OLCUC
- | OLCUC
+ | OLCUC
#endif
#ifdef OCRNL
- | OCRNL
+ | OCRNL
#endif
#ifdef ONOCR
- | ONOCR
+ | ONOCR
#endif
#ifdef ONLRET
- | ONLRET
+ | ONLRET
#endif
#ifdef OFILL
- | OFILL
+ | OFILL
#endif
#ifdef OFDEL
- | OFDEL
+ | OFDEL
#endif
#ifdef NLDLY
- | NLDLY
+ | NLDLY
#endif
#ifdef CRDLY
- | CRDLY
+ | CRDLY
#endif
#ifdef TABDLY
- | TABDLY
+ | TABDLY
#endif
#ifdef BSDLY
- | BSDLY
+ | BSDLY
#endif
#ifdef VTDLY
- | VTDLY
+ | VTDLY
#endif
#ifdef FFDLY
- | FFDLY
+ | FFDLY
#endif
- );
+ ));
mode.c_oflag |= (OPOST
#ifdef ONLCR
@@ -848,19 +853,19 @@ reset_mode(void)
#endif
);
- mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
+ mode.c_cflag &= ~((unsigned) (CSIZE | CSTOPB | PARENB | PARODD | CLOCAL));
mode.c_cflag |= (CS8 | CREAD);
- mode.c_lflag &= ~(ECHONL | NOFLSH
+ mode.c_lflag &= ~((unsigned) (ECHONL | NOFLSH
#ifdef TOSTOP
- | TOSTOP
+ | TOSTOP
#endif
#ifdef ECHOPTR
- | ECHOPRT
+ | ECHOPRT
#endif
#ifdef XCASE
- | XCASE
+ | XCASE
#endif
- );
+ ));
mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
#ifdef ECHOCTL
@@ -907,14 +912,23 @@ static void
set_control_chars(void)
{
#ifdef TERMIOS
- if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0)
- mode.c_cc[VERASE] = (terasechar >= 0) ? terasechar : default_erase();
+ if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) {
+ mode.c_cc[VERASE] = UChar((terasechar >= 0)
+ ? terasechar
+ : default_erase());
+ }
- if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0)
- mode.c_cc[VINTR] = (intrchar >= 0) ? intrchar : CINTR;
+ if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) {
+ mode.c_cc[VINTR] = UChar((intrchar >= 0)
+ ? intrchar
+ : CINTR);
+ }
- if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0)
- mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL;
+ if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) {
+ mode.c_cc[VKILL] = UChar((tkillchar >= 0)
+ ? tkillchar
+ : CKILL);
+ }
#endif
}
@@ -970,9 +984,9 @@ set_conversions(void)
if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
/* Newline, not linefeed. */
#ifdef ONLCR
- mode.c_oflag &= ~ONLCR;
+ mode.c_oflag &= ~((unsigned) ONLCR);
#endif
- mode.c_iflag &= ~ICRNL;
+ mode.c_iflag &= ~((unsigned) ICRNL);
}
#ifdef __OBSOLETE__
if (tgetflag("HD")) /* Half duplex. */
@@ -1043,11 +1057,18 @@ set_tabs(void)
{
if (set_tab && clear_all_tabs) {
int c;
+ int lim =
+#if HAVE_SIZECHANGE
+ tcolumns
+#else
+ columns
+#endif
+ ;
(void) putc('\r', stderr); /* Force to left margin. */
tputs(clear_all_tabs, 0, outc);
- for (c = 8; c < tcolumns; c += 8) {
+ for (c = 8; c < lim; c += 8) {
/* Get to the right column. In BSD tset, this
* used to try a bunch of half-clever things
* with cup and hpa, for an average saving of
@@ -1273,10 +1294,10 @@ main(int argc, char **argv)
(void) get_termcap_entry(*argv);
if (!noset) {
+#if HAVE_SIZECHANGE
tcolumns = columns;
tlines = lines;
-#if HAVE_SIZECHANGE
if (opt_w) {
STRUCT_WINSIZE win;
/* Set window size if not set already */