diff options
Diffstat (limited to 'contrib/ncurses/progs')
-rwxr-xr-x | contrib/ncurses/progs/MKtermsort.sh | 121 | ||||
-rw-r--r-- | contrib/ncurses/progs/Makefile.in | 243 | ||||
-rwxr-xr-x | contrib/ncurses/progs/capconvert | 229 | ||||
-rw-r--r-- | contrib/ncurses/progs/clear.c | 58 | ||||
-rwxr-xr-x | contrib/ncurses/progs/clear.sh | 1 | ||||
-rw-r--r-- | contrib/ncurses/progs/dump_entry.c | 913 | ||||
-rw-r--r-- | contrib/ncurses/progs/dump_entry.h | 60 | ||||
-rw-r--r-- | contrib/ncurses/progs/infocmp.c | 1321 | ||||
-rw-r--r-- | contrib/ncurses/progs/modules | 40 | ||||
-rw-r--r-- | contrib/ncurses/progs/progs.priv.h | 160 | ||||
-rw-r--r-- | contrib/ncurses/progs/tic.c | 812 | ||||
-rw-r--r-- | contrib/ncurses/progs/toe.c | 303 | ||||
-rw-r--r-- | contrib/ncurses/progs/tput.c | 312 | ||||
-rw-r--r-- | contrib/ncurses/progs/tset.c | 1200 |
14 files changed, 5773 insertions, 0 deletions
diff --git a/contrib/ncurses/progs/MKtermsort.sh b/contrib/ncurses/progs/MKtermsort.sh new file mode 100755 index 0000000..6cbe954 --- /dev/null +++ b/contrib/ncurses/progs/MKtermsort.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# +# MKtermsort.sh -- generate indirection vectors for the various sort methods +# +# The output of this script is C source for nine arrays that list three sort +# orders for each of the three different classes of terminfo capabilities. +# +AWK=${1-awk} +DATA=${2-../include/Caps} + +echo "/*"; +echo " * termsort.c --- sort order arrays for use by infocmp."; +echo " *"; +echo " * Note: this file is generated using termsort.sh, do not edit by hand."; +echo " */"; + +echo "static const int bool_terminfo_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "bool" {printf("%s\t%d\n", $2, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int num_terminfo_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "num" {printf("%s\t%d\n", $2, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int str_terminfo_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "str" {printf("%s\t%d\n", $2, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int bool_variable_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "bool" {printf("%s\t%d\n", $1, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int num_variable_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "num" {printf("%s\t%d\n", $1, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int str_variable_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "str" {printf("%s\t%d\n", $1, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int bool_termcap_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "bool" {printf("%s\t%d\n", $4, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int num_termcap_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "num" {printf("%s\t%d\n", $4, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int str_termcap_sort[] = {"; +$AWK <$DATA ' +BEGIN {i = 0;} +/^#/ {next;} +$3 == "str" {printf("%s\t%d\n", $4, i++);} +' | sort | $AWK '{print "\t", $2, ",\t/* ", $1, " */";}'; +echo "};"; +echo ""; + +echo "static const int bool_from_termcap[] = {"; +$AWK <$DATA ' +$3 == "bool" && substr($5, 1, 1) == "-" {print "0,\t/* ", $2, " */";} +$3 == "bool" && substr($5, 1, 1) == "Y" {print "1,\t/* ", $2, " */";} +' +echo "};"; +echo ""; + +echo "static const int num_from_termcap[] = {"; +$AWK <$DATA ' +$3 == "num" && substr($5, 1, 1) == "-" {print "0,\t/* ", $2, " */";} +$3 == "num" && substr($5, 1, 1) == "Y" {print "1,\t/* ", $2, " */";} +' +echo "};"; +echo ""; + +echo "static const int str_from_termcap[] = {"; +$AWK <$DATA ' +$3 == "str" && substr($5, 1, 1) == "-" {print "0,\t/* ", $2, " */";} +$3 == "str" && substr($5, 1, 1) == "Y" {print "1,\t/* ", $2, " */";} +' +echo "};"; +echo ""; + diff --git a/contrib/ncurses/progs/Makefile.in b/contrib/ncurses/progs/Makefile.in new file mode 100644 index 0000000..f22a016 --- /dev/null +++ b/contrib/ncurses/progs/Makefile.in @@ -0,0 +1,243 @@ +# $Id: Makefile.in,v 1.37 1998/05/31 00:07:33 tom Exp $ +############################################################################## +# Copyright (c) 1998 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 <dickey@clark.net> 1996,1997 +# +# Makefile for ncurses source code. +# +# This makes the ncurses utility programs. +# +# The variable 'srcdir' refers to the source-distribution, and can be set with +# the configure script by "--srcdir=DIR". +# +# The rules are organized to produce the libraries for the configured models, +# and the programs with the configured default model. + +# turn off _all_ suffix rules; we'll generate our own +.SUFFIXES: + +SHELL = /bin/sh +THIS = Makefile + +CF_MFLAGS = @cf_cv_makeflags@ +@SET_MAKE@ +x = @PROG_EXT@ + +MODEL = ../@DFT_OBJ_SUBDIR@ +INSTALL_PREFIX = @INSTALL_PREFIX@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +libdir = @libdir@ +includedir = @includedir@ +datadir = @datadir@ + +ticdir = $(datadir)/terminfo + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ + +AWK = @AWK@ +LN_S = @LN_S@ + +CC = @CC@ +CFLAGS = @CFLAGS@ + +INCDIR = $(srcdir)/../include +CPPFLAGS = -I../progs -I$(srcdir) @CPPFLAGS@ \ + -DHAVE_CONFIG_H -DTERMINFO=\"$(ticdir)\" + +CCFLAGS = $(CPPFLAGS) $(CFLAGS) + +CFLAGS_NORMAL = $(CCFLAGS) +CFLAGS_DEBUG = $(CCFLAGS) @CC_G_OPT@ -DTRACE +CFLAGS_PROFILE = $(CCFLAGS) -pg +CFLAGS_SHARED = $(CCFLAGS) # @CC_SHARED_OPTS@ + +CFLAGS_DEFAULT = $(CFLAGS_@DFT_UPR_MODEL@) + +LD = @LD@ +LINK = @LINK_PROGS@ $(CC) +LDFLAGS = @EXTRA_LDFLAGS@ \ + @PROG_ARGS@ @LDFLAGS@ @LD_MODEL@ @LIBS@ @EXTRA_LIBS@ + +LDFLAGS_NORMAL = $(LDFLAGS) +LDFLAGS_DEBUG = $(LDFLAGS) @CC_G_OPT@ +LDFLAGS_PROFILE = $(LDFLAGS) -pg +LDFLAGS_SHARED = $(LDFLAGS) @LD_SHARED_OPTS@ + +LDFLAGS_DEFAULT = $(LDFLAGS_@DFT_UPR_MODEL@) + +LINT = @LINT@ +LINT_OPTS = @LINT_OPTS@ +LINT_LIBS = -lncurses @LIBS@ + +AUTO_SRC = \ + termsort.c + +PROGS = tic$x toe$x infocmp$x clear$x tput$x tset$x + +TESTPROGS = mvcur$x tctest$x hardscroll$x hashmap$x + +# Default library, for linking applications +DEPS_CURSES = @LIB_PREFIX@ncurses@DFT_DEP_SUFFIX@ + +################################################################################ +all: $(AUTO_SRC) $(PROGS) + +sources: $(AUTO_SRC) + +install: install.progs +uninstall: uninstall.progs + +# this line simplifies the configure-script +install.libs: +uninstall.libs: + +install.progs: $(PROGS) $(INSTALL_PREFIX)$(bindir) + $(INSTALL_PROGRAM) tic$x $(INSTALL_PREFIX)$(bindir)/tic$x + $(INSTALL_PROGRAM) toe$x $(INSTALL_PREFIX)$(bindir)/toe$x + $(INSTALL_PROGRAM) infocmp$x $(INSTALL_PREFIX)$(bindir)/infocmp$x + $(INSTALL_PROGRAM) clear$x $(INSTALL_PREFIX)$(bindir)/clear$x + $(INSTALL_PROGRAM) tput$x $(INSTALL_PREFIX)$(bindir)/tput$x + $(INSTALL_PROGRAM) tset$x $(INSTALL_PREFIX)$(bindir)/tset$x + @echo "linking captoinfo to tic" + -@rm -f $(INSTALL_PREFIX)$(bindir)/captoinfo$x + (cd $(INSTALL_PREFIX)$(bindir) && $(LN_S) tic$x captoinfo$x) + @echo "linking infotocap to tic" + -@rm -f $(INSTALL_PREFIX)$(bindir)/infotocap$x + (cd $(INSTALL_PREFIX)$(bindir) && $(LN_S) tic$x infotocap$x) + @echo "linking reset to tset" + -@rm -f $(INSTALL_PREFIX)$(bindir)/reset$x + (cd $(INSTALL_PREFIX)$(bindir) && $(LN_S) tset$x reset$x) + +uninstall.progs: + -@rm -f $(INSTALL_PREFIX)$(bindir)/tic$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/toe$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/infocmp$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/clear$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/tput$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/tset$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/captoinfo$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/infotocap$x + -@rm -f $(INSTALL_PREFIX)$(bindir)/reset$x + +$(INSTALL_PREFIX)$(bindir) : + $(srcdir)/../mkinstalldirs $@ + +# +# Utilities normally built by make all start here +# + +DEPS_TIC = \ + $(MODEL)/tic.o \ + $(MODEL)/dump_entry.o + +tic$x: $(DEPS_TIC) $(DEPS_CURSES) + @ECHO_LINK@ $(LINK) $(DEPS_TIC) $(LDFLAGS_DEFAULT) -o $@ + +DEPS_TOE = \ + $(MODEL)/toe.o \ + $(MODEL)/dump_entry.o + +toe$x: $(DEPS_TOE) $(DEPS_CURSES) + @ECHO_LINK@ $(LINK) $(DEPS_TOE) $(LDFLAGS_DEFAULT) -o $@ + +DEPS_CLEAR = \ + $(MODEL)/clear.o + +clear$x: $(DEPS_CLEAR) $(DEPS_CURSES) + @ECHO_LINK@ $(LINK) $(DEPS_CLEAR) $(LDFLAGS_DEFAULT) -o $@ + +DEPS_TPUT = \ + $(MODEL)/tput.o + +tput$x: $(DEPS_TPUT) $(DEPS_CURSES) + @ECHO_LINK@ $(LINK) $(DEPS_TPUT) $(LDFLAGS_DEFAULT) -o $@ + +DEPS_INFOCMP = \ + $(MODEL)/infocmp.o \ + $(MODEL)/dump_entry.o + +infocmp$x: $(DEPS_INFOCMP) $(DEPS_CURSES) + @ECHO_LINK@ $(LINK) $(DEPS_INFOCMP) $(LDFLAGS_DEFAULT) -o $@ + +DEPS_TSET = \ + $(MODEL)/tset.o \ + $(MODEL)/dump_entry.o + +tset$x: $(DEPS_TSET) $(DEPS_CURSES) + @ECHO_LINK@ $(LINK) $(DEPS_TSET) $(LDFLAGS_DEFAULT) -o $@ + +termsort.c: $(srcdir)/MKtermsort.sh + sh -c "$(srcdir)/MKtermsort.sh $(AWK) $(srcdir)/../include/Caps" >$@ + +# +# Utility productions start here +# + +tags: + ctags *.[ch] + +TAGS: + etags *.[ch] + +mostlyclean :: + -rm -f core tags TAGS *~ *.ln *.atac trace + -rm -f $(TESTPROGS) + +clean :: mostlyclean + -rm -f $(AUTO_SRC) + -rm -f $(PROGS) + +distclean :: clean + -rm -f Makefile + +realclean :: distclean + +# These rules are used to allow "make -n" to work on a clean directory-tree +../include/hashsize.h \ +../include/parametrized.h \ +../include/term.h : + cd ../include; $(MAKE) $(CF_MFLAGS) +$(DEPS_CURSES) : + cd ../ncurses; $(MAKE) $(CF_MFLAGS) + +lint: + $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/clear.c $(LINT_LIBS) + $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/infocmp.c $(srcdir)/dump_entry.c $(LINT_LIBS) + $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tic.c $(srcdir)/dump_entry.c $(LINT_LIBS) + $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/toe.c $(srcdir)/dump_entry.c $(LINT_LIBS) + $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tput.c $(LINT_LIBS) + $(LINT) $(LINT_OPTS) $(CPPFLAGS) $(srcdir)/tset.c $(srcdir)/dump_entry.c $(LINT_LIBS) + +############################################################################### +# The remainder of this file is automatically generated during configuration +############################################################################### diff --git a/contrib/ncurses/progs/capconvert b/contrib/ncurses/progs/capconvert new file mode 100755 index 0000000..2125a0d --- /dev/null +++ b/contrib/ncurses/progs/capconvert @@ -0,0 +1,229 @@ +#!/bin/sh +# $Id: capconvert,v 1.3 1997/08/02 21:52:06 tom Exp $ +# +# capconvert -- automated conversion from termcap to terminfo +# + +echo "This script tries to automatically set you up so that your applications" +echo "that now use termcap can use terminfo and the ncurses library." +echo "" + +# Note, except for telling if we're running under xterm we don't use TERM at +# all. This is because BSD users not infrequently have multiple termtypes +# selected by conditionals in tset -- unless they're xterm users, in which +# case they're on a workstation and probably don't. + +# Check to make sure TERMINFO is not already defined +if test -n "$TERMINFO" +then + echo "TERMINFO is already defined in your environment. This means" + echo "you already have a local terminfo tree, so you do not need any" + echo "conversion." + if test ! -d $TERMINFO ; then + echo "Caution: TERMINFO does not point to a directory!" + fi + exit; +fi + +# Check to see if terminfo is present in one of the standard locations. +terminfo=no +for p in $TERMINFO \ + /usr/lib/terminfo \ + /usr/share/lib/terminfo \ + /usr/share/terminfo \ + /usr/local/lib/terminfo \ + /usr/local/share/terminfo +do + if test -d $p ; then + terminfo=yes + break + fi +done + +if test $terminfo = yes +then + echo "Your system already has a system-wide terminfo tree." + echo "" + if test -z "$TERMCAP" + then + echo "You have no TERMCAP variable set, so we are done." + # Assumes the terminfo master covers all canned terminal types + exit; + fi + if test "$TERM" = "xterm" + then + 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 + echo "We will have to make a local one for you anyway, to capture the effect" + echo "of your TERMCAP variable." + fi +else + echo "No system-wide terminfo tree. We will make you a local one." +fi +echo ""; + +# Check if test -x works (it's not portable, but useful) +OPT="-x" +TMP=test$$; touch $TMP && chmod 755 $TMP +if test $OPT $TMP ; then + chmod 644 $TMP + test $OPT $TMP && OPT="-f" +else + OPT="-f" +fi +rm -f $TMP + +# First step -- go find tic +TIC= +IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" +for x in $PATH . +do + if test $OPT $x/tic + then + TIC=$x/tic + break + fi +done +IFS="$ac_save_ifs" + +if test -n "$TIC" +then + echo "I see tic at $TIC." + case $TIC in # (vi + ./tic) + if test $OPT ../misc/shlib ; then + TIC="../misc/shlib $TIC" + fi + ;; + esac +else + echo "You do not have tic installed anywhere I can see, please fix that." + exit; +fi +echo ""; + +# We have tic. Either there's no system terminfo tree or there is one but +# the user has a TERMCAP variable that may modify a stock description. +# + +# Make the user a terminfo directory +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 "really want me to try auto-configuring for you, remove or" + echo "rename $HOME/terminfo and run me again." + exit; +else + echo "I am creating your private terminfo directory at $HOME/.terminfo" + mkdir $HOME/.terminfo + # Ensure that that's where tic's compilation results. + # This isn't strictly necessary with a 1.9.7 or later tic. + TERMINFO="$HOME/.terminfo"; export TERMINFO +fi +echo ""; + +# Find a terminfo source to work from +if test -f ../misc/terminfo.src +then + echo "I see the terminfo master source is handy; I will use that." + master=../misc/terminfo.src +else + # Ooops...looks like we're running from somewhere other than the + # progs directory of an ncurses source tree. + master=`find $HOME -name "*terminfo.src" -print` + mcount=`echo $master | wc -l` + case $mcount in + 0) + echo "I can not find a terminfo source file anywhere under your home directory." + echo "There should be a file called terminfo.src somewhere in your" + echo "ncurses distribution; please put it in your home directotry" + echo "and run me again (it does not have to live there permanently)." + exit; + ;; + 1) + echo "I see a file called $master." + echo "I am going to assume this is the terminfo source included with" + echo "the ncurses distribution. If this assumption is wrong, please" + echo "interrupt me now! OK to continue?" + read ans; + ;; + 2) + echo "I see more than one possible terminfo source. Here they are:" + echo $master | sed "/^/s// /"; + while : + do + echo "Please tell me which one to use:" + read master; + if test -f $master + then + break + else + echo "That file does not exist. Try again?"; + fi + done + ;; + esac +fi +echo ""; + +# Now that we have a master, compile it into the local tree +echo "OK, now I will make your private terminfo tree. This may take a bit..." +# +# Kluge alert: we compile terminfo.src in two pieces because a lot of machines +# with < 16MB RAM choke on tic's core-hog habits. +trap "rm -f tsplit$$.*" 0 1 2 5 15 +sed -n $master \ + -e '1,/SPLIT HERE/w 'tsplit$$.01 \ + -e '/SPLIT HERE/,$w 'tsplit$$.02 \ + 2>/dev/null +for x in tsplit$$.*; do eval $TIC $x; done +rm tsplit$$.* +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." + +# We're done unless user has a .termcap file or equivalent named by TERMCAP +if test -z "$TERMCAP" +then + echo "You have no TERMCAP set, so we are done." +fi + +# OK, here comes the nasty case...user has a TERMCAP. Instead of +# trying to follow all the convolutions of the relationship between +# TERM and TERMCAP (partly because it's too painful, and partly because +# we don't actually know what TERM will be nor even if it always has +# the same value for this user) we do the following three steps... + +if test -f $HOME/.termcap +then + echo 'I see you have a $HOME/.termcap file. I will compile that.' + eval $TIC $HOME/.termcap + echo "Done." + echo "Note that editing $HOME/.termcap will no longer change the data curses sees." +elif test -f "$TERMCAP" +then + echo "Your TERMCAP names the file $TERMCAP. I will compile that." + eval $TIC $TERMCAP + echo "Done." + echo "Note that editing $TERMCAP will no longer change the data curses sees." +else + echo "Your TERMCAP value appears to be an entry in termcap format." + echo "I will compile it." + echo $TERMCAP >myterm$$ + eval $TIC myterm$$ + rm myterm$$ + echo "Done." + echo "Note that editing TERMCAP will no longer change the data curses sees." +fi +echo "To do that, decompile the terminal decription you want with infocmp(1)," +echo "edit to taste, and recompile using tic(1)." + +# capconvert ends here + diff --git a/contrib/ncurses/progs/clear.c b/contrib/ncurses/progs/clear.c new file mode 100644 index 0000000..d27b625 --- /dev/null +++ b/contrib/ncurses/progs/clear.c @@ -0,0 +1,58 @@ +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * clear.c -- clears the terminal's screen + */ + +#include <progs.priv.h> + +#include <curses.h> + +MODULE_ID("$Id: clear.c,v 1.8 1998/09/26 11:42:50 tom Exp $") + +static int putch(int c) +{ + return putchar(c); +} + +int main( + int argc GCC_UNUSED, + char *argv[] GCC_UNUSED) +{ + setupterm((char *) 0, STDOUT_FILENO, (int *) 0); + return (tputs(clear_screen, lines > 0 ? lines : 1, putch) == ERR) + ? EXIT_FAILURE + : EXIT_SUCCESS; +} diff --git a/contrib/ncurses/progs/clear.sh b/contrib/ncurses/progs/clear.sh new file mode 100755 index 0000000..1b6b0bb --- /dev/null +++ b/contrib/ncurses/progs/clear.sh @@ -0,0 +1 @@ +exec tput clear diff --git a/contrib/ncurses/progs/dump_entry.c b/contrib/ncurses/progs/dump_entry.c new file mode 100644 index 0000000..8324fe2 --- /dev/null +++ b/contrib/ncurses/progs/dump_entry.c @@ -0,0 +1,913 @@ +/**************************************************************************** + * Copyright (c) 1998,1999 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +#define __INTERNAL_CAPS_VISIBLE +#include <progs.priv.h> + +#include "dump_entry.h" +#include "termsort.c" /* this C file is generated */ +#include <parametrized.h> /* so is this */ + +MODULE_ID("$Id: dump_entry.c,v 1.37 1999/03/14 12:29:30 tom Exp $") + +#define INDENT 8 + +#define DISCARD(string) string = ABSENT_STRING + +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 column; /* current column, limited by 'width' */ +static int oldcol; /* last value of column before wrap */ +static int tracelevel; /* level of debug output */ +static bool pretty; /* true if we format if-then-else strings */ + +static char *outbuf; /* the output-buffer */ +static size_t out_used; /* ...its current length */ +static size_t out_size; /* ...and its allocated length */ + +/* indirection pointers for implementing sort and display modes */ +static const int *bool_indirect, *num_indirect, *str_indirect; +static NCURSES_CONST char * const *bool_names; +static NCURSES_CONST char * const *num_names; +static NCURSES_CONST char * const *str_names; + +static const char *separator, *trailer; + +/* cover various ports and variants of terminfo */ +#define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ +#define V_SVR1 1 /* SVR1, Ultrix */ +#define V_HPUX 2 /* HP/UX */ +#define V_AIX 3 /* AIX */ +#define V_BSD 4 /* BSD */ + +#define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') + +#if NCURSES_XNAMES +#define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) +#define NumIndirect(j) ((j >= NUMCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : num_indirect[j])) +#define StrIndirect(j) ((j >= STRCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : str_indirect[j])) +#else +#define BoolIndirect(j) ((sortmode == S_NOSORT) ? (j) : bool_indirect[j]) +#define NumIndirect(j) ((sortmode == S_NOSORT) ? (j) : num_indirect[j]) +#define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) +#endif + +#if NO_LEAKS +void _nc_leaks_dump_entry(void) +{ + if (outbuf != 0) { + free(outbuf); + outbuf = 0; + } +} +#endif + +NCURSES_CONST char *nametrans(const char *name) +/* translate a capability name from termcap to terminfo */ +{ + const struct name_table_entry *np; + + if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) + switch(np->nte_type) + { + case BOOLEAN: + if (bool_from_termcap[np->nte_index]) + return(boolcodes[np->nte_index]); + break; + + case NUMBER: + if (num_from_termcap[np->nte_index]) + return(numcodes[np->nte_index]); + break; + + case STRING: + if (str_from_termcap[np->nte_index]) + return(strcodes[np->nte_index]); + break; + } + + return(0); +} + +void dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool formatted) +/* set up for entry display */ +{ + width = twidth; + pretty = formatted; + tracelevel = traceval; + + /* versions */ + if (version == 0) + tversion = V_ALLCAPS; + else if (!strcmp(version, "SVr1") || !strcmp(version, "SVR1") + || !strcmp(version, "Ultrix")) + tversion = V_SVR1; + else if (!strcmp(version, "HP")) + tversion = V_HPUX; + else if (!strcmp(version, "AIX")) + tversion = V_AIX; + else if (!strcmp(version, "BSD")) + tversion = V_BSD; + else + tversion = V_ALLCAPS; + + /* implement display modes */ + switch (outform = mode) + { + case F_LITERAL: + case F_TERMINFO: + bool_names = boolnames; + num_names = numnames; + str_names = strnames; + separator = twidth ? ", " : ","; + trailer = "\n\t"; + break; + + case F_VARIABLE: + bool_names = boolfnames; + num_names = numfnames; + str_names = strfnames; + separator = twidth ? ", " : ","; + trailer = "\n\t"; + break; + + case F_TERMCAP: + case F_TCONVERR: + bool_names = boolcodes; + num_names = numcodes; + str_names = strcodes; + separator = ":"; + trailer = "\\\n\t:"; + break; + } + + /* implement sort modes */ + switch(sortmode = sort) + { + case S_NOSORT: + if (traceval) + (void) fprintf(stderr, + "%s: sorting by term structure order\n", _nc_progname); + break; + + case S_TERMINFO: + if (traceval) + (void) fprintf(stderr, + "%s: sorting by terminfo name order\n", _nc_progname); + bool_indirect = bool_terminfo_sort; + num_indirect = num_terminfo_sort; + str_indirect = str_terminfo_sort; + break; + + case S_VARIABLE: + if (traceval) + (void) fprintf(stderr, + "%s: sorting by C variable order\n", _nc_progname); + bool_indirect = bool_variable_sort; + num_indirect = num_variable_sort; + str_indirect = str_variable_sort; + break; + + case S_TERMCAP: + if (traceval) + (void) fprintf(stderr, + "%s: sorting by termcap name order\n", _nc_progname); + bool_indirect = bool_termcap_sort; + num_indirect = num_termcap_sort; + str_indirect = str_termcap_sort; + break; + } + + if (traceval) + (void) fprintf(stderr, + "%s: width = %d, tversion = %d, outform = %d\n", + _nc_progname, width, tversion, outform); +} + +static TERMTYPE *cur_type; + +static int dump_predicate(int type, int idx) +/* predicate function to use for ordinary decompilation */ +{ + switch(type) { + case BOOLEAN: + return (cur_type->Booleans[idx] == FALSE) + ? FAIL : cur_type->Booleans[idx]; + + case NUMBER: + return (cur_type->Numbers[idx] == ABSENT_NUMERIC) + ? FAIL : cur_type->Numbers[idx]; + + case STRING: + return (cur_type->Strings[idx] != ABSENT_STRING) + ? (int)TRUE : FAIL; + } + + return(FALSE); /* pacify compiler */ +} + +static void set_obsolete_termcaps(TERMTYPE *tp); +static void repair_acsc(TERMTYPE *tp); + +/* is this the index of a function key string? */ +#define FNKEY(i) (((i)<= 65 && (i)>= 75) || ((i)<= 216 && (i)>= 268)) + +static bool version_filter(int type, int idx) +/* filter out capabilities we may want to suppress */ +{ + switch (tversion) + { + case V_ALLCAPS: /* SVr4, XSI Curses */ + return(TRUE); + + case V_SVR1: /* System V Release 1, Ultrix */ + switch (type) + { + case BOOLEAN: + /* below and including xon_xoff */ + return ((idx <= 20) ? TRUE : FALSE); + case NUMBER: + /* below and including width_status_line */ + return ((idx <= 7) ? TRUE : FALSE); + case STRING: + /* below and including prtr_non */ + return ((idx <= 144) ? TRUE : FALSE); + } + break; + + case V_HPUX: /* Hewlett-Packard */ + switch (type) + { + case BOOLEAN: + /* below and including xon_xoff */ + return ((idx <= 20) ? TRUE : FALSE); + case NUMBER: + /* below and including label_width */ + return ((idx <= 10) ? TRUE : FALSE); + case STRING: + if (idx <= 144) /* below and including prtr_non */ + return(TRUE); + else if (FNKEY(idx)) /* function keys */ + return(TRUE); + else if (idx==147||idx==156||idx==157) /* plab_norm,label_on,label_off */ + return(TRUE); + else + return(FALSE); + } + break; + + case V_AIX: /* AIX */ + switch (type) + { + case BOOLEAN: + /* below and including xon_xoff */ + return ((idx <= 20) ? TRUE : FALSE); + case NUMBER: + /* below and including width_status_line */ + return ((idx <= 7) ? TRUE : FALSE); + case STRING: + if (idx <= 144) /* below and including prtr_non */ + return(TRUE); + else if (FNKEY(idx)) /* function keys */ + return(TRUE); + else + return(FALSE); + } + break; + + case V_BSD: /* BSD */ + switch (type) + { + case BOOLEAN: + return bool_from_termcap[idx]; + case NUMBER: + return num_from_termcap[idx]; + case STRING: + return str_from_termcap[idx]; + } + break; + } + + return(FALSE); /* pacify the compiler */ +} + +static +void append_output (const char *src) +{ + if (src == 0) { + out_used = 0; + append_output(""); + } else { + size_t need = strlen(src); + size_t want = need + out_used + 1; + if (want > out_size) { + out_size += want; /* be generous */ + if (outbuf == 0) + outbuf = malloc(out_size); + else + outbuf = realloc(outbuf, out_size); + } + (void)strcpy(outbuf + out_used, src); + out_used += need; + } +} + +static +void force_wrap(void) +{ + oldcol = column; + append_output(trailer); + column = INDENT; +} + +static +void wrap_concat(const char *src) +{ + int need = strlen(src); + int want = strlen(separator) + need; + + if (column > INDENT + && column + want > width) { + force_wrap(); + } + append_output(src); + append_output(separator); + column += need; +} + +#define IGNORE_SEP_TRAIL(first,last,sep_trail) \ + if ((size_t)(last - first) > sizeof(sep_trail)-1 \ + && !strncmp(first, sep_trail, sizeof(sep_trail)-1)) \ + first += sizeof(sep_trail)-2 + +/* Returns the nominal length of the buffer assuming it is termcap format, + * i.e., the continuation sequence is treated as a single character ":". + * + * There are several implementations of termcap which read the text into a + * fixed-size buffer. Generally they strip the newlines from the text, but may + * not do it until after the buffer is read. Also, "tc=" resolution may be + * expanded in the same buffer. This function is useful for measuring the size + * of the best fixed-buffer implementation; the worst case may be much worse. + */ +#ifdef TEST_TERMCAP_LENGTH +static int termcap_length(const char *src) +{ + static const char pattern[] = ":\\\n\t:"; + + int len = 0; + const char *const t = src + strlen(src); + + while (*src != '\0') { + IGNORE_SEP_TRAIL(src, t, pattern); + src++; + len++; + } + return len; +} +#else +#define termcap_length(src) strlen(src) +#endif + +static char * fmt_complex(char *dst, char *src, int level) +{ + int percent = 0; + int n; + + dst += strlen(dst); + while (*src != '\0') { + switch (*src) { + case '\\': + percent = 0; + *dst++ = *src++; + break; + case '%': + percent = 1; + break; + case '?': /* "if" */ + case 't': /* "then" */ + case 'e': /* "else" */ + if (percent) { + percent = 0; + dst[-1] = '\n'; + for (n = 0; n <= level; n++) + *dst++ = '\t'; + *dst++ = '%'; + *dst++ = *src; + *dst = '\0'; + if (*src++ == '?') { + src = fmt_complex(dst, src, level+1); + dst += strlen(dst); + } else if (level == 1) { + _nc_warning("%%%c without %%?", *src); + } + continue; + } + break; + case ';': /* "endif" */ + if (percent) { + percent = 0; + if (level > 1) { + dst[-1] = '\n'; + for (n = 0; n < level; n++) + *dst++ = '\t'; + *dst++ = '%'; + *dst++ = *src++; + *dst = '\0'; + return src; + } + _nc_warning("%%; without %%?"); + } + break; + default: + percent = 0; + break; + } + *dst++ = *src++; + } + *dst = '\0'; + return src; +} + +int fmt_entry(TERMTYPE *tterm, + int (*pred)(int type, int idx), + bool suppress_untranslatable, + bool infodump, + int numbers) +{ +int i, j; +char buffer[MAX_TERMINFO_LENGTH]; +NCURSES_CONST char *name; +int predval, len; +int num_bools = 0; +int num_values = 0; +int num_strings = 0; +bool outcount = 0; + +#define WRAP_CONCAT \ + wrap_concat(buffer); \ + outcount = TRUE + + len = 12; /* terminfo file-header */ + + if (pred == 0) { + cur_type = tterm; + pred = dump_predicate; + } + + append_output(0); + append_output(tterm->term_names); + append_output(separator); + column = out_used; + force_wrap(); + + for_each_boolean(j,tterm) { + i = BoolIndirect(j); + name = ExtBoolname(tterm,i,bool_names); + + if (!version_filter(BOOLEAN, i)) + continue; + else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE) + && (OBSOLETE(name) && outform != F_LITERAL)) + continue; + + predval = pred(BOOLEAN, i); + if (predval != FAIL) { + (void) strcpy(buffer, name); + if (predval <= 0) + (void) strcat(buffer, "@"); + else if (i + 1 > num_bools) + num_bools = i + 1; + WRAP_CONCAT; + } + } + + if (column != INDENT) + force_wrap(); + + for_each_number(j,tterm) { + i = NumIndirect(j); + name = ExtNumname(tterm,i,num_names); + + if (!version_filter(NUMBER, i)) + continue; + else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE) + && (OBSOLETE(name) && outform != F_LITERAL)) + continue; + + predval = pred(NUMBER, i); + if (predval != FAIL) { + if (tterm->Numbers[i] < 0) { + sprintf(buffer, "%s@", name); + } else { + sprintf(buffer, "%s#%d", name, tterm->Numbers[i]); + if (i + 1 > num_values) + num_values = i + 1; + } + WRAP_CONCAT; + } + } + + if (column != INDENT) + force_wrap(); + + len += num_bools + + num_values * 2 + + strlen(tterm->term_names) + 1; + if (len & 1) + len++; + + repair_acsc(tterm); + for_each_string(j, tterm) { + i = StrIndirect(j); + name = ExtStrname(tterm,i,str_names); + + if (!version_filter(STRING, i)) + continue; + else if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE) + && (OBSOLETE(name) && outform != F_LITERAL)) + continue; + + /* + * Some older versions of vi want rmir/smir to be defined + * for ich/ich1 to work. If they're not defined, force + * them to be output as defined and empty. + */ + if (outform==F_TERMCAP) + { +#undef CUR +#define CUR tterm-> + if (insert_character || parm_ich) + { + if (&tterm->Strings[i] == &enter_insert_mode + && enter_insert_mode == ABSENT_STRING) + { + (void) strcpy(buffer, "im="); + goto catenate; + } + + if (&tterm->Strings[i] == &exit_insert_mode + && exit_insert_mode == ABSENT_STRING) + { + (void) strcpy(buffer, "ei="); + goto catenate; + } + } + + if (init_3string != 0 + && termcap_reset != 0 + && !strcmp(init_3string, termcap_reset)) + DISCARD(init_3string); + + if (reset_2string != 0 + && termcap_reset != 0 + && !strcmp(reset_2string, termcap_reset)) + DISCARD(reset_2string); + } + + predval = pred(STRING, i); + buffer[0] = '\0'; + if (predval != FAIL) { + if (tterm->Strings[i] != ABSENT_STRING + && i + 1 > num_strings) + num_strings = i + 1; + if (!VALID_STRING(tterm->Strings[i])) + sprintf(buffer, "%s@", name); + else if (outform == F_TERMCAP || outform == F_TCONVERR) + { + char *srccap = _nc_tic_expand(tterm->Strings[i], FALSE, numbers); + char *cv = _nc_infotocap(name, srccap, parametrized[i]); + + if (cv == 0) + { + if (outform == F_TCONVERR) + sprintf(buffer, "%s=!!! %s WILL NOT CONVERT !!!", name, srccap); + else if (suppress_untranslatable) + continue; + else + sprintf(buffer, "..%s=%s", name, srccap); + } + else + sprintf(buffer, "%s=%s", name, cv); + len += strlen(tterm->Strings[i]) + 1; + } + else + { + char *src = _nc_tic_expand(tterm->Strings[i], outform==F_TERMINFO, numbers); + sprintf(buffer, "%s=", name); + if (pretty && outform==F_TERMINFO) + fmt_complex(buffer + strlen(buffer), src, 1); + else + strcat(buffer, src); + len += strlen(tterm->Strings[i]) + 1; + } + + catenate: + WRAP_CONCAT; + } + } + len += num_strings * 2; + + /* + * This piece of code should be an effective inverse of the functions + * postprocess_terminfo and postprocess_terminfo in parse_entry.c. + * Much more work should be done on this to support dumping termcaps. + */ + if (tversion == V_HPUX) + { + if (memory_lock) + { + (void) sprintf(buffer, "meml=%s", memory_lock); + WRAP_CONCAT; + } + if (memory_unlock) + { + (void) sprintf(buffer, "memu=%s", memory_unlock); + WRAP_CONCAT; + } + } + else if (tversion == V_AIX) + { + if (VALID_STRING(acs_chars)) + { + bool box_ok = TRUE; + const char *acstrans = "lqkxjmwuvtn"; + const char *cp; + char *tp, *sp, boxchars[11]; + + tp = boxchars; + for (cp = acstrans; *cp; cp++) + { + sp = strchr(acs_chars, *cp); + if (sp) + *tp++ = sp[1]; + else + { + box_ok = FALSE; + break; + } + } + tp[0] = '\0'; + + if (box_ok) + { + (void) strcpy(buffer, "box1="); + (void) strcat(buffer, _nc_tic_expand(boxchars, outform==F_TERMINFO, numbers)); + WRAP_CONCAT; + } + } + } + + /* + * kludge: trim off trailer to avoid an extra blank line + * in infocmp -u output when there are no string differences + */ + if (outcount) + { + j = out_used; + if (j >= 2 + && outbuf[j-1] == '\t' + && outbuf[j-2] == '\n') { + out_used -= 2; + } else if (j >= 4 + && outbuf[j-1] == ':' + && outbuf[j-2] == '\t' + && outbuf[j-3] == '\n' + && outbuf[j-4] == '\\') { + out_used -= 4; + } + outbuf[out_used] = '\0'; + column = oldcol; + } + +#if 0 + fprintf(stderr, "num_bools = %d\n", num_bools); + fprintf(stderr, "num_values = %d\n", num_values); + fprintf(stderr, "num_strings = %d\n", num_strings); + fprintf(stderr, "term_names=%s, len=%d, strlen(outbuf)=%d, outbuf=%s\n", + tterm->term_names, len, out_used, outbuf); +#endif + /* + * Here's where we use infodump to trigger a more stringent length check + * for termcap-translation purposes. + * Return the length of the raw entry, without tc= expansions, + * It gives an idea of which entries are deadly to even *scan past*, + * as opposed to *use*. + */ + return(infodump ? len : termcap_length(outbuf)); +} + +int dump_entry(TERMTYPE *tterm, bool limited, int numbers, int (*pred)(int type, int idx)) +/* dump a single entry */ +{ + int len, critlen; + const char *legend; + bool infodump; + + if (outform==F_TERMCAP || outform==F_TCONVERR) + { + critlen = MAX_TERMCAP_LENGTH; + legend = "older termcap"; + infodump = FALSE; + set_obsolete_termcaps(tterm); + } + else + { + critlen = MAX_TERMINFO_LENGTH; + legend = "terminfo"; + infodump = TRUE; + } + + if (((len = fmt_entry(tterm, pred, FALSE, infodump, numbers)) > critlen) && limited) + { + (void) printf("# (untranslatable capabilities removed to fit entry within %d bytes)\n", + critlen); + if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) + { + /* + * We pick on sgr because it's a nice long string capability that + * is really just an optimization hack. + */ + char *oldsgr = set_attributes; + set_attributes = ABSENT_STRING; + (void) printf("# (sgr removed to fit entry within %d bytes)\n", + critlen); + if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) + { + int oldversion = tversion; + + tversion = V_BSD; + (void) printf("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", + critlen); + + if ((len = fmt_entry(tterm, pred, TRUE, infodump, numbers)) > critlen) + { + (void) fprintf(stderr, + "warning: %s entry is %d bytes long\n", + _nc_first_name(tterm->term_names), + len); + (void) printf( + "# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", + len, legend); + } + tversion = oldversion; + } + set_attributes = oldsgr; + } + } + + (void) fputs(outbuf, stdout); + return len; +} + +int dump_uses(const char *name, bool infodump) +/* dump "use=" clauses in the appropriate format */ +{ + char buffer[MAX_TERMINFO_LENGTH]; + + append_output(0); + (void)sprintf(buffer, "%s%s", infodump ? "use=" : "tc=", name); + wrap_concat(buffer); + (void) fputs(outbuf, stdout); + return out_used; +} + +void compare_entry(void (*hook)(int t, int i, const char *name), TERMTYPE *tp GCC_UNUSED) +/* compare two entries */ +{ + int i, j; + NCURSES_CONST char * name; + + (void) fputs(" comparing booleans.\n", stdout); + for_each_boolean(j,tp) + { + i = BoolIndirect(j); + name = ExtBoolname(tp,i,bool_names); + + if ((outform == F_LITERAL || outform == F_TERMINFO || outform == F_VARIABLE) + && (OBSOLETE(name) && outform != F_LITERAL)) + continue; + + (*hook)(BOOLEAN, i, name); + } + + (void) fputs(" comparing numbers.\n", stdout); + for_each_number(j,tp) + { + i = NumIndirect(j); + name = ExtNumname(tp,i,num_names); + + if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE) + && (OBSOLETE(name) && outform != F_LITERAL)) + continue; + + (*hook)(NUMBER, i, name); + } + + (void) fputs(" comparing strings.\n", stdout); + for_each_string(j,tp) + { + i = StrIndirect(j); + name = ExtStrname(tp,i,str_names); + + if ((outform==F_LITERAL || outform==F_TERMINFO || outform==F_VARIABLE) + && (OBSOLETE(name) && outform != F_LITERAL)) + continue; + + (*hook)(STRING, i, name); + } +} + +#define NOTSET(s) ((s) == 0) + +/* + * This bit of legerdemain turns all the terminfo variable names into + * references to locations in the arrays Booleans, Numbers, and Strings --- + * precisely what's needed. + */ +#undef CUR +#define CUR tp-> + +static void set_obsolete_termcaps(TERMTYPE *tp) +{ +#include "capdefaults.c" +} + +/* + * Convert an alternate-character-set string to canonical form: sorted and + * unique. + */ +static void repair_acsc(TERMTYPE *tp) +{ + if (VALID_STRING(acs_chars)) { + size_t n, m; + char mapped[256]; + char extra = 0; + unsigned source; + unsigned target; + bool fix_needed = FALSE; + + for (n = 0, source = 0; acs_chars[n] != 0; n++) { + target = acs_chars[n]; + if (source >= target) { + fix_needed = TRUE; + break; + } + source = target; + if (acs_chars[n+1]) + n++; + } + if (fix_needed) { + memset(mapped, 0, sizeof(mapped)); + for (n = 0; acs_chars[n] != 0; n++) { + source = acs_chars[n]; + if ((target = (unsigned char)acs_chars[n+1]) != 0) { + mapped[source] = target; + n++; + } else { + extra = source; + } + } + for (n = m = 0; n < sizeof(mapped); n++) { + if (mapped[n]) { + acs_chars[m++] = n; + acs_chars[m++] = mapped[n]; + } + } + if (extra) + acs_chars[m++] = extra; /* garbage in, garbage out */ + acs_chars[m] = 0; + } + } +} diff --git a/contrib/ncurses/progs/dump_entry.h b/contrib/ncurses/progs/dump_entry.h new file mode 100644 index 0000000..d7e27c5 --- /dev/null +++ b/contrib/ncurses/progs/dump_entry.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * Copyright (c) 1998,1999 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * Dump control definitions and variables + */ + +/* capability output formats */ +#define F_TERMINFO 0 /* use terminfo names */ +#define F_VARIABLE 1 /* use C variable names */ +#define F_TERMCAP 2 /* termcap names with capability conversion */ +#define F_TCONVERR 3 /* as T_TERMCAP, no skip of untranslatables */ +#define F_LITERAL 4 /* like F_TERMINFO, but no smart defaults */ + +/* capability sort modes */ +#define S_DEFAULT 0 /* sort by terminfo name (implicit) */ +#define S_NOSORT 1 /* don't sort */ +#define S_TERMINFO 2 /* sort by terminfo names (explicit) */ +#define S_VARIABLE 3 /* sort by C variable names */ +#define S_TERMCAP 4 /* sort by termcap names */ + +extern NCURSES_CONST char *nametrans(const char *); +extern void dump_init(const char *, int, int, int, int, bool); +extern int fmt_entry(TERMTYPE *, int (*)(int, int), bool, bool, int); +extern int dump_entry(TERMTYPE *, bool, int, int (*)(int, int)); +extern int dump_uses(const char *, bool); +extern void compare_entry(void (*)(int, int, const char *), TERMTYPE *); + +#define FAIL -1 diff --git a/contrib/ncurses/progs/infocmp.c b/contrib/ncurses/progs/infocmp.c new file mode 100644 index 0000000..5965224 --- /dev/null +++ b/contrib/ncurses/progs/infocmp.c @@ -0,0 +1,1321 @@ +/**************************************************************************** + * Copyright (c) 1998,1999 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * infocmp.c -- decompile an entry, or compare two entries + * written by Eric S. Raymond + */ + +#include <progs.priv.h> + +#include <term_entry.h> +#include <dump_entry.h> + +MODULE_ID("$Id: infocmp.c,v 1.44 1999/06/16 00:39:48 tom Exp $") + +#define L_CURL "{" +#define R_CURL "}" + +#define MAXTERMS 32 /* max # terminal arguments we can handle */ + +const char *_nc_progname = "infocmp"; + +typedef char path[PATH_MAX]; + +/*************************************************************************** + * + * The following control variables, together with the contents of the + * terminfo entries, completely determine the actions of the program. + * + ***************************************************************************/ + +static char *tname[MAXTERMS]; /* terminal type names */ +static TERMTYPE term[MAXTERMS]; /* terminfo entries */ +static int termcount; /* count of terminal entries */ + +static const char *tversion; /* terminfo version selected */ +static int numbers = 0; /* format "%'char'" to/from "%{number}" */ +static int outform; /* output format */ +static int sortmode; /* sort_mode */ +static int itrace; /* trace flag for debugging */ +static int mwidth = 60; + +/* main comparison mode */ +static int compare; +#define C_DEFAULT 0 /* don't force comparison mode */ +#define C_DIFFERENCE 1 /* list differences between two terminals */ +#define C_COMMON 2 /* list common capabilities */ +#define C_NAND 3 /* list capabilities in neither terminal */ +#define C_USEALL 4 /* generate relative use-form entry */ +static bool ignorepads; /* ignore pad prefixes when diffing */ + +#if NO_LEAKS +#undef ExitProgram +static void ExitProgram(int code) GCC_NORETURN; +static void ExitProgram(int code) +{ + while (termcount-- > 0) + _nc_free_termtype(&term[termcount]); + _nc_leaks_dump_entry(); + _nc_free_and_exit(code); +} +#endif + +static char *canonical_name(char *ptr, char *buf) +/* extract the terminal type's primary name */ +{ + char *bp; + + (void) strcpy(buf, ptr); + if ((bp = strchr(buf, '|')) != (char *)NULL) + *bp = '\0'; + + return(buf); +} + +/*************************************************************************** + * + * Predicates for dump function + * + ***************************************************************************/ + +static int capcmp(const char *s, const char *t) +/* capability comparison function */ +{ + if (!VALID_STRING(s) && !VALID_STRING(t)) + return(0); + else if (!VALID_STRING(s) || !VALID_STRING(t)) + return(1); + + if (ignorepads) + return(_nc_capcmp(s, t)); + else + return(strcmp(s, t)); +} + +static int use_predicate(int type, int idx) +/* predicate function to use for use decompilation */ +{ + TERMTYPE *tp; + + switch(type) + { + case BOOLEAN: { + int is_set = FALSE; + + /* + * This assumes that multiple use entries are supposed + * to contribute the logical or of their boolean capabilities. + * This is true if we take the semantics of multiple uses to + * be 'each capability gets the first non-default value found + * in the sequence of use entries'. + */ + for (tp = &term[1]; tp < term + termcount; tp++) + if (tp->Booleans[idx]) { + is_set = TRUE; + break; + } + if (is_set != term->Booleans[idx]) + return(!is_set); + else + return(FAIL); + } + + case NUMBER: { + int value = ABSENT_NUMERIC; + + /* + * We take the semantics of multiple uses to be 'each + * capability gets the first non-default value found + * in the sequence of use entries'. + */ + for (tp = &term[1]; tp < term + termcount; tp++) + if (tp->Numbers[idx] >= 0) { + value = tp->Numbers[idx]; + break; + } + + if (value != term->Numbers[idx]) + return(value != ABSENT_NUMERIC); + else + return(FAIL); + } + + case STRING: { + char *termstr, *usestr = ABSENT_STRING; + + termstr = term->Strings[idx]; + + /* + * We take the semantics of multiple uses to be 'each + * capability gets the first non-default value found + * in the sequence of use entries'. + */ + for (tp = &term[1]; tp < term + termcount; tp++) + if (tp->Strings[idx]) + { + usestr = tp->Strings[idx]; + break; + } + + if (usestr == ABSENT_STRING && termstr == ABSENT_STRING) + return(FAIL); + else if (!usestr || !termstr || capcmp(usestr, termstr)) + return(TRUE); + else + return(FAIL); + } + } + + return(FALSE); /* pacify compiler */ +} + +static bool entryeq(TERMTYPE *t1, TERMTYPE *t2) +/* are two terminal types equal */ +{ + int i; + + for (i = 0; i < NUM_BOOLEANS(t1); i++) + if (t1->Booleans[i] != t2->Booleans[i]) + return(FALSE); + + for (i = 0; i < NUM_NUMBERS(t1); i++) + if (t1->Numbers[i] != t2->Numbers[i]) + return(FALSE); + + for (i = 0; i < NUM_STRINGS(t1); i++) + if (capcmp(t1->Strings[i], t2->Strings[i])) + return(FALSE); + + return(TRUE); +} + +#define TIC_EXPAND(result) _nc_tic_expand(result, outform==F_TERMINFO, numbers) + +static void compare_predicate(int type, int idx, const char *name) +/* predicate function to use for entry difference reports */ +{ + register TERMTYPE *t1 = &term[0]; + register TERMTYPE *t2 = &term[1]; + char *s1, *s2; + + switch(type) + { + case BOOLEAN: + switch(compare) + { + case C_DIFFERENCE: + if (t1->Booleans[idx] != t2->Booleans[idx]) + (void) printf("\t%s: %c:%c.\n", + name, + t1->Booleans[idx] ? 'T' : 'F', + t2->Booleans[idx] ? 'T' : 'F'); + break; + + case C_COMMON: + if (t1->Booleans[idx] && t2->Booleans[idx]) + (void) printf("\t%s= T.\n", name); + break; + + case C_NAND: + if (!t1->Booleans[idx] && !t2->Booleans[idx]) + (void) printf("\t!%s.\n", name); + break; + } + break; + + case NUMBER: + switch(compare) + { + case C_DIFFERENCE: + if (t1->Numbers[idx] != t2->Numbers[idx]) + (void) printf("\t%s: %d:%d.\n", + name, t1->Numbers[idx], t2->Numbers[idx]); + break; + + case C_COMMON: + if (t1->Numbers[idx]!=-1 && t2->Numbers[idx]!=-1 + && t1->Numbers[idx] == t2->Numbers[idx]) + (void) printf("\t%s= %d.\n", name, t1->Numbers[idx]); + break; + + case C_NAND: + if (t1->Numbers[idx]==-1 && t2->Numbers[idx] == -1) + (void) printf("\t!%s.\n", name); + break; + } + break; + + case STRING: + s1 = t1->Strings[idx]; + s2 = t2->Strings[idx]; + switch(compare) + { + case C_DIFFERENCE: + if (capcmp(s1, s2)) + { + char buf1[BUFSIZ], buf2[BUFSIZ]; + + if (s1 == (char *)NULL) + (void) strcpy(buf1, "NULL"); + else + { + (void) strcpy(buf1, "'"); + (void) strcat(buf1, TIC_EXPAND(s1)); + (void) strcat(buf1, "'"); + } + + if (s2 == (char *)NULL) + (void) strcpy(buf2, "NULL"); + else + { + (void) strcpy(buf2, "'"); + (void) strcat(buf2, TIC_EXPAND(s2)); + (void) strcat(buf2, "'"); + } + + if (strcmp(buf1, buf2)) + (void) printf("\t%s: %s, %s.\n", + name, buf1, buf2); + } + break; + + case C_COMMON: + if (s1 && s2 && !capcmp(s1, s2)) + (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1)); + break; + + case C_NAND: + if (!s1 && !s2) + (void) printf("\t!%s.\n", name); + break; + } + break; + } + +} + +/*************************************************************************** + * + * Init string analysis + * + ***************************************************************************/ + +typedef struct {const char *from; const char *to;} assoc; + +static const assoc std_caps[] = +{ + /* these are specified by X.364 and iBCS2 */ + {"\033c", "RIS"}, /* full reset */ + {"\0337", "SC"}, /* save cursor */ + {"\0338", "RC"}, /* restore cursor */ + {"\033[r", "RSR"}, /* not an X.364 mnemonic */ + {"\033[m", "SGR0"}, /* not an X.364 mnemonic */ + {"\033[2J", "ED2"}, /* clear page */ + + /* this group is specified by ISO 2022 */ + {"\033(0", "ISO DEC G0"}, /* enable DEC graphics for G0 */ + {"\033(A", "ISO UK G0"}, /* enable UK chars for G0 */ + {"\033(B", "ISO US G0"}, /* enable US chars for G0 */ + {"\033)0", "ISO DEC G1"}, /* enable DEC graphics for G1 */ + {"\033)A", "ISO UK G1"}, /* enable UK chars for G1 */ + {"\033)B", "ISO US G1"}, /* enable US chars for G1 */ + + /* these are DEC private modes widely supported by emulators */ + {"\033=", "DECPAM"}, /* application keypad mode */ + {"\033>", "DECPNM"}, /* normal keypad mode */ + {"\033<", "DECANSI"}, /* enter ANSI mode */ + + { (char *)0, (char *)0} +}; + +static const assoc private_modes[] = +/* DEC \E[ ... [hl] modes recognized by many emulators */ +{ + {"1", "CKM"}, /* application cursor keys */ + {"2", "ANM"}, /* set VT52 mode */ + {"3", "COLM"}, /* 132-column mode */ + {"4", "SCLM"}, /* smooth scroll */ + {"5", "SCNM"}, /* reverse video mode */ + {"6", "OM"}, /* origin mode */ + {"7", "AWM"}, /* wraparound mode */ + {"8", "ARM"}, /* auto-repeat mode */ + {(char *)0, (char *)0} +}; + +static const assoc ecma_highlights[] = +/* recognize ECMA attribute sequences */ +{ + {"0", "NORMAL"}, /* normal */ + {"1", "+BOLD"}, /* bold on */ + {"2", "+DIM"}, /* dim on */ + {"3", "+ITALIC"}, /* italic on */ + {"4", "+UNDERLINE"}, /* underline on */ + {"5", "+BLINK"}, /* blink on */ + {"6", "+FASTBLINK"}, /* fastblink on */ + {"7", "+REVERSE"}, /* reverse on */ + {"8", "+INVISIBLE"}, /* invisible on */ + {"9", "+DELETED"}, /* deleted on */ + {"10", "MAIN-FONT"}, /* select primary font */ + {"11", "ALT-FONT-1"}, /* select alternate font 1 */ + {"12", "ALT-FONT-2"}, /* select alternate font 2 */ + {"13", "ALT-FONT-3"}, /* select alternate font 3 */ + {"14", "ALT-FONT-4"}, /* select alternate font 4 */ + {"15", "ALT-FONT-5"}, /* select alternate font 5 */ + {"16", "ALT-FONT-6"}, /* select alternate font 6 */ + {"17", "ALT-FONT-7"}, /* select alternate font 7 */ + {"18", "ALT-FONT-1"}, /* select alternate font 1 */ + {"19", "ALT-FONT-1"}, /* select alternate font 1 */ + {"20", "FRAKTUR"}, /* Fraktur font */ + {"21", "DOUBLEUNDER"}, /* double underline */ + {"22", "-DIM"}, /* dim off */ + {"23", "-ITALIC"}, /* italic off */ + {"24", "-UNDERLINE"}, /* underline off */ + {"25", "-BLINK"}, /* blink off */ + {"26", "-FASTBLINK"}, /* fastblink off */ + {"27", "-REVERSE"}, /* reverse off */ + {"28", "-INVISIBLE"}, /* invisible off */ + {"29", "-DELETED"}, /* deleted off */ + {(char *)0, (char *)0} +}; + +static void analyze_string(const char *name, const char *cap, TERMTYPE *tp) +{ + char buf[MAX_TERMINFO_LENGTH]; + char buf2[MAX_TERMINFO_LENGTH]; + const char *sp, *ep; + const assoc *ap; + + if (cap == ABSENT_STRING || cap == CANCELLED_STRING) + return; + (void) printf("%s: ", name); + + buf[0] = '\0'; + for (sp = cap; *sp; sp++) + { + int i; + size_t len = 0; + const char *expansion = 0; + + /* first, check other capabilities in this entry */ + 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') + continue; + + + if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp != cap) + { + len = strlen(cp); + (void) strncpy(buf2, sp, len); + buf2[len] = '\0'; + + if (_nc_capcmp(cp, buf2)) + continue; + +#define ISRS(s) (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2)) + /* + * Theoretically we just passed the test for translation + * (equality once the padding is stripped). However, there + * are a few more hoops that need to be jumped so that + * identical pairs of initialization and reset strings + * don't just refer to each other. + */ + if (ISRS(name) || ISRS(strnames[i])) + if (cap < cp) + continue; +#undef ISRS + + expansion = strnames[i]; + break; + } + } + + /* now check the standard capabilities */ + if (!expansion) + for (ap = std_caps; ap->from; ap++) + { + len = strlen(ap->from); + + if (strncmp(ap->from, sp, len) == 0) + { + expansion = ap->to; + break; + } + } + + /* now check for private-mode sequences */ + if (!expansion + && sp[0] == '\033' && sp[1] == '[' && sp[2] == '?' + && (len = strspn(sp + 3, "0123456789;")) + && ((sp[3 + len] == 'h') || (sp[3 + len] == 'l'))) + { + char buf3[MAX_TERMINFO_LENGTH]; + + (void) strcpy(buf2, (sp[3 + len] == 'h') ? "DEC+" : "DEC-"); + (void) strncpy(buf3, sp + 3, len); + len += 4; + buf3[len] = '\0'; + + ep = strtok(buf3, ";"); + do { + bool found = FALSE; + + for (ap = private_modes; ap->from; ap++) + { + size_t tlen = strlen(ap->from); + + if (strncmp(ap->from, ep, tlen) == 0) + { + (void) strcat(buf2, ap->to); + found = TRUE; + break; + } + } + + if (!found) + (void) strcat(buf2, ep); + (void) strcat(buf2, ";"); + } while + ((ep = strtok((char *)NULL, ";"))); + buf2[strlen(buf2) - 1] = '\0'; + expansion = buf2; + } + + /* now check for ECMA highlight sequences */ + if (!expansion + && sp[0] == '\033' && sp[1] == '[' + && (len = strspn(sp + 2, "0123456789;")) + && sp[2 + len] == 'm') + { + char buf3[MAX_TERMINFO_LENGTH]; + + (void) strcpy(buf2, "SGR:"); + (void) strncpy(buf3, sp + 2, len); + len += 3; + buf3[len] = '\0'; + + ep = strtok(buf3, ";"); + do { + bool found = FALSE; + + for (ap = ecma_highlights; ap->from; ap++) + { + size_t tlen = strlen(ap->from); + + if (strncmp(ap->from, ep, tlen) == 0) + { + (void) strcat(buf2, ap->to); + found = TRUE; + break; + } + } + + if (!found) + (void) strcat(buf2, ep); + (void) strcat(buf2, ";"); + } while + ((ep = strtok((char *)NULL, ";"))); + + buf2[strlen(buf2) - 1] = '\0'; + expansion = buf2; + } + /* now check for scroll region reset */ + if (!expansion) + { + (void) sprintf(buf2, "\033[1;%dr", tp->Numbers[2]); + len = strlen(buf2); + if (strncmp(buf2, sp, len) == 0) + expansion = "RSR"; + } + + /* now check for home-down */ + if (!expansion) + { + (void) sprintf(buf2, "\033[%d;1H", tp->Numbers[2]); + len = strlen(buf2); + if (strncmp(buf2, sp, len) == 0) + expansion = "LL"; + } + + /* now look at the expansion we got, if any */ + if (expansion) + { + (void) sprintf(buf + strlen(buf), "{%s}", expansion); + sp += len - 1; + continue; + } + else + { + /* couldn't match anything */ + buf2[0] = *sp; + buf2[1] = '\0'; + (void) strcat(buf, TIC_EXPAND(buf2)); + } + } + (void) printf("%s\n", buf); +} + +/*************************************************************************** + * + * File comparison + * + ***************************************************************************/ + +static void file_comparison(int argc, char *argv[]) +{ +#define MAXCOMPARE 2 + /* someday we may allow comparisons on more files */ + int filecount = 0; + ENTRY *heads[MAXCOMPARE]; + ENTRY *tails[MAXCOMPARE]; + ENTRY *qp, *rp; + int i, n; + + dump_init((char *)NULL, F_LITERAL, S_TERMINFO, 0, itrace, FALSE); + + for (n = 0; n < argc && n < MAXCOMPARE; n++) + { + if (freopen(argv[n], "r", stdin) == NULL) + _nc_err_abort("Can't open %s", argv[n]); + + _nc_head = _nc_tail = (ENTRY *)NULL; + + /* parse entries out of the source file */ + _nc_set_source(argv[n]); + _nc_read_entry_source(stdin, NULL, TRUE, FALSE, NULLHOOK); + + if (itrace) + (void) fprintf(stderr, "Resolving file %d...\n", n-0); + + /* do use resolution */ + if (!_nc_resolve_uses()) + { + (void) fprintf(stderr, + "There are unresolved use entries in %s:\n", + argv[n]); + for_entry_list(qp) + if (qp->nuses) + { + (void) fputs(qp->tterm.term_names, stderr); + (void) fputc('\n', stderr); + } + exit(EXIT_FAILURE); + } + + heads[filecount] = _nc_head; + tails[filecount] = _nc_tail; + filecount++; + } + + /* OK, all entries are in core. Ready to do the comparison */ + if (itrace) + (void) fprintf(stderr, "Entries are now in core...\n"); + + /* + * The entry-matching loop. We're not using the use[] + * slots any more (they got zeroed out by resolve_uses) so + * we stash each entry's matches in the other file there. + * Sigh, this is intrinsically quadratic. + */ + for (qp = heads[0]; qp; qp = qp->next) + { + for (rp = heads[1]; rp; rp = rp->next) + if (_nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) + { + /* + * This is why the uses structure parent element is + * (void *) -- so we can have either (char *) for + * names or entry structure pointers in them and still + * be type-safe. + */ + if (qp->nuses < MAX_USES) + qp->uses[qp->nuses].parent = (void *)rp; + qp->nuses++; + + if (rp->nuses < MAX_USES) + rp->uses[rp->nuses].parent = (void *)qp; + rp->nuses++; + } + } + + /* now we have two circular lists with crosslinks */ + if (itrace) + (void) fprintf(stderr, "Name matches are done...\n"); + + for (qp = heads[0]; qp; qp = qp->next) + if (qp->nuses > 1) + { + (void) fprintf(stderr, + "%s in file 1 (%s) has %d matches in file 2 (%s):\n", + _nc_first_name(qp->tterm.term_names), + argv[0], + qp->nuses, + argv[1]); + for (i = 0; i < qp->nuses; i++) + (void) fprintf(stderr, + "\t%s\n", + _nc_first_name(((ENTRY *)qp->uses[i].parent)->tterm.term_names)); + } + for (rp = heads[1]; rp; rp = rp->next) + if (rp->nuses > 1) + { + (void) fprintf(stderr, + "%s in file 2 (%s) has %d matches in file 1 (%s):\n", + _nc_first_name(rp->tterm.term_names), + argv[1], + rp->nuses, + argv[0]); + for (i = 0; i < rp->nuses; i++) + (void) fprintf(stderr, + "\t%s\n", + _nc_first_name(((ENTRY *)rp->uses[i].parent)->tterm.term_names)); + } + + (void) printf("In file 1 (%s) only:\n", argv[0]); + for (qp = heads[0]; qp; qp = qp->next) + if (qp->nuses == 0) + (void) printf("\t%s\n", + _nc_first_name(qp->tterm.term_names)); + + (void) printf("In file 2 (%s) only:\n", argv[1]); + for (rp = heads[1]; rp; rp = rp->next) + if (rp->nuses == 0) + (void) printf("\t%s\n", + _nc_first_name(rp->tterm.term_names)); + + (void) printf("The following entries are equivalent:\n"); + for (qp = heads[0]; qp; qp = qp->next) + { + rp = (ENTRY *)qp->uses[0].parent; + + if (qp->nuses == 1 && entryeq(&qp->tterm, &rp->tterm)) + { + char name1[NAMESIZE], name2[NAMESIZE]; + + (void) canonical_name(qp->tterm.term_names, name1); + (void) canonical_name(rp->tterm.term_names, name2); + + (void) printf("%s = %s\n", name1, name2); + } + } + + (void) printf("Differing entries:\n"); + termcount = 2; + for (qp = heads[0]; qp; qp = qp->next) + { + rp = (ENTRY *)qp->uses[0].parent; + +#if NCURSES_XNAMES + if (termcount > 1) + _nc_align_termtype(&qp->tterm, &rp->tterm); +#endif + if (qp->nuses == 1 && !entryeq(&qp->tterm, &rp->tterm)) + { + char name1[NAMESIZE], name2[NAMESIZE]; + + term[0] = qp->tterm; + term[1] = rp->tterm; + + (void) canonical_name(qp->tterm.term_names, name1); + (void) canonical_name(rp->tterm.term_names, name2); + + switch (compare) + { + case C_DIFFERENCE: + if (itrace) + (void)fprintf(stderr, "infocmp: dumping differences\n"); + (void) printf("comparing %s to %s.\n", name1, name2); + compare_entry(compare_predicate, term); + break; + + case C_COMMON: + if (itrace) + (void) fprintf(stderr, + "infocmp: dumping common capabilities\n"); + (void) printf("comparing %s to %s.\n", name1, name2); + compare_entry(compare_predicate, term); + break; + + case C_NAND: + if (itrace) + (void) fprintf(stderr, + "infocmp: dumping differences\n"); + (void) printf("comparing %s to %s.\n", name1, name2); + compare_entry(compare_predicate, term); + break; + + } + } + } +} + +static void usage(void) +{ + static const char *tbl[] = { + "Usage: infocmp [options] [-A directory] [-B directory] [termname...]" + ,"" + ,"Options:" + ," -1 print single-column" + ," -C use termcap-names" + ," -F compare terminfo-files" + ," -I use terminfo-names" + ," -L use long names" + ," -R subset (see manpage)" + ," -T eliminate size limits (test)" + ," -V print version" + ," -c list common capabilities" + ," -d list different capabilities" + ," -e format output for C initializer" + ," -E format output as C tables" + ," -f with -1, format complex strings" + ," -G format %{number} to %'char'" + ," -g format %'char' to %{number}" + ," -i analyze initialization/reset" + ," -l output terminfo names" + ," -n list capabilities in neither" + ," -p ignore padding specifiers" + ," -r with -C, output in termcap form" + ," -s [d|i|l|c] sort fields" + ," -u produce source with 'use='" + ," -v number (verbose)" + ," -w number (width)" + }; + const size_t first = 3; + const size_t last = sizeof(tbl)/sizeof(tbl[0]); + const size_t left = (last - first + 1) / 2 + first; + size_t n; + + for (n = 0; n < left; n++) { + size_t m = (n < first) ? last : n + left - first; + if (m < last) + fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]); + else + fprintf(stderr, "%s\n", tbl[n]); + } + exit(EXIT_FAILURE); +} + +static char * name_initializer(const char *type) +{ + static char *initializer; + char *s; + + if (initializer == 0) + initializer = malloc(strlen(term->term_names) + 20); + + (void) sprintf(initializer, "%s_data_%s", type, term->term_names); + for (s = initializer; *s != 0 && *s != '|'; s++) + { + if (!isalnum(*s)) + *s = '_'; + } + *s = 0; + return initializer; +} + +/* dump C initializers for the terminal type */ +static void dump_initializers(void) +{ + int n; + const char *str = 0; + int size; + + (void) printf("static bool %s[] = %s\n", name_initializer("bool"), L_CURL); + + for_each_boolean(n,term) + { + switch((int)(term->Booleans[n])) + { + case TRUE: + str = "TRUE"; + break; + + case FALSE: + str = "FALSE"; + break; + + case ABSENT_BOOLEAN: + str = "ABSENT_BOOLEAN"; + break; + + case CANCELLED_BOOLEAN: + str = "CANCELLED_BOOLEAN"; + break; + } + (void) printf("\t/* %3d: %-8s */\t%s,\n", + n, ExtBoolname(term,n,boolnames), str); + } + (void) printf("%s;\n", R_CURL); + + (void) printf("static short %s[] = %s\n", name_initializer("number"), L_CURL); + + for_each_number(n,term) + { + char buf[BUFSIZ]; + switch (term->Numbers[n]) + { + case ABSENT_NUMERIC: + str = "ABSENT_NUMERIC"; + break; + case CANCELLED_NUMERIC: + str = "CANCELLED_NUMERIC"; + break; + default: + sprintf(buf, "%d", term->Numbers[n]); + str = buf; + break; + } + (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtNumname(term,n,numnames), str); + } + (void) printf("%s;\n", R_CURL); + + size = sizeof(TERMTYPE) + + (NUM_BOOLEANS(term) * sizeof(term->Booleans[0])) + + (NUM_NUMBERS(term) * sizeof(term->Numbers[0])); + + (void) printf("static char * %s[] = %s\n", name_initializer("string"), L_CURL); + + for_each_string(n,term) + { + char buf[BUFSIZ], *sp, *tp; + + if (term->Strings[n] == ABSENT_STRING) + str = "ABSENT_STRING"; + else if (term->Strings[n] == CANCELLED_STRING) + str = "CANCELLED_STRING"; + else + { + tp = buf; + *tp++ = '"'; + for (sp = term->Strings[n]; *sp; sp++) + { + if (isascii(*sp) && isprint(*sp) && *sp !='\\' && *sp != '"') + *tp++ = *sp; + else + { + (void) sprintf(tp, "\\%03o", *sp & 0xff); + tp += 4; + } + } + *tp++ = '"'; + *tp = '\0'; + size += (strlen(term->Strings[n]) + 1); + str = buf; + } +#if NCURSES_XNAMES + if (n == STRCOUNT) + { + (void) printf("%s;\n", R_CURL); + + (void) printf("static char * %s[] = %s\n", name_initializer("string_ext"), L_CURL); + } +#endif + (void) printf("\t/* %3d: %-8s */\t%s,\n", n, ExtStrname(term,n,strnames), str); + } + (void) printf("%s;\n", R_CURL); +} + +/* dump C initializers for the terminal type */ +static void dump_termtype(void) +{ + (void) printf("\t%s\n\t\t\"%s\",\n", L_CURL, term->term_names); + (void) printf("\t\t(char *)0,\t/* pointer to string table */\n"); + + (void) printf("\t\t%s,\n", name_initializer("bool")); + (void) printf("\t\t%s,\n", name_initializer("number")); + + (void) printf("\t\t%s,\n", name_initializer("string")); + +#if NCURSES_XNAMES + (void) printf("#if NCURSES_XNAMES\n"); + (void) printf("\t\t(char *)0,\t/* pointer to extended string table */\n"); + (void) printf("\t\t%s,\t/* ...corresponding names */\n", + (NUM_STRINGS(term) != STRCOUNT) + ? name_initializer("string_ext") + : "(char **)0"); + + (void) printf("\t\t%d,\t\t/* count total Booleans */\n", NUM_BOOLEANS(term)); + (void) printf("\t\t%d,\t\t/* count total Numbers */\n", NUM_NUMBERS(term)); + (void) printf("\t\t%d,\t\t/* count total Strings */\n", NUM_STRINGS(term)); + + (void) printf("\t\t%d,\t\t/* count extensions to Booleans */\n", NUM_BOOLEANS(term) - BOOLCOUNT); + (void) printf("\t\t%d,\t\t/* count extensions to Numbers */\n", NUM_NUMBERS(term) - NUMCOUNT); + (void) printf("\t\t%d,\t\t/* count extensions to Strings */\n", NUM_STRINGS(term) - STRCOUNT); + + (void) printf("#endif /* NCURSES_XNAMES */\n"); +#endif /* NCURSES_XNAMES */ + (void) printf("\t%s\n", R_CURL); +} + +/*************************************************************************** + * + * Main sequence + * + ***************************************************************************/ + +int main(int argc, char *argv[]) +{ + char *terminal, *firstdir, *restdir; + /* Avoid "local data >32k" error with mwcc */ + /* Also avoid overflowing smaller stacks on systems like AmigaOS */ + path *tfile = malloc(sizeof(path)*MAXTERMS); + int c, i, len; + bool formatted = FALSE; + bool filecompare = FALSE; + int initdump = 0; + bool init_analyze = FALSE; + bool limited = TRUE; + + if ((terminal = getenv("TERM")) == NULL) + { + (void) fprintf(stderr, + "infocmp: environment variable TERM not set\n"); + return EXIT_FAILURE; + } + + /* where is the terminfo database location going to default to? */ + restdir = firstdir = 0; + + while ((c = getopt(argc, argv, "deEcCfFGgIinlLprR:s:uv:Vw:A:B:1T")) != EOF) + switch (c) + { + case 'd': + compare = C_DIFFERENCE; + break; + + case 'e': + initdump |= 1; + break; + + case 'E': + initdump |= 2; + break; + + case 'c': + compare = C_COMMON; + break; + + case 'C': + outform = F_TERMCAP; + tversion = "BSD"; + if (sortmode == S_DEFAULT) + sortmode = S_TERMCAP; + break; + + case 'f': + formatted = TRUE; + break; + + case 'G': + numbers = 1; + break; + + case 'g': + numbers = -1; + break; + + case 'F': + filecompare = TRUE; + break; + + case 'I': + outform = F_TERMINFO; + if (sortmode == S_DEFAULT) + sortmode = S_VARIABLE; + tversion = 0; + break; + + case 'i': + init_analyze = TRUE; + break; + + case 'l': + outform = F_TERMINFO; + break; + + case 'L': + outform = F_VARIABLE; + if (sortmode == S_DEFAULT) + sortmode = S_VARIABLE; + break; + + case 'n': + compare = C_NAND; + break; + + case 'p': + ignorepads = TRUE; + break; + + case 'r': + tversion = 0; + limited = FALSE; + break; + + case 'R': + tversion = optarg; + break; + + case 's': + if (*optarg == 'd') + sortmode = S_NOSORT; + else if (*optarg == 'i') + sortmode = S_TERMINFO; + else if (*optarg == 'l') + sortmode = S_VARIABLE; + else if (*optarg == 'c') + sortmode = S_TERMCAP; + else + { + (void) fprintf(stderr, + "infocmp: unknown sort mode\n"); + return EXIT_FAILURE; + } + break; + + case 'u': + compare = C_USEALL; + break; + + case 'v': + itrace = atoi(optarg); + _nc_tracing = (1 << itrace) - 1; + break; + + case 'V': + (void) fputs(NCURSES_VERSION, stdout); + putchar('\n'); + ExitProgram(EXIT_SUCCESS); + + case 'w': + mwidth = atoi(optarg); + break; + + case 'A': + firstdir = optarg; + break; + + case 'B': + restdir = optarg; + break; + + case '1': + mwidth = 0; + break; + + case 'T': + limited = FALSE; + break; + default: + usage(); + } + + /* by default, sort by terminfo name */ + 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; + + /* if user is after a comparison, make sure we have two entries */ + if (compare != C_DEFAULT && optind >= argc - 1) + argv[argc++] = terminal; + + /* exactly two terminal names with no options means do -d */ + if (argc - optind == 2 && compare == C_DEFAULT) + compare = C_DIFFERENCE; + + if (!filecompare) + { + /* grab the entries */ + termcount = 0; + for (; optind < argc; optind++) + { + if (termcount >= MAXTERMS) + { + (void) fprintf(stderr, + "infocmp: too many terminal type arguments\n"); + return EXIT_FAILURE; + } + else + { + const char *directory = termcount ? restdir : firstdir; + int status; + + tname[termcount] = argv[optind]; + + if (directory) + { + (void) sprintf(tfile[termcount], "%s/%c/%s", + directory, + *argv[optind], argv[optind]); + if (itrace) + (void) fprintf(stderr, + "infocmp: reading entry %s from file %s\n", + argv[optind], tfile[termcount]); + + status = _nc_read_file_entry(tfile[termcount], + &term[termcount]); + } + else + { + if (itrace) + (void) fprintf(stderr, + "infocmp: reading entry %s from system directories %s\n", + argv[optind], tname[termcount]); + + status = _nc_read_entry(tname[termcount], + tfile[termcount], + &term[termcount]); + directory = TERMINFO; /* for error message */ + } + + if (status <= 0) + { + (void) fprintf(stderr, + "infocmp: couldn't open terminfo file %s.\n", + tfile[termcount]); + return EXIT_FAILURE; + } + termcount++; + } + } + +#if NCURSES_XNAMES + if (termcount > 1) + _nc_align_termtype(&term[0], &term[1]); +#endif + + /* dump as C initializer for the terminal type */ + if (initdump) + { + if (initdump & 1) + dump_termtype(); + if (initdump & 2) + dump_initializers(); + ExitProgram(EXIT_SUCCESS); + } + + /* analyze the init strings */ + if (init_analyze) + { +#undef CUR +#define CUR term[0]. + analyze_string("is1", init_1string, &term[0]); + analyze_string("is2", init_2string, &term[0]); + analyze_string("is3", init_3string, &term[0]); + analyze_string("rs1", reset_1string, &term[0]); + analyze_string("rs2", reset_2string, &term[0]); + analyze_string("rs3", reset_3string, &term[0]); + analyze_string("smcup", enter_ca_mode, &term[0]); + analyze_string("rmcup", exit_ca_mode, &term[0]); +#undef CUR + ExitProgram(EXIT_SUCCESS); + } + + /* + * Here's where the real work gets done + */ + switch (compare) + { + case C_DEFAULT: + if (itrace) + (void) fprintf(stderr, + "infocmp: about to dump %s\n", + tname[0]); + (void) printf("#\tReconstructed via infocmp from file: %s\n", + tfile[0]); + len = dump_entry(&term[0], limited, numbers, NULL); + putchar('\n'); + if (itrace) + (void)fprintf(stderr, "infocmp: length %d\n", len); + break; + + case C_DIFFERENCE: + if (itrace) + (void)fprintf(stderr, "infocmp: dumping differences\n"); + (void) printf("comparing %s to %s.\n", tname[0], tname[1]); + compare_entry(compare_predicate, term); + break; + + case C_COMMON: + if (itrace) + (void) fprintf(stderr, + "infocmp: dumping common capabilities\n"); + (void) printf("comparing %s to %s.\n", tname[0], tname[1]); + compare_entry(compare_predicate, term); + break; + + case C_NAND: + if (itrace) + (void) fprintf(stderr, + "infocmp: dumping differences\n"); + (void) printf("comparing %s to %s.\n", tname[0], tname[1]); + compare_entry(compare_predicate, term); + break; + + case C_USEALL: + if (itrace) + (void) fprintf(stderr, "infocmp: dumping use entry\n"); + len = dump_entry(&term[0], limited, numbers, use_predicate); + for (i = 1; i < termcount; i++) + len += dump_uses(tname[i], !(outform==F_TERMCAP || outform==F_TCONVERR)); + putchar('\n'); + if (itrace) + (void)fprintf(stderr, "infocmp: length %d\n", len); + break; + } + } + else if (compare == C_USEALL) + (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n"); + else if (compare == C_DEFAULT) + (void) fprintf(stderr, "Use `tic -[CI] <file>' for this.\n"); + else if (argc - optind != 2) + (void) fprintf(stderr, + "File comparison needs exactly two file arguments.\n"); + else + file_comparison(argc-optind, argv+optind); + + ExitProgram(EXIT_SUCCESS); +} + +/* infocmp.c ends here */ diff --git a/contrib/ncurses/progs/modules b/contrib/ncurses/progs/modules new file mode 100644 index 0000000..54cd202 --- /dev/null +++ b/contrib/ncurses/progs/modules @@ -0,0 +1,40 @@ +# Program modules (some are in ncurses lib!) +############################################################################## +# Copyright (c) 1998 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 <dickey@clark.net> 1995,1997 +# + +@ base +clear progs $(srcdir) ../include/term.h +tic progs $(srcdir) ../include/term.h $(INCDIR)/tic.h $(srcdir)/dump_entry.h +toe progs $(srcdir) ../include/term.h $(INCDIR)/tic.h $(srcdir)/dump_entry.h +dump_entry progs $(srcdir) ../include/term.h $(INCDIR)/tic.h $(srcdir)/dump_entry.h ../include/parametrized.h termsort.c +infocmp progs $(srcdir) ../include/term.h $(INCDIR)/tic.h $(srcdir)/dump_entry.h +tput progs $(srcdir) ../include/term.h +tset progs $(srcdir) ../include/term.h diff --git a/contrib/ncurses/progs/progs.priv.h b/contrib/ncurses/progs/progs.priv.h new file mode 100644 index 0000000..3384d37c --- /dev/null +++ b/contrib/ncurses/progs/progs.priv.h @@ -0,0 +1,160 @@ +/**************************************************************************** + * Copyright (c) 1998 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 <dickey@clark.net> 1997,1998 * + ****************************************************************************/ +/* + * $Id: progs.priv.h,v 1.19 1999/02/23 11:10:32 tom Exp $ + * + * progs.priv.h + * + * Header file for curses utility programs + */ + +#include <ncurses_cfg.h> + +#ifdef USE_RCS_IDS +#define MODULE_ID(id) static const char Ident[] = id; +#else +#define MODULE_ID(id) /*nothing*/ +#endif + +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <sys/types.h> + +#if HAVE_UNISTD_H +#include <unistd.h> +#else +# if HAVE_LIBC_H +# include <libc.h> +# endif +#endif + +#if HAVE_SYS_BSDTYPES_H +#include <sys/bsdtypes.h> /* needed for ISC */ +#endif + +#if HAVE_LIMITS_H +# include <limits.h> +#elif HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif + +#if HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#include <errno.h> + +#if DECL_ERRNO +extern int errno; +#endif + +#if HAVE_GETOPT_H +#include <getopt.h> +#else +/* 'getopt()' may be prototyped in <stdlib.h>, but declaring its + * variables doesn't hurt. + */ +extern char *optarg; +extern int optind; +#endif /* HAVE_GETOPT_H */ + +#include <curses.h> +#include <term_entry.h> +#include <tic.h> +#include <nc_alloc.h> + +/* usually in <unistd.h> */ +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#ifndef F_OK +#define F_OK 0 /* Test for existence. */ +#endif + +/* usually in <unistd.h> */ +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + +/* may be in limits.h, included from various places */ +#ifndef PATH_MAX +# if defined(_POSIX_PATH_MAX) +# define PATH_MAX _POSIX_PATH_MAX +# elif defined(MAXPATHLEN) +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 255 /* the Posix minimum pathsize */ +# endif +#endif + +/* We use isascii only to guard against use of 7-bit ctype tables in the + * isprint test in infocmp. + */ +#ifndef HAVE_ISASCII +# undef isascii +# if ('z'-'a' == 25) && ('z' < 127) && ('Z'-'A' == 25) && ('Z' < 127) && ('9' < 127) +# define isascii(c) (((c) & 0xff) <= 127) +# else +# define isascii(c) 1 /* not really ascii anyway */ +# endif +#endif diff --git a/contrib/ncurses/progs/tic.c b/contrib/ncurses/progs/tic.c new file mode 100644 index 0000000..d81af0a --- /dev/null +++ b/contrib/ncurses/progs/tic.c @@ -0,0 +1,812 @@ +/**************************************************************************** + * Copyright (c) 1998,1999 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +/* + * tic.c --- Main program for terminfo compiler + * by Eric S. Raymond + * + */ + +#include <progs.priv.h> + +#include <dump_entry.h> +#include <term_entry.h> + +MODULE_ID("$Id: tic.c,v 1.51 1999/06/19 21:35:36 Philippe.De.Muyter Exp $") + +const char *_nc_progname = "tic"; + +static FILE *log_fp; +static FILE *tmp_fp; +static bool showsummary = FALSE; +static const char *to_remove; + +static void (*save_check_termtype)(TERMTYPE *); +static void check_termtype(TERMTYPE *tt); + +static const char usage_string[] = "[-h] [-v[n]] [-e names] [-CILNRTcfrswx1] source-file\n"; + +static void cleanup(void) +{ + if (tmp_fp != 0) + fclose(tmp_fp); + if (to_remove != 0) { +#if HAVE_REMOVE + remove(to_remove); +#else + unlink(to_remove); +#endif + } +} + +static void failed(const char *msg) +{ + perror(msg); + cleanup(); + exit(EXIT_FAILURE); +} + +static void usage(void) +{ + static const char *const tbl[] = { + "Options:", + " -1 format translation output one capability per line", + " -C translate entries to termcap source form", + " -I translate entries to terminfo source form", + " -L translate entries to full terminfo source form", + " -N disable smart defaults for source translation", + " -R restrict translation to given terminfo/termcap version", + " -T remove size-restrictions on compiled description", + " -c check only, validate input without compiling or translating", + " -f format complex strings for readability", + " -G format %{number} to %'char'", + " -g format %'char' to %{number}", + " -e<names> translate/compile only entries named by comma-separated list", + " -o<dir> set output directory for compiled entry writes", + " -r force resolution of all use entries in source translation", + " -s print summary statistics", + " -v[n] set verbosity level", + " -w[n] set format width for translation output", +#if NCURSES_XNAMES + " -x treat unknown capabilities as user-defined", +#endif + "", + "Parameters:", + " <file> file to translate or compile" + }; + size_t j; + + printf("Usage: %s %s\n", _nc_progname, usage_string); + for (j = 0; j < sizeof(tbl)/sizeof(tbl[0]); j++) + puts(tbl[j]); + exit(EXIT_FAILURE); +} + +#define L_BRACE '{' +#define R_BRACE '}' +#define S_QUOTE '\''; + +static void write_it(ENTRY *ep) +{ + unsigned n; + int ch; + char *s, *d, *t; + char result[MAX_ENTRY_SIZE]; + + /* + * Look for strings that contain %{number}, convert them to %'char', + * which is shorter and runs a little faster. + */ + for (n = 0; n < STRCOUNT; n++) { + s = ep->tterm.Strings[n]; + if (VALID_STRING(s) + && strchr(s, L_BRACE) != 0) { + d = result; + t = s; + while ((ch = *t++) != 0) { + *d++ = ch; + if (ch == '\\') { + *d++ = *t++; + } else if ((ch == '%') + && (*t == L_BRACE)) { + char *v = 0; + long value = strtol(t+1, &v, 0); + if (v != 0 + && *v == R_BRACE + && value > 0 + && value != '\\' /* FIXME */ + && value < 127 + && isprint((int)value)) { + *d++ = S_QUOTE; + *d++ = (int)value; + *d++ = S_QUOTE; + t = (v + 1); + } + } + } + *d = 0; + if (strlen(result) < strlen(s)) + strcpy(s, result); + } + } + + _nc_set_type(_nc_first_name(ep->tterm.term_names)); + _nc_curr_line = ep->startline; + _nc_write_entry(&ep->tterm); +} + +static bool immedhook(ENTRY *ep GCC_UNUSED) +/* write out entries with no use capabilities immediately to save storage */ +{ +#ifndef HAVE_BIG_CORE + /* + * This is strictly a core-economy kluge. The really clean way to handle + * compilation is to slurp the whole file into core and then do all the + * name-collision checks and entry writes in one swell foop. But the + * terminfo master file is large enough that some core-poor systems swap + * like crazy when you compile it this way...there have been reports of + * this process taking *three hours*, rather than the twenty seconds or + * less typical on my development box. + * + * So. This hook *immediately* writes out the referenced entry if it + * has no use capabilities. The compiler main loop refrains from + * adding the entry to the in-core list when this hook fires. If some + * other entry later needs to reference an entry that got written + * immediately, that's OK; the resolution code will fetch it off disk + * when it can't find it in core. + * + * Name collisions will still be detected, just not as cleanly. The + * write_entry() code complains before overwriting an entry that + * postdates the time of tic's first call to write_entry(). Thus + * it will complain about overwriting entries newly made during the + * tic run, but not about overwriting ones that predate it. + * + * The reason this is a hook, and not in line with the rest of the + * compiler code, is that the support for termcap fallback cannot assume + * it has anywhere to spool out these entries! + * + * The _nc_set_type() call here requires a compensating one in + * _nc_parse_entry(). + * + * If you define HAVE_BIG_CORE, you'll disable this kluge. This will + * make tic a bit faster (because the resolution code won't have to do + * disk I/O nearly as often). + */ + if (ep->nuses == 0) + { + int oldline = _nc_curr_line; + + write_it(ep); + _nc_curr_line = oldline; + free(ep->tterm.str_table); + return(TRUE); + } +#endif /* HAVE_BIG_CORE */ + return(FALSE); +} + +static void put_translate(int c) +/* emit a comment char, translating terminfo names to termcap names */ +{ + static bool in_name = FALSE; + static char namebuf[132], suffix[132], *sp; + + if (!in_name) + { + if (c == '<') + { + in_name = TRUE; + sp = namebuf; + } + else + putchar(c); + } + else if (c == '\n' || c == '@') + { + *sp++ = '\0'; + (void) putchar('<'); + (void) fputs(namebuf, stdout); + putchar(c); + in_name = FALSE; + } + else if (c != '>') + *sp++ = c; + else /* ah! candidate name! */ + { + char *up; + NCURSES_CONST char *tp; + + *sp++ = '\0'; + in_name = FALSE; + + suffix[0] = '\0'; + if ((up = strchr(namebuf, '#')) != 0 + || (up = strchr(namebuf, '=')) != 0 + || ((up = strchr(namebuf, '@')) != 0 && up[1] == '>')) + { + (void) strcpy(suffix, up); + *up = '\0'; + } + + if ((tp = nametrans(namebuf)) != 0) + { + (void) putchar(':'); + (void) fputs(tp, stdout); + (void) fputs(suffix, stdout); + (void) putchar(':'); + } + else + { + /* couldn't find a translation, just dump the name */ + (void) putchar('<'); + (void) fputs(namebuf, stdout); + (void) fputs(suffix, stdout); + (void) putchar('>'); + } + + } +} + +/* Returns a string, stripped of leading/trailing whitespace */ +static char *stripped(char *src) +{ + while (isspace(*src)) + src++; + if (*src != '\0') { + char *dst = strcpy(malloc(strlen(src)+1), src); + size_t len = strlen(dst); + while (--len != 0 && isspace(dst[len])) + dst[len] = '\0'; + return dst; + } + return 0; +} + +/* Parse the "-e" option-value into a list of names */ +static const char **make_namelist(char *src) +{ + const char **dst = 0; + + char *s, *base; + unsigned pass, n, nn; + char buffer[BUFSIZ]; + + if (src == 0) { + /* EMPTY */; + } else if (strchr(src, '/') != 0) { /* a filename */ + FILE *fp = fopen(src, "r"); + if (fp == 0) + failed(src); + + for (pass = 1; pass <= 2; pass++) { + nn = 0; + while (fgets(buffer, sizeof(buffer), fp) != 0) { + if ((s = stripped(buffer)) != 0) { + if (dst != 0) + dst[nn] = s; + nn++; + } + } + if (pass == 1) { + dst = (const char **)calloc(nn+1, sizeof(*dst)); + rewind(fp); + } + } + fclose(fp); + } else { /* literal list of names */ + for (pass = 1; pass <= 2; pass++) { + for (n = nn = 0, base = src; ; n++) { + int mark = src[n]; + if (mark == ',' || mark == '\0') { + if (pass == 1) { + nn++; + } else { + src[n] = '\0'; + if ((s = stripped(base)) != 0) + dst[nn++] = s; + base = &src[n+1]; + } + } + if (mark == '\0') + break; + } + if (pass == 1) + dst = (const char **)calloc(nn+1, sizeof(*dst)); + } + } + if (showsummary) { + fprintf(log_fp, "Entries that will be compiled:\n"); + for (n = 0; dst[n] != 0; n++) + fprintf(log_fp, "%d:%s\n", n+1, dst[n]); + } + return dst; +} + +static bool matches(const char **needle, const char *haystack) +/* does entry in needle list match |-separated field in haystack? */ +{ + bool code = FALSE; + size_t n; + + if (needle != 0) + { + for (n = 0; needle[n] != 0; n++) + { + if (_nc_name_match(haystack, needle[n], "|")) + { + code = TRUE; + break; + } + } + } + else + code = TRUE; + return(code); +} + +int main (int argc, char *argv[]) +{ +char my_tmpname[PATH_MAX]; +int v_opt = -1, debug_level; +int smart_defaults = TRUE; +char *termcap; +ENTRY *qp; + +int this_opt, last_opt = '?'; + +int outform = F_TERMINFO; /* output format */ +int sortmode = S_TERMINFO; /* sort_mode */ + +int width = 60; +bool formatted = FALSE; /* reformat complex strings? */ +int numbers = 0; /* format "%'char'" to/from "%{number}" */ +bool infodump = FALSE; /* running as captoinfo? */ +bool capdump = FALSE; /* running as infotocap? */ +bool forceresolve = FALSE; /* force resolution */ +bool limited = TRUE; +char *tversion = (char *)NULL; +const char *source_file = "terminfo"; +const char **namelst = 0; +char *outdir = (char *)NULL; +bool check_only = FALSE; + + log_fp = stderr; + + if ((_nc_progname = strrchr(argv[0], '/')) == NULL) + _nc_progname = argv[0]; + else + _nc_progname++; + + infodump = (strcmp(_nc_progname, "captoinfo") == 0); + capdump = (strcmp(_nc_progname, "infotocap") == 0); +#if NCURSES_XNAMES + use_extended_names(FALSE); +#endif + + /* + * Processing arguments is a little complicated, since someone made a + * design decision to allow the numeric values for -w, -v options to + * be optional. + */ + while ((this_opt = getopt(argc, argv, "0123456789CILNR:TVce:fGgo:rsvwx")) != EOF) { + if (isdigit(this_opt)) { + switch (last_opt) { + case 'v': + v_opt = (v_opt * 10) + (this_opt - '0'); + break; + case 'w': + width = (width * 10) + (this_opt - '0'); + break; + default: + if (this_opt != '1') + usage(); + last_opt = this_opt; + width = 0; + } + continue; + } + switch (this_opt) { + case 'C': + capdump = TRUE; + outform = F_TERMCAP; + sortmode = S_TERMCAP; + break; + case 'I': + infodump = TRUE; + outform = F_TERMINFO; + sortmode = S_TERMINFO; + break; + case 'L': + infodump = TRUE; + outform = F_VARIABLE; + sortmode = S_VARIABLE; + break; + case 'N': + smart_defaults = FALSE; + break; + case 'R': + tversion = optarg; + break; + case 'T': + limited = FALSE; + break; + case 'V': + puts(NCURSES_VERSION); + return EXIT_SUCCESS; + case 'c': + check_only = TRUE; + break; + case 'e': + namelst = make_namelist(optarg); + break; + case 'f': + formatted = TRUE; + break; + case 'G': + numbers = 1; + break; + case 'g': + numbers = -1; + break; + case 'o': + outdir = optarg; + break; + case 'r': + forceresolve = TRUE; + break; + case 's': + showsummary = TRUE; + break; + case 'v': + v_opt = 0; + break; + case 'w': + width = 0; + break; +#if NCURSES_XNAMES + case 'x': + use_extended_names(TRUE); + break; +#endif + default: + usage(); + } + last_opt = this_opt; + } + + debug_level = (v_opt > 0) ? v_opt : (v_opt == 0); + _nc_tracing = (1 << debug_level) - 1; + + if (_nc_tracing) + { + save_check_termtype = _nc_check_termtype; + _nc_check_termtype = check_termtype; + } + +#ifndef HAVE_BIG_CORE + /* + * Aaargh! immedhook seriously hoses us! + * + * One problem with immedhook is it means we can't do -e. Problem + * is that we can't guarantee that for each terminal listed, all the + * terminals it depends on will have been kept in core for reference + * resolution -- in fact it's certain the primitive types at the end + * of reference chains *won't* be in core unless they were explicitly + * in the select list themselves. + */ + if (namelst && (!infodump && !capdump)) + { + (void) fprintf(stderr, + "Sorry, -e can't be used without -I or -C\n"); + cleanup(); + return EXIT_FAILURE; + } +#endif /* HAVE_BIG_CORE */ + + if (optind < argc) { + source_file = argv[optind++]; + if (optind < argc) { + fprintf (stderr, + "%s: Too many file names. Usage:\n\t%s %s", + _nc_progname, + _nc_progname, + usage_string); + return EXIT_FAILURE; + } + } else { + if (infodump == TRUE) { + /* captoinfo's no-argument case */ + source_file = "/etc/termcap"; + if ((termcap = getenv("TERMCAP")) != 0 + && (namelst = make_namelist(getenv("TERM"))) != 0) { + if (access(termcap, F_OK) == 0) { + /* file exists */ + source_file = termcap; + } else + if ((source_file = tmpnam(my_tmpname)) != 0 + && (tmp_fp = fopen(source_file, "w")) != 0) { + fprintf(tmp_fp, "%s\n", termcap); + fclose(tmp_fp); + tmp_fp = fopen(source_file, "r"); + to_remove = source_file; + } else { + failed("tmpnam"); + } + } + } else { + /* tic */ + fprintf (stderr, + "%s: File name needed. Usage:\n\t%s %s", + _nc_progname, + _nc_progname, + usage_string); + cleanup(); + return EXIT_FAILURE; + } + } + + if (tmp_fp == 0 + && (tmp_fp = fopen(source_file, "r")) == 0) { + fprintf (stderr, "%s: Can't open %s\n", _nc_progname, source_file); + return EXIT_FAILURE; + } + + if (infodump) + dump_init(tversion, + smart_defaults + ? outform + : F_LITERAL, + sortmode, width, debug_level, formatted); + else if (capdump) + dump_init(tversion, + outform, + sortmode, width, debug_level, FALSE); + + /* parse entries out of the source file */ + _nc_set_source(source_file); +#ifndef HAVE_BIG_CORE + if (!(check_only || infodump || capdump)) + _nc_set_writedir(outdir); +#endif /* HAVE_BIG_CORE */ + _nc_read_entry_source(tmp_fp, (char *)NULL, + !smart_defaults, FALSE, + (check_only || infodump || capdump) ? NULLHOOK : immedhook); + + /* do use resolution */ + if (check_only || (!infodump && !capdump) || forceresolve) { + if (!_nc_resolve_uses() && !check_only) { + cleanup(); + return EXIT_FAILURE; + } + } + + /* length check */ + if (check_only && (capdump || infodump)) + { + for_entry_list(qp) + { + if (matches(namelst, qp->tterm.term_names)) + { + int len = fmt_entry(&qp->tterm, NULL, TRUE, infodump, numbers); + + if (len>(infodump?MAX_TERMINFO_LENGTH:MAX_TERMCAP_LENGTH)) + (void) fprintf(stderr, + "warning: resolved %s entry is %d bytes long\n", + _nc_first_name(qp->tterm.term_names), + len); + } + } + } + + /* write or dump all entries */ + if (!check_only) + { + if (!infodump && !capdump) + { + _nc_set_writedir(outdir); + for_entry_list(qp) + if (matches(namelst, qp->tterm.term_names)) + write_it(qp); + } + else + { + /* this is in case infotocap() generates warnings */ + _nc_curr_col = _nc_curr_line = -1; + + for_entry_list(qp) + if (matches(namelst, qp->tterm.term_names)) + { + int j = qp->cend - qp->cstart; + int len = 0; + + /* this is in case infotocap() generates warnings */ + _nc_set_type(_nc_first_name(qp->tterm.term_names)); + + (void) fseek(tmp_fp, qp->cstart, SEEK_SET); + while (j-- ) + if (infodump) + (void) putchar(fgetc(tmp_fp)); + else + put_translate(fgetc(tmp_fp)); + + len = dump_entry(&qp->tterm, limited, numbers, NULL); + for (j = 0; j < qp->nuses; j++) + len += dump_uses((char *)(qp->uses[j].parent), infodump); + (void) putchar('\n'); + if (debug_level != 0 && !limited) + printf("# length=%d\n", len); + } + if (!namelst) + { + int c, oldc = '\0'; + bool in_comment = FALSE; + bool trailing_comment = FALSE; + + (void) fseek(tmp_fp, _nc_tail->cend, SEEK_SET); + while ((c = fgetc(tmp_fp)) != EOF) + { + if (oldc == '\n') { + if (c == '#') { + trailing_comment = TRUE; + in_comment = TRUE; + } else { + in_comment = FALSE; + } + } + if (trailing_comment + && (in_comment || (oldc == '\n' && c == '\n'))) + putchar(c); + oldc = c; + } + } + } + } + + /* Show the directory into which entries were written, and the total + * number of entries + */ + if (showsummary + && (!(check_only || infodump || capdump))) { + int total = _nc_tic_written(); + if (total != 0) + fprintf(log_fp, "%d entries written to %s\n", + total, + _nc_tic_dir((char *)0)); + else + fprintf(log_fp, "No entries written\n"); + } + cleanup(); + return(EXIT_SUCCESS); +} + +/* + * This bit of legerdemain turns all the terminfo variable names into + * references to locations in the arrays Booleans, Numbers, and Strings --- + * precisely what's needed (see comp_parse.c). + */ + +TERMINAL *cur_term; /* tweak to avoid linking lib_cur_term.c */ + +#undef CUR +#define CUR tp-> + +/* 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 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). + */ + memset(fkeys, 0, sizeof(fkeys)); + for (j = 0; _nc_tinfo_fkeys[j].code; j++) { + char *a = tp->Strings[_nc_tinfo_fkeys[j].offset]; + bool first = TRUE; + if (!VALID_STRING(a)) + continue; + for (k = j+1; _nc_tinfo_fkeys[k].code; k++) { + char *b = tp->Strings[_nc_tinfo_fkeys[k].offset]; + if (!VALID_STRING(b) + || fkeys[k]) + continue; + if (!strcmp(a,b)) { + fkeys[j] = 1; + fkeys[k] = 1; + if (first) { + if (!conflict) { + _nc_warning("Conflicting key definitions (using the last)"); + conflict = TRUE; + } + fprintf(stderr, "... %s is the same as %s", + keyname(_nc_tinfo_fkeys[j].code), + keyname(_nc_tinfo_fkeys[k].code)); + first = FALSE; + } else { + fprintf(stderr, ", %s", + keyname(_nc_tinfo_fkeys[k].code)); + } + } + } + if (!first) + fprintf(stderr, "\n"); + } + + /* + * Quick check for color. We could also check if the ANSI versus + * non-ANSI strings are misused. + */ + if ((max_colors > 0) != (max_pairs > 0) + || (max_colors > max_pairs)) + _nc_warning("inconsistent values for max_colors and max_pairs"); + + PAIRED(set_foreground, set_background) + PAIRED(set_a_foreground, set_a_background) + + /* + * These may be mismatched because the terminal description relies on + * restoring the cursor visibility by resetting it. + */ + ANDMISSING(cursor_invisible, cursor_normal) + ANDMISSING(cursor_visible, cursor_normal) + + /* + * From XSI & O'Reilly, we gather that sc/rc are required if csr is + * given, because the cursor position after the scrolling operation is + * performed is undefined. + */ + ANDMISSING(change_scroll_region, save_cursor) + ANDMISSING(change_scroll_region, restore_cursor) + + /* + * Some standard applications (e.g., vi) and some non-curses + * applications (e.g., jove) get confused if we have both ich/ich1 and + * smir/rmir. Let's be nice and warn about that, too, even though + * ncurses handles it. + */ + if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode)) + && (PRESENT(insert_character) || PRESENT(parm_ich))) { + _nc_warning("non-curses applications may be confused by ich/ich1 with smir/rmir"); + } + + /* + * Finally, do the non-verbose checks + */ + if (save_check_termtype != 0) + save_check_termtype(tp); +} diff --git a/contrib/ncurses/progs/toe.c b/contrib/ncurses/progs/toe.c new file mode 100644 index 0000000..f2c5c5e --- /dev/null +++ b/contrib/ncurses/progs/toe.c @@ -0,0 +1,303 @@ +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + +/* + * toe.c --- table of entries report generator + * + */ + +#include <progs.priv.h> + +#include <sys/stat.h> + +#include <dump_entry.h> +#include <term_entry.h> + +MODULE_ID("$Id: toe.c,v 0.19 1998/03/08 01:02:46 tom Exp $") + +const char *_nc_progname; + +static int typelist(int eargc, char *eargv[], bool, + void (*)(const char *, TERMTYPE *)); +static void deschook(const char *, TERMTYPE *); + +#if NO_LEAKS +#undef ExitProgram +static void ExitProgram(int code) GCC_NORETURN; +static void ExitProgram(int code) +{ + _nc_free_entries(_nc_head); + _nc_leaks_dump_entry(); + _nc_free_and_exit(code); +} +#endif + +int main (int argc, char *argv[]) +{ + bool direct_dependencies = FALSE; + bool invert_dependencies = FALSE; + bool header = FALSE; + int i, c, debug_level = 0; + int code; + + if ((_nc_progname = strrchr(argv[0], '/')) == NULL) + _nc_progname = argv[0]; + else + _nc_progname++; + + while ((c = getopt(argc, argv, "huv:UV")) != EOF) + switch (c) + { + case 'h': + header = TRUE; + break; + case 'u': + direct_dependencies = TRUE; + break; + case 'v': + debug_level = atoi(optarg); + _nc_tracing = (1 << debug_level) - 1; + break; + case 'U': + invert_dependencies = TRUE; + break; + case 'V': + (void) fputs(NCURSES_VERSION, stdout); + putchar('\n'); + ExitProgram(EXIT_SUCCESS); + default: + (void) fprintf (stderr, "usage: toe [-huUV] [-v n] [file...]\n"); + ExitProgram(EXIT_FAILURE); + } + + if (direct_dependencies || invert_dependencies) + { + if (freopen(argv[optind], "r", stdin) == NULL) + { + (void) fflush(stdout); + fprintf(stderr, "%s: can't open %s\n", _nc_progname, argv[optind]); + ExitProgram(EXIT_FAILURE); + } + + /* parse entries out of the source file */ + _nc_set_source(argv[optind]); + _nc_read_entry_source(stdin, (char *)NULL, + FALSE, FALSE, + NULLHOOK); + } + + /* maybe we want a direct-dependency listing? */ + if (direct_dependencies) + { + ENTRY *qp; + + for_entry_list(qp) + if (qp->nuses) + { + int j; + + (void) printf("%s:", _nc_first_name(qp->tterm.term_names)); + for (j = 0; j < qp->nuses; j++) + (void) printf(" %s", (char *)(qp->uses[j].parent)); + putchar('\n'); + } + + ExitProgram(EXIT_SUCCESS); + } + + /* maybe we want a reverse-dependency listing? */ + if (invert_dependencies) + { + ENTRY *qp, *rp; + int matchcount; + + for_entry_list(qp) + { + matchcount = 0; + for_entry_list(rp) + { + if (rp->nuses == 0) + continue; + + for (i = 0; i < rp->nuses; i++) + if (_nc_name_match(qp->tterm.term_names,(char*)rp->uses[i].parent, "|")) + { + if (matchcount++ == 0) + (void) printf("%s:", + _nc_first_name(qp->tterm.term_names)); + (void) printf(" %s", + _nc_first_name(rp->tterm.term_names)); + } + } + if (matchcount) + putchar('\n'); + } + + ExitProgram(EXIT_SUCCESS); + } + + /* + * If we get this far, user wants a simple terminal type listing. + */ + if (optind < argc) { + code = typelist(argc-optind, argv+optind, header, deschook); + } else { + char *by_env, *home, *eargv[3]; + int j; + + j = 0; + if ((by_env = getenv("TERMINFO")) != (char *)NULL) + eargv[j++] = by_env; + else + { + if ((home = getenv("HOME")) != (char *)NULL) + { + char personal[PATH_MAX]; + struct stat sb; + + (void) sprintf(personal, PRIVATE_INFO, home); + if (stat(personal, &sb) == 0 + && (sb.st_mode & S_IFMT) == S_IFDIR) + eargv[j++] = personal; + } + eargv[j++] = TERMINFO; + } + eargv[j] = (char *)NULL; + + code = typelist(j, eargv, header, deschook); + } + + ExitProgram(code); +} + +static void deschook(const char *cn, TERMTYPE *tp) +/* display a description for the type */ +{ + const char *desc; + + if ((desc = strrchr(tp->term_names, '|')) == (char *)NULL) + desc = "(No description)"; + else + ++desc; + + (void) printf("%-10s\t%s\n", cn, desc); +} + +static int typelist(int eargc, char *eargv[], + bool verbosity, + void (*hook)(const char *, TERMTYPE *tp)) +/* apply a function to each entry in given terminfo directories */ +{ + int i; + + for (i = 0; i < eargc; i++) + { + DIR *termdir; + struct dirent *subdir; + + if ((termdir = opendir(eargv[i])) == (DIR *)NULL) + { + (void) fflush(stdout); + (void) fprintf(stderr, + "%s: can't open terminfo directory %s\n", + _nc_progname, eargv[i]); + return(EXIT_FAILURE); + } + else if (verbosity) + (void) printf("#\n#%s:\n#\n", eargv[i]); + + while ((subdir = readdir(termdir)) != NULL) + { + size_t len = NAMLEN(subdir); + char buf[PATH_MAX]; + char name_1[PATH_MAX]; + DIR *entrydir; + struct dirent *entry; + + strncpy(name_1, subdir->d_name, len)[len] = '\0'; + if (!strcmp(name_1, ".") + || !strcmp(name_1, "..")) + continue; + + (void) strcpy(buf, eargv[i]); + (void) strcat(buf, "/"); + (void) strcat(buf, name_1); + (void) strcat(buf, "/"); + chdir(buf); + entrydir = opendir("."); + while ((entry = readdir(entrydir)) != NULL) + { + char name_2[PATH_MAX]; + TERMTYPE lterm; + char *cn; + int status; + + len = NAMLEN(entry); + strncpy(name_2, entry->d_name, len)[len] = '\0'; + if (!strcmp(name_2, ".") + || !strcmp(name_2, "..")) + continue; + + status = _nc_read_file_entry(name_2, <erm); + if (status <= 0) + { + (void) fflush(stdout); + (void) fprintf(stderr, + "toe: couldn't open terminfo file %s.\n", + name_2); + return(EXIT_FAILURE); + } + + /* only visit things once, by primary name */ + cn = _nc_first_name(lterm.term_names); + if (!strcmp(cn, name_2)) + { + /* apply the selected hook function */ + (*hook)(cn, <erm); + } + if (lterm.term_names) { + free(lterm.term_names); + lterm.term_names = NULL; + } + if (lterm.str_table) { + free(lterm.str_table); + lterm.str_table = NULL; + } + } + closedir(entrydir); + } + closedir(termdir); + } + + return(EXIT_SUCCESS); +} diff --git a/contrib/ncurses/progs/tput.c b/contrib/ncurses/progs/tput.c new file mode 100644 index 0000000..7a859f1 --- /dev/null +++ b/contrib/ncurses/progs/tput.c @@ -0,0 +1,312 @@ +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * tput.c -- shellscript access to terminal capabilities + * + * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from + * Ross Ridge's mytinfo package. + */ + +#include <progs.priv.h> +#ifndef PURE_TERMINFO +#include <termsort.c> +#endif + +MODULE_ID("$Id: tput.c,v 1.14 1999/07/31 21:18:29 Goran.Uddeborg Exp $") + +#define PUTS(s) fputs(s, stdout) +#define PUTCHAR(c) putchar(c) +#define FLUSH fflush(stdout) + +static char *prg_name; + +static void quit(int status, const char *fmt, ...) +{ +va_list argp; + + va_start(argp,fmt); + vfprintf (stderr, fmt, argp); + fprintf(stderr, "\n"); + va_end(argp); + exit(status); +} + +static void usage(void) +{ + fprintf(stderr, "usage: %s [-S] [-T term] capname\n", prg_name); + exit(EXIT_FAILURE); +} + +static int tput(int argc, char *argv[]) +{ +char *name; +char *s; +int i, j, c; +int reset, status; +FILE *f; + + reset = 0; + name = argv[0]; + if (strcmp(name, "reset") == 0) { + reset = 1; + } + if (reset || strcmp(name, "init") == 0) { + if (init_prog != NULL) { + system(init_prog); + } + FLUSH; + + if (reset && reset_1string != NULL) { + PUTS(reset_1string); + } else if (init_1string != NULL) { + PUTS(init_1string); + } + FLUSH; + + if (reset && reset_2string != NULL) { + PUTS(reset_2string); + } else if (init_2string != NULL) { + PUTS(init_2string); + } + FLUSH; + + if (set_lr_margin != NULL) { + PUTS(tparm(set_lr_margin, 0, columns - 1)); + } else if (set_left_margin_parm != NULL + && set_right_margin_parm != NULL) { + PUTS(tparm(set_left_margin_parm, 0)); + PUTS(tparm(set_right_margin_parm, columns - 1)); + } else if (clear_margins != NULL && set_left_margin != NULL + && set_right_margin != NULL) { + PUTS(clear_margins); + if (carriage_return != NULL) { + PUTS(carriage_return); + } else { + PUTCHAR('\r'); + } + PUTS(set_left_margin); + if (parm_right_cursor) { + PUTS(tparm(parm_right_cursor, columns - 1)); + } else { + for(i = 0; i < columns - 1; i++) { + PUTCHAR(' '); + } + } + PUTS(set_right_margin); + if (carriage_return != NULL) { + PUTS(carriage_return); + } else { + PUTCHAR('\r'); + } + } + FLUSH; + + if (init_tabs != 8) { + if (clear_all_tabs != NULL && set_tab != NULL) { + for(i = 0; i < columns - 1; i += 8) { + if (parm_right_cursor) { + PUTS(tparm(parm_right_cursor, 8)); + } else { + for(j = 0; j < 8; j++) + PUTCHAR(' '); + } + PUTS(set_tab); + } + FLUSH; + } + } + + if (reset && reset_file != NULL) { + f = fopen(reset_file, "r"); + if (f == NULL) { + quit(errno, "Can't open reset_file: '%s'", reset_file); + } + while((c = fgetc(f)) != EOF) { + PUTCHAR(c); + } + fclose(f); + } else if (init_file != NULL) { + f = fopen(init_file, "r"); + if (f == NULL) { + quit(errno, "Can't open init_file: '%s'", init_file); + } + while((c = fgetc(f)) != EOF) { + PUTCHAR(c); + } + fclose(f); + } + FLUSH; + + if (reset && reset_3string != NULL) { + PUTS(reset_3string); + } else if (init_2string != NULL) { + PUTS(init_2string); + } + FLUSH; + return 0; + } + + if (strcmp(name, "longname") == 0) { + PUTS(longname()); + return 0; + } + +#ifndef PURE_TERMINFO + { + const struct name_table_entry *np; + + if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0) + switch(np->nte_type) + { + case BOOLEAN: + if (bool_from_termcap[np->nte_index]) + name = boolnames[np->nte_index]; + break; + + case NUMBER: + if (num_from_termcap[np->nte_index]) + name = numnames[np->nte_index]; + break; + + case STRING: + if (str_from_termcap[np->nte_index]) + name = strnames[np->nte_index]; + break; + } + } +#endif + + if ((status = tigetflag(name)) != -1) + return(status != 0); + else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { + (void) printf("%d\n", status); + return(0); + } + else if ((s = tigetstr(name)) == CANCELLED_STRING) + quit(4, "%s: unknown terminfo capability '%s'", prg_name, name); + else if (s != (char *)NULL) { + if (argc > 1) { + int k; + + /* Nasty hack time. The tparm function needs to see numeric + * parameters as numbers, not as pointers to their string + * representations + */ + + for (k = 1; k < argc; k++) + if (isdigit(argv[k][0])) { + long val = atol(argv[k]); + argv[k] = (char *)val; + } + + s = tparm(s,argv[1],argv[2],argv[3],argv[4], + argv[5],argv[6],argv[7],argv[8], + argv[9]); + } + + /* use putp() in order to perform padding */ + putp(s); + return(0); + } + return(0); +} + +int main(int argc, char **argv) +{ +char *s, *term; +int errret, cmdline = 1; +int c; +char buf[BUFSIZ]; +int errors = 0; + + prg_name = argv[0]; + s = strrchr(prg_name, '/'); + if (s != NULL && *++s != '\0') + prg_name = s; + + term = getenv("TERM"); + + while ((c = getopt (argc, argv, "ST:")) != EOF) + switch (c) + { + case 'S': + cmdline = 0; + break; + case 'T': + use_env(FALSE); + term = optarg; + break; + default: + usage(); + /* NOTREACHED */ + } + argc -= optind; + argv += optind; + + if (cmdline && argc == 0) { + usage(); + /* NOTREACHED */ + } + + if (term == NULL || *term == '\0') + quit(2, "No value for $TERM and no -T specified"); + + if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0) + quit(3, "unknown terminal \"%s\"", term); + + if (cmdline) + return tput(argc, argv); + + while (fgets(buf, sizeof(buf), stdin) != (char *)NULL) { + char *argvec[16]; /* command, 9 parms, null, & slop */ + int argnum = 0; + char *cp; + + /* crack the argument list into a dope vector */ + for (cp = buf; *cp; cp++) { + if (isspace(*cp)) + *cp = '\0'; + else if (cp == buf || cp[-1] == 0) + argvec[argnum++] = cp; + } + argvec[argnum] = (char *)NULL; + + if (tput(argnum, argvec) != 0) + errors++; + } + + return errors > 0; +} + diff --git a/contrib/ncurses/progs/tset.c b/contrib/ncurses/progs/tset.c new file mode 100644 index 0000000..cef980a --- /dev/null +++ b/contrib/ncurses/progs/tset.c @@ -0,0 +1,1200 @@ +/**************************************************************************** + * Copyright (c) 1998 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: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * + * and: Eric S. Raymond <esr@snark.thyrsus.com> * + ****************************************************************************/ + + +/* + * tset.c - terminal initialization utility + * + * This code was mostly swiped from 4.4BSD tset, with some obsolescent + * cruft removed and substantial portions rewritten. A Regents of the + * University of California copyright applies to some portions of the + * code, and is reproduced below: + */ +/*- + * Copyright (c) 1980, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */ +#include <progs.priv.h> + +#include <errno.h> +#include <stdio.h> +#include <termcap.h> +#include <fcntl.h> + +#if HAVE_GETTTYNAM && HAVE_TTYENT_H +#include <ttyent.h> +#endif +#ifdef NeXT +char *ttyname(int fd); +#endif + +/* this is just to stifle a missing-prototype warning */ +#ifdef linux +# include <sys/ioctl.h> +#endif + +#if NEED_PTEM_H +/* they neglected to define struct winsize in termios.h -- it's only + in termio.h */ +#include <sys/stream.h> +#include <sys/ptem.h> +#endif + +#include <curses.h> /* for bool typedef */ +#include <dump_entry.h> + +MODULE_ID("$Id: tset.c,v 0.37 1999/03/14 12:30:02 tom Exp $") + +extern char **environ; + +#undef CTRL +#define CTRL(x) ((x) & 0x1f) + +const char *_nc_progname = "tset"; + +static TTY mode, oldmode; + +static int terasechar = -1; /* new erase character */ +static int intrchar = -1; /* new interrupt character */ +static int isreset; /* invoked as reset */ +static int tkillchar = -1; /* new kill character */ +static int tlines, tcolumns; /* window size */ + +#define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c)) + +static int +CaselessCmp(const char *a, const char *b) /* strcasecmp isn't portable */ +{ + while (*a && *b) { + int cmp = LOWERCASE(*a) - LOWERCASE(*b); + if (cmp != 0) + break; + a++, b++; + } + return LOWERCASE(*a) - LOWERCASE(*b); +} + +#if !HAVE_STRDUP +#define strdup _nc_strdup +extern char *_nc_strdup(const char *); +#endif /* not HAVE_STRDUP */ + +static void +err(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + (void)fprintf(stderr, "tset: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(EXIT_FAILURE); + /* NOTREACHED */ +} + +static void +failed(const char *msg) +{ + char temp[BUFSIZ]; + perror(strcat(strcpy(temp, "tset: "), msg)); + exit(EXIT_FAILURE); + /* NOTREACHED */ +} + +static void +cat(char *file) +{ + register int fd, nr, nw; + char buf[BUFSIZ]; + + if ((fd = open(file, O_RDONLY, 0)) < 0) + failed(file); + + while ((nr = read(fd, buf, sizeof(buf))) > 0) + if ((nw = write(STDERR_FILENO, buf, (size_t)nr)) == -1) + failed("write to stderr"); + if (nr != 0) + failed(file); + (void)close(fd); +} + +static int +outc(int c) +{ + return putc(c, stderr); +} + +/* Prompt the user for a terminal type. */ +static const char * +askuser(const char *dflt) +{ + static char answer[256]; + char *p; + + /* We can get recalled; if so, don't continue uselessly. */ + if (feof(stdin) || ferror(stdin)) { + (void)fprintf(stderr, "\n"); + exit(EXIT_FAILURE); + } + for (;;) { + if (dflt) + (void)fprintf(stderr, "Terminal type? [%s] ", dflt); + else + (void)fprintf(stderr, "Terminal type? "); + (void)fflush(stderr); + + if (fgets(answer, sizeof(answer), stdin) == 0) { + if (dflt == 0) { + (void)fprintf(stderr, "\n"); + exit(EXIT_FAILURE); + } + return (dflt); + } + + if ((p = strchr(answer, '\n')) != 0) + *p = '\0'; + if (answer[0]) + return (answer); + if (dflt != 0) + return (dflt); + } +} + +/************************************************************************** + * + * Mapping logic begins here + * + **************************************************************************/ + +/* Baud rate conditionals for mapping. */ +#define GT 0x01 +#define EQ 0x02 +#define LT 0x04 +#define NOT 0x08 +#define GE (GT | EQ) +#define LE (LT | EQ) + +typedef struct map { + struct map *next; /* Linked list of maps. */ + const char *porttype; /* Port type, or "" for any. */ + const char *type; /* Terminal type to select. */ + int conditional; /* Baud rate conditionals bitmask. */ + speed_t speed; /* Baud rate to compare against. */ +} MAP; + +static MAP *cur, *maplist; + +typedef struct speeds { + const char *string; + int speed; +} SPEEDS; + +static const SPEEDS speeds[] = { + { "0", B0 }, + { "50", B50 }, + { "75", B75 }, + { "110", B110 }, + { "134", B134 }, + { "134.5", B134 }, + { "150", B150 }, + { "200", B200 }, + { "300", B300 }, + { "600", B600 }, + { "1200", B1200 }, + { "1800", B1800 }, + { "2400", B2400 }, + { "4800", B4800 }, + { "9600", B9600 }, + { "19200", B19200 }, + { "38400", B38400 }, + { "19200", B19200 }, + { "38400", B38400 }, +#ifdef B19200 + { "19200", B19200 }, +#else +#ifdef EXTA + { "19200", EXTA }, +#endif +#endif +#ifdef B38400 + { "38400", B38400 }, +#else +#ifdef EXTB + { "38400", EXTB }, +#endif +#endif +#ifdef B57600 + { "57600", B57600 }, +#endif +#ifdef B115200 + { "115200", B115200 }, +#endif +#ifdef B230400 + { "230400", B230400 }, +#endif +#ifdef B460800 + { "460800", B460800 }, +#endif + { (char *)0, 0 } +}; + +static int +tbaudrate(char *rate) +{ + const SPEEDS *sp; + int found = FALSE; + + /* The baudrate number can be preceded by a 'B', which is ignored. */ + if (*rate == 'B') + ++rate; + + for (sp = speeds; sp->string; ++sp) { + if (!CaselessCmp(rate, sp->string)) { + found = TRUE; + break; + } + } + if (!found) + err("unknown baud rate %s", rate); + return (sp->speed); +} + +/* + * Syntax for -m: + * [port-type][test baudrate]:terminal-type + * The baud rate tests are: >, <, @, =, ! + */ +static void +add_mapping(const char *port, char *arg) +{ + MAP *mapp; + char *copy, *p; + const char *termp; + char *base = 0; + + copy = strdup(arg); + mapp = malloc(sizeof(MAP)); + if (copy == 0 || mapp == 0) + failed("malloc"); + mapp->next = 0; + if (maplist == 0) + cur = maplist = mapp; + else { + cur->next = mapp; + cur = mapp; + } + + mapp->porttype = arg; + mapp->conditional = 0; + + arg = strpbrk(arg, "><@=!:"); + + if (arg == 0) { /* [?]term */ + mapp->type = mapp->porttype; + mapp->porttype = 0; + goto done; + } + + if (arg == mapp->porttype) /* [><@=! baud]:term */ + termp = mapp->porttype = 0; + else + termp = base = arg; + + for (;; ++arg) /* Optional conditionals. */ + switch(*arg) { + case '<': + if (mapp->conditional & GT) + goto badmopt; + mapp->conditional |= LT; + break; + case '>': + if (mapp->conditional & LT) + goto badmopt; + mapp->conditional |= GT; + break; + case '@': + case '=': /* Not documented. */ + mapp->conditional |= EQ; + break; + case '!': + mapp->conditional |= NOT; + break; + default: + goto next; + } + +next: if (*arg == ':') { + if (mapp->conditional) + goto badmopt; + ++arg; + } else { /* Optional baudrate. */ + arg = strchr(p = arg, ':'); + if (arg == 0) + goto badmopt; + *arg++ = '\0'; + mapp->speed = tbaudrate(p); + } + + if (arg == (char *)0) /* Non-optional type. */ + goto badmopt; + + mapp->type = arg; + + /* Terminate porttype, if specified. */ + if (termp != 0) + *base = '\0'; + + /* If a NOT conditional, reverse the test. */ + if (mapp->conditional & NOT) + mapp->conditional = ~mapp->conditional & (EQ | GT | LT); + + /* If user specified a port with an option flag, set it. */ +done: if (port) { + if (mapp->porttype) +badmopt: err("illegal -m option format: %s", copy); + mapp->porttype = port; + } + +#ifdef MAPDEBUG + (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); + (void)printf("type: %s\n", mapp->type); + (void)printf("conditional: "); + p = ""; + if (mapp->conditional & GT) { + (void)printf("GT"); + p = "/"; + } + if (mapp->conditional & EQ) { + (void)printf("%sEQ", p); + p = "/"; + } + if (mapp->conditional & LT) + (void)printf("%sLT", p); + (void)printf("\nspeed: %d\n", mapp->speed); +#endif +} + +/* + * Return the type of terminal to use for a port of type 'type', as specified + * by the first applicable mapping in 'map'. If no mappings apply, return + * 'type'. + */ +static const char * +mapped(const char *type) +{ + MAP *mapp; + int match; + + for (mapp = maplist; mapp; mapp = mapp->next) + if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) { + switch (mapp->conditional) { + case 0: /* No test specified. */ + match = TRUE; + break; + case EQ: + match = (ospeed == mapp->speed); + break; + case GE: + match = (ospeed >= mapp->speed); + break; + case GT: + match = (ospeed > mapp->speed); + break; + case LE: + match = (ospeed <= mapp->speed); + break; + case LT: + match = (ospeed < mapp->speed); + break; + default: + match = FALSE; + } + if (match) + return (mapp->type); + } + /* No match found; return given type. */ + return (type); +} + +/************************************************************************** + * + * Entry fetching + * + **************************************************************************/ + +/* + * Figure out what kind of terminal we're dealing with, and then read in + * its termcap entry. + */ +static const char * +get_termcap_entry(char *userarg) +{ + int rval, errret; + char *p; + const char *ttype; +#if HAVE_GETTTYNAM + struct ttyent *t; +#else + FILE *fp; +#endif + char *ttypath; + + if (userarg) { + ttype = userarg; + goto found; + } + + /* Try the environment. */ + if ((ttype = getenv("TERM")) != 0) + goto map; + + if ((ttypath = ttyname(STDERR_FILENO)) != 0) { + if ((p = strrchr(ttypath, '/')) != 0) + ++p; + else + p = ttypath; +#if HAVE_GETTTYNAM + /* + * We have the 4.3BSD library call getttynam(3); that means + * there's an /etc/ttys to look up device-to-type mappings in. + * Try ttyname(3); check for dialup or other mapping. + */ + if ((t = getttynam(p))) { + ttype = t->ty_type; + goto map; + } +#else + if ((fp = fopen("/etc/ttytype", "r")) != 0 + || (fp = fopen("/etc/ttys", "r")) != 0) { + char buffer[BUFSIZ]; + char *s, *t, *d; + + while (fgets(buffer, sizeof(buffer)-1, fp) != 0) { + for (s = buffer, t = d = 0; *s; s++) { + if (isspace(*s)) + *s = '\0'; + else if (t == 0) + t = s; + else if (d == 0 && s != buffer && s[-1] == '\0') + d = s; + } + if (t != 0 && d != 0 && !strcmp(d,p)) { + ttype = strdup(t); + fclose(fp); + goto map; + } + } + fclose(fp); + } +#endif /* HAVE_GETTTYNAM */ + } + + /* If still undefined, use "unknown". */ + ttype = "unknown"; + +map: ttype = mapped(ttype); + + /* + * If not a path, remove TERMCAP from the environment so we get a + * 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 && *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)) { + while ((environ[n] = environ[n+1]) != 0) { + n++; + } + break; + } + } + } + + /* + * ttype now contains a pointer to the type of the terminal. + * If the first character is '?', ask the user. + */ + if (ttype[0] == '?') { + if (ttype[1] != '\0') + ttype = askuser(ttype + 1); + else + ttype = askuser(0); + } + /* Find the terminfo entry. If it doesn't exist, ask the user. */ + while ((rval = setupterm((NCURSES_CONST char *)ttype, STDOUT_FILENO, &errret)) != OK) { + if (errret == 0) { + (void)fprintf(stderr, "tset: unknown terminal type %s\n", + ttype); + ttype = 0; + } + else { + (void)fprintf(stderr, "tset: can't initialize terminal type %s (error %d)\n", ttype, errret); + ttype = 0; + } + ttype = askuser(ttype); + } +#if BROKEN_LINKER + tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */ +#endif + return (ttype); +} + +/************************************************************************** + * + * Mode-setting logic + * + **************************************************************************/ + +/* some BSD systems have these built in, some systems are missing + * one or more definitions. The safest solution is to override. + */ +#undef CEOF +#undef CERASE +#undef CINTR +#undef CKILL +#undef CLNEXT +#undef CRPRNT +#undef CQUIT +#undef CSTART +#undef CSTOP +#undef CSUSP + +/* control-character defaults */ +#define CEOF CTRL('D') +#define CERASE CTRL('H') +#define CINTR 127 /* ^? */ +#define CKILL CTRL('U') +#define CLNEXT CTRL('v') +#define CRPRNT CTRL('r') +#define CQUIT CTRL('\\') +#define CSTART CTRL('Q') +#define CSTOP CTRL('S') +#define CSUSP CTRL('Z') + +#define CHK(val, dft) ((int)val <= 0 ? dft : val) + +static bool set_tabs (void); + +/* + * Reset the terminal mode bits to a sensible state. Very useful after + * a child program dies in raw mode. + */ +static void +reset_mode(void) +{ +#ifdef TERMIOS + tcgetattr(STDERR_FILENO, &mode); +#else + stty(STDERR_FILENO,&mode); +#endif + +#ifdef TERMIOS +#if defined(VDISCARD) && defined(CDISCARD) + mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); +#endif + mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); + mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); +#if defined(VFLUSH) && defined(CFLUSH) + mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); +#endif + mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); + mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); +#if defined(VLNEXT) && defined(CLNEXT) + mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); +#endif + mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); +#if defined(VREPRINT) && defined(CRPRNT) + mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); +#endif +#if defined(VSTART) && defined(CSTART) + mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); +#endif +#if defined(VSTOP) && defined(CSTOP) + mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); +#endif +#if defined(VSUSP) && defined(CSUSP) + mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); +#endif +#if defined(VWERASE) && defined(CWERASE) + mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); +#endif + + mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR +#ifdef IUCLC + | IUCLC +#endif +#ifdef IXANY + | IXANY +#endif + | IXOFF); + + mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON +#ifdef IMAXBEL + | IMAXBEL +#endif + ); + + mode.c_oflag &= ~(0 +#ifdef OLCUC + | OLCUC +#endif +#ifdef OCRNL + | OCRNL +#endif +#ifdef ONOCR + | ONOCR +#endif +#ifdef ONLRET + | ONLRET +#endif +#ifdef OFILL + | OFILL +#endif +#ifdef OFDEL + | OFDEL +#endif +#ifdef NLDLY + | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY +#endif + ); + + mode.c_oflag |= (OPOST +#ifdef ONLCR + | ONLCR +#endif + ); + + mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); + mode.c_cflag |= (CS8 | CREAD); + mode.c_lflag &= ~(ECHONL | NOFLSH +#ifdef TOSTOP + | TOSTOP +#endif +#ifdef ECHOPTR + | ECHOPRT +#endif +#ifdef XCASE + | XCASE +#endif + ); + + mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK +#ifdef ECHOCTL + | ECHOCTL +#endif +#ifdef ECHOKE + | ECHOKE +#endif + ); +#endif + +#ifdef TERMIOS + tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); +#else + stty(STDERR_FILENO, &mode); +#endif +} + +/* + * Returns a "good" value for the erase character. This is loosely based on + * the BSD4.4 logic. + */ +static int +default_erase(void) +{ + int result; + + if (over_strike + && key_backspace != 0 + && strlen(key_backspace) == 1) + result = key_backspace[0]; + else + result = CERASE; + + return result; +} + +/* + * Update the values of the erase, interrupt, and kill characters in 'mode'. + * + * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase + * characters if they're unset, or if we specify them as options. This differs + * from BSD 4.4 tset, which always sets erase. + */ +static void +set_control_chars(void) +{ +#ifdef TERMIOS + if (mode.c_cc[VERASE] == 0 || terasechar >= 0) + mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase(); + + if (mode.c_cc[VINTR] == 0 || intrchar >= 0) + mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR; + + if (mode.c_cc[VKILL] == 0 || tkillchar >= 0) + mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL; +#endif +} + +/* + * Set up various conversions in 'mode', including parity, tabs, returns, + * echo, and case, according to the termcap entry. If the program we're + * running was named with a leading upper-case character, map external + * uppercase to internal lowercase. + */ +static void +set_conversions(void) +{ +#ifdef __OBSOLETE__ + /* + * Conversion logic for some *really* ancient terminal glitches, + * not supported in terminfo. Left here for succeeding generations + * to marvel at. + */ + if (tgetflag("UC")) { +#ifdef IUCLC + mode.c_iflag |= IUCLC; + mode.c_oflag |= OLCUC; +#endif + } else if (tgetflag("LC")) { +#ifdef IUCLC + mode.c_iflag &= ~IUCLC; + mode.c_oflag &= ~OLCUC; +#endif + } + mode.c_iflag &= ~(PARMRK | INPCK); + mode.c_lflag |= ICANON; + if (tgetflag("EP")) { + mode.c_cflag |= PARENB; + mode.c_cflag &= ~PARODD; + } + if (tgetflag("OP")) { + mode.c_cflag |= PARENB; + mode.c_cflag |= PARODD; + } +#endif /* __OBSOLETE__ */ + +#ifdef TERMIOS +#ifdef ONLCR + mode.c_oflag |= ONLCR; +#endif + mode.c_iflag |= ICRNL; + mode.c_lflag |= ECHO; +#ifdef OXTABS + mode.c_oflag |= OXTABS; +#endif /* OXTABS */ + + /* test used to be tgetflag("NL") */ + if (newline != (char *)0 && newline[0] == '\n' && !newline[1]) { + /* Newline, not linefeed. */ +#ifdef ONLCR + mode.c_oflag &= ~ONLCR; +#endif + mode.c_iflag &= ~ICRNL; + } +#ifdef __OBSOLETE__ + if (tgetflag("HD")) /* Half duplex. */ + mode.c_lflag &= ~ECHO; +#endif /* __OBSOLETE__ */ +#ifdef OXTABS + /* test used to be tgetflag("pt") */ + if (has_hardware_tabs) /* Print tabs. */ + mode.c_oflag &= ~OXTABS; +#endif /* OXTABS */ + mode.c_lflag |= (ECHOE | ECHOK); +#endif +} + +/* Output startup string. */ +static void +set_init(void) +{ + char *p; + bool settle; + +#ifdef __OBSOLETE__ + if (pad_char != (char *)0) /* Get/set pad character. */ + PC = pad_char[0]; +#endif /* OBSOLETE */ + +#ifdef TAB3 + if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { + oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); + tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); + } +#endif + settle = set_tabs(); + + if (isreset) { + if ((p = reset_1string) != 0) { + tputs(p, 0, outc); + settle = TRUE; + } + if ((p = reset_2string) != 0) { + tputs(p, 0, outc); + settle = TRUE; + } + /* What about rf, rs3, as per terminfo man page? */ + /* also might be nice to send rmacs, rmul, rmm */ + if ((p = reset_file) != 0 + || (p = init_file) != 0) { + cat(p); + settle = TRUE; + } + } + + if (settle) { + (void)putc('\r', stderr); + (void)fflush(stderr); + (void)napms(1000); /* Settle the terminal. */ + } +} + +/* + * Set the hardware tabs on the terminal, using the ct (clear all tabs), + * st (set one tab) and ch (horizontal cursor addressing) capabilities. + * This is done before if and is, so they can patch in case we blow this. + * Return TRUE if we set any tab stops, FALSE if not. + */ +static bool +set_tabs() +{ + if (set_tab && clear_all_tabs) { + int c; + + (void)putc('\r', stderr); /* Force to left margin. */ + tputs(clear_all_tabs, 0, outc); + + for (c = 8; c < tcolumns; 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 + * somewhat less than two character times per + * tab stop, less that .01 sec at 2400cps. We + * lost all this cruft because it seemed to be + * introducing some odd bugs. + * ----------12345678----------- */ + (void)fputs(" ", stderr); + tputs(set_tab, 0, outc); + } + putc('\r', stderr); + return (TRUE); + } + return (FALSE); +} + +/************************************************************************** + * + * Main sequence + * + **************************************************************************/ + +/* + * Tell the user if a control key has been changed from the default value. + */ +static void +report(const char *name, int which, unsigned def) +{ +#ifdef TERMIOS + unsigned older, newer; + char *p; + + newer = mode.c_cc[which]; + older = oldmode.c_cc[which]; + + if (older == newer && older == def) + return; + + (void)fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to"); + + /* + * Check 'delete' before 'backspace', since the key_backspace value + * is ambiguous. + */ + if (newer == 0177) + (void)fprintf(stderr, "delete.\n"); + else if ((p = key_backspace) != 0 + && newer == (unsigned char)p[0] + && p[1] == '\0') + (void)fprintf(stderr, "backspace.\n"); + else if (newer < 040) { + newer ^= 0100; + (void)fprintf(stderr, "control-%c (^%c).\n", newer, newer); + } else + (void)fprintf(stderr, "%c.\n", newer); +#endif +} + +/* + * Convert the obsolete argument forms into something that getopt can handle. + * This means that -e, -i and -k get default arguments supplied for them. + */ +static void +obsolete(char **argv) +{ + for (; *argv; ++argv) { + char *parm = argv[0]; + + if (parm[0] == '-' && parm[1] == '\0') + { + argv[0] = strdup("-q"); + continue; + } + + if ((parm[0] != '-') + || (argv[1] && argv[1][0] != '-') + || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k') + || (parm[2] != '\0')) + continue; + switch(argv[0][1]) { + case 'e': + argv[0] = strdup("-e^H"); + break; + case 'i': + argv[0] = strdup("-i^C"); + break; + case 'k': + argv[0] = strdup("-k^U"); + break; + } + } +} + +static void +usage(const char* pname) +{ + (void)fprintf(stderr, +"usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname); + exit(EXIT_FAILURE); +} + +static char arg_to_char(void) +{ + return (optarg[0] == '^' && optarg[1] != '\0') + ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1])) + : optarg[0]; +} + +int +main(int argc, char **argv) +{ +#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ) + struct winsize win; +#endif + int ch, noinit, noset, quiet, Sflag, sflag, showterm; + const char *p; + const char *ttype; + +#ifdef TERMIOS + if (tcgetattr(STDERR_FILENO, &mode) < 0) + failed("standard error"); + + oldmode = mode; + ospeed = cfgetospeed(&mode); +#else + if (gtty(STDERR_FILENO, &mode) < 0) + failed("standard error"); + + oldmode = mode; + ospeed = mode.sg_ospeed; +#endif + + if ((p = strrchr(*argv, '/')) != 0) + ++p; + else + p = *argv; + if (!CaselessCmp(p, "reset")) { + isreset = 1; + reset_mode(); + } + + obsolete(argv); + noinit = noset = quiet = Sflag = sflag = showterm = 0; + while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrs")) != EOF) { + switch (ch) { + case 'q': /* display term only */ + noset = 1; + break; + case 'a': /* OBSOLETE: map identifier to type */ + add_mapping("arpanet", optarg); + break; + case 'd': /* OBSOLETE: map identifier to type */ + add_mapping("dialup", optarg); + break; + case 'e': /* erase character */ + terasechar = arg_to_char(); + break; + case 'I': /* no initialization strings */ + noinit = 1; + break; + case 'i': /* interrupt character */ + intrchar = arg_to_char(); + break; + case 'k': /* kill character */ + tkillchar = arg_to_char(); + break; + case 'm': /* map identifier to type */ + add_mapping(0, optarg); + break; + case 'n': /* OBSOLETE: set new tty driver */ + break; + case 'p': /* OBSOLETE: map identifier to type */ + add_mapping("plugboard", optarg); + break; + case 'Q': /* don't output control key settings */ + quiet = 1; + break; + case 'S': /* OBSOLETE: output TERM & TERMCAP */ + Sflag = 1; + break; + case 'r': /* display term on stderr */ + showterm = 1; + break; + case 's': /* output TERM set command */ + sflag = 1; + break; + case '?': + default: + usage(*argv); + } + } + argc -= optind; + argv += optind; + + if (argc > 1) + usage(*argv); + + ttype = get_termcap_entry(*argv); + + if (!noset) { + tcolumns = columns; + tlines = lines; + +#if defined(TIOCGWINSZ) && defined(TIOCSWINSZ) + /* Set window size */ + (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); + if (win.ws_row == 0 && win.ws_col == 0 && + tlines > 0 && tcolumns > 0) { + win.ws_row = tlines; + win.ws_col = tcolumns; + (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); + } +#endif + set_control_chars(); + set_conversions(); + + if (!noinit) + set_init(); + + /* Set the modes if they've changed. */ + if (memcmp(&mode, &oldmode, sizeof(mode))) +#ifdef TERMIOS + tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); +#else + stty(STDERR_FILENO, &mode); +#endif + } + + /* Get the terminal name from the entry. */ + ttype = _nc_first_name(cur_term->type.term_names); + + if (noset) + (void)printf("%s\n", ttype); + else { + if (showterm) + (void)fprintf(stderr, "Terminal type is %s.\n", ttype); + /* + * If erase, kill and interrupt characters could have been + * modified and not -Q, display the changes. + */ + if (!quiet) { + report("Erase", VERASE, CERASE); + report("Kill", VKILL, CINTR); + report("Interrupt", VINTR, CKILL); + } + } + + if (Sflag) + err("The -S option is not supported under terminfo."); + + if (sflag) { + /* + * Figure out what shell we're using. A hack, we look for an + * environmental variable SHELL ending in "csh". + */ + if ((p = getenv("SHELL")) != 0 + && !strcmp(p + strlen(p) - 3, "csh")) + p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n"; + else + p = "TERM=%s;\n"; + (void) printf(p, ttype); + } + + return EXIT_SUCCESS; +} + +/* tset.c ends here */ |