Initial revision

This commit is contained in:
Gunnar Ritter 2004-12-04 13:17:05 +00:00
commit 92e4e9fdf7
58 changed files with 32735 additions and 0 deletions

140
Changes Normal file
View File

@ -0,0 +1,140 @@
Release 12/2/04
* Support for multibyte character locales was added.
* The code has been converted to ANSI C, and support for pre-POSIX systems has
been dropped.
* When the end of the current line consists of blank characters and the 'w'
visual command is given at this point, vi now advances to the start of the
next line instead of ringing the bell. This is compatible with SVR4 vi and
seems to be what POSIX specifies.
* If the replacement part of a substitute command consists of a single '%',
as in ':s/foo/%/', the replacement part of the previous substitution is
used. This is compatible with SVR4 vi and is specified by POSIX.
* Fixed a number of possible heap overflows, e.g. because of too long tag
strings.
Release 6/5/04
* Some changes were made to the Makefile to support RPM builds. In particular,
the meaning of the DESTDIR and PREFIX variables was changed.
* An insufficient size of a variable caused the window size set to 8 on
FreeBSD if the terminal baud rate was 38400.
Release 1/3/04
* Changes to the included libterm only: Made multiple tc= capabilities in
a termcap entry work; recognize tc= also if it is not the last capability
in an entry (Bugreport by Andrew Minter).
Release 9/3/03
* The code did not check st_blksize from stat(2) at other points besides
the one fixed in the last release.
* The keyboard input character with code 255 ("y in ISO-8859-1) was
misinterpreted as end-of-file indicator.
Release 8/27/03
* Compile fixes for AIX and HP-UX (Mike Jetzer).
* Delete temporary file when preserving was successful after receiving
SIGHUP or SIGTERM (Fix taken from 4.3BSD Reno).
* Set MAILRC to /dev/null in expreserve to avoid reading the user's
mail initialization file.
* Optionally use Caldera's 'UNIX(R) Regular Expression Library' to
get POSIX.2 compatible REs.
* Don't refuse to quit with 'No write since last change' if a line of a
newly read input file is too long but no changes were made by the user.
* The POSIX_2 preprocessor define has been removed. The behavior previously
enabled by this variable is now the default (except as noted below).
* Backslash inside RE bracket expresssions (as in [\]]) is now recognized
as an escape character by default. This is not POSIX.2 compliant, but is
compatible with historic vi behavior, is demanded by the some traditional
standards such as the System V Interface definition, and is compatible
with vim. To get POSIX.2 compliant behavior here, define NO_BE_BACKSLASH.
* The input buffer did overflow with large values of st_blksize from stat(2).
Release 4/3/02
* Option "showmode" has no effect on hardcopy or glass terminals (P).
* Fixed undo for :r! command.
* Interrupt character is not misinterpreted as DEL on insertion (P).
* Fixed interaction of <count>~ vi command with abbreviations and macros (P).
* Avoid horizontal scrolling of showmode string on wraparound to last line (P).
* No showmode string is printed when executing a macro.
* Recovery listing fixed not to mix characters from long filenames in
/var/preserve with /var/tmp listing (P).
* Catch SIGXFSZ (file size limit exceeded).
Release 3/3/02
* Separated terse/noterse messages for RE errors (P).
* The expreserve and exrecover commands work again (P).
* Passing beyond EOL in <count>~ vi command is not an error (P).
* Fixed segmentation violation on mdjc'd and related bugs (Sven Mascheck).
* Marks remain on lines changed in an undo operation.
* Close mapmalloc file descriptor for /dev/zero on exec() (P).
* Added -L and -V command line options as in SVr4 ex.
* POSIX.2: Processing EXINIT does not depend on stdin being a terminal.
* POSIX.2: No newline is appended to an empty file in visual mode.
* Fixed segmentation violation on :f^V^M^M and similar commands.
* Mapmalloc extended to allocate and release multiple memory pools.
* Exrecover lists /var/tmp in addition to /var/preserve.
* Have multiple attempts to create named buffer temporary file.
* Size limit for temporary file names removed.
Release 2/17/02
* POSIX.2: Backslash has no special meaning inside RE bracket expressions.
* RE cleanup; make it compile without POSIX_2 defined (P).
* Fixed $(CC) to "$(CC)" for libterm compilation (Felix von Leitner) (P).
* Support for LC_MESSAGES using catgets() added.
* Renamed POSIX define to POSIX_1.
* Renamed UNIX98 define to POSIX_2.
* POSIX.2: Fixed a conflict between -t tag and wrapscan option.
* POSIX.2: Take the initial value for the vi scroll command from scroll var.
* <count>~ vi command fixed to work with repeat and control chars in text (P).
* Fixed recursion on :ab abbreviations (Bugreport by Matthias Kopfermann).
* Fixed undo for :<addr>r command in visual mode.
* Made modelines compatible to SVr4 ex: The option name is "modelines" or
"ml" now; a space or tab preceeding "ex:" or "vi:" is not required.
* Use O_EXCL and O_NOFOLLOW when creating temporary files, if possible.
Release 1/26/02
* Use mmap() for memory allocation if possible.
* POSIX.2: Added RE interval expressions \{m,n\} (taken from V7 expr).
* POSIX.2: Added backreferences \1 ... \9.
* Print one-character mode strings if both "showmode" and "terse" are set.
* Added the "flash" variable.
* POSIX.2: "~" visual command accepts a count.
* License notices added.
Release 5/21/01
* If compiled using BIT8, all characters except ASCII NUL can now be handled.
* Support larger files if LARGEF is defined.
Release 09/23/00
* POSIX locale support for 8bit character sets is enabled by -DBIT8.
* Regex code is 8bit clean.
* Smaller fixes for SVR4 systems.
* POSIX termios support including job control.
* POSIX sigaction support.
* Check for ELF executables and compressed files.
* Extended the pattern for temporary files from 5 to 10 digits.
* ANSI C stdarg function calling added, Linux/ia64 needs them.
* Reintegrated the UCVISUAL routines from 4.4BSD ex.
* Only use the "ic" termcap sequence if "im" is empty.
* POSIX.2: Command line options added and revised.
* POSIX.2: Added a "showmode" option for novices.
* POSIX.2: Ex respects the environment variables COLUMNS and LINES.
* POSIX.2: Added an "exrc" option like on POSIX.2 ex; arbitrary .exrc
files are ignored unless it is set in EXINIT or ~/.exrc.
* POSIX.2: If .exrc files are world or group writeable, they are ignored
unless "sourceany" is set.
* Ex now provides malloc routines. They are necessary since C library
calls like setlocale could otherwise break the sbrk calls in ex. As
an additional benefit, linking against ncurses is now possible.
Release 31/05/00
* String extraction using mkstr and xstr is not longer be done.
* An ANSI C preprocessor may be used.
* Changes of symbol names due to collisions on newer systems.
* Fixed a null pointer reference in ex_tty.c.
* Included the 2.11BSD termcap in a subdirectory. Ex could use any
termcap library, however, that does not use malloc().
* Support of eight bit characters excluding the range 0200 to 0237 is
enabled with -DISO8859_1. It does not include the regular expression code,
but otherwise works well in practice with the ISO-8859-1 character set.
Fixes for problems that were introduced in this port are marked (P).

109
LICENSE Normal file
View File

@ -0,0 +1,109 @@
This code contains changes by
Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
Conditions 1, 2, and 4 and the no-warranty notice below apply
to these changes.
Copyright (c) 1980, 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.
Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code and documentation must retain the
above copyright notice, this list of conditions and the following
disclaimer.
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.
All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed or owned by Caldera
International, Inc.
Neither the name of Caldera International, Inc. nor the names of
other contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
The mmap-based memory allocation code is derived from mm-1.1.3:
Copyright (c) 1999-2000 Ralf S. Engelschall. 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 acknowledgment:
"This product includes software developed by
Ralf S. Engelschall <rse@engelschall.com>."
4. Redistributions of any form whatsoever must retain the following
acknowledgment:
"This product includes software developed by
Ralf S. Engelschall <rse@engelschall.com>."
THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
EXPRESSED 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 RALF S. ENGELSCHALL OR
ITS 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.

388
Makefile Normal file
View File

@ -0,0 +1,388 @@
#
# This code contains changes by
# Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
#
# Conditions 1, 2, and 4 and the no-warranty notice below apply
# to these changes.
#
#
# Copyright (c) 1980, 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.
#
#
# Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# Redistributions of source code and documentation must retain the
# above copyright notice, this list of conditions and the following
# disclaimer.
# 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.
# All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed or owned by Caldera
# International, Inc.
# Neither the name of Caldera International, Inc. nor the names of
# other contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
# INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
#
# from Makefile 7.13.1.3 (2.11BSD GTE) 1996/10/23
#
# @(#)Makefile 1.45 (gritter) 12/1/04
#
#
# Destinations for installation. $(PRESERVEDIR) is used for recovery files.
# It will get mode 1777.
#
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
LIBEXECDIR = $(PREFIX)/libexec
MANDIR = $(PREFIX)/share/man
PRESERVEDIR = /var/preserve
#
# DESTDIR is prepended to the installation paths. It is mostly useful
# for package building and should be left empty otherwise.
#
DESTDIR =
#
# A BSD-like install program. GNU install will fit well here, too.
#
INSTALL = /usr/ucb/install
#
# Compiler and linker flags.
#
# On HP-UX, add -D_INCLUDE__STDC_A1_SOURCE to CPPFLAGS.
#
#CFLAGS =
#CPPFLAGS =
#LDFLAGS =
#LDADD =
#
# All of the following settings are quite recommended, so you should only
# change them if it becomes really necessary.
#
# Remove -DMB to build without multibyte character support. This will be
# necessary if the compiler complains about a missing wchar.h, wctype.h,
# mbtowc(), mbrtowc(), btowc(), wcwidth() etc. You will likely also have
# to use the old regular expression code in these cases (see below).
# Remove -DBIT8 to get a 7bit-only ex. This setting is mostly provided for
# testing the internationalization code against the older version and
# should not normally be removed.
# Add -DNO_BE_BACKSLASH to make backslash a regular character inside RE
# bracket expressions.
#
# Some historic comments:
#
# Ex is very large - this version will not fit on PDP-11's without overlay
# software. Things that can be turned off to save
# space include LISPCODE (-l flag, showmatch and lisp options), CHDIR (the
# previously undocumented chdir command.)
#
# If your system expands tabs to 4 spaces you should -DTABS=4 below
#
FEATURES = -DLISPCODE -DCHDIR -DFASTTAG -DUCVISUAL -DMB -DBIT8
#
# This disables the LC_CTYPE locale settings and assumes all characters
# upwards from octal 0240 are printable ones, like in ISO 8859-1. It
# should only be used if the system's locales are broken. It cannot be
# used in combination with -DMB.
#
#CHARSET = -DISO8859_1
#
# If you want LC_MESSAGES support using catgets(), define this. To make
# any practical use of it, you also have to create a message catalogue,
# put it in a proper location and change UNKNOWN to its name. See your
# system's documentation on "gencat" or on language support in general
# for further information. This setting is not interesting at the current
# time unless you want to contribute internationalized message catalogues.
#
#LANGMSG = -DLANGMSG -DCATNAME='"UNKNOWN"'
#
# For multibyte character support in regular expressions, and for the
# features of localized regular expressions ([:class:], [.c.], [=c=],
# \(re\)*, \(re\)\{m,n\}), you need Caldera's 'UNIX(R) Regular Expression
# Library' or a derivative of it. Comment out the three following lines if
# you don't have it or if it does not compile; it needs some advanced
# multibyte character support (wchar.h, wctype.h, btowc() etc.) which is
# not provided by older compilation environments.
#
REINC = -I./libuxre -DUXRE
RELIB = -L./libuxre -luxre
RETGT = uxre
#
# VMUNIX should be correct for any modern Unix.
#
# Historic comments:
#
# VMUNIX makes ex considerably larger, raising
# many limits and improving speed and simplicity of maintenance. It is
# suitable only for a VAX or other large machine, and then probably only in
# a paged system.
#
# Don't define VFORK unless your system has the VFORK system call,
# which is like fork but the two processes have only one data space until the
# child execs. This speeds up ex by saving the memory copy.
#
# Note by Gunnar Ritter: vfork() is unreliable and one of the worst
# hacks in Unix history. Do not define VFORK unless you have a
# special good reason for that.
#
OSTYPE = -DVMUNIX
#
# On VMUNIX systems, ex can normally edit files up to 32 MB of size. LARGEF
# raises this limit to around 1 GB, but ex will consume much more of core
# and temp file space then.
#
#LARGEF = -DLARGEF
#
# The next setting is a crucial one since it determines the way ex
# gets its knowledge about the terminal's capabilities. If you get
# weird results, try using another library here. Uncomment exactly
# one entry.
#
# On System V, the terminfo library may be more accurate than the termcap
# file. To use it, link against the curses library.
#
#TERMLIB = curses
#
# You may also get terminfo access by using the ncurses library.
#
#TERMLIB = ncurses
#
# The preferred choice for ex on Linux distributions and other systems that
# provide a good termcap file is the 2.11BSD termcap library included here.
#
TERMLIB = termlib
#
# Since ex uses sbrk() internally, a conflict with the libc's version of
# malloc() must be avoided. There are two ways to work around this problem.
# The first is to allocate a static pool for all malloc purposes. This will
# work on any kind of system.
#
#MALLOC=malloc.o
#
# If mmap() can be used to allocate anonymous memory, this is the preferred
# choice as it allows to grow memory dynamically as it is needed. This will
# usually work unless you are compiling for a vector machine or another
# unusual enviroment.
MALLOC=mapmalloc.o
###############################################################################
# #
# That's it. You do not normally need to change anything below here. #
# #
###############################################################################
#WARN = -Wall -Wno-parentheses -Werror
STRIP = -s
RECOVER = -DEXRECOVER=\"$(LIBEXECDIR)/exrecover\" \
-DEXPRESERVE=\"$(LIBEXECDIR)/expreserve\"
CCFLAGS = $(CFLAGS) $(WARN) $(CPPFLAGS) $(FEATURES) $(CHARSET) $(OSTYPE) \
$(LARGEF) $(RECOVER) $(LANGMSG) $(REINC) $(RPMCFLAGS)
TLIB = libterm/libtermlib.a
INCLUDE = /usr/include
OBJS = ex.o ex_addr.o ex_cmds.o ex_cmds2.o ex_cmdsub.o \
ex_data.o ex_extern.o ex_get.o ex_io.o ex_put.o ex_re.o \
ex_set.o ex_subr.o ex_tagio.o ex_temp.o ex_tty.o ex_unix.o \
ex_v.o ex_vadj.o ex_vget.o ex_vmain.o ex_voper.o \
ex_vops.o ex_vops2.o ex_vops3.o ex_vput.o ex_vwind.o \
printf.o ex_version.o $(MALLOC)
HDRS = ex.h ex_argv.h ex_re.h ex_temp.h ex_tty.h ex_tune.h ex_vars.h \
ex_vis.h libterm/libterm.h
SRC1 = ex.c ex_addr.c ex_cmds.c ex_cmds2.c ex_cmdsub.c
SRC2 = ex_data.c ex_get.c ex_io.c ex_put.c ex_re.c
SRC3 = ex_set.c ex_subr.c ex_tagio.c ex_temp.c ex_tty.c ex_unix.c
SRC4 = ex_v.c ex_vadj.c ex_vget.c ex_vmain.c ex_voper.c
SRC5 = ex_vops.c ex_vops2.c ex_vops3.c ex_vput.c ex_vwind.c
SRC6 = printf.c expreserve.c exrecover.c ex_version.c
SRC7 = mapmalloc.c malloc.c
.SUFFIXES: .o .c
.c.o: ; $(CC) $(CCFLAGS) -c $<
all: $(RETGT) exrecover expreserve ex
ex: $(TLIB) $(OBJS)
$(CC) -o ex $(LDFLAGS) $(OBJS) $(LDADD) -Llibterm -l$(TERMLIB) $(RELIB)
size ex
$(TLIB): libterm/termcap.c libterm/tgoto.c libterm/tputs.c libterm/libterm.h
@cd libterm && $(MAKE) CC="$(CC)" \
COPT="$(CFLAGS) $(WARN) $(CPPFLAGS) $(OSTYPE)"
exrecover: exrecover.o $(MALLOC)
$(CC) -o exrecover $(LDFLAGS) exrecover.o $(MALLOC) $(LDADD)
expreserve: expreserve.o
$(CC) -o expreserve $(LDFLAGS) expreserve.o $(LDADD)
ex_vars.h: ex_data.c
sh makeoptions $(CCFLAGS)
uxre:
@cd libuxre && $(MAKE) CC="$(CC)" \
COPT="$(CFLAGS) $(WARN) $(CPPFLAGS) $(OSTYPE)"
clean:
@cd libterm && $(MAKE) clean
@test ! -d libuxre || (cd libuxre && $(MAKE) clean)
# If we dont have ex we cant make it so don't rm ex_vars.h
-rm -f ex exrecover expreserve *.o x*.[cs] core errs trace
mrproper: clean
-rm -f log
# install in standard place
install-man:
test -d $(DESTDIR)$(PREFIX) || mkdir -p $(DESTDIR)$(PREFIX)
test -d $(DESTDIR)$(MANDIR) || mkdir -p $(DESTDIR)$(MANDIR)
test -d $(DESTDIR)$(MANDIR)/man1 || mkdir -p $(DESTDIR)$(MANDIR)/man1
rm -f $(DESTDIR)$(MANDIR)/man1/ex.1 $(DESTDIR)$(MANDIR)/man1/edit.1 \
$(DESTDIR)$(MANDIR)/man1/vedit.1 \
$(DESTDIR)$(MANDIR)/man1/vi.1 \
$(DESTDIR)$(MANDIR)/man1/view.1
$(INSTALL) -c -m 644 ex.1 $(DESTDIR)$(MANDIR)/man1/ex.1
$(INSTALL) -c -m 644 vi.1 $(DESTDIR)$(MANDIR)/man1/vi.1
ln -s ex.1 $(DESTDIR)$(MANDIR)/man1/edit.1
ln -s vi.1 $(DESTDIR)$(MANDIR)/man1/vedit.1
ln -s vi.1 $(DESTDIR)$(MANDIR)/man1/view.1
install: all install-man
rm -f $(DESTDIR)$(BINDIR)/ex $(DESTDIR)$(BINDIR)/edit \
$(DESTDIR)$(BINDIR)/vedit $(DESTDIR)$(BINDIR)/vi \
$(DESTDIR)$(BINDIR)/view
test -d $(DESTDIR)$(BINDIR) || mkdir -p $(DESTDIR)$(BINDIR)
# special provisions for sticky install
if test -f $(DESTDIR)$(BINDIR)/ex; \
then test -f $(DESTDIR)$(BINDIR)/ex.old.$$$$ && exit 1; \
chmod 755 $(DESTDIR)$(BINDIR)/ex; \
echo q | $(DESTDIR)$(BINDIR)/ex; \
mv $(DESTDIR)$(BINDIR)/ex $(DESTDIR)$(BINDIR)/ex.old.$$$$; \
rm -f $(DESTDIR)$(BINDIR)/ex.old.$$$$; \
fi
$(INSTALL) -c $(STRIP) -m 1755 ex $(DESTDIR)$(BINDIR)/ex
test -d $(DESTDIR)$(LIBEXECDIR) || mkdir -p $(DESTDIR)$(LIBEXECDIR)
$(INSTALL) -c $(STRIP) exrecover $(DESTDIR)$(LIBEXECDIR)/exrecover
$(INSTALL) -c $(STRIP) expreserve $(DESTDIR)$(LIBEXECDIR)/expreserve
ln -s ex $(DESTDIR)$(BINDIR)/edit
ln -s ex $(DESTDIR)$(BINDIR)/vedit
ln -s ex $(DESTDIR)$(BINDIR)/vi
ln -s ex $(DESTDIR)$(BINDIR)/view
test -d $(DESTDIR)$(PRESERVEDIR) || mkdir -p $(DESTDIR)$(PRESERVEDIR)
chmod 1777 $(DESTDIR)$(PRESERVEDIR)
ex.o: config.h ex_argv.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h
ex.o: ex_vars.h libterm/libterm.h
ex_addr.o: config.h ex.h ex_proto.h ex_re.h ex_tune.h ex_vars.h
ex_cmds.o: config.h ex_argv.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h
ex_cmds.o: ex_vars.h ex_vis.h libterm/libterm.h
ex_cmds2.o: config.h ex_argv.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h
ex_cmds2.o: ex_vars.h ex_vis.h libterm/libterm.h
ex_cmdsub.o: config.h ex_argv.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h
ex_cmdsub.o: ex_vars.h ex_vis.h libterm/libterm.h
ex_data.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h
ex_data.o: libterm/libterm.h
ex_extern.o: config.h ex_argv.h ex.h ex_proto.h ex_re.h ex_temp.h ex_tty.h
ex_extern.o: ex_tune.h ex_vars.h ex_vis.h libterm/libterm.h
ex_get.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h
ex_get.o: libterm/libterm.h
ex_io.o: config.h ex_argv.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h
ex_io.o: ex_vars.h ex_vis.h libterm/libterm.h
ex_put.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_put.o: libterm/libterm.h
ex_re.o: config.h ex.h ex_proto.h ex_re.h ex_tune.h ex_vars.h
ex_set.o: config.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h ex_vars.h
ex_set.o: libterm/libterm.h
ex_subr.o: config.h ex.h ex_proto.h ex_re.h ex_tty.h ex_tune.h ex_vars.h
ex_subr.o: ex_vis.h libterm/libterm.h
ex_tagio.o: config.h ex.h ex_proto.h ex_tune.h ex_vars.h
ex_temp.o: config.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h ex_vars.h
ex_temp.o: ex_vis.h libterm/libterm.h
ex_tty.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h
ex_tty.o: libterm/libterm.h
ex_unix.o: config.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h ex_vars.h
ex_unix.o: ex_vis.h libterm/libterm.h
ex_v.o: config.h ex.h ex_proto.h ex_re.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_v.o: libterm/libterm.h
ex_vadj.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vadj.o: libterm/libterm.h
ex_vget.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vget.o: libterm/libterm.h
ex_vmain.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vmain.o: libterm/libterm.h
ex_voper.o: config.h ex.h ex_proto.h ex_re.h ex_tty.h ex_tune.h ex_vars.h
ex_voper.o: ex_vis.h libterm/libterm.h
ex_vops.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vops.o: libterm/libterm.h
ex_vops2.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vops2.o: libterm/libterm.h
ex_vops3.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vops3.o: libterm/libterm.h
ex_vput.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vput.o: libterm/libterm.h
ex_vwind.o: config.h ex.h ex_proto.h ex_tty.h ex_tune.h ex_vars.h ex_vis.h
ex_vwind.o: libterm/libterm.h
expreserve.o: config.h
exrecover.o: config.h ex.h ex_proto.h ex_temp.h ex_tty.h ex_tune.h ex_vars.h
exrecover.o: libterm/libterm.h
malloc.o: config.h
mapmalloc.o: config.h
printf.o: config.h

107
README Normal file
View File

@ -0,0 +1,107 @@
Welcome to the ex/vi port!
==========================
This implementation is derived from ex/vi 3.7 of 6/7/85 and the BSD
termcap library, originally from the 2.11BSD distribution. All of them
were changed to compile and run on newer POSIX compatible Unix systems.
Support for international character sets was added, including support
for multibyte locales (in particular UTF-8), and some changes were made
to get closer to the POSIX.2 guidelines for ex and vi. Some issues that
were clearly bugs and not features have also been resolved; the the
Changes file for details.
New releases are announced on Fresmeat. If you want to get
notified by email on each release, use their subscription service at
<http://freshmeat.net/projects/vi/>.
The project homepage is currently at <http://ex-vi.sourceforge.net>.
How to build
============
First look at the Makefile and change the settings there to match your
build environment. Explanations are provided directly in this file.
You can tune the sizes of some internal buffers by editing config.h. In
particular, you will have to raise the size of the 'TUBE' constants if
you wish to use really large-sized terminals.
Then type 'make' and 'make install'.
It is possible to build a RPM file directly from the source distribution
by executing
rpmbuild -tb ex-<version>.tar.bz2
Note that the RPM spec installs the binary in /usr/5bin by default to
avoid conflicts with vendor files in /usr/bin. The default locations
match those of the Heirloom Toolchest <http://heirloom.sourceforge.net>.
The following systems have been reported to compile this code:
Linux Kernel 2.0 and above; libc4, libc5, glibc 2.2 and above,
diet libc, uClibc; gcc, Intel C
Sun Solaris 2.5.1 and above
Open UNIX 8.0.0
UnixWare 7.1.1, 7.0.1, 2.1.2
HP HP-UX B.11.23, B.11.11, B.11.00, B.10.20
HP Tru64 UNIX 4.0G, 5.1B
IBM AIX 5.1, 4.3
NEC SUPER-UX 10.2
NEC UX/4800 Release11.5 Rev.A
FreeBSD 3.1, 4.5, 5.x
NetBSD 1.6
Reports about other Unix systems are welcome, whether successful or not
(in the latter case add a detailed description). This port of vi is only
aimed at Unix, though, so I am not interested about results from running
this software on Windows etc.
Prerequisites for ports to other systems are:
- The system must provide an ANSI C-89 compiler and POSIX.1-1990 functions.
- The system must provide an sbrk() call to increase the memory heap size.
If only a fake sbrk() call is provided that works by pre-allocating
several MB, vi will probably work too.
- The system library must allow replacement of malloc() and printf() by the
versions provided by vi. For malloc(), it also must make its own internal
memory requests using the vi malloc(). Otherwise, vi will likely die with
a segmentation fault because the storage allocated by sbrk() interferes
with usual Unix library implementations of malloc().
The last two requirements could probably be eliminated with some effort, but
it would not result in any real improvements for usual the Unix platforms vi
is targeted at, so it has not be done yet.
Multibyte locale support
========================
Support for multibyte locales has been added to vi. It requires a number of
functions that, while specified in XPG6, are not present on all systems that
provide basic multibyte support. In particular, vi needs wcwidth() to
determine the visual width of a character, and mbrtowc() to detect when a
byte sequence that is entered at the terminal has been completed.
The multibyte code is known to work with UTF-8 locales on the following
systems:
Linux glibc 2.3.3
Sun Solaris 10
FreeBSD 5.3
It has been tested with xterm patch #192 and rxvt-unicode 4.2.
To use UTF-8 locales in ex mode, the terminal must be put in 'stty iutf8'
mode on Linux if it does not perform this automatically. Otherwise, typing
the erase key once after entering a multibyte character will result in an
incomplete byte sequence.
Gunnar Ritter 12/2/04
Freiburg i. Br.
Germany
<Gunnar.Ritter@pluto.uni-freiburg.de>

30
TODO Normal file
View File

@ -0,0 +1,30 @@
TODO list for ex
- Some support for UTF-8 combining characters should probably be added.
- Since the POSIX standard developers did not include a method to
determine whether something is a valid collation symbol or an
equivalence class, and since there is no access to the basic
collation sequence, LC_COLLATE locales are completely ignored.
- There may be other unresolved POSIX.2 demands I did not notice yet.
Please write me if you find one. You can get SUSv2 from The Open
Group <http://www.UNIX-systems.org/> for $0, it contains nearly the
same text for ex/vi as POSIX.2 and is a good reference manual.
- SVr4 ex probably has some silent features that this one should have too.
- SUSv3 / POSIX.1-200x ex/vi support.
I did not yet decide whether this is worth implementing. It requires
a lot of mostly small changes that make vi more nvi-like in general.
If SUSv3 has as little success in the Open Source world as its
predecessors, it might be better to ignore it and stay on the
officially obsolete SUSv2 / POSIX.2 level.
- The traditional regular expression code in ex_re.c could be updated to
work with multibyte characters. This would mostly involve to take the
code from libcommon/regexp.h of the Heirloom Toolchest.
- Translated message catalogues.
Gunnar Ritter 12/2/04

309
catd/en_US Normal file
View File

@ -0,0 +1,309 @@
$ Message catalogue for ex/vi
$ Sccsid @(#)en_US 1.4 (gritter) 3/18/03
$quote "
$set 1
1 "Usage: %s [- | -s] [-l] [-L] [-R] [-r [file]] [-t tag]\n\
[-v] [-V] [-w size] [+cmd | -c cmd] file...\n"
2 "%s: option requires an argument -- %c\n"
3 "%s: illegal option -- %c\n"
4 "Trace create error\n"
5 "Unknown option %s\n"
6 "Addr1 > addr2|First address exceeds second"
7 "Bad count|Nonzero count required"
8 "No address allowed@on this command"
9 "Badly formed address"
10 "No match to BOTTOM|Address search hit BOTTOM without matching pattern"
11 "No match to TOP|Address search hit TOP without matching pattern"
12 "Fail|Pattern not found"
13 "Marks are ' and a-z"
14 "Undefined mark@referenced"
15 "Negative address@- first buffer line is 1"
16 "Not that many lines@in buffer"
17 "Offset out-of-bounds|Offset after command too large"
18 "Home directory unknown"
19 "Mark what?|%s requires following letter"
20 "Bad mark|Mark must specify a letter"
21 "Preserve failed!"
22 "File preserved."
23 "No write@since last change (:rewind! overrides)"
24 "Old tty driver|Not using new tty driver/shell"
25 "Bad register"
26 "At EOF|At end-of-file"
27 "What?|Unknown command character '%c'"
28 "Extra chars|Extra characters at end of command"
29 " [Warning - %s is incomplete]"
30 "%d files@to edit"
31 "No more files@to edit"
$quote
32 Extra chars|Extra characters at end of "%s" command
$quote "
33 "%d more file"
34 "%s@to edit"
35 "No write@since last change (:%s! overrides)"
36 "What?|%s: No such command from open/visual"
37 "What?|%s: Not an editor command"
38 "[Hit return to continue] "
39 "Out of memory@- too many lines in file"
40 "Line overflow|Result line of join would be too long"
41 "That move would do nothing!"
42 "Move to a moved line"
43 "%s where?|%s requires a trailing address"
44 "Cannot put inside global/macro"
45 "Line too long|Result line after shift would be too long"
46 "Bad tag|Give one tag per line"
47 "No previous tag"
48 "%s: Bad tags file entry"
49 "No write@since last change (:tag! overrides)"
50 "No tags file"
51 "%s: No such tag@in tags file"
52 "Can't yank inside global/macro"
53 "\nAt EOF"
54 "At EOF"
55 "Hit BOTTOM"
56 "Hit TOP"
57 "Nothing to undo"
58 "Nothing changed|Last undoable command didn't change anything"
59 "Can't undo in global@commands"
60 "Missing lhs"
61 "Missing rhs"
62 "Missing rhs"
63 "No tail recursion"
64 "Too dangerous to map that"
65 "No tail recursion"
66 "Missing lhs"
67 "Not mapped|That macro wasn't mapped"
68 "Too many macros"
69 "Too much macro text"
70 "^H discarded\n"
71 "Input line too long"
72 "No file|No current filename"
73 " [Read only]"
74 " [Not edited]"
75 " [Modified]"
76 "No file "
77 " line %d of %d --%ld%%--"
78 "Pattern too long"
79 "Argument buffer overflow"
80 "No alternate filename@to substitute for #"
81 "No current filename@to substitute for %%"
82 "Can't make pipe to glob"
83 "Can't fork to do glob"
84 "Arg list too long"
85 "Arg list too long"
86 "No match"
87 "Missing filename"
88 "Ambiguous|Too many file names"
89 "Filename too long"
90 " [New file]"
91 " Block special file"
92 " Teletype"
93 " Character special file"
94 " Directory"
95 " Socket"
96 " Named pipe"
97 " Executable"
98 " Compressed Data"
99 " ELF object"
100 " Archive"
101 " Non-ascii file"
102 " [Read only]"
103 " %d/%d"
104 " %d line%s, %d character%s"
105 " ("
106 "%d null"
107 ", "
108 "%d non-ASCII"
109 "Write forms are 'w' and 'w>>'"
110 "No file|No current filename"
$quote #
111 # File exists| File exists - use "w! %s" to overwrite#
$quote "
112 " File is read only"
113 " File is read only"
$quote #
114 # Use "w!" to write partial buffer#
$quote "
115 " [New file]"
116 " [Existing file]"
117 " [Incomplete last line]"
118 " Line too long"
119 "Too many nested sources"
120 "Open and visual must be used interactively"
121 "Global within global@not allowed"
122 "Global needs re|Missing regular expression for global"
123 "Global command too long"
124 "substitution loop"
125 "Fail|Substitute pattern match failed"
126 "Substitute needs re|Missing regular expression for substitute"
127 "No previous re|No previous regular expression"
128 "No previous substitute re|No previous substitute to repeat"
129 "Replacement pattern too long@- limit 256 characters"
130 "Line overflow@in substitute"
131 "%d subs|%d substitutions"
132 " on %d lines"
133 "Regular expressions cannot be delimited by letters or digits"
134 "No previous scan re|No previous scanning regular expression"
135 "No previous substitute re|No previous substitute regular expression"
136 "Badly formed re|Regular expression \\ must be followed by / or ?"
137 "No previous re|No previous regular expression"
138 "Missing closing delimiter@for regular expression"
139 "Re too complex|Regular expression too complicated"
140 "Unmatched \\(|More \\('s than \\)'s in regular expression"
141 "Awash in \\('s!|Too many \\('d subexressions in a regular expression"
142 "Extra \\)|More \\)'s than \\('s in regular expression"
143 "Bad number|Bad number in regular expression"
144 "Range endpoint too large|Range endpoint too large in regular expression"
145 "More than 2 numbers given in \\{~\\}"
146 "} expected after \\"
147 "First number exceeds second in \\{~\\}"
$quote
148 "\\digit" out of range
$quote "
149 "Replacement pattern contains &@- cannot use in re"
150 "Replacement pattern contains \\d@- cannot use in re"
151 "Illegal *|Can't * a \\( ... \\) in regular expression")
152 "Illegal *|Can't * a \\n in regular expression"
153 "Bad character class|Empty character class '[]' or '[^]' cannot match"
154 "Missing ]"
155 "No newlines in re's|Can't escape newlines into regular expressions"
156 "Bad \\n|\\n in regular expression with n greater than the number of \\('s"
157 "Badly formed re|Missing closing delimiter for regular expression"
158 "Re internal error"
159 "%s: No such option@- 'set all' gives all option values"
160 "Option %s is not a toggle"
161 "Missing =@in assignment to option %s"
162 "Digits required@after ="
163 "String too long@in option assignment"
164 "Can't change type of terminal from within open/visual"
165 "%s%s"
166 ""
167 "no"
168 "%s=%d"
169 "%s=%s"
170 "%d lines"
171 " %c%s"
172 "Nonzero address required@on this command"
173 "No lines@in the buffer"
174 "more "
175 "fewer "
176 ""
177 "%d %slines@in file after %s"
178 ""
179 "s"
180 "Out of memory@saving lines for undo - try using ed"
181 "emt trap, _ovno is %d @ - try again"
182 "\nInterrupt"
183 " Tmp file too large"
184 " Tmp file too large"
185 " Tmp file too large"
186 "Out of register space (ugh)"
187 "Nothing in register %c"
188 "Can't put partial line inside macro"
189 "Nothing in register %c"
190 "Register too long@to fit in memory"
191 "%s: Unknown terminal type"
192 "Incomplete shell escape command@- use 'shell' to get a shell"
193 "Command too long"
194 "No previous command@to substitute for !"
195 "No alternate filename@to substitute for #"
196 "No filename@to substitute for %%"
197 "[No write]|[No write since last change]"
198 "No previous command@to repeat"
199 "Can't make pipe for filter"
200 "No more processes"
201 "No %s!\n"
202 "Can't make pipe"
203 "No more processes"
204 " Can't make pipe for recovery"
205 " Can't fork to execute recovery"
206 " No recovery routine"
207 "Fail|Pattern not found on addressed line"
208 "Can't use open/visual unless open option is set"
209 "Recursive open/visual not allowed"
210 "[Using open mode]"
211 "Visual needs addressible cursor or upline capability"
212 Can't use visual on a terminal which overstrikes"
213 "Visual requires clear screen capability"
214 "Visual requires scrolling"
215 "Screen too large for internal buffer"
216 "Don't know enough about your terminal to use %s"
217 "Terminal too wide"
218 "Screen too large"
219 "Internal error: vscroll"
220 "No lines in buffer"
221 "Internal error: vredraw"
222 "Input read error"
223 "%d %sline"
224 "Macro too long@ - maybe recursive?"
225 "Infinite macro loop"
226 "Q gets ex command mode, :q leaves vi"
227 " "
228 "AAPPEND MODE"
229 "CCHANGE MODE"
230 "OOPEN MODE"
231 "RREPLACE MODE"
232 "rREPLACE 1 CHAR"
233 "IINSERT MODE"
234 "Infinite macro loop"
235 "Line too long"
236 "Line too long"
237 "Internal error: vclreol"
238 "Internal error: vgoto"
239 "Line too long for open"
240 "Line too long"
241 "No memory pool"
242 "Memory pool exhausted"
243 "failed to memory map anonymous area"
244 "failed to open /dev/zero"
245 "failed to memory map /dev/zero"
246 "chunk of memory already in free list"
247 "out of memory"
248 "(null pointer)"
249 "y"
$ exrecover
$set 2
1 " Wrong number of arguments to exrecover"
2 " [Dated: %s"
3 ", newest of %d saved]"
4 "]"
5 " Not enough core for lines"
6 "No files saved.\n"
7 "On %s at "
$quote #
8 # saved %d lines of file "%s"\n#
$quote "
9 " File not found"
10 " [Lost line(s):"
11 " %d"
12 "-%d"
13 " [Lost line(s):"
14 " %d"
15 "-%d"
16 "]"
17 " Tmp file too large"
$ expreserve
$set 3
1 "NOT super user\n"
2 "the system went down"
3 "the editor was killed"
4 "Subject: editor saved ``LOST''\n"
5 "You were editing a file without a name\n"
6 "at <%s> on the machine ``%s'' when %s.\n"
$quote #
7 #Since the file had no name, it has been named "LOST".\n#
$quote "
8 "Subject: editor saved ``%s''\n"
$quote #
9 #You were editing the file "%s"\n#
$quote "
10 "at <%s> on the machine ``%s''\n"
11 "when %s.\n"
12 "\nYou can retrieve most of your changes to this file\n"
$quote #
13 #using the "recover" command of the editor.\n#
14 #An easy way to do this is to give the command "vi -r %s".\n#
15 #This method also works using "ex" and "edit".\n#
$quote "
16 "Buffer format error\t"
17 "Buffer read error"
18 "Can't find a name\t"

132
config.h Normal file
View File

@ -0,0 +1,132 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* @(#)config.h 1.11 (gritter) 12/1/04
*/
/*
* Configurable settings for the ex editor.
*/
/*
* Maximum screen size in visual mode.
*
* Because the routine "alloca" is not portable, TUBESIZE
* bytes are allocated on the stack each time you go into visual
* and then never freed by the system. Thus if you have no terminals
* which are larger than 24 * 80 you may well want to make TUBESIZE
* smaller. TUBECOLS should stay at 160 since this defines the maximum
* length of opening on hardcopies and allows two lines of open on
* terminals like adm3's (glass tty's) where it switches to pseudo
* hardcopy mode when a line gets longer than 80 characters.
*/
#ifndef VMUNIX
#define TUBELINES 70 /* Number of screen lines for visual */
#define TUBECOLS 160 /* Number of screen columns for visual */
#define TUBESIZE 6000 /* Maximum screen size for visual */
#else /* VMUNIX */
#define TUBELINES 100
#define TUBECOLS 160
#define TUBESIZE 16000
#endif /* VMUNIX */
/*
* Various buffer sizes.
*/
#ifndef VMUNIX
#define ESIZE 128 /* Regular expression buffer size */
#define RHSSIZE 256 /* Size of rhs of substitute */
#define TAGSIZE 128 /* Tag length */
#define ONMSZ 64 /* Option name size */
#else /* VMUNIX */
#define ESIZE 1024
#define RHSSIZE 512
#define TAGSIZE 256
#define ONMSZ 256
#endif /* VMUNIX */
/*
* Intptr_t was introduced by SUSv2, and it is highly necessary to achieve
* portability between various processors. It is a signed integer type
* capable of holding pointers: sizeof(intptr_t) == sizeof(char *).
*
* Type Environment Typical systems
* int IP16 PDP11, 80286
* int ILP32 Most VAX, M68k, IA32, SPARC
* long LP32 Some IA32 and M68k
* long LP64 64 bit mode of IA64, SPARC v9, and Alpha
*
* The argument to the sbrk() system call has this type.
*/
#ifdef notdef
typedef int intptr_t;
#endif

2045
ex.1 Normal file

File diff suppressed because it is too large Load Diff

677
ex.c Normal file
View File

@ -0,0 +1,677 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
char *copyright =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
static char sccsid[] = "@(#)ex.c 1.34 (gritter) 12/1/04";
#endif /* DOSCCS */
#endif /* !lint */
/* from ex.c 7.5.1.1 (Berkeley) 8/12/86 */
#include "ex.h"
#include "ex_argv.h"
#include "ex_temp.h"
#include "ex_tty.h"
#ifdef TRACE
char tttrace[] = { '/','d','e','v','/','t','t','y','x','x',0 };
#endif
/*
* The code for ex is divided as follows:
*
* ex.c Entry point and routines handling interrupt, hangup
* signals; initialization code.
*
* ex_addr.c Address parsing routines for command mode decoding.
* Routines to set and check address ranges on commands.
*
* ex_cmds.c Command mode command decoding.
*
* ex_cmds2.c Subroutines for command decoding and processing of
* file names in the argument list. Routines to print
* messages and reset state when errors occur.
*
* ex_cmdsub.c Subroutines which implement command mode functions
* such as append, delete, join.
*
* ex_data.c Initialization of options.
*
* ex_get.c Command mode input routines.
*
* ex_io.c General input/output processing: file i/o, unix
* escapes, filtering, source commands, preserving
* and recovering.
*
* ex_put.c Terminal driving and optimizing routines for low-level
* output (cursor-positioning); output line formatting
* routines.
*
* ex_re.c Global commands, substitute, regular expression
* compilation and execution.
*
* ex_set.c The set command.
*
* ex_subr.c Loads of miscellaneous subroutines.
*
* ex_temp.c Editor buffer routines for main buffer and also
* for named buffers (Q registers if you will.)
*
* ex_tty.c Terminal dependent initializations from termcap
* data base, grabbing of tty modes (at beginning
* and after escapes).
*
* ex_unix.c Routines for the ! command and its variations.
*
* ex_v*.c Visual/open mode routines... see ex_v.c for a
* guide to the overall organization.
*/
static char *progname;
void
erropen(void)
{
close(1);
dup(2);
}
void
usage(void)
{
printf(catgets(catd, 1, 1, "\
Usage: %s [- | -s] [-l] [-L] [-R] [-r [file]] [-t tag]\n\
[-v] [-V] [-w size] [+cmd | -c cmd] file...\n"),
progname);
flush();
exitex(1);
}
void
needarg(int c)
{
erropen();
printf(catgets(catd, 1, 2,
"%s: option requires an argument -- %c\n"), progname, c);
usage();
}
void
invopt(int c)
{
erropen();
printf(catgets(catd, 1, 3, "%s: illegal option -- %c\n"), progname, c);
usage();
}
/*
* Return last component of unix path name p.
*/
char *
tailpath(register char *p)
{
register char *r;
for (r=p; *p; p++)
if (*p == '/')
r = p+1;
return(r);
}
/*
* Check ownership of file. Return nonzero if it exists and is owned by the
* user or the option sourceany is used
*/
int
iownit(char *file)
{
struct stat sb;
if (*file == '.' && value(EXRC) == 0)
return 0;
if (stat(file, &sb))
return 0;
if (value(SOURCEANY))
return 1;
if (sb.st_uid != getuid())
return 0;
if (sb.st_mode & (S_IWOTH | S_IWGRP))
return 0;
return 1;
}
shand
setsig(int signum, shand handler)
{
struct sigaction nact, oact;
nact.sa_handler = handler;
sigemptyset(&nact.sa_mask);
nact.sa_flags = 0;
if (signum == SIGALRM) {
#ifdef SA_INTERRUPT
nact.sa_flags |= SA_INTERRUPT;
#endif
/*EMPTY*/ ;
} else {
#ifdef SA_RESTART
nact.sa_flags |= SA_RESTART;
#endif
/*EMPTY*/ ;
}
if (sigaction(signum, &nact, &oact) != 0)
return SIG_ERR;
return oact.sa_handler;
}
/*
* Initialization, before editing a new file.
* Main thing here is to get a new buffer (in fileinit),
* rest is peripheral state resetting.
*/
void
init(void)
{
register int i;
fileinit();
dot = zero = truedol = unddol = dol = fendcore;
one = zero+1;
undkind = UNDNONE;
chng = 0;
edited = 0;
for (i = 0; i <= 'z'-'a'+1; i++)
names[i] = 1;
anymarks = 0;
}
/*
* Main procedure. Process arguments and then
* transfer control to the main command processing loop
* in the routine commands. We are entered as either "ex", "edit", "vi"
* or "view" and the distinction is made here. Actually, we are "vi" if
* there is a 'v' in our name, "view" is there is a 'w', and "edit" if
* there is a 'd' in our name. For edit we just diddle options;
* for vi we actually force an early visual command.
*/
int
main(register int ac, register char *av[])
{
#ifndef VMUNIX
char *erpath = EXSTRINGS;
#endif
char *cp = NULL;
register int c;
bool ivis;
bool fast = 0;
#ifdef TRACE
register char *tracef;
#endif
CLOBBGRD(ivis);
CLOBBGRD(fast);
CLOBBGRD(cp);
/*
* Initialize the built-in memory allocator.
*/
#ifdef VMUNIX
poolsbrk(0);
#endif
/*
* Immediately grab the tty modes so that we wont
* get messed up if an interrupt comes in quickly.
*/
gTTY(1);
normf = tty;
ppid = getpid();
/*
* Defend against d's, v's, w's, and a's in directories of
* path leading to our true name.
*/
av[0] = tailpath(av[0]);
/*
* Figure out how we were invoked: ex, edit, vi, view.
*/
ivis = any('v', av[0]); /* "vi" */
if (any('w', av[0])) /* "view" */
value(READONLY) = 1;
if (any('d', av[0])) { /* "edit" */
value(SHOWMODE) = 1;
/*
* I do not understand why novices should not
* switch to visual mode. So they can now. gritter
*/
/*value(OPEN) = 0;*/
value(REPORT) = 1;
value(MAGIC) = 0;
}
#ifndef VMUNIX
/*
* For debugging take files out of . if name is a.out.
*/
if (av[0][0] == 'a')
erpath = tailpath(erpath);
#endif /* !VMUNIX */
progname = av[0];
/*
* Open the error message file.
*/
draino();
#ifndef VMUNIX
erfile = open(erpath+4, O_RDONLY);
if (erfile < 0) {
erfile = open(erpath, O_RDONLY);
}
#endif /* !VMUNIX */
pstop();
/*
* Initialize interrupt handling.
*/
oldhup = signal(SIGHUP, SIG_IGN);
if (oldhup == SIG_DFL)
signal(SIGHUP, onhup);
oldquit = signal(SIGQUIT, SIG_IGN);
#ifdef SIGXFSZ
oldxfsz = signal(SIGXFSZ, SIG_IGN);
#endif
ruptible = signal(SIGINT, SIG_IGN) == SIG_DFL;
if (signal(SIGTERM, SIG_IGN) == SIG_DFL)
signal(SIGTERM, onhup);
#ifdef SIGEMT
if (signal(SIGEMT, SIG_IGN) == SIG_DFL)
signal(SIGEMT, onemt);
#endif
#ifdef BIT8
#ifndef ISO8859_1
setlocale(LC_CTYPE, "");
#endif
#endif
#ifdef MB_CUR_MAX
mb_cur_max = MB_CUR_MAX;
#else
mb_cur_max = 1;
#endif
#ifdef MB
TRIM = mb_cur_max > 1 ? 0x6fffffff : 0xff;
QUOTE = mb_cur_max > 1 ? 0x10000000 : 0x100;
#endif
#ifdef LANGMSG
setlocale(LC_MESSAGES, "");
catd = catopen(CATNAME, NL_CAT_LOCALE);
#endif
/*
* Process flag arguments.
*/
ac--, av++;
while (ac) {
if (av[0][0] == '+') {
firstpat = &av[0][1];
if (*firstpat == '\0')
needarg('+');
} else if (av[0][0] == '-') {
arggroup:
c = av[0][1];
if (c == 0
|| c == 's'
) {
hush = 1;
value(AUTOPRINT) = 0;
fast++;
} else switch (c) {
case '-':
if (av[0][2])
invopt('-');
ac--, av++;
goto argend;
case 'R':
value(READONLY) = 1;
break;
#ifdef TRACE
case 'T':
if (av[0][2] == 0)
tracef = "trace";
else {
tracef = tttrace;
tracef[8] = av[0][2];
if (tracef[8])
tracef[9] = av[0][3];
else
tracef[9] = 0;
}
trace = fopen(tracef, "w");
#define tracbuf NULL
if (trace == NULL)
printf(catgets(catd, 1, 4,
"Trace create error\n"));
else
setbuf(trace, tracbuf);
break;
#endif /* TRACE */
case 'c':
if (av[0][2] == '\0' && (av[1] == NULL
|| *av[1] == '-' || *av[1] == '+'))
needarg('c');
if (av[0][2]) {
firstpat = &av[0][2];
} else {
firstpat = av[1];
ac--, av++;
}
break;
case 'e':
ivis = 0;
break;
#ifdef LISPCODE
case 'l':
value(LISP) = 1;
value(SHOWMATCH) = 1;
break;
#endif
case 'L':
case 'r':
recov++;
break;
case 't':
if (ac > 1 && av[1][0] != '-' && av[1][0] != '+') {
ac--, av++;
tflag = 1;
safecp(lasttag, av[0], sizeof lasttag,
"argument to -t too long");
}
else if (av[0][2]) {
tflag = 1;
safecp(lasttag, av[0], sizeof lasttag,
"argument to -t too long");
} else
needarg('t');
break;
case 'v':
ivis = 1;
break;
case 'V':
verbose = 1;
break;
case 'w':
if (ac > 1 && av[1][0] != '-' && av[1][0] != '+')
cp = av[1];
else if (av[0][2])
cp = &av[0][2];
else
needarg('w');
defwind = atoi(cp);
break;
default:
invopt(c);
}
if (c && c != 'c' && c != 't' && c != 'w' && av[0][2]) {
av[0]++;
goto arggroup;
}
} else
break;
ac--, av++;
}
argend:
cntrlhm = catgets(catd, 1, 70, "^H discarded\n");
/*
* Initialize end of core pointers.
* Normally we avoid breaking back to fendcore after each
* file since this can be expensive (much core-core copying).
* If your system can scatter load processes you could do
* this as ed does, saving a little core, but it will probably
* not often make much difference.
*/
fendcore = (line *) sbrk(0);
endcore = fendcore - 2;
#ifdef SIGTSTP
if (!hush && signal(SIGTSTP, SIG_IGN) == SIG_DFL)
signal(SIGTSTP, onsusp), dosusp++;
#endif /* SIGTSTP */
/*
* If we are doing a recover and no filename
* was given, then execute an exrecover command with
* the -r option to type out the list of saved file names.
* Otherwise set the remembered file name to the first argument
* file name so the "recover" initial command will find it.
*/
if (recov) {
if (ac == 0) {
ppid = 0;
setrupt();
execl(EXRECOVER, "exrecover", "-r", (char *)0);
filioerr(EXRECOVER);
exitex(1);
}
safecp(savedfile, *av++, sizeof savedfile, "Filename too long");
ac--;
}
/*
* Initialize the argument list.
*/
argv0 = av;
argc0 = ac;
args0 = av[0];
erewind();
/*
* Initialize a temporary file (buffer) and
* set up terminal environment. Read user startup commands.
*/
if (setexit() == 0) {
setrupt();
intty = isatty(0);
value(PROMPT) = intty;
if (cp = getenv("SHELL"))
safecp(shell, cp, sizeof shell, "$SHELL too long");
if (fast || !intty)
setterm("dumb");
else {
gettmode();
if ((cp = getenv("TERM")) != 0 && *cp) {
setterm(cp);
}
}
}
if (setexit() == 0) {
/*
* This is necessary because 'if (setexit() == 0 && !fast)'
* is rejected on the Cray.
*/
if (fast)
goto skip;
if ((globp = getenv("EXINIT")) && *globp)
commands(1,1);
else {
globp = 0;
if ((cp = getenv("HOME")) != 0 && *cp) {
safecat(safecp(genbuf, cp, sizeof genbuf,
"$HOME too long"),
"/.exrc", sizeof genbuf,
"$HOME too long");
if (iownit(genbuf))
source(genbuf, 1);
}
}
/*
* Allow local .exrc too. This loses if . is $HOME,
* but nobody should notice unless they do stupid things
* like putting a version command in .exrc. Besides,
* they should be using EXINIT, not .exrc, right?
*
* This may not be done anymore. GR
*/
/*
* The getcwd() function is not present on very
* old Unix systems. So if this fails, comment out
* the following three lines or supply code e.g. from
* the `pwd' utility.
*/
if (cp == NULL || *cp == '\0'
|| getcwd(genbuf, MAXBSIZE) == NULL
|| strcmp(cp, genbuf) != 0)
if (iownit(".exrc"))
source(".exrc", 1);
}
skip: init(); /* moved after prev 2 chunks to fix directory option */
/*
* Initial processing. Handle tag, recover, and file argument
* implied next commands. If going in as 'vi', then don't do
* anything, just set initev so we will do it later (from within
* visual).
*/
if (setexit() == 0) {
if (recov)
globp = "recover";
else if (tflag)
globp = ivis ? "tag" : "tag|p";
else if (argc)
globp = "next";
if (ivis)
initev = globp;
else if (globp) {
inglobal = 1;
commands(1, 1);
inglobal = 0;
}
}
/*
* Vi command... go into visual.
* Strange... everything in vi usually happens
* before we ever "start".
*/
if (ivis) {
/*
* Don't have to be upward compatible with stupidity
* of starting editing at line $.
*/
if (dol > zero)
dot = one;
globp = "visual";
if (setexit() == 0)
commands(1, 1);
}
/*
* Clear out trash in state accumulated by startup,
* and then do the main command loop for a normal edit.
* If you quit out of a 'vi' command by doing Q or ^\,
* you also fall through to here.
*/
seenprompt = 1;
ungetchar(0);
globp = 0;
initev = 0;
setlastchar('\n');
setexit();
commands(0, 0);
cleanup(1);
exitex(0);
/*NOTREACHED*/
return 0;
}

580
ex.h Normal file
View File

@ -0,0 +1,580 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex.h 7.7.1.1 (Berkeley) 8/12/86
*
* @(#)ex.h 1.48 (gritter) 12/2/04
*/
/*
* Ex version 3 (see exact version in ex_version.c).
*
* Mark Horton, UC Berkeley
* Bill Joy, UC Berkeley
* November 1979
*
* Changes by Gunnar Ritter, Freiburg i. Br., Germany
* May 2000
*
* This file contains most of the declarations common to a large number
* of routines. The file ex_vis.h contains declarations
* which are used only inside the screen editor.
* The file config.h contains parameters which can be diddled per installation.
* The file ex_tune.h contains parameters which should be changed by
* maintainers only.
*
* The declarations relating to the argument list, regular expressions,
* the temporary file data structure used by the editor
* and the data describing terminals are each fairly substantial and
* are kept in the files ex_{argv,re,temp,tty}.h which
* we #include separately.
*
* If you are going to dig into ex, you should look at the outline of the
* distribution of the code into files at the beginning of ex.c and ex_v.c.
* Code which is similar to that of ed is lightly or undocumented in spots
* (e.g. the regular expression code). Newer code (e.g. open and visual)
* is much more carefully documented, and still rough in spots.
*
* Please forward bug reports to
*
* Mark Horton
* Computer Science Division, EECS
* EVANS HALL
* U.C. Berkeley 94704
* (415) 642-4948
* (415) 642-1024 (dept. office)
*
* or to csvax.mark@berkeley on the ARPA-net. I would particularly like to hear
* of additional terminal descriptions you add to the termcap data base.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#ifdef BIT8
#ifndef ISO8859_1
#include <locale.h>
#endif
#endif
#ifdef MB
#include <wchar.h>
#include <wctype.h>
#endif
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif
#include "config.h"
typedef void (*shand)(int);
#ifdef signal
#undef signal
#endif
#define signal(a, b) setsig((a), (b))
/*
* Avoid clobbering of automatic variables with an ANSI C compiler.
*/
#define CLOBBGRD(a) (void)(&(a));
#ifndef MB_LEN_MAX
#define MB_LEN_MAX 1
#endif
/*
* Feature dependency checks.
*/
#ifdef ISO8859_1
#ifndef BIT8
#define BIT8
#endif
#endif
#ifndef LISPCODE
#define LISPCODE
#endif
#ifndef CHDIR
#define CHDIR
#endif
#ifndef var
#define var extern
#endif
#ifndef VMUNIX
typedef short line;
#else
typedef int line;
#endif
typedef short bool;
#ifdef LARGEF
typedef off_t bloc;
#else
typedef short bloc;
#endif
#ifdef VMUNIX
#ifdef LARGEF
typedef off_t bbloc;
#else
typedef int bbloc;
#endif
#else
typedef short bbloc;
#endif
/*
* The editor does not normally use the standard i/o library. Because
* we expect the editor to be a heavily used program and because it
* does a substantial amount of input/output processing it is appropriate
* for it to call low level read/write primitives directly. In fact,
* when debugging the editor we use the standard i/o library. In any
* case the editor needs a printf which prints through "putchar" ala the
* old version 6 printf. Thus we normally steal a copy of the "printf.c"
* and "strout" code from the standard i/o library and mung it for our
* purposes to avoid dragging in the stdio library headers, etc if we
* are not debugging. Such a modified printf exists in "printf.c" here.
*/
#ifdef TRACE
# include <stdio.h>
var FILE *trace;
var bool trubble;
var bool techoin;
var char tracbuf[BUFSIZ];
# undef putchar
# undef getchar
#else /* !TRACE */
#ifndef BUFSIZ
#ifdef LINE_MAX
#define BUFSIZ LINE_MAX /* POSIX line size */
#else /* !LINE_MAX */
#ifdef VMUNIX
#define BUFSIZ 1024
#else /* !VMUNIX */
#ifdef u370
#define BUFSIZ 4096
#else /* !u370 */
#define BUFSIZ 512
#endif /* !u370 */
#endif
#endif /* !VMUNIX */
#endif /* !LINE_MAX */
#ifdef NULL
#undef NULL
#endif
#ifdef EOF
#undef EOF
#endif
#ifdef printf
#undef printf
#endif
#ifdef vprintf
#undef vprintf
#endif
#ifdef getchar
#undef getchar
#endif
#ifdef putchar
#undef putchar
#endif
#define NULL 0
#define EOF -1
#endif /* !TRACE */
typedef sigjmp_buf JMP_BUF;
#define SETJMP(a) sigsetjmp(a, 1)
#define LONGJMP(a, b) siglongjmp(a, b)
#ifndef MAXBSIZE
#define MAXBSIZE 8192 /* Same as in 4.2BSD */
#endif
#include "ex_tune.h"
#include "ex_vars.h"
/*
* Options in the editor are referred to usually by "value(name)" where
* name is all uppercase, i.e. "value(PROMPT)". This is actually a macro
* which expands to a fixed field in a static structure and so generates
* very little code. The offsets for the option names in the structure
* are generated automagically from the structure initializing them in
* ex_data.c... see the shell script "makeoptions".
*/
struct option {
char *oname;
char *oabbrev;
short otype; /* Types -- see below */
short odefault; /* Default value */
short ovalue; /* Current value */
char *osvalue;
};
#define ONOFF 0
#define NUMERIC 1
#define STRING 2 /* SHELL or DIRECTORY */
#define OTERM 3
#define value(a) options[a].ovalue
#define svalue(a) options[a].osvalue
extern struct option options[NOPTS + 1];
/*
* Character constants and bits
*
* The editor uses the QUOTE bit as a flag to pass on with characters
* e.g. to the putchar routine. The editor never uses a simple char variable.
* Only arrays of and pointers to characters are used and parameters and
* registers are never declared character.
*/
#ifdef CTRL
#undef CTRL
#endif
#define CTRL(c) ((c) & 037)
#define NL CTRL('j')
#define CR CTRL('m')
#define DELETE 0177 /* See also ATTN, QUIT in ex_tune.h */
#define ESCAPE 033
/*
* BIT8 and MB routines by Gunnar Ritter 2000, 2004.
*
* -DISO8859_1 enables all characters >= 0240 regardless of
* LC_CTYPE.
*/
#define MULTICOL 0x40000000
#if defined (MB)
/*
* This type is used to represent a single character cell.
*/
typedef int cell;
var int TRIM;
var int QUOTE;
#define INVBIT 0x20000000
#define printable(c) (((c)&INVBIT) == 0 && \
(mb_cur_max > 1 ? iswprint((c)&TRIM) : isprint((c)&TRIM)))
#define ext(c) (((c) & 0177) == 0)
#elif defined (BIT8)
typedef short cell;
#define QUOTE 0400
#define TRIM 0377
#ifndef ISO8859_1
#define printable(c) isprint((c)&TRIM)
#else /* ISO8859_1 */
#define printable(c) (((c) & 0140) && (c) != DELETE)
#endif /* ISO8859_1 */
#else /* !BIT8 */
typedef char cell;
#define QUOTE 0200
#define TRIM 0177
#endif /* !BIT8 */
/*
* Miscellaneous random variables used in more than one place
*/
var bool aiflag; /* Append/change/insert with autoindent */
var bool anymarks; /* We have used '[a-z] */
var int bsize; /* Block size for disk i/o */
var int chng; /* Warn "No write" */
var char *Command;
var short defwind; /* -w# change default window size */
var int dirtcnt; /* When >= MAXDIRT, should sync temporary */
var bool dosusp; /* Do SIGTSTP in visual when ^Z typed */
var bool edited; /* Current file is [Edited] */
var line *endcore; /* Last available core location */
extern bool endline; /* Last cmd mode command ended with \n */
#ifndef VMUNIX
var short erfile; /* Error message file unit */
#endif
var line *fendcore; /* First address in line pointer space */
var char file[FNSIZE]; /* Working file name */
var bool fixedzero; /* zero file size was fixed (for visual) */
var char genbuf[MAXBSIZE]; /* Working buffer when manipulating linebuf */
var bool hush; /* Command line option - was given, hush up! */
var char *globp; /* (Untyped) input string to command mode */
var bool holdcm; /* Don't cursor address */
var bool inappend; /* in ex command append mode */
var bool inglobal; /* Inside g//... or v//... */
var char *initev; /* Initial : escape for visual */
var bool inopen; /* Inside open or visual */
var char *input; /* Current position in cmd line input buffer */
var bool intty; /* Input is a tty */
var short io; /* General i/o unit (auto-closed on error!) */
extern short lastc; /* Last character ret'd from cmd input */
var bool laste; /* Last command was an "e" (or "rec") */
var char lastmac; /* Last macro called for ** */
var char lasttag[TAGSIZE]; /* Last argument to a tag command */
var char *linebp; /* Used in substituting in \n */
var char linebuf[LBSIZE]; /* The primary line buffer */
var bool listf; /* Command should run in list mode */
var line names['z'-'a'+2]; /* Mark registers a-z,' */
var int notecnt; /* Count for notify (to visual from cmd) */
var bool numberf; /* Command should run in number mode */
var char obuf[BUFSIZ]; /* Buffer for tty output */
var shand oldhup; /* Previous SIGHUP handler */
var shand oldquit; /* Previous SIGQUIT handler */
#ifdef SIGXFSZ
var shand oldxfsz; /* Previous SIGXFSZ handler */
#endif
var short oprompt; /* Saved during source */
extern unsigned short ospeed; /* Output speed (from gtty) */
var int otchng; /* Backup tchng to find changes in macros */
var short peekc; /* Peek ahead character (cmd mode input) */
var char *pkill[2]; /* Trim for put with ragged (LISP) delete */
var bool pfast; /* Have stty -nl'ed to go faster */
var pid_t pid; /* Process id of child */
var pid_t ppid; /* Process id of parent (e.g. main ex proc) */
var JMP_BUF resetlab; /* For error throws to top level (cmd mode) */
var pid_t rpid; /* Pid returned from wait() */
var bool recov; /* A `n' command is executed as `recov' */
var bool ruptible; /* Interruptible is normal state */
var bool seenprompt; /* 1 if have gotten user input */
var bool shudclob; /* Have a prompt to clobber (e.g. on ^D) */
var int status; /* Status returned from wait() */
var int tchng; /* If nonzero, then [Modified] */
extern int tfile; /* Temporary file unit */
var bool tflag; /* -t option given on command line */
var bool vcatch; /* Want to catch an error (open/visual) */
var bool verbose; /* -V option; print command input to stderr */
var JMP_BUF vreslab; /* For error throws to a visual catch */
var bool writing; /* 1 if in middle of a file write */
var int xchng; /* Suppresses multiple "No writes" in !cmd */
/*
* Macros
*/
#define CP(a, b) (ignore(movestr(a, b)))
/*
* FIXUNDO: do we want to mung undo vars?
* Usually yes unless in a macro or global.
*/
#define FIXUNDO (inopen >= 0 && (inopen || !inglobal))
#define ckaw() {if (chng && value(AUTOWRITE)) wop(0);}
#define copy(a,b,c) Copy((char *) (a), (char *) (b), (c))
#define eq(a, b) ((a) && (b) && strcmp(a, b) == 0)
#define getexit(a) copy(a, resetlab, sizeof (JMP_BUF))
#define lastchar() lastc
#define outchar(c) (*Outchar)(c)
#define pastwh() (ignore(skipwh()))
#define pline(no) (*Pline)(no)
#define reset() LONGJMP(resetlab,1)
#define resexit(a) copy(resetlab, a, sizeof (JMP_BUF))
#define setexit() SETJMP(resetlab)
#define setlastchar(c) lastc = c
#define ungetchar(c) peekc = c
#define CATCH vcatch = 1; if (SETJMP(vreslab) == 0) {
#define ONERR } else { vcatch = 0;
#define ENDCATCH } vcatch = 0;
/*
* Environment like memory
*/
var char altfile[FNSIZE]; /* Alternate file name */
extern char direct[ONMSZ]; /* Temp file goes here */
extern char shell[ONMSZ]; /* Copied to be settable */
extern char ttylongname[ONMSZ]; /* A long and pretty name */
var char uxb[UXBSIZE + 2]; /* Last !command for !! */
/*
* The editor data structure for accessing the current file consists
* of an incore array of pointers into the temporary file tfile.
* Each pointer is 15 bits (the low bit is used by global) and is
* padded with zeroes to make an index into the temp file where the
* actual text of the line is stored.
*
* To effect undo, copies of affected lines are saved after the last
* line considered to be in the buffer, between dol and unddol.
* During an open or visual, which uses the command mode undo between
* dol and unddol, a copy of the entire, pre-command buffer state
* is saved between unddol and truedol.
*/
var line *addr1; /* First addressed line in a command */
var line *addr2; /* Second addressed line */
var line *dol; /* Last line in buffer */
var line *dot; /* Current line */
var line *one; /* First line */
var line *truedol; /* End of all lines, including saves */
var line *unddol; /* End of undo saved lines */
var line *zero; /* Points to empty slot before one */
/*
* Undo information
*
* For most commands we save lines changed by salting them away between
* dol and unddol before they are changed (i.e. we save the descriptors
* into the temp file tfile which is never garbage collected). The
* lines put here go back after unddel, and to complete the undo
* we delete the lines [undap1,undap2).
*
* Undoing a move is much easier and we treat this as a special case.
* Similarly undoing a "put" is a special case for although there
* are lines saved between dol and unddol we don't stick these back
* into the buffer.
*/
var short undkind;
var line *unddel; /* Saved deleted lines go after here */
var line *undap1; /* Beginning of new lines */
var line *undap2; /* New lines end before undap2 */
var line *undadot; /* If we saved all lines, dot reverts here */
#define UNDCHANGE 0
#define UNDMOVE 1
#define UNDALL 2
#define UNDNONE 3
#define UNDPUT 4
extern int (*Outchar)(int);
extern void (*Pline)(int);
extern int (*Putchar)(int);
#define NOSTR (char *) 0
#define NOLINE (line *) 0
#define ignore(a) a
#define ignorf(a) a
#ifdef LANGMSG
#include <nl_types.h>
var nl_catd catd;
#else /* !LANGMSG */
#define catgets(a, b, c, d) (d)
#endif /* !LANGMSG */
var char *cntrlhm;
#include "ex_proto.h"
var int mb_cur_max;
#ifdef MB
#define nextc(c, s, n) (mb_cur_max > 1 && *(s) & 0200 ? \
((n) = mbtowi(&(c), (s), mb_cur_max), \
(n) = ((n) > 0 ? (n) : (n) < 0 ? (c=WEOF, 1) : 1)) :\
((c) = *(s) & 0377, (n) = 1))
#define colsc(c) (mb_cur_max > 1 && ((c)&0177) != (c) ? wcwidth(c) : 1)
#define skipleft(l, p) (mb_cur_max > 1 && ((p)[0]&0200 || \
(p)>(l) && (p)[-1]&0200) ? wskipleft(l, p) : -1)
#define skipright(l, p) (mb_cur_max > 1 && (p)[0]&0200 ? wskipright(l, p) : 1)
#define samechar(cp, c) (mb_cur_max > 1 && *(cp)&0200 ? wsamechar(cp, c) : \
(*(cp)&0377) == c)
#define xisdigit(c) (mb_cur_max > 1 ? iswdigit(c) : isdigit(c))
#define xisalpha(c) (mb_cur_max > 1 ? iswalpha(c) : isalpha(c))
#define xisalnum(c) (mb_cur_max > 1 ? iswalnum(c) : isalnum(c))
#define xisspace(c) (mb_cur_max > 1 ? iswspace(c) : isspace(c))
#define xisupper(c) (mb_cur_max > 1 ? iswupper(c) : isupper(c))
#define xislower(c) (mb_cur_max > 1 ? iswlower(c) : islower(c))
#define xtolower(c) (mb_cur_max > 1 ? towlower(c) : tolower(c))
#define xtoupper(c) (mb_cur_max > 1 ? towupper(c) : toupper(c))
#else /* !MB */
#define nextc(c, s, n) ((c) = *(s) & 0377, (n) = 1)
#define colsc(c) (1)
#define skipleft(l, p) (-1)
#define skipright(l, p) (1)
#define samechar(cp, c) (*(cp)&0377 == c)
#define xisdigit(c) isdigit(c)
#define xisalpha(c) isalpha(c)
#define xisalnum(c) isalnum(c)
#define xisspace(c) isspace(c)
#define xisupper(c) isupper(c)
#define xislower(c) islower(c)
#define xtolower(c) tolower(c)
#define xtoupper(c) toupper(c)
#endif /* !MB */

57
ex.spec Normal file
View File

@ -0,0 +1,57 @@
#
# Sccsid @(#)ex.spec 1.6 (gritter) 11/27/04
#
Summary: A port of the traditional ex/vi editors
Name: ex
Version: 041202
Release: 1
License: BSD
Source: %{name}-%{version}.tar.bz2
Group: System Environment/Base
Vendor: Gunnar Ritter <Gunnar.Ritter@pluto.uni-freiburg.de>
URL: <http://ex-vi.sourceforge.net>
BuildRoot: %{_tmppath}/%{name}-root
Requires: /etc/termcap
# prefix applies to bindir, libexecdir, and mandir.
%define prefix /usr
%define bindir %{prefix}/5bin
%define libexecdir %{prefix}/5lib
%define mandir %{prefix}/share/man/5man
%define preservedir /var/preserve
# install command
%define ucbinstall install
%define cflags -Os -fomit-frame-pointer
%define makeflags PREFIX=%{prefix} BINDIR=%{bindir} LIBEXECDIR=%{libexecdir} MANDIR=%{mandir} PRESERVEDIR=%{preservedir} INSTALL=%{ucbinstall} RPMCFLAGS="%{cflags}"
%description
This is a port of the traditional ex and vi editor implementation. It
was enhanced to support most of the additions in System V and POSIX.2,
and international character sets (including UTF-8).
%prep
rm -rf %{buildroot}
%setup
%build
make %{makeflags}
%install
make DESTDIR=%{buildroot} %{makeflags} install
%clean
cd ..; rm -rf %{_builddir}/%{name}-%{version}
rm -rf %{buildroot}
%files
%defattr(-,root,root)
%doc Changes LICENSE README TODO
%{bindir}/*
%{libexecdir}/*
%{mandir}/man1/*
%{preservedir}

399
ex_addr.c Normal file
View File

@ -0,0 +1,399 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_addr.c 1.9 (gritter) 11/23/04";
#endif
#endif /* not lint */
/* from ex_addr.c 7.3 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_re.h"
/*
* Routines for address parsing and assignment and checking of address bounds
* in command mode. The routine address is called from ex_cmds.c
* to parse each component of a command (terminated by , ; or the beginning
* of the command itself. It is also called by the scanning routine
* in ex_voperate.c from within open/visual.
*
* Other routines here manipulate the externals addr1 and addr2.
* These are the first and last lines for the current command.
*
* The variable bigmove remembers whether a non-local glitch of . was
* involved in an address expression, so we can set the previous context
* mark '' when such a motion occurs.
*/
static bool bigmove;
/*
* Set up addr1 and addr2 for commands whose default address is dot.
*/
void
setdot(void)
{
setdot1();
if (bigmove)
markDOT();
}
/*
* Call setdot1 to set up default addresses without ever
* setting the previous context mark.
*/
void
setdot1(void)
{
if (addr2 == 0)
addr1 = addr2 = dot;
if (addr1 > addr2) {
notempty();
error(catgets(catd, 1, 6,
"Addr1 > addr2|First address exceeds second"));
}
}
/*
* Ex allows you to say
* delete 5
* to delete 5 lines, etc.
* Such nonsense is implemented by setcount.
*/
void
setcount(void)
{
register int cnt;
pastwh();
if (!isdigit(peekchar())) {
setdot();
return;
}
addr1 = addr2;
setdot();
cnt = getnum();
if (cnt <= 0)
error(catgets(catd, 1, 7, "Bad count|Nonzero count required"));
addr2 += cnt - 1;
if (addr2 > dol)
addr2 = dol;
nonzero();
}
/*
* Parse a number out of the command input stream.
*/
int
getnum(void)
{
register int cnt;
for (cnt = 0; isdigit(peekcd());)
cnt = cnt * 10 + getchar() - '0';
return (cnt);
}
/*
* Set the default addresses for commands which use the whole
* buffer as default, notably write.
*/
void
setall(void)
{
if (addr2 == 0) {
addr1 = one;
addr2 = dol;
if (dol == zero) {
dot = zero;
return;
}
}
/*
* Don't want to set previous context mark so use setdot1().
*/
setdot1();
}
/*
* No address allowed on, e.g. the file command.
*/
void
setnoaddr(void)
{
if (addr2 != 0)
error(catgets(catd, 1, 8,
"No address allowed@on this command"));
}
/*
* Parse an address.
* Just about any sequence of address characters is legal.
*
* If you are tricky you can use this routine and the = command
* to do simple addition and subtraction of cardinals less
* than the number of lines in the file.
*/
line *
address(char *in_line)
{
register line *addr;
register int offset, c;
short lastsign;
bigmove = 0;
lastsign = 0;
offset = 0;
addr = 0;
for (;;) {
if (isdigit(peekcd())) {
if (addr == 0) {
addr = zero;
bigmove = 1;
}
loc1 = 0;
addr += offset;
offset = getnum();
if (lastsign >= 0)
addr += offset;
else
addr -= offset;
lastsign = 0;
offset = 0;
}
switch (c = getcd()) {
case '?':
case '/':
case '$':
case '\'':
case '\\':
bigmove++;
case '.':
if (addr || offset)
error(catgets(catd, 1, 9,
"Badly formed address"));
}
offset += lastsign;
lastsign = 0;
switch (c) {
case ' ':
case '\t':
continue;
case '+':
lastsign = 1;
if (addr == 0)
addr = dot;
continue;
case '^':
case '-':
lastsign = -1;
if (addr == 0)
addr = dot;
continue;
case '\\':
case '?':
case '/':
c = compile(c, 1);
notempty();
savere(&scanre);
addr = dot;
if (in_line && execute(0, dot)) {
if (c == '/') {
while (loc1 <= in_line) {
if (loc1 == loc2)
loc2++;
if (!execute(1, NULL))
goto nope;
}
break;
} else if (loc1 < in_line) {
char *last;
doques:
do {
last = loc1;
if (loc1 == loc2)
loc2++;
if (!execute(1, NULL))
break;
} while (loc1 < in_line);
loc1 = last;
break;
}
}
nope:
for (;;) {
if (c == '/') {
addr++;
if (addr > dol) {
if (value(WRAPSCAN) == 0)
error(catgets(catd, 1, 10, "No match to BOTTOM|Address search hit BOTTOM without matching pattern"));
addr = zero;
}
} else {
addr--;
if (addr < zero) {
if (value(WRAPSCAN) == 0)
error(catgets(catd, 1, 11, "No match to TOP|Address search hit TOP without matching pattern"));
addr = dol;
}
}
if (execute(0, addr)) {
if (in_line && c == '?') {
in_line = &linebuf[LBSIZE];
goto doques;
}
break;
}
if (addr == dot)
error(catgets(catd, 1, 12,
"Fail|Pattern not found"));
}
continue;
case '$':
addr = dol;
continue;
case '.':
addr = dot;
continue;
case '\'':
c = markreg(getchar());
if (c == 0)
error(catgets(catd, 1, 13,
"Marks are ' and a-z"));
addr = getmark(c);
if (addr == 0)
error(catgets(catd, 1, 14,
"Undefined mark@referenced"));
break;
default:
ungetchar(c);
if (offset) {
if (addr == 0)
addr = dot;
addr += offset;
loc1 = 0;
}
if (addr == 0) {
bigmove = 0;
return (0);
}
if (addr != zero)
notempty();
addr += lastsign;
if (addr < zero)
error(catgets(catd, 1, 15,
"Negative address@- first buffer line is 1"));
if (addr > dol)
error(catgets(catd, 1, 16,
"Not that many lines@in buffer"));
return (addr);
}
}
}
/*
* Abbreviations to make code smaller
* Left over from squashing ex version 1.1 into
* 11/34's and 11/40's.
*/
void
setCNL(void)
{
setcount();
newline();
}
void
setNAEOL(void)
{
setnoaddr();
eol();
}

105
ex_argv.h Normal file
View File

@ -0,0 +1,105 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex_argv.h 7.3 (Berkeley) 5/31/85
*
* @(#)ex_argv.h 1.8 (gritter) 11/23/04
*/
/*
* The current implementation of the argument list is poor,
* using an argv even for internally done "next" commands.
* It is not hard to see that this is restrictive and a waste of
* space. The statically allocated glob structure could be replaced
* by a dynamically allocated argument area space.
*/
var char **argv;
var char **argv0;
var char *args;
var char *args0;
var short argc;
var short argc0;
var short morargc; /* Used with "More files to edit..." */
var int firstln; /* From +lineno */
var char *firstpat; /* From +/pat */
/* Yech... */
struct glob {
short argc; /* Index of current file in argv */
short argc0; /* Number of arguments in argv */
char *argv[NARGS + 1]; /* WHAT A WASTE! */
char argspac[NCARGS + sizeof (int)];
};
var struct glob frob;
extern void gglob(struct glob *);

975
ex_cmds.c Normal file
View File

@ -0,0 +1,975 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_cmds.c 1.17 (gritter) 11/27/04";
#endif
#endif
/* from ex_cmds.c 7.10.1 (2.11BSD) 1996/11/23 */
#include "ex.h"
#include "ex_argv.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
bool pflag, nflag;
int poffset;
#define nochng() lchng = chng
/*
* Main loop for command mode command decoding.
* A few commands are executed here, but main function
* is to strip command addresses, do a little address oriented
* processing and call command routines to do the real work.
*/
void
commands(int noprompt, int exitoneof)
{
register line *addr;
register int c;
register int lchng;
int given;
int seensemi;
int cnt;
bool hadpr = 0;
resetflav();
nochng();
for (;;) {
/*
* If dot at last command
* ended up at zero, advance to one if there is a such.
*/
if (dot <= zero) {
dot = zero;
if (dol > zero)
dot = one;
}
shudclob = 0;
/*
* If autoprint or trailing print flags,
* print the line at the specified offset
* before the next command.
*/
if (pflag ||
lchng != chng && value(AUTOPRINT) && !inglobal && !inopen && endline) {
pflag = 0;
nochng();
if (dol != zero) {
addr1 = addr2 = dot + poffset;
if (addr1 < one || addr1 > dol)
error(catgets(catd, 1, 17,
"Offset out-of-bounds|Offset after command too large"));
setdot1();
goto print;
}
}
nochng();
/*
* Print prompt if appropriate.
* If not in global flush output first to prevent
* going into pfast mode unreasonably.
*/
if (inglobal == 0) {
flush();
if (!hush && value(PROMPT) && !globp && !noprompt && endline) {
putchar(':');
hadpr = 1;
}
TSYNC();
}
/*
* Gobble up the address.
* Degenerate addresses yield ".".
*/
addr2 = 0;
given = seensemi = 0;
do {
addr1 = addr2;
addr = address(0);
c = getcd();
if (addr == 0)
if (c == ',')
addr = dot;
else if (addr1 != 0) {
addr2 = dot;
break;
} else
break;
addr2 = addr;
given++;
if (c == ';') {
c = ',';
dot = addr;
seensemi = 1;
}
} while (c == ',');
if (c == '%') {
/* %: same as 1,$ */
addr1 = one;
addr2 = dol;
given = 2;
c = getchar();
}
if (addr1 == 0)
addr1 = addr2;
if (c == ':')
c = getchar();
/*
* Set command name for special character commands.
*/
tailspec(c);
/*
* If called via : escape from open or visual, limit
* the set of available commands here to save work below.
*/
if (inopen) {
if (c=='\n' || c=='\r' || c==CTRL('d') || c==EOF) {
if (addr2)
dot = addr2;
if (c == EOF)
return;
continue;
}
if (any(c, "o"))
notinvis:
tailprim(Command, 1, 1);
}
/* choice: */
switch (c) {
case 'a':
switch(peekchar()) {
case 'b':
/* abbreviate */
tail("abbreviate");
setnoaddr();
mapcmd(0, 1);
anyabbrs = 1;
continue;
case 'r':
/* args */
tail("args");
setnoaddr();
eol();
pargs();
continue;
}
/* append */
if (inopen)
goto notinvis;
tail("append");
setdot();
aiflag = exclam();
newline();
vmacchng(0);
deletenone();
setin(addr2);
inappend = 1;
ignore(append(gettty, addr2));
inappend = 0;
nochng();
continue;
case 'c':
switch (peekchar()) {
/* copy */
case 'o':
tail("copy");
vmacchng(0);
move();
continue;
#ifdef CHDIR
/* cd */
case 'd':
tail("cd");
goto changdir;
/* chdir */
case 'h':
ignchar();
if (peekchar() == 'd') {
register char *p;
tail2of("chdir");
changdir:
if (savedfile[0] == '/' || !value(WARN))
ignore(exclam());
else
ignore(quickly());
if (skipend()) {
p = getenv("HOME");
if (p == NULL)
error(catgets(catd, 1,
18, "Home directory unknown"));
} else
getone(), p = file;
eol();
if (chdir(p) < 0)
filioerr(p);
if (savedfile[0] != '/')
edited = 0;
continue;
}
if (inopen)
tailprim("change", 2, 1);
tail2of("change");
break;
#endif
default:
if (inopen)
goto notinvis;
tail("change");
break;
}
/* change */
aiflag = exclam();
setCNL();
vmacchng(0);
setin(addr1);
delete(0);
inappend = 1;
ignore(append(gettty, addr1 - 1));
inappend = 0;
nochng();
continue;
/* delete */
case 'd':
/*
* Caution: dp and dl have special meaning already.
*/
tail("delete");
c = cmdreg();
setCNL();
vmacchng(0);
if (c)
YANKreg(c);
delete(0);
appendnone();
continue;
/* edit */
/* ex */
case 'e':
tail(peekchar() == 'x' ? "ex" : "edit");
editcmd:
if (!exclam() && chng)
c = 'E';
filename(c);
if (c == 'E') {
ungetchar(lastchar());
ignore(quickly());
}
setnoaddr();
doecmd:
init();
addr2 = zero;
laste++;
synced();
rop(c);
#ifdef INCORB
tlaste();
#endif
laste = 0;
synced();
nochng();
continue;
/* file */
case 'f':
tail("file");
setnoaddr();
filename(c);
noonl();
/*
synctmp();
*/
continue;
/* global */
case 'g':
tail("global");
global(!exclam());
nochng();
continue;
/* insert */
case 'i':
if (inopen)
goto notinvis;
tail("insert");
setdot();
nonzero();
aiflag = exclam();
newline();
vmacchng(0);
deletenone();
setin(addr2);
inappend = 1;
ignore(append(gettty, addr2 - 1));
inappend = 0;
if (dot == zero && dol > zero)
dot = one;
nochng();
continue;
/* join */
case 'j':
tail("join");
c = exclam();
setcount();
nonzero();
newline();
vmacchng(0);
if (given < 2 && addr2 != dol)
addr2++;
join(c);
continue;
/* k */
case 'k':
casek:
pastwh();
c = getchar();
if (endcmd(c))
serror(catgets(catd, 1, 19,
"Mark what?|%s requires following letter"), Command);
newline();
if (!islower(c))
error(catgets(catd, 1, 20,
"Bad mark|Mark must specify a letter"));
setdot();
nonzero();
names[c - 'a'] = *addr2 &~ 01;
anymarks = 1;
continue;
/* list */
case 'l':
tail("list");
setCNL();
ignorf(setlist(1));
pflag = 0;
goto print;
case 'm':
if (peekchar() == 'a') {
ignchar();
if (peekchar() == 'p') {
/* map */
tail2of("map");
setnoaddr();
mapcmd(0, 0);
continue;
}
/* mark */
tail2of("mark");
goto casek;
}
/* move */
tail("move");
vmacchng(0);
move();
continue;
case 'n':
if (peekchar() == 'u') {
tail("number");
goto numberit;
}
/* next */
tail("next");
setnoaddr();
ckaw();
ignore(quickly());
if (getargs())
makargs();
next();
c = 'e';
filename(c);
if (recov)
goto recovnext;
goto doecmd;
/* open */
case 'o':
tail("open");
oop();
pflag = 0;
nochng();
continue;
case 'p':
case 'P':
switch (peekchar()) {
/* put */
case 'u':
tail("put");
setdot();
c = cmdreg();
eol();
vmacchng(0);
if (c)
putreg(c);
else
put(0);
continue;
case 'r':
ignchar();
if (peekchar() == 'e') {
/* preserve */
tail2of("preserve");
eol();
if (preserve() == 0)
error(catgets(catd, 1, 21,
"Preserve failed!"));
else
error(catgets(catd, 1, 22,
"File preserved."));
}
tail2of("print");
break;
default:
tail("print");
break;
}
/* print */
setCNL();
pflag = 0;
print:
nonzero();
if (CL && span() > TLINES) {
flush1();
vclear();
}
plines(addr1, addr2, 1);
continue;
/* quit */
case 'q':
tail("quit");
setnoaddr();
c = quickly();
eol();
if (!c)
quit:
nomore();
if (inopen) {
vgoto(WECHO, 0);
if (!ateopr())
vnfl();
else {
tostop();
}
flush();
setty(normf);
}
cleanup(1);
exitex(0);
case 'r':
if (peekchar() == 'e') {
ignchar();
switch (peekchar()) {
/* rewind */
case 'w':
tail2of("rewind");
setnoaddr();
if (!exclam()) {
ckaw();
if (chng && dol > zero)
error(catgets(catd,
1, 23, "No write@since last change (:rewind! overrides)"));
}
eol();
erewind();
next();
c = 'e';
ungetchar(lastchar());
filename(c);
goto doecmd;
/* recover */
case 'c':
tail2of("recover");
setnoaddr();
c = 'e';
if (!exclam() && chng)
c = 'E';
filename(c);
if (c == 'E') {
ungetchar(lastchar());
ignore(quickly());
}
recovnext:
init();
addr2 = zero;
laste++;
synced();
recover();
rop2();
revocer();
if (status == 0)
rop3(c);
if (dol != zero)
change();
#ifdef INCORB
tlaste();
#endif
laste = 0;
nochng();
continue;
}
tail2of("read");
} else
tail("read");
/* read */
if (savedfile[0] == 0 && dol == zero)
c = 'e';
pastwh();
vmacchng(0);
if (peekchar() == '!') {
setdot();
ignchar();
unix0(0);
filter(0);
continue;
}
filename(c);
rop(c);
nochng();
if (inopen && endline && addr1 > zero && addr1 < dol)
dot = addr1 + 1;
continue;
case 's':
switch (peekchar()) {
/*
* Caution: 2nd char cannot be c, g, or r
* because these have meaning to substitute.
*/
/* set */
case 'e':
tail("set");
setnoaddr();
set();
continue;
/* shell */
case 'h':
tail("shell");
setNAEOL();
vnfl();
putpad(TE);
flush();
unixwt(1, unixex("-i", (char *) 0, 0, 0));
vcontin(0);
continue;
/* source */
case 'o':
#ifdef notdef
if (inopen)
goto notinvis;
#endif
tail("source");
setnoaddr();
getone();
eol();
source(file, 0);
continue;
#ifdef SIGTSTP
/* stop, suspend */
case 't':
tail("stop");
goto suspend;
case 'u':
tail("suspend");
suspend:
if (!ldisc)
error(catgets(catd, 1, 24,
"Old tty driver|Not using new tty driver/shell"));
c = exclam();
eol();
if (!c)
ckaw();
#ifdef SIGTSTP
onsusp(SIGTSTP);
#endif
continue;
#endif
}
/* fall into ... */
/* & */
/* ~ */
/* substitute */
case '&':
case '~':
Command = "substitute";
if (c == 's')
tail(Command);
vmacchng(0);
if (!substitute(c))
pflag = 0;
continue;
/* t */
case 't':
if (peekchar() == 'a') {
tail("tag");
tagfind(exclam());
if (!inopen)
lchng = chng - 1;
else
nochng();
continue;
}
tail("t");
vmacchng(0);
move();
continue;
case 'u':
if (peekchar() == 'n') {
ignchar();
switch(peekchar()) {
/* unmap */
case 'm':
tail2of("unmap");
setnoaddr();
mapcmd(1, 0);
continue;
/* unabbreviate */
case 'a':
tail2of("unabbreviate");
setnoaddr();
mapcmd(1, 1);
anyabbrs = 1;
continue;
}
/* undo */
tail2of("undo");
} else
tail("undo");
setnoaddr();
markDOT();
c = exclam();
newline();
undo(c);
continue;
case 'v':
switch (peekchar()) {
case 'e':
/* version */
tail("version");
setNAEOL();
printver();
noonl();
continue;
/* visual */
case 'i':
tail("visual");
if (inopen) {
c = 'e';
goto editcmd;
}
vop();
pflag = 0;
nochng();
continue;
}
/* v */
tail("v");
global(0);
nochng();
continue;
/* write */
case 'w':
c = peekchar();
tail(c == 'q' ? "wq" : "write");
wq:
if (skipwh() && peekchar() == '!') {
pofix();
ignchar();
setall();
unix0(0);
filter(1);
} else {
setall();
wop(1);
nochng();
}
if (c == 'q')
goto quit;
continue;
/* xit */
case 'x':
tail("xit");
if (!chng)
goto quit;
c = 'q';
goto wq;
/* yank */
case 'y':
tail("yank");
c = cmdreg();
setcount();
eol();
vmacchng(0);
if (c)
YANKreg(c);
else
yank(0);
continue;
/* z */
case 'z':
zop(0);
pflag = 0;
continue;
/* * */
/* @ */
case '*':
case '@':
c = getchar();
if (c=='\n' || c=='\r')
ungetchar(c);
if (any(c, "@*\n\r"))
c = lastmac;
if (isupper(c))
c = tolower(c);
if (!islower(c))
error(catgets(catd, 1, 25, "Bad register"));
newline();
setdot();
cmdmac(c);
continue;
/* | */
case '|':
endline = 0;
goto caseline;
/* \n */
case '\n':
endline = 1;
caseline:
notempty();
if (addr2 == 0) {
if (UP != NOSTR && c == '\n' && !inglobal)
c = CTRL('k');
if (inglobal)
addr1 = addr2 = dot;
else {
if (dot == dol)
error(catgets(catd, 1, 26,
"At EOF|At end-of-file"));
addr1 = addr2 = dot + 1;
}
}
setdot();
nonzero();
if (seensemi)
addr1 = addr2;
getline(*addr1);
if (c == CTRL('k')) {
flush1();
destline--;
if (hadpr)
shudclob = 1;
}
plines(addr1, addr2, 1);
continue;
/* " */
case '"':
comment();
continue;
/* # */
case '#':
numberit:
setCNL();
ignorf(setnumb(1));
pflag = 0;
goto print;
/* = */
case '=':
newline();
setall();
if (inglobal == 2)
pofix();
printf("%d", lineno(addr2));
noonl();
continue;
/* ! */
case '!':
if (addr2 != 0) {
vmacchng(0);
unix0(0);
setdot();
filter(2);
} else {
unix0(1);
pofix();
putpad(TE);
flush();
unixwt(1, unixex("-c", uxb, 0, 0));
vclrech(1); /* vcontin(0); */
nochng();
}
continue;
/* < */
/* > */
case '<':
case '>':
for (cnt = 1; peekchar() == c; cnt++)
ignchar();
setCNL();
vmacchng(0);
shift(c, cnt);
continue;
/* ^D */
/* EOF */
case CTRL('d'):
case EOF:
if (exitoneof) {
if (addr2 != 0)
dot = addr2;
return;
}
if (!isatty(0)) {
if (intty)
/*
* Chtty sys call at UCB may cause a
* input which was a tty to suddenly be
* turned into /dev/null.
*/
onhup(SIGHUP);
return;
}
if (addr2 != 0) {
setlastchar('\n');
putnl();
}
if (dol == zero) {
if (addr2 == 0)
putnl();
notempty();
}
ungetchar(EOF);
zop(hadpr);
continue;
default:
if (!isalpha(c) && (c&0200) == 0)
break;
ungetchar(c);
tailprim("", 0, 0);
}
error(catgets(catd, 1, 27,
"What?|Unknown command character '%c'"), c);
}
}

673
ex_cmds2.c Normal file
View File

@ -0,0 +1,673 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_cmds2.c 1.17 (gritter) 12/1/04";
#endif
#endif
/* from ex_cmds2.c 7.4 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_argv.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
extern bool pflag, nflag; /* mjm: extern; also in ex_cmds.c */
extern int poffset; /* mjm: extern; also in ex_cmds.c */
/*
* Subroutines for major command loop.
*/
/*
* Is there a single letter indicating a named buffer next?
*/
int
cmdreg(void)
{
register int c = 0;
register int wh = skipwh();
if (wh && isalpha(peekchar()))
c = getchar();
return (c);
}
/*
* Tell whether the character ends a command
*/
int
endcmd(int ch)
{
switch (ch) {
case '\n':
case EOF:
endline = 1;
return (1);
case '|':
case '"':
endline = 0;
return (1);
}
return (0);
}
/*
* Insist on the end of the command.
*/
void
eol(void)
{
if (!skipend())
error(catgets(catd, 1, 28,
"Extra chars|Extra characters at end of command"));
ignnEOF();
}
/*
* Guts of the pre-printing error processing.
* If in visual and catching errors, then we dont mung up the internals,
* just fixing up the echo area for the print.
* Otherwise we reset a number of externals, and discard unused input.
*/
void
error0(void)
{
if (vcatch) {
if (splitw == 0)
fixech();
if (!SO || !SE)
dingdong();
return;
}
if (input) {
input = strend(input) - 1;
if (*input == '\n')
setlastchar('\n');
input = 0;
}
setoutt();
flush();
resetflav();
if (!SO || !SE)
dingdong();
if (inopen) {
/*
* We are coming out of open/visual ungracefully.
* Restore TCOLUMNS, undo, and fix tty mode.
*/
TCOLUMNS = OCOLUMNS;
undvis();
ostop(normf);
/* ostop should be doing this
putpad(VE);
putpad(KE);
*/
putnl();
}
inopen = 0;
holdcm = 0;
}
/*
* Post error printing processing.
* Close the i/o file if left open.
* If catching in visual then throw to the visual catch,
* else if a child after a fork, then exit.
* Otherwise, in the normal command mode error case,
* finish state reset, and throw to top.
*/
int
error1(char *str)
{
bool die;
if (io > 0) {
close(io);
io = -1;
}
die = (getpid() != ppid); /* Only children die */
inappend = inglobal = 0;
globp = NULL, vmacp = NULL, vglobp = NULL;
if (vcatch && !die) {
inopen = 1;
vcatch = 0;
if (str)
noonl();
fixol();
LONGJMP(vreslab,1);
}
if (str && !vcatch)
putNFL();
if (die)
exitex(1);
lseek(0, (off_t)0, SEEK_END);
if (inglobal)
setlastchar('\n');
while (lastchar() != '\n' && lastchar() != EOF)
ignchar();
ungetchar(0);
endline = 1;
reset();
}
/*
* Print out the message in the error message file at str,
* with i an integer argument to printf.
*/
/*VARARGS2*/
void
error(char *str, ...)
{
va_list ap;
error0();
va_start(ap, str);
vmerror(str, ap);
va_end(ap);
if (writing) {
serror(catgets(catd, 1, 29,
" [Warning - %s is incomplete]"), file);
writing = 0;
}
error1(str);
}
/*
* Same as error(), but using a va_list as argument.
*/
void
verror(char *str, va_list ap)
{
error0();
vmerror(str, ap);
error(NULL);
if (writing) {
serror(catgets(catd, 1, 29,
" [Warning - %s is incomplete]"), file);
writing = 0;
}
error1(str);
}
/*
* Rewind the argument list.
*/
void
erewind(void)
{
argc = argc0;
argv = argv0;
args = args0;
if (argc > 1 && !hush) {
printf(mesg(catgets(catd, 1, 30, "%d files@to edit")), argc);
if (inopen)
putchar(' ');
else
putNFL();
}
}
void
fixol(void)
{
if (Outchar != vputchar) {
flush();
if (state == ONEOPEN || state == HARDOPEN)
outline = destline = 0;
Outchar = vputchar;
vcontin(1);
} else {
if (destcol)
vclreol();
vclean();
}
}
/*
* Does an ! character follow in the command stream?
*/
int
exclam(void)
{
if (peekchar() == '!') {
ignchar();
return (1);
}
return (0);
}
/*
* Make an argument list for e.g. next.
*/
void
makargs(void)
{
gglob(&frob);
argc0 = frob.argc0;
argv0 = frob.argv;
args0 = argv0[0];
erewind();
}
/*
* Advance to next file in argument list.
*/
void
next(void)
{
extern short isalt; /* defined in ex_io.c */
if (argc == 0)
error(catgets(catd, 1, 31, "No more files@to edit"));
morargc = argc;
isalt = (strcmp(altfile, args)==0) + 1;
if (savedfile[0])
strcpy(altfile, savedfile);
safecp(savedfile, args, sizeof savedfile, "File name too long");
argc--;
args = argv ? *++argv : strend(args) + 1;
}
/*
* Eat trailing flags and offsets after a command,
* saving for possible later post-command prints.
*/
void
newline(void)
{
register int c;
resetflav();
for (;;) {
c = getchar();
switch (c) {
case '^':
case '-':
poffset--;
break;
case '+':
poffset++;
break;
case 'l':
listf++;
break;
case '#':
nflag++;
break;
case 'p':
listf = 0;
break;
case ' ':
case '\t':
continue;
case '"':
comment();
setflav();
return;
default:
if (!endcmd(c))
serror(catgets(catd, 1, 32,
"Extra chars|Extra characters at end of \"%s\" command"), Command);
if (c == EOF)
ungetchar(c);
setflav();
return;
}
pflag++;
}
}
/*
* Before quit or respec of arg list, check that there are
* no more files in the arg list.
*/
void
nomore(void)
{
if (argc == 0 || morargc == argc)
return;
morargc = argc;
merror(catgets(catd, 1, 33, "%d more file"), argc);
serror(catgets(catd, 1, 34, "%s@to edit"), plural((long) argc));
}
/*
* Before edit of new file check that either an ! follows
* or the file has not been changed.
*/
int
quickly(void)
{
if (exclam())
return (1);
if (chng && dol > zero) {
/*
chng = 0;
*/
xchng = 0;
error(catgets(catd, 1, 35,
"No write@since last change (:%s! overrides)"), Command);
}
return (0);
}
/*
* Reset the flavor of the output to print mode with no numbering.
*/
void
resetflav(void)
{
if (inopen)
return;
listf = 0;
nflag = 0;
pflag = 0;
poffset = 0;
setflav();
}
/*
* Print an error message with a %s type argument to printf.
* Message text comes from error message file.
*/
void
serror(char *str, ...)
{
va_list ap;
if (str == NULL)
return;
va_start(ap, str);
error0();
vsmerror(str, ap);
error1(str);
va_end(ap);
}
/*
* Set the flavor of the output based on the flags given
* and the number and list options to either number or not number lines
* and either use normally decoded (ARPAnet standard) characters or list mode,
* where end of lines are marked and tabs print as ^I.
*/
void
setflav(void)
{
if (inopen)
return;
setnumb(nflag || value(NUMBER));
setlist(listf || value(LIST));
setoutt();
}
/*
* Skip white space and tell whether command ends then.
*/
int
skipend(void)
{
pastwh();
return (endcmd(peekchar()) && peekchar() != '"');
}
/*
* Set the command name for non-word commands.
*/
void
tailspec(int c)
{
static char foocmd[2];
foocmd[0] = c;
Command = foocmd;
}
/*
* Try to read off the rest of the command word.
* If alphabetics follow, then this is not the command we seek.
*/
void
tail(char *comm)
{
tailprim(comm, 1, 0);
}
void
tail2of(char *comm)
{
tailprim(comm, 2, 0);
}
char tcommand[20];
void
tailprim(register char *comm, int xi, bool notinvis)
{
register char *cp;
register int c;
int i = xi;
Command = comm;
for (cp = tcommand; i > 0; i--)
*cp++ = *comm++;
while (*comm && peekchar() == *comm)
*cp++ = getchar(), comm++;
c = peekchar();
if (notinvis || isalpha(c)
#ifdef BIT8
|| xi == 0 && (c&(0200|QUOTE)) == 0200
#endif
) {
/*
* Of the trailing lp funny business, only dl and dp
* survive the move from ed to ex.
*/
if (tcommand[0] == 'd' && any(c, "lp"))
goto ret;
if (tcommand[0] == 's' && any(c, "gcr"))
goto ret;
while (cp < &tcommand[19] && (c = peekchar(),
isalpha(c)
#ifdef BIT8
|| xi == 0 && (c&(0200|QUOTE)) == 0200
#endif
))
*cp++ = getchar();
*cp = 0;
if (notinvis)
serror(catgets(catd, 1, 36,
"What?|%s: No such command from open/visual"), tcommand);
else
serror(catgets(catd, 1, 37,
"What?|%s: Not an editor command"), tcommand);
}
ret:
*cp = 0;
}
/*
* Continue after a : command from open/visual.
*/
void
vcontin(bool ask)
{
if (vcnt > 0)
vcnt = -vcnt;
if (inopen) {
if (state != VISUAL) {
/*
* We don't know what a shell command may have left on
* the screen, so we move the cursor to the right place
* and then put out a newline. But this makes an extra
* blank line most of the time so we only do it for :sh
* since the prompt gets left on the screen.
*
* BUG: :!echo longer than current line \\c
* will screw it up, but be reasonable!
*/
if (state == CRTOPEN) {
termreset();
vgoto(WECHO, 0);
}
if (!ask) {
putch('\r');
putch('\n');
}
return;
}
if (ask) {
merror(catgets(catd, 1, 38,
"[Hit return to continue] "));
flush();
}
if (ask) {
#ifdef EATQS
/*
* Gobble ^Q/^S since the tty driver should be eating
* them (as far as the user can see)
*/
while (peekkey(0) == CTRL('Q')
|| peekkey() == CTRL('S'))
ignore(getkey());
#endif
if(getkey() == ':') {
/* Ugh. Extra newlines, but no other way */
putch('\n');
outline = WECHO;
ungetkey(':');
}
}
vclrech(1);
if (Peekkey != ':') {
putpad(TI);
tostart();
/* replaced by ostart.
putpad(VS);
putpad(KS);
*/
}
}
}
/*
* Put out a newline (before a shell escape)
* if in open/visual.
*/
void
vnfl(void)
{
if (inopen) {
if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
vclean();
else
vmoveitup(1, 0);
vgoto(WECHO, 0);
vclrcell(vtube[WECHO], WCOLS);
tostop();
/* replaced by the ostop above
putpad(VE);
putpad(KE);
*/
}
flush();
}

1431
ex_cmdsub.c Normal file

File diff suppressed because it is too large Load Diff

170
ex_data.c Normal file
View File

@ -0,0 +1,170 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_data.c 1.14 (gritter) 11/23/04";
#endif
#endif
/* from ex_data.c 7.5 (Berkeley) 8/29/85 */
#include "ex.h"
#include "ex_tty.h"
/*
* Initialization of option values.
* The option #defines in ex_vars.h are made
* from this file by the script makeoptions.
*
* These initializations are done char by char instead of as strings
* to confuse xstr so it will leave them alone.
*/
#ifdef notdef
char direct[ONMSZ] =
{'/', 't', 'm', 'p'};
#else
char direct[ONMSZ] =
{'/', 'v', 'a', 'r', '/', 't', 'm', 'p' };
#endif
char paragraphs[ONMSZ] = {
'I', 'P', 'L', 'P', 'P', 'P', 'Q', 'P', /* -ms macros */
'P', ' ', 'L', 'I', /* -mm macros */
'p', 'p', 'l', 'p', 'i', 'p', /* -me macros */
'b', 'p' /* bare nroff */
};
char sections[ONMSZ] = {
'N', 'H', 'S', 'H', /* -ms macros */
'H', ' ', 'H', 'U', /* -mm macros */
'n', 'h', 's', 'h' /* -me macros */
};
char shell[ONMSZ] =
{ '/', 'b', 'i', 'n', '/', 's', 'h' };
char tags[ONMSZ] = {
't', 'a', 'g', 's', ' ',
'/', 'u', 's', 'r', '/', 'l', 'i', 'b', '/', 't', 'a', 'g', 's'
};
char ttylongname[ONMSZ] =
{ 'd', 'u', 'm', 'b' };
short TCOLUMNS = 80;
short TLINES = 24;
struct option options[NOPTS + 1] = {
{ "autoindent", "ai", ONOFF, 0, 0, 0, },
{ "autoprint", "ap", ONOFF, 1, 1, 0, },
{ "autowrite", "aw", ONOFF, 0, 0, 0, },
{ "beautify", "bf", ONOFF, 0, 0, 0, },
{ "directory", "dir", STRING, 0, 0, direct, },
{ "edcompatible","ed", ONOFF, 0, 0, 0, },
{ "errorbells", "eb", ONOFF, 0, 0, 0, },
{ "exrc", "ex", ONOFF, 0, 0, 0, },
{ "flash", "fl", ONOFF, 1, 1, 0, },
{ "hardtabs", "ht", NUMERIC, 8, 8, 0, },
{ "ignorecase", "ic", ONOFF, 0, 0, 0, },
{ "lisp", 0, ONOFF, 0, 0, 0, },
{ "list", 0, ONOFF, 0, 0, 0, },
{ "magic", 0, ONOFF, 1, 1, 0, },
{ "mesg", 0, ONOFF, 1, 1, 0, },
{ "modelines", "ml", ONOFF, 0, 0, 0, },
{ "number", "nu", ONOFF, 0, 0, 0, },
{ "open", 0, ONOFF, 1, 1, 0, },
{ "optimize", "opt", ONOFF, 0, 0, 0, },
{ "paragraphs", "para", STRING, 0, 0, paragraphs, },
{ "prompt", 0, ONOFF, 1, 1, 0, },
{ "readonly", "ro", ONOFF, 0, 0, 0, },
{ "redraw", 0, ONOFF, 0, 0, 0, },
{ "remap", 0, ONOFF, 1, 1, 0, },
{ "report", 0, NUMERIC, 5, 5, 0, },
{ "scroll", "scr", NUMERIC, 12, 12, 0, },
{ "sections", "sect", STRING, 0, 0, sections, },
{ "shell", "sh", STRING, 0, 0, shell, },
{ "shiftwidth", "sw", NUMERIC, TABS, TABS, 0, },
{ "showmatch", "sm", ONOFF, 0, 0, 0, },
{ "showmode", "smd", ONOFF, 0, 0, 0, },
{ "slowopen", "slow", ONOFF, 0, 0, 0, },
{ "sourceany", 0, ONOFF, 0, 0, 0, },
{ "tabstop", "ts", NUMERIC, TABS, TABS, 0, },
{ "taglength", "tl", NUMERIC, 0, 0, 0, },
{ "tags", "tag", STRING, 0, 0, tags, },
{ "term", 0, OTERM, 0, 0, ttylongname, },
{ "terse", 0, ONOFF, 0, 0, 0, },
{ "timeout", "to", ONOFF, 1, 1, 0, },
{ "ttytype", "tty", OTERM, 0, 0, ttylongname, },
{ "warn", 0, ONOFF, 1, 1, 0, },
{ "window", "wi", NUMERIC, 23, 23, 0, },
{ "wrapscan", "ws", ONOFF, 1, 1, 0, },
{ "wrapmargin", "wm", NUMERIC, 0, 0, 0, },
{ "writeany", "wa", ONOFF, 0, 0, 0, },
{ 0, 0, 0, 0, 0, 0, }
};

98
ex_extern.c Normal file
View File

@ -0,0 +1,98 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_extern.c 1.6 (gritter) 11/23/04";
#endif
#endif
/* from ex_extern.c 7.4 (Berkeley) 6/7/85 */
/*
* Provide defs of the global variables.
* This crock is brought to you by the turkeys
* who broke Unix on the Bell Labs 3B machine,
* all in the name of "but that's what the C
* book says!"
*/
# define var /* nothing */
# include "ex.h"
# include "ex_argv.h"
# include "ex_re.h"
# include "ex_temp.h"
# include "ex_tty.h"
/* # include "ex_tune.h" */
# include "ex_vars.h"
# include "ex_vis.h"

355
ex_get.c Normal file
View File

@ -0,0 +1,355 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_get.c 1.16 (gritter) 11/24/04";
#endif
#endif
/* from ex_get.c 7.6 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_tty.h"
/*
* Input routines for command mode.
* Since we translate the end of reads into the implied ^D's
* we have different flavors of routines which do/don't return such.
*/
static bool junkbs;
short lastc = '\n';
void
ignchar(void)
{
ignore(getchar());
}
int
getach(void)
{
register int c;
static char in_line[BUFSIZ];
/* struct stat statb; */
c = peekc;
if (c != 0) {
peekc = 0;
return (c);
}
if (globp) {
if (*globp)
return (*globp++&0377);
globp = 0;
return (lastc = EOF);
}
top:
if (input) {
if (c = *input++&0377) {
if (verbose && !intty)
write(2, &input[-1], 1);
if (c &= TRIM)
return (lastc = c);
goto top;
}
input = 0;
}
flush();
if (intty) {
c = read(0, in_line, sizeof in_line - 4);
if (c < 0)
return (lastc = EOF);
if (c == 0 || in_line[c-1] != '\n')
in_line[c++] = CTRL('d');
if (in_line[c-1] == '\n')
noteinp();
in_line[c] = 0;
for (c--; c >= 0; c--)
if (in_line[c] == 0)
#ifndef BIT8
in_line[c] = QUOTE;
#else
in_line[c] = '\200';
#endif
input = in_line;
goto top;
}
c = read(0, in_line, sizeof in_line - 1);
if(c <= 0)
return(lastc = EOF);
in_line[c] = '\0';
input = in_line;
goto top;
}
int
getchar(void)
{
register int c;
do
c = getcd();
while (!globp && c == CTRL('d'));
return (c);
}
void
checkjunk(int c)
{
if (junkbs == 0 && c == '\b') {
write(2, cntrlhm, 13);
junkbs = 1;
}
}
int
getcd(void)
{
register int c;
again:
c = getach();
if (c == EOF)
return (c);
c &= TRIM;
if (!inopen)
if (!globp && c == CTRL('d'))
setlastchar('\n');
else if (junk(c)) {
checkjunk(c);
goto again;
}
return (c);
}
int
peekchar(void)
{
if (peekc == 0)
peekc = getchar();
return (peekc);
}
int
peekcd(void)
{
if (peekc == 0)
peekc = getcd();
return (peekc);
}
/*
* Crunch the indent.
* Hard thing here is that in command mode some of the indent
* is only implicit, so we must seed the column counter.
* This should really be done differently so as to use the whitecnt routine
* and also to hack indenting for LISP.
*/
int
smunch(register int col, char *ocp)
{
register char *cp;
cp = ocp;
for (;;)
switch (*cp++) {
case ' ':
col++;
continue;
case '\t':
col += value(TABSTOP) - (col % value(TABSTOP));
continue;
default:
cp--;
CP(ocp, cp);
return (col);
}
}
/*
* Input routine for insert/append/change in command mode.
* Most work here is in handling autoindent.
*/
static short lastin;
int
gettty(void)
{
register int c = 0;
register char *cp = genbuf;
char hadup = 0;
int offset = Pline == numbline ? 8 : 0;
int ch;
if (intty && !inglobal) {
if (offset) {
holdcm = 1;
printf(" %4d ", lineDOT() + 1);
flush();
holdcm = 0;
}
if (value(AUTOINDENT) ^ aiflag) {
holdcm = 1;
#ifdef LISPCODE
if (value(LISP))
lastin = lindent(dot + 1);
#endif
tab(lastin + offset);
while ((c = getcd()) == CTRL('d')) {
if (lastin == 0 && isatty(0) == -1) {
holdcm = 0;
return (EOF);
}
lastin = backtab(lastin);
tab(lastin + offset);
}
switch (c) {
case '^':
case '0':
ch = getcd();
if (ch == CTRL('d')) {
if (c == '0')
lastin = 0;
if (!OS) {
putchar('\b' | QUOTE);
putchar(' ' | QUOTE);
putchar('\b' | QUOTE);
}
tab(offset);
hadup = 1;
c = getchar();
} else
ungetchar(ch);
break;
case '.':
if (peekchar() == '\n') {
ignchar();
noteinp();
holdcm = 0;
return (EOF);
}
break;
case '\n':
hadup = 1;
break;
}
}
flush();
holdcm = 0;
}
if (c == 0)
c = getchar();
while (c != EOF && c != '\n') {
if (cp > &genbuf[LBSIZE - 2])
error(catgets(catd, 1, 71, "Input line too long"));
*cp++ = c;
c = getchar();
}
if (c == EOF) {
if (inglobal)
ungetchar(EOF);
return (EOF);
}
*cp = 0;
cp = linebuf;
if ((value(AUTOINDENT) ^ aiflag) && hadup == 0 && intty && !inglobal) {
lastin = c = smunch(lastin, genbuf);
for (c = lastin; c >= value(TABSTOP); c -= value(TABSTOP))
*cp++ = '\t';
for (; c > 0; c--)
*cp++ = ' ';
}
CP(cp, genbuf);
if (linebuf[0] == '.' && linebuf[1] == 0)
return (EOF);
return (0);
}
void
setin(line *addr)
{
if (addr == zero)
lastin = 0;
else
getline(*addr), lastin = smunch(0, linebuf);
}

1104
ex_io.c Normal file

File diff suppressed because it is too large Load Diff

568
ex_proto.h Normal file
View File

@ -0,0 +1,568 @@
/*
*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
* @(#)ex_proto.h 1.24 (gritter) 12/1/04
*/
/*
* Function type definitions
*/
#define join xjoin
#define word xword
#define getline xgetline
/* ex.c */
extern void erropen(void);
extern void usage(void);
extern void needarg(int);
extern void invopt(int);
extern char *tailpath(register char *);
extern int iownit(char *);
extern shand setsig(int, shand);
extern void init(void);
/* ex_addr.c */
extern void setdot(void);
extern void setdot1(void);
extern void setcount(void);
extern int getnum(void);
extern void setall(void);
extern void setnoaddr(void);
extern line *address(char *);
extern void setCNL(void);
extern void setNAEOL(void);
/* ex_cmds.c */
extern void commands(int, int);
/* ex_cmds2.c */
extern int cmdreg(void);
extern int endcmd(int);
extern void eol(void);
extern void error0(void);
extern int error1(char *);
extern void verror(char *, va_list);
extern void error(char *, ...);
extern void erewind(void);
extern void fixol(void);
extern int exclam(void);
extern void makargs(void);
extern void next(void);
extern void newline(void);
extern void nomore(void);
extern int quickly(void);
extern void resetflav(void);
extern void serror(char *, ...);
extern void setflav(void);
extern int skipend(void);
extern void tailspec(int);
extern void tail(char *);
extern void tail2of(char *);
extern void tailprim(register char *, int, bool);
extern void vcontin(bool);
extern void vnfl(void);
/* ex_cmdsub.c */
extern int append(int (*)(void), line *);
extern void appendnone(void);
extern void pargs(void);
extern void delete(int);
extern void deletenone(void);
extern void squish(void);
extern void join(int);
extern void move1(int, line *);
extern void move(void);
extern int getcopy(void);
extern int getput(void);
extern void put(int);
extern void pragged(int);
extern void shift(int, int);
extern void tagfind(bool);
extern void yank(int);
extern void zop(int);
extern void zop2(register int, register int);
extern void plines(line *, register line *, bool);
extern void pofix(void);
extern void somechange(void);
extern void undo(bool);
extern void mapcmd(int, int);
extern void cmdmac(char);
/* ex_data.c */
/* ex_extern.c */
/* ex_get.c */
extern void ignchar(void);
extern int getach(void);
extern int getchar(void);
extern void checkjunk(int);
extern int getcd(void);
extern int peekchar(void);
extern int peekcd(void);
extern int smunch(register int, char *);
extern int gettty(void);
extern void setin(line *);
/* ex_io.c */
extern void filename(int);
extern int getargs(void);
extern int gscan(void);
extern void getone(void);
extern int samei(struct stat *, char *);
extern void rop(int);
extern void rop2(void);
extern int iostats(void);
extern void rop3(int);
extern int edfile(void);
extern void wop(bool);
extern int getfile(void);
extern void putfile(int);
extern void wrerror(void);
extern void source(char *, bool);
extern void clrstats(void);
extern void checkmodeline(char *);
#ifdef MB
extern int mbtowi(int *c, const char *s, size_t n);
extern int widthok(int c);
extern int GETWC(char *);
#endif /* MB */
/* ex_put.c */
extern int (*setlist(int))(int);
extern void (*setnumb(int))(int);
extern int listchar(int);
extern int normchar(register int);
extern void slobber(int);
extern void numbline(int);
extern void normline(int);
extern int putchar(int);
extern int termchar(int);
extern void flush2(void);
extern void flush(void);
extern void flush1(void);
extern int plodput(int);
extern int plod(int);
extern void fgoto(void);
extern void tab(int);
extern void noteinp(void);
extern void termreset(void);
extern void draino(void);
extern void flusho(void);
extern void putnl(void);
extern void putS(char *);
extern int putch(int);
extern void putpad(char *);
extern void setoutt(void);
extern void vlprintf(char *, va_list);
extern void lprintf(char *, ...);
extern void putNFL(void);
extern void sTTY(int);
extern void pstart(void);
extern void pstop(void);
extern void ttcharoff(void);
extern struct termios ostart(void);
extern void normal(struct termios);
/* ex_re.c */
extern void global(int);
extern void gdelete(void);
extern int substitute(int);
extern int compsub(int);
extern void comprhs(int);
extern int getsub(void);
extern int dosubcon(bool, line *);
extern int confirmed(line *);
extern void ugo(int, int);
extern void dosub(void);
extern int fixcase(register int);
extern char *place(register char *, register char *, register char *);
extern void snote(register int, register int);
extern void cerror(char *);
extern struct regexp *savere(struct regexp *);
extern struct regexp *resre(struct regexp *);
extern int compile(int, int);
extern int same(register int, register int);
extern int ecmp(register char *, register char *, register int);
extern int execute(int, line *);
extern void getrnge(register char *);
extern int advance(register char *, register char *);
extern int cclass(register char *, register int, int);
/* ex_set.c */
extern void set(void);
extern int setend(void);
extern void prall(void);
extern void propts(void);
extern void propt(register struct option *);
/* ex_subr.c */
extern int any(int, register char *);
extern int backtab(register int);
extern void change(void);
extern int column(register char *);
extern void comment(void);
extern void Copy(register char *, register char *, register int);
extern void copyw(register line *, register line *, register int);
extern void copywR(register line *, register line *, register int);
extern int ctlof(int);
extern void dingdong(void);
extern int fixindent(int);
extern void filioerr(char *);
extern char *genindent(register int);
extern void getDOT(void);
extern line *getmark(register int);
extern int getn(register char *);
extern void ignnEOF(void);
extern int is_white(int);
extern int junk(register int);
extern void killed(void);
extern void killcnt(register int);
extern int lineno(line *);
extern int lineDOL(void);
extern int lineDOT(void);
extern void markDOT(void);
extern void markpr(line *);
extern int markreg(register int);
extern char *mesg(register char *);
extern void merror1(intptr_t);
extern void vmerror(char *, va_list);
extern void merror(char *, ...);
extern int morelines(void);
extern void nonzero(void);
extern int notable(int);
extern void notempty(void);
extern void netchHAD(int);
extern void netchange(register int);
extern int printof(int);
extern void putmark(line *);
extern void putmk1(register line *, int);
extern char *plural(long);
extern int qcolumn(register char *, register char *);
extern int qcount(int);
extern void reverse(register line *, register line *);
extern void save(line *, register line *);
extern void save12(void);
extern void saveall(void);
extern int span(void);
extern void synced(void);
extern int skipwh(void);
extern void vsmerror(char *, va_list);
extern void smerror(char *, ...);
extern char *strend(register char *);
extern void strcLIN(char *);
extern void syserror(void);
extern int tabcol(int, int);
extern char *vfindcol(int);
extern char *vskipwh(register char *);
extern char *vpastwh(register char *);
extern int whitecnt(register char *);
extern void markit(line *);
extern void onhup(int);
extern void onintr(int);
extern void setrupt(void);
extern int preserve(void);
extern int exitex(int);
extern void onsusp(int);
extern void onemt(int);
extern char *movestr(char *, const char *);
extern char *safecp(char *, const char *, size_t, char *, ...);
extern char *safecat(char *, const char *, size_t, char *, ...);
/* ex_tagio.c */
extern int topen(char *, char *);
extern int tseek(int, off_t);
extern int tgets(char *, int, int);
extern void tclose(int);
/* ex_temp.c */
extern void fileinit(void);
extern void cleanup(bool);
extern void getline(line);
extern line putline(void);
extern char *getblock(line, int);
extern void blkio(bloc, char *, ssize_t (*)(int, void *, size_t));
extern void tlaste(void);
extern void tflush(void);
extern void synctmp(void);
extern void TSYNC(void);
extern void regio(short, ssize_t (*)(int, void *, size_t));
extern int REGblk(void);
extern struct strreg *mapreg(register int);
extern void KILLreg(register int);
extern ssize_t shread(void);
extern void putreg(int);
extern int partreg(int);
extern void notpart(register int);
extern int getREG(void);
extern void YANKreg(register int);
extern void kshift(void);
extern void YANKline(void);
extern void rbflush(void);
extern void regbuf(char, char *, int);
extern void tlaste(void);
/* ex_tty.c */
extern void gettmode(void);
extern void setterm(char *);
extern void setsize(void);
extern void zap(void);
extern char *gettlongname(register char *, char *);
extern char *fkey(int);
extern int cost(char *);
extern int countnum(int);
extern struct termios ostart(void);
extern void tostart(void);
extern void ostop(struct termios);
extern void tostop(void);
extern struct termios setty(struct termios);
extern void gTTY(int);
extern void noonl(void);
/* ex_unix.c */
extern void unix0(int);
extern struct termios unixex(char *, char *, int, int);
extern void unixwt(int, struct termios);
extern void filter(register int);
extern void recover(void);
extern void waitfor(void);
extern void revocer(void);
/* ex_v.c */
extern void oop(void);
extern void ovbeg(void);
extern void ovend(struct termios);
extern void vop(void);
extern void fixzero(void);
extern void savevis(void);
extern void undvis(void);
extern void setwind(void);
extern void vok(register cell *);
extern void vintr(int);
extern void vsetsiz(int);
extern void onwinch(int);
/* ex_vadj.c */
extern void vopen(line *, int);
extern int vreopen(int, int, int);
extern int vglitchup(int, int);
extern void vinslin(register int, register int, int);
extern void vopenup(int, int, int);
extern void vadjAL(int, int);
extern void vrollup(int);
extern void vup1(void);
extern void vmoveitup(register int, int);
extern void vscroll(register int);
extern void vscrap(void);
extern void vrepaint(char *);
extern void vredraw(register int);
extern void vdellin(int, int, int);
extern void vadjDL(int, int);
extern void vsyncCL(void);
extern void vsync(register int);
extern void vsync1(register int);
extern void vcloseup(int, register int);
extern void vreplace(int, int, int);
extern void sethard(void);
extern void vdirty(register int, register int);
/* ex_version.c */
extern void printver(void);
/* ex_vget.c */
extern void ungetkey(int);
extern int getkey(void);
extern int peekbr(void);
extern int getbr(void);
extern int getesc(void);
extern int peekkey(void);
extern int readecho(int);
extern void setLAST(void);
extern void addtext(char *);
extern void setDEL(void);
extern void setBUF(register cell *);
extern void addto(register cell *, register char *);
extern int noteit(int);
extern void obeep(void);
extern void macpush(char *, int);
extern int vgetcnt(void);
extern void trapalarm(int);
extern int fastpeekkey(void);
/* ex_vmain.c */
extern void vmain(void);
extern void grabtag(void);
extern void prepapp(void);
extern void vremote(int, void (*)(int), int);
extern void vsave(void);
extern void vzop(int, int, register int);
extern cell *str2cell(cell *, register char *);
extern char *cell2str(char *, register cell *);
extern cell *cellcpy(cell *, register cell *);
extern size_t cellen(register cell *);
extern cell *cellcat(cell *, register cell *);
/* ex_voper.c */
extern void operate(register int, register int);
extern int find(int);
extern int word(register void (*)(int), int);
extern void eend(register void (*)(int));
extern int wordof(int, register char *);
extern int wordch(char *);
extern int edge(void);
extern int margin(void);
/* ex_vops.c */
extern void vUndo(void);
extern void vundo(int);
extern void vmacchng(int);
extern void vnoapp(void);
extern void vmove(int);
extern void vdelete(int);
extern void vchange(int);
extern void voOpen(int, register int);
extern void vshftop(int);
extern void vfilter(int);
extern int xdw(void);
extern void vshift(int);
extern void vrep(register int);
extern void vyankit(int);
extern void setpk(void);
/* ex_vops2.c */
extern void bleep(register int, char *);
extern int vdcMID(void);
extern void takeout(cell *);
extern int ateopr(void);
extern void showmode(int);
extern void addc(cell);
extern void vappend(int, int, int);
extern void back1(void);
extern char *vgetline(int, register char *, bool *, int);
extern void vdoappend(char *);
extern int vgetsplit(void);
extern int vmaxrep(int, register int);
/* ex_vops3.c */
extern int llfind(bool, int, void (*)(int), line *);
extern int endsent(bool);
extern int endPS(void);
extern int lindent(line *);
extern int lmatchp(line *);
extern void lsmatch(char *);
extern int ltosolid(void);
extern int ltosol1(register char *);
extern int lskipbal(register char *);
extern int lskipatom(void);
extern int lskipa1(register char *);
extern int lnext(void);
extern int lbrack(register int, void (*)(int));
extern int isa(register char *);
extern void vswitch(int);
#ifdef MB
extern int wskipleft(char *, char *);
extern int wskipright(char *, char *);
extern int wsamechar(char *, int);
#endif /* MB */
/* ex_vput.c */
extern void vclear(void);
extern void vclrcell(register cell *, register int);
extern void vclrlin(int, line *);
extern void vclreol(void);
extern void vclrech(bool);
extern void fixech(void);
extern void vcursbef(register char *);
extern void vcursat(register char *);
extern void vcursaft(register char *);
extern void vfixcurs(void);
extern void vsetcurs(register char *);
extern void vigoto(int, int);
extern void vcsync(void);
extern void vgotoCL(register int);
extern void vigotoCL(register int);
extern void vgoto(register int, register int);
extern void vgotab(void);
extern void vprepins(void);
extern void vmaktop(register int, cell *);
extern int vinschar(int);
extern void vrigid(void);
extern void vneedpos(int);
extern void vnpins(int);
extern void vishft(void);
extern void viin(int);
extern void godm(void);
extern void enddm(void);
extern void goim(void);
extern void endim(void);
extern int vputchar(register int);
extern void physdc(int, int);
extern int vputch(int);
/* ex_vwind.c */
extern void vmoveto(register line *, char *, int);
extern void vjumpto(register line *, char *, int);
extern void vupdown(register int, char *);
extern void vup(register int, register int, int);
extern void vdown(register int, register int, int);
extern void vcontext(register line *, int);
extern void vclean(void);
extern void vshow(line *, line *);
extern void vreset(int);
extern line *vback(register line *, register int);
extern int vfit(register line *, int);
extern void vroll(register int);
extern void vrollR(register int);
extern int vcookit(register int);
extern int vdepth(void);
extern void vnline(char *);
/* malloc.c */
/* mapmalloc.c */
extern char *poolsbrk(intptr_t);
/* printf.c */
extern int printf(const char *, ...);
extern int vprintf(const char *, va_list);
extern char *p_dconv(long, char *);

1300
ex_put.c Normal file

File diff suppressed because it is too large Load Diff

1678
ex_re.c Normal file

File diff suppressed because it is too large Load Diff

165
ex_re.h Normal file
View File

@ -0,0 +1,165 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex_re.h 7.3 (Berkeley) 5/31/85
*
* @(#)ex_re.h 1.18 (gritter) 11/23/04
*/
#ifdef UXRE
#include <regex.h>
#endif
/*
* Regular expression definitions.
* The regular expressions in ex are similar to those in ed,
* with the addition of the word boundaries from Toronto ed
* and allowing character classes to have [a-b] as in the shell.
* The numbers for the nodes below are spaced further apart then
* necessary because I at one time partially put in + and | (one or
* more and alternation.)
*/
struct regexp {
#ifdef UXRE
char Expbuf[2*LBSIZE + 1];
regex_t Re;
long Re_ident;
bool Re_used;
#else /* !UXRE */
char Expbuf[ESIZE + 2];
int Low;
int Siz;
#endif /* !UXRE */
bool Circfl;
short Nbra;
};
/*
* There are three regular expressions here, the previous (in re),
* the previous substitute (in subre) and the previous scanning (in scanre).
* It would be possible to get rid of "re" by making it a stack parameter
* to the appropriate routines.
*/
var struct regexp re; /* Last re */
var struct regexp scanre; /* Last scanning re */
var struct regexp subre; /* Last substitute re */
/*
* Defining circfl and expbuf like this saves us from having to change
* old code in the ex_re.c stuff.
*/
#define expbuf re.Expbuf
#define circfl re.Circfl
#define nbra re.Nbra
#define low re.Low
#define siz re.Siz
var char *loc1; /* Where re began to match (in linebuf) */
var char *loc2; /* First char after re match (") */
/*
* Since the phototypesetter v7-epsilon
* C compiler doesn't have structure assignment...
*/
extern struct regexp *savere(struct regexp *);
extern struct regexp *resre(struct regexp *);
/*
* Definitions for substitute
*/
var char *braslist[NBRA]; /* Starts of \(\)'ed text in lhs */
var char *braelist[NBRA]; /* Ends... */
var char rhsbuf[RHSSIZE]; /* Rhs of last substitute */
#ifdef BIT8
var char rhsquo[RHSSIZE]; /* Quote indicator for rhsbuf */
#endif
/*
* Definitions of codes for the compiled re's.
* The re algorithm is described in a paper
* by K. Thompson in the CACM about 10 years ago
* and is the same as in ed.
*/
#define STAR 1
#define RNGE 0100
#define CBRA 1
#define CDOT 4
#define CCL 8
#define NCCL 12
#define CDOL 16
#define CEOFC 17
#define CKET 18
#define CCHR 20
#define CBRC 24
#define CLET 25
#define CBACK 36

313
ex_set.c Normal file
View File

@ -0,0 +1,313 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_set.c 1.11 (gritter) 11/24/04";
#endif
#endif
/* from ex_set.c 7.4 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_temp.h"
#include "ex_tty.h"
/*
* Set command.
*/
char optname[ONMSZ];
void
set(void)
{
register char *cp;
register struct option *op;
register int c;
bool no;
setnoaddr();
if (skipend()) {
if (peekchar() != EOF)
ignchar();
propts();
return;
}
do {
cp = optname;
do {
if (cp < &optname[ONMSZ - 2])
*cp++ = getchar();
} while (isalnum(peekchar()));
*cp = 0;
cp = optname;
if (eq("all", cp)) {
if (inopen)
pofix();
prall();
goto setnext;
}
no = 0;
if (cp[0] == 'n' && cp[1] == 'o') {
cp += 2;
no++;
}
/* Implement w300, w1200, and w9600 specially */
if (eq(cp, "w300")) {
if (ospeed >= B1200) {
dontset:
ignore(getchar()); /* = */
ignore(getnum()); /* value */
continue;
}
cp = "window";
} else if (eq(cp, "w1200")) {
if (ospeed < B1200 || ospeed >= B2400)
goto dontset;
cp = "window";
} else if (eq(cp, "w9600")) {
if (ospeed < B2400)
goto dontset;
cp = "window";
}
for (op = options; op < &options[NOPTS]; op++)
if (eq(op->oname, cp) || op->oabbrev && eq(op->oabbrev, cp))
break;
if (op->oname == 0)
serror(catgets(catd, 1, 159,
"%s: No such option@- 'set all' gives all option values"), cp);
c = skipwh();
if (peekchar() == '?') {
ignchar();
printone:
propt(op);
noonl();
goto setnext;
}
if (op->otype == ONOFF) {
op->ovalue = 1 - no;
if (op == &options[PROMPT])
oprompt = 1 - no;
goto setnext;
}
if (no)
serror(catgets(catd, 1, 160,
"Option %s is not a toggle"), op->oname);
if (c != 0 || setend())
goto printone;
if (getchar() != '=')
serror(catgets(catd, 1, 161,
"Missing =@in assignment to option %s"), op->oname);
switch (op->otype) {
case NUMERIC:
if (!isdigit(peekchar()))
error(catgets(catd, 1, 162,
"Digits required@after ="));
op->ovalue = getnum();
if (value(TABSTOP) <= 0)
value(TABSTOP) = TABS;
if (value(HARDTABS) <= 0)
value(HARDTABS) = TABS;
if (op == &options[WINDOW]) {
if (value(WINDOW) >= TLINES)
value(WINDOW) = TLINES-1;
vsetsiz(value(WINDOW));
}
break;
case STRING:
case OTERM:
cp = optname;
while (!setend()) {
if (cp >= &optname[ONMSZ])
error(catgets(catd, 1, 163,
"String too long@in option assignment"));
/* adb change: allow whitepace in strings */
if( (*cp = getchar()) == '\\')
if( peekchar() != EOF)
*cp = getchar();
cp++;
}
*cp = 0;
if (op->otype == OTERM) {
/*
* At first glance it seems like we shouldn't care if the terminal type
* is changed inside visual mode, as long as we assume the screen is
* a mess and redraw it. However, it's a much harder problem than that.
* If you happen to change from 1 crt to another that both have the same
* size screen, it's OK. But if the screen size if different, the stuff
* that gets initialized in vop() will be wrong. This could be overcome
* by redoing the initialization, e.g. making the first 90% of vop into
* a subroutine. However, the most useful case is where you forgot to do
* a setenv before you went into the editor and it thinks you're on a dumb
* terminal. Ex treats this like hardcopy and goes into HARDOPEN mode.
* This loses because the first part of vop calls oop in this case.
* The problem is so hard I gave up. I'm not saying it can't be done,
* but I am saying it probably isn't worth the effort.
*/
if (inopen)
error(catgets(catd, 1, 164,
"Can't change type of terminal from within open/visual"));
setterm(optname);
} else {
CP(op->osvalue, optname);
op->odefault = 1;
}
break;
}
setnext:
flush();
} while (!skipend());
eol();
}
int
setend(void)
{
return (is_white(peekchar()) || endcmd(peekchar()));
}
void
prall(void)
{
register int incr = (NOPTS + 2) / 3;
register int rows = incr;
register struct option *op = options;
for (; rows; rows--, op++) {
propt(op);
tab(24);
propt(&op[incr]);
if (&op[2*incr] < &options[NOPTS]) {
tab(56);
propt(&op[2 * incr]);
}
putNFL();
}
}
void
propts(void)
{
register struct option *op;
for (op = options; op < &options[NOPTS]; op++) {
if (op == &options[TTYTYPE])
continue;
switch (op->otype) {
case ONOFF:
case NUMERIC:
if (op->ovalue == op->odefault)
continue;
break;
case STRING:
if (op->odefault == 0)
continue;
break;
}
propt(op);
putchar(' ');
}
noonl();
flush();
}
void
propt(register struct option *op)
{
register char *name;
name = op->oname;
switch (op->otype) {
case ONOFF:
printf(catgets(catd, 1, 165, "%s%s"),
op->ovalue ? catgets(catd, 1, 166, "")
: catgets(catd, 1, 167, "no"), name);
break;
case NUMERIC:
printf(catgets(catd, 1, 168, "%s=%d"), name, op->ovalue);
break;
case STRING:
case OTERM:
printf(catgets(catd, 1, 169, "%s=%s"), name, op->osvalue);
break;
}
}

1116
ex_subr.c Normal file

File diff suppressed because it is too large Load Diff

177
ex_tagio.c Normal file
View File

@ -0,0 +1,177 @@
/* Copyright (c) 1985 Regents of the University of California */
/*
* These routines are for faster tag lookup. They support the binary
* search used in tagfind() instead of the linear search. The speedup
* is quite noticable looking for a tag at the end of a long tags
* file. Define FASTTAG in the Makefile to use these routines.
*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifdef FASTTAG
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_tagio.c 1.11 (gritter) 11/27/04";
#endif
#endif
/* from ex_tagio.c 7.3 (Berkeley) 1/31/86 */
#include "ex.h"
static long offset = -1;
static long block = -1;
static int bcnt = 0;
static int b_size = MAXBSIZE;
static char *ibuf;
int
topen(char *file, char *buf)
{
int fd;
struct stat statb;
offset = -1;
block = -1;
if ((fd = open(file, O_RDONLY, 0)) < 0)
return(-1);
if (fstat(fd, &statb) < 0) {
close(fd);
return(-1);
}
ibuf = buf;
if (statb.st_blksize <= MAXBSIZE)
b_size = statb.st_blksize;
return(fd);
}
int
tseek(int fd, off_t off)
{
off_t nblock;
nblock = off / b_size * b_size;
offset = off % b_size;
if (nblock == block)
return(0);
block = nblock;
if (lseek(fd, (off_t) nblock, SEEK_SET) < 0)
return(-1);
if ((bcnt = read(fd, ibuf, b_size)) < 0)
return(-1);
return(0);
}
int
tgets(register char *buf, int cnt, int fd)
{
register char *cp;
register int cc;
cc = offset;
if (cc == -1) {
if ((bcnt = read(fd, ibuf, b_size)) <= 0)
return 0;
cc = 0;
block = 0;
}
if (bcnt == 0) /* EOF */
return 0;
cp = ibuf + cc;
while (--cnt > 0) {
if (++cc > bcnt) {
block += b_size;
if ((bcnt = read(fd, ibuf, b_size)) <= 0) {
offset = cc;
return 0;
}
cp = ibuf;
cc = 1;
}
if ((*buf++ = *cp++) == '\n')
break;
}
*--buf = 0;
offset = cc;
return(1);
}
void
tclose(int fd)
{
close(fd);
offset = -1;
block = -1;
bcnt = 0;
}
#endif

771
ex_temp.c Normal file
View File

@ -0,0 +1,771 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_temp.c 1.24 (gritter) 11/24/04";
#endif
#endif
/* from ex_temp.c 7.5.1.1 (Berkeley) 8/12/86 */
#include "ex.h"
#include "ex_temp.h"
#include "ex_vis.h"
#include "ex_tty.h"
#include <sys/wait.h>
#include <time.h>
/*
* Editor temporary file routines.
* Very similar to those of ed, except uses 2 input buffers.
*/
#define READ 0
#define WRITE 1
/*
* Maximum number of attempts to create temporary file.
*/
#define ATTEMPTS 20
char *tfname;
char *rfname;
int havetmp;
int tfile = -1;
int rfile = -1;
void
fileinit(void)
{
register char *p;
struct stat stbuf;
register int i, j;
pid_t mypid = getpid();
char *tfend;
int attempts = 0;
CLOBBGRD(attempts);
if (tline == INCRMT * (HBLKS+2))
return;
cleanup(0);
if (tfile != -1)
close(tfile);
tline = INCRMT * (HBLKS+2);
blocks[0] = HBLKS;
blocks[1] = HBLKS+1;
blocks[2] = -1;
dirtcnt = 0;
iblock = -1;
iblock2 = -1;
oblock = -1;
tfname = realloc(tfname, strlen(svalue(DIRECTORY)) + 14);
CP(tfname, svalue(DIRECTORY));
if (stat(tfname, &stbuf)) {
dumbness:
if (setexit() == 0)
filioerr(tfname);
else
putNFL();
cleanup(1);
exitex(1);
}
if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
errno = ENOTDIR;
goto dumbness;
}
ichanged = 0;
ichang2 = 0;
#ifdef notdef /* GR */
ignore(strcat(tfname, "/ExXXXXX"));
for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
*--p = j % 10 | '0';
tfile = creat(tfname, 0600);
#else
ignore(strcat(tfname, "/ExXXXXXXXXXX"));
tfend = strend(tfname);
do {
for (p = tfend, i = 10, j = mypid + attempts;
i > 0; i--, j /= 10)
*--p = j % 10 | '0';
tfile = open(tfname, O_CREAT|O_EXCL|O_RDWR
#ifdef O_NOFOLLOW
|O_NOFOLLOW
#endif /* O_NOFOLLOW */
, 0600);
} while (tfile < 0 && attempts++ < ATTEMPTS);
#endif /* !notdef */
if (tfile < 0)
goto dumbness;
#ifdef INCORB
{
extern bloc stilinc; /* see below */
stilinc = 0;
}
#endif
havetmp = 1;
/* brk((char *)fendcore); */
}
void
cleanup(bool all)
{
if (all) {
putpad(TE);
flush();
}
if (havetmp)
unlink(tfname);
havetmp = 0;
if (all && rfile >= 0) {
unlink(rfname);
close(rfile);
rfile = -1;
}
}
void
getline(line tl)
{
register char *bp, *lp;
register bbloc nl;
lp = linebuf;
bp = getblock(tl, READ);
nl = nleft;
tl &= ~OFFMSK;
while (*lp++ = *bp++)
if (--nl == 0) {
bp = getblock(tl += INCRMT, READ);
nl = nleft;
}
}
line
putline(void)
{
register char *bp, *lp;
register bbloc nl;
line tl;
dirtcnt++;
lp = linebuf;
change();
tl = tline;
bp = getblock(tl, WRITE);
nl = nleft;
tl &= ~OFFMSK;
while (*bp = *lp++) {
if (*bp++ == '\n') {
*--bp = 0;
linebp = lp;
break;
}
if (--nl == 0) {
bp = getblock(tl += INCRMT, WRITE);
nl = nleft;
}
}
tl = tline;
tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
return (tl);
}
char *
getblock(line atl, int iof)
{
register bbloc bno, off;
bno = (atl >> OFFBTS) & BLKMSK;
off = (atl << SHFT) & LBTMSK;
if (bno >= NMBLKS)
error(catgets(catd, 1, 183, " Tmp file too large"));
nleft = BUFSIZ - off;
if (bno == iblock) {
ichanged |= iof;
hitin2 = 0;
return (ibuff + off);
}
if (bno == iblock2) {
ichang2 |= iof;
hitin2 = 1;
return (ibuff2 + off);
}
if (bno == oblock)
return (obuff + off);
if (iof == READ) {
if (hitin2 == 0) {
if (ichang2) {
blkio(iblock2, ibuff2, (ssize_t(*)())write);
}
ichang2 = 0;
iblock2 = bno;
blkio(bno, ibuff2, (ssize_t(*)())read);
hitin2 = 1;
return (ibuff2 + off);
}
hitin2 = 0;
if (ichanged) {
blkio(iblock, ibuff, (ssize_t(*)())write);
}
ichanged = 0;
iblock = bno;
blkio(bno, ibuff, (ssize_t(*)())read);
return (ibuff + off);
}
if (oblock >= 0) {
blkio(oblock, obuff, (ssize_t(*)())write);
}
oblock = bno;
return (obuff + off);
}
#ifdef INCORB
char incorb[INCORB+1][BUFSIZ];
#define pagrnd(a) ((char *)(((size_t)a)&~(BUFSIZ-1)))
bloc stilinc; /* up to here not written yet */
#endif
void
blkio(bloc b, char *buf, ssize_t (*iofcn)(int, void *, size_t))
{
#ifdef INCORB
if (b < INCORB) {
if (iofcn == (ssize_t(*)())read) {
copy(buf, pagrnd(incorb[b+1]), (size_t) BUFSIZ);
return;
}
copy(pagrnd(incorb[b+1]), buf, (size_t) BUFSIZ);
if (laste) {
if (b >= stilinc)
stilinc = b + 1;
return;
}
} else if (stilinc)
tflush();
#endif
lseek(tfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET);
if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
filioerr(tfname);
}
#ifdef INCORB
void
tlaste(void)
{
if (stilinc)
dirtcnt = 0;
}
void
tflush(void)
{
bbloc i = stilinc;
stilinc = 0;
lseek(tfile, (off_t) 0, SEEK_SET);
if (write(tfile, pagrnd(incorb[1]), i * BUFSIZ) != (i * BUFSIZ))
filioerr(tfname);
}
#endif
/*
* Synchronize the state of the temporary file in case
* a crash occurs.
*/
void
synctmp(void)
{
register bbloc cnt;
register line *a;
register bloc *bp, *up;
#ifdef INCORB
if (stilinc)
return;
#endif
if (dol == zero)
return;
if (ichanged)
blkio(iblock, ibuff, (ssize_t(*)())write);
ichanged = 0;
if (ichang2)
blkio(iblock2, ibuff2, (ssize_t(*)())write);
ichang2 = 0;
if (oblock != -1)
blkio(oblock, obuff, (ssize_t(*)())write);
time(&H.Time);
uid = getuid();
*zero = (line) H.Time;
up = blocks + LBLKS;
for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
if (bp >= up)
error(catgets(catd, 1, 184, " Tmp file too large"));
if (*bp < 0) {
tline = (tline + OFFMSK) &~ OFFMSK;
*bp = ((tline >> OFFBTS) & BLKMSK);
if (*bp > NMBLKS)
error(catgets(catd, 1, 185,
" Tmp file too large"));
tline += INCRMT;
oblock = *bp + 1;
bp[1] = -1;
}
lseek(tfile, (off_t) ((*bp & BLKMSK) * BUFSIZ), SEEK_SET);
cnt = ((dol - a) + 2) * sizeof (line);
if (cnt > BUFSIZ)
cnt = BUFSIZ;
if (write(tfile, (char *) a, cnt) != cnt) {
oops:
*zero = 0;
filioerr(tfname);
}
*zero = 0;
}
flines = lineDOL();
lseek(tfile, (off_t) 0, SEEK_SET);
if (write(tfile, (char *) &H, sizeof H) != sizeof H)
goto oops;
#ifdef notdef
/*
* This will insure that exrecover gets as much
* back after a crash as is absolutely possible,
* but can result in pregnant pauses between commands
* when the TSYNC call is made, so...
*/
fsync(tfile);
#endif
}
void
TSYNC(void)
{
if (dirtcnt > MAXDIRT) { /* mjm: 12 --> MAXDIRT */
#ifdef INCORB
if (stilinc)
tflush();
#endif
dirtcnt = 0;
synctmp();
}
}
/*
* Named buffer routines.
* These are implemented differently than the main buffer.
* Each named buffer has a chain of blocks in the register file.
* Each block contains roughly 508 chars of text,
* and a previous and next block number. We also have information
* about which blocks came from deletes of multiple partial lines,
* e.g. deleting a sentence or a LISP object.
*
* We maintain a free map for the temp file. To free the blocks
* in a register we must read the blocks to find how they are chained
* together.
*
* BUG: The default savind of deleted lines in numbered
* buffers may be rather inefficient; it hasn't been profiled.
*/
struct strreg {
short rg_flags;
short rg_nleft;
short rg_first;
short rg_last;
} strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
struct rbuf {
short rb_prev;
short rb_next;
char rb_text[BUFSIZ - 2 * sizeof (short)];
} *rbuf, KILLrbuf, putrbuf, YANKrbuf, regrbuf;
#ifdef VMUNIX
#ifdef LARGEF
short rused[4096];
#else /* !LARGEF */
short rused[256];
#endif /* !LARGEF */
#else /* !VMUNIX */
short rused[32];
#endif /* !VMUNIX */
short rnleft;
short rblock;
short rnext;
char *rbufcp;
void
regio(short b, ssize_t (*iofcn)(int, void *, size_t))
{
register char *p;
char *rfend;
int attempts = 0;
register int i, j;
pid_t mypid = getpid();
if (rfile == -1) {
rfname = realloc(rfname, strlen(svalue(DIRECTORY)) + 14);
CP(rfname, tfname);
rfend = strend(rfname);
#ifdef notdef /* GR */
*(rfend - 7) = 'R';
#else
*(rfend - 12) = 'R';
#endif
do {
for (p = rfend, i = 10, j = mypid + attempts;
i > 0; i--, j /= 10)
*--p = j % 10 | '0';
rfile = open(rfname, O_CREAT|O_EXCL|O_RDWR
#ifdef O_NOFOLLOW
|O_NOFOLLOW
#endif /* O_NOFOLLOW */
, 0600);
} while (rfile < 0 && attempts++ < ATTEMPTS);
if (rfile < 0)
oops:
filioerr(rfname);
}
lseek(rfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET);
if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
goto oops;
rblock = b;
}
int
REGblk(void)
{
register int i, j, m;
for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
m = (rused[i] ^ 0177777) & 0177777;
if (i == 0)
m &= ~1;
if (m != 0) {
j = 0;
while ((m & 1) == 0)
j++, m >>= 1;
rused[i] |= (1 << j);
#ifdef RDEBUG
printf("allocating block %d\n", i * 16 + j);
#endif
return (i * 16 + j);
}
}
error(catgets(catd, 1, 186, "Out of register space (ugh)"));
/*NOTREACHED*/
return 0;
}
struct strreg *
mapreg(register int c)
{
if (isupper(c))
c = tolower(c);
return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
}
void
KILLreg(register int c)
{
register struct strreg *sp;
rbuf = &KILLrbuf;
sp = mapreg(c);
rblock = sp->rg_first;
sp->rg_first = sp->rg_last = 0;
sp->rg_flags = sp->rg_nleft = 0;
while (rblock != 0) {
#ifdef RDEBUG
printf("freeing block %d\n", rblock);
#endif
rused[rblock / 16] &= ~(1 << (rblock % 16));
regio(rblock, (ssize_t (*)(int, void *, size_t))shread);
rblock = rbuf->rb_next;
}
}
ssize_t
shread(void)
{
struct front { short a; short b; };
if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
return (sizeof (struct rbuf));
return (0);
}
int getREG();
void
putreg(int c)
{
register line *odot = dot;
register line *odol = dol;
register int cnt;
deletenone();
appendnone();
rbuf = &putrbuf;
rnleft = 0;
rblock = 0;
rnext = mapreg(c)->rg_first;
if (rnext == 0) {
if (inopen) {
splitw++;
vclean();
vgoto(WECHO, 0);
}
vreg = -1;
error(catgets(catd, 1, 187, "Nothing in register %c"), c);
}
if (inopen && partreg(c)) {
if (!FIXUNDO) {
splitw++; vclean(); vgoto(WECHO, 0); vreg = -1;
error(catgets(catd, 1, 188,
"Can't put partial line inside macro"));
}
squish();
addr1 = addr2 = dol;
}
cnt = append(getREG, addr2);
if (inopen && partreg(c)) {
unddol = dol;
dol = odol;
dot = odot;
pragged(0);
}
killcnt(cnt);
notecnt = cnt;
}
int
partreg(int c)
{
return (mapreg(c)->rg_flags);
}
void
notpart(register int c)
{
if (c)
mapreg(c)->rg_flags = 0;
}
int
getREG(void)
{
register char *lp = linebuf;
register int c;
for (;;) {
if (rnleft == 0) {
if (rnext == 0)
return (EOF);
regio(rnext, read);
rnext = rbuf->rb_next;
rbufcp = rbuf->rb_text;
rnleft = sizeof rbuf->rb_text;
}
c = *rbufcp;
if (c == 0)
return (EOF);
rbufcp++, --rnleft;
if (c == '\n') {
*lp++ = 0;
return (0);
}
*lp++ = c;
}
}
void
YANKreg(register int c)
{
register line *addr;
register struct strreg *sp;
char savelb[LBSIZE];
if (isdigit(c))
kshift();
if (islower(c))
KILLreg(c);
strp = sp = mapreg(c);
sp->rg_flags = inopen && cursor && wcursor;
rbuf = &YANKrbuf;
if (sp->rg_last) {
regio(sp->rg_last, read);
rnleft = sp->rg_nleft;
rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
} else {
rblock = 0;
rnleft = 0;
}
CP(savelb,linebuf);
for (addr = addr1; addr <= addr2; addr++) {
getline(*addr);
if (sp->rg_flags) {
if (addr == addr2)
*wcursor = 0;
if (addr == addr1)
strcpy(linebuf, cursor);
}
YANKline();
}
rbflush();
killed();
CP(linebuf,savelb);
}
void
kshift(void)
{
register int i;
KILLreg('9');
for (i = '8'; i >= '0'; i--)
copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
}
void
YANKline(void)
{
register char *lp = linebuf;
register struct rbuf *rp = rbuf;
register int c;
do {
c = *lp++;
if (c == 0)
c = '\n';
if (rnleft == 0) {
rp->rb_next = REGblk();
rbflush();
rblock = rp->rb_next;
rp->rb_next = 0;
rp->rb_prev = rblock;
rnleft = sizeof rp->rb_text;
rbufcp = rp->rb_text;
}
*rbufcp++ = c;
--rnleft;
} while (c != '\n');
if (rnleft)
*rbufcp = 0;
}
void
rbflush(void)
{
register struct strreg *sp = strp;
if (rblock == 0)
return;
regio(rblock, (ssize_t (*)(int, void *, size_t))write);
if (sp->rg_first == 0)
sp->rg_first = rblock;
sp->rg_last = rblock;
sp->rg_nleft = rnleft;
}
/* Register c to char buffer buf of size buflen */
void
regbuf(char c, char *buf, int buflen)
{
register char *p, *lp;
rbuf = &regrbuf;
rnleft = 0;
rblock = 0;
rnext = mapreg(c)->rg_first;
if (rnext==0) {
*buf = 0;
error(catgets(catd, 1, 189, "Nothing in register %c"),c);
}
p = buf;
while (getREG()==0) {
for (lp=linebuf; *lp;) {
if (p >= &buf[buflen])
error(catgets(catd, 1, 190,
"Register too long@to fit in memory"));
*p++ = *lp++;
}
*p++ = '\n';
}
if (partreg(c)) p--;
*p = '\0';
getDOT();
}

191
ex_temp.h Normal file
View File

@ -0,0 +1,191 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex_temp.h 7.4 (Berkeley) 5/31/85
*
* @(#)ex_temp.h 1.8 (gritter) 1/26/02
*/
/*
* The editor uses a temporary file for files being edited, in a structure
* similar to that of ed. The first block of the file is used for a header
* block which guides recovery after editor/system crashes.
* Lines are represented in core by a pointer into the temporary file which
* is packed into 16 bits (32 on VMUNIX). All but the low bit index the temp
* file; the last is used by global commands. The parameters below control
* how much the other bits are shifted left before they index the temp file.
* Larger shifts give more slop in the temp file but allow larger files
* to be edited.
*
* The editor does not garbage collect the temporary file. When a new
* file is edited, the temporary file is rather discarded and a new one
* created for the new file. Garbage collection would be rather complicated
* in ex because of the general undo, and in any case would require more
* work when throwing lines away because marks would have be carefully
* checked before reallocating temporary file space. Said another way,
* each time you create a new line in the temporary file you get a unique
* number back, and this is a property used by marks.
*
* The following temp file parameters allow 256k bytes in the temporary
* file. By changing to the numbers in comments you can get 512k.
* For VMUNIX you get more than you could ever want.
* VMUNIX uses long (32 bit) integers giving much more
* space in the temp file and no waste. This doubles core
* requirements but allows files of essentially unlimited size to be edited.
*/
#ifndef VMUNIX
#define BLKMSK 0777 /* 01777 */
#define BNDRY 8 /* 16 */
#define INCRMT 0200 /* 0100 */
#define LBTMSK 0770 /* 0760 */
#define NMBLKS 506 /* 1018 */
#define OFFBTS 7 /* 6 */
#define OFFMSK 0177 /* 077 */
#define SHFT 2 /* 3 */
#else
#ifdef LARGEF
#define BLKMSK 017777777777
#else
#define BLKMSK 077777
#endif
#define BNDRY 2
#define INCRMT 02000
#define LBTMSK 01776
#ifdef LARGEF
#define NMBLKS 017777777770
#else
#define NMBLKS 077770
#endif
#define OFFBTS 10
#define OFFMSK 01777
#define SHFT 0
#endif
/*
* The editor uses three buffers into the temporary file (ed uses two
* and is very similar). These are two read buffers and one write buffer.
* Basically, the editor deals with the file as a sequence of BUFSIZ character
* blocks. Each block contains some number of lines (and lines
* can run across block boundaries.
*
* New lines are written into the last block in the temporary file
* which is in core as obuf. When a line is needed which isn't in obuf,
* then it is brought into an input buffer. As there are two, the choice
* is to take the buffer into which the last read (of the two) didn't go.
* Thus this is a 2 buffer LRU replacement strategy. Measurement
* shows that this saves roughly 25% of the buffer reads over a one
* input buffer strategy. Since the editor (on our VAX over 1 week)
* spends (spent) roughly 30% of its time in the system read routine,
* this can be a big help.
*/
var bool hitin2; /* Last read hit was ibuff2 not ibuff */
var bool ichang2; /* Have actually changed ibuff2 */
var bool ichanged; /* Have actually changed ibuff */
var bloc iblock; /* Temp file block number of ibuff (or -1) */
var bloc iblock2; /* Temp file block number of ibuff2 (or -1) */
var bloc ninbuf; /* Number useful chars left in input buffer */
var bloc nleft; /* Number usable chars left in output buffer */
var bloc oblock; /* Temp file block number of obuff (or -1) */
var bbloc tline; /* Current temp file ptr */
var char ibuff[BUFSIZ];
var char ibuff2[BUFSIZ];
var char obuff[BUFSIZ];
/*
* Structure of the descriptor block which resides
* in the first block of the temporary file and is
* the guiding light for crash recovery.
*
* As the Blocks field below implies, there are temporary file blocks
* devoted to (some) image of the incore array of pointers into the temp
* file. Thus, to recover from a crash we use these indices to get the
* line pointers back, and then use the line pointers to get the text back.
* Except for possible lost lines due to sandbagged I/O, the entire
* file (at the time of the last editor "sync") can be recovered from
* the temp file.
*/
/* This definition also appears in expreserve.c... beware */
struct header {
time_t Time; /* Time temp file last updated */
uid_t Uid;
bbloc Flines; /* Number of lines in file */
char Savedfile[FNSIZE]; /* The current file name */
bloc Blocks[LBLKS]; /* Blocks where line pointers stashed */
};
var struct header H;
#define uid H.Uid
#define flines H.Flines
#define savedfile H.Savedfile
#define blocks H.Blocks

402
ex_tty.c Normal file
View File

@ -0,0 +1,402 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_tty.c 1.27 (gritter) 12/1/04";
#endif
#endif
/* from ex_tty.c 7.10.1 (2.11BSD GTE) 12/9/94 */
#include "ex.h"
#include "ex_tty.h"
int ATTN = DELETE;
/*
* Terminal type initialization routines,
* and calculation of flags at entry or after
* a shell escape which may change them.
*/
/* short ospeed = -1; mjm: def also in tputs.c of termcap.a */
void
gettmode(void)
{
speed_t pospeed;
if (tcgetattr(1, &tty) < 0)
return;
pospeed = cfgetospeed(&tty);
if (ospeed != pospeed)
value(SLOWOPEN) = pospeed < B1200;
ospeed = pospeed;
normf = tty;
#if defined (UCVISUAL) && defined (IUCLC)
UPPERCASE = (tty.c_iflag & IUCLC) != 0;
#endif
#if defined (TAB3)
GT = (tty.c_oflag & TABDLY) != TAB3 && !XT;
#elif defined (XTABS)
GT = (tty.c_oflag & TABDLY) != XTABS && !XT;
#else
GT = !XT;
#endif /* !TAB3, XTABS */
/*
* Tabs and multi-column characters do not combine properly
* unless vi performs a look-ahead on the current line. Just
* do not use them for now.
*/
if (mb_cur_max > 1)
GT = 0;
NONL = (tty.c_oflag & ONLCR) == 0;
ATTN = tty.c_cc[VINTR];
}
char *xPC;
char **sstrs[] = {
&AL, &BC, &BT, &CD, &CE, &CL, &CM, &xCR, &xCS, &DC, &DL, &DM, &DO,
&ED, &EI, &F0, &F1, &F2, &F3, &F4, &F5, &F6, &F7, &F8, &F9,
&HO, &IC, &IM, &IP, &KD, &KE, &KH, &KL, &KR, &KS, &KU, &LL, &ND, &xNL,
&xPC, &RC, &SC, &SE, &SF, &SO, &SR, &TA, &TE, &TI, &UP, &VB, &VS, &VE,
&AL_PARM, &DL_PARM, &UP_PARM, &DOWN_PARM, &LEFT_PARM, &RIGHT_PARM
};
bool *sflags[] = {
&AM, &BS, &DA, &DB, &EO, &HC,
#ifdef UCVISUAL
&xHZ,
#endif
&IN, &MI, &NC, &NS, &OS, &UL,
&XB, &XN, &XT, &XX
};
char **fkeys[10] = {
&F0, &F1, &F2, &F3, &F4, &F5, &F6, &F7, &F8, &F9
};
void
setterm(char *type)
{
register int unknown;
char ltcbuf[TCBUFSIZE];
if (type[0] == 0)
type = "xx";
unknown = 0;
putpad(TE);
if (tgetent(ltcbuf, type) != 1) {
unknown++;
CP(ltcbuf, "xx|dumb:");
}
gettmode(); /* must call gettmode() before setsize(). GR */
setsize();
aoftspace = tspace;
zap();
/*
* Initialize keypad arrow keys.
*/
addmac1(KU, "k", "up", arrows, 1);
addmac1(KD, "j", "down", arrows, 1);
addmac1(KL, "h", "left", arrows, 1);
addmac1(KR, "l", "right", arrows, 1);
addmac1(KH, "H", "home", arrows, 1);
/*
* Handle funny termcap capabilities
*/
if (xCS && SC && RC) {
if (AL==NULL) AL="";
if (DL==NULL) DL="";
}
if (AL_PARM && AL==NULL) AL="";
if (DL_PARM && DL==NULL) DL="";
if (IC && IM==NULL) IM="";
if (IC && EI==NULL) EI="";
if (!GT) BT=NULL; /* If we can't tab, we can't backtab either */
#ifdef TIOCLGET
#define HAS_JOB_CONTROL
#endif
#ifdef _SC_JOB_CONTROL
#define HAS_JOB_CONTROL
#endif
#ifdef HAS_JOB_CONTROL
/*
* Now map users susp char to ^Z, being careful that the susp
* overrides any arrow key, but only for hackers (=new tty driver).
*/
{
static char sc[2];
int i /* , fnd */;
if (sysconf(_SC_JOB_CONTROL) != -1)
{
/*
* If a system supports job control but no job
* control shell is used, only one method of
* detection remains: Our session id equals our
* process group id. Any job control shell would
* have created at least one new process group.
* But as the VSUSP key may be active, we have
* to override arrow keys either.
*/
#ifndef _CRAY /* getsid() is a bad syscall on UNICOS */
if (getsid(0) != getpgid(0))
#endif /* !_CRAY */
ldisc = 2; /* value of NTTYDISC */
sc[0] = tty.c_cc[VSUSP];
sc[1] = 0;
if (tty.c_cc[VSUSP] == CTRL('z')) {
for (i=0; i<=4; i++)
if (arrows[i].cap &&
arrows[i].cap[0] == CTRL('z'))
addmac(sc, NULL, NULL, arrows);
} else if (sc[0]
#ifdef _PC_VDISABLE
&& sc[0] != fpathconf(1, _PC_VDISABLE)
#endif
)
addmac(sc, "\32", "susp", arrows);
}
}
#endif /* HAS_JOB_CONTROL */
if (CM != 0) {
if (tgoto(CM, 2, 2)[0] == 'O') /* OOPS */
CA = 0, CM = 0;
else
CA = 1, costCM = cost(tgoto(CM, 8, 10));
} else {
CA = 0, CM = 0;
}
costSR = cost(SR);
costAL = cost(AL);
costDP = cost(tgoto(DOWN_PARM, 10, 10));
costLP = cost(tgoto(LEFT_PARM, 10, 10));
costRP = cost(tgoto(RIGHT_PARM, 10, 10));
PC = xPC ? xPC[0] : 0;
aoftspace = tspace;
safecp(ttylongname, gettlongname(ltcbuf, type), sizeof ttylongname,
"Terminal name too long");
/* proper strings to change tty type */
termreset();
gettmode();
value(REDRAW) = AL && DL;
value(OPTIMIZE) = !CA && !GT;
if (ospeed == B1200 && !value(REDRAW))
value(SLOWOPEN) = 1; /* see also gettmode above */
if (unknown)
serror(catgets(catd, 1, 191,
"%s: Unknown terminal type"), type);
}
void
setsize(void)
{
register int l, i;
#ifdef TIOCGWINSZ
struct winsize win;
#endif
char *e;
#ifdef TIOCGWINSZ
i = ioctl(0, TIOCGWINSZ, &win);
#endif
TLINES = TCOLUMNS = 0;
e = getenv("COLUMNS");
if (e != NULL && *e != '\0')
TCOLUMNS = atoi(e);
if (TCOLUMNS <= 0) {
#ifdef TIOCGWINSZ
if (i >= 0 && win.ws_col != 0)
TCOLUMNS = winsz.ws_col = win.ws_col;
else
#endif
TCOLUMNS = tgetnum("co");
}
e = getenv("LINES");
if (e != NULL && *e != '\0')
TLINES = atoi(e);
if (TLINES <= 0) {
#ifdef TIOCGWINSZ
if (i >= 0 && win.ws_row != 0)
TLINES = winsz.ws_row = win.ws_row;
else
#endif
TLINES = tgetnum("li");
}
i = TLINES;
if (TLINES <= 5)
TLINES = 24;
if (TLINES > TUBELINES)
TLINES = TUBELINES;
l = TLINES;
if (ospeed < B1200)
l = 9; /* including the message line at the bottom */
else if (ospeed < B2400)
l = 17;
if (l > TLINES)
l = TLINES;
if (TCOLUMNS <= 4)
TCOLUMNS = 1000;
options[WINDOW].ovalue = options[WINDOW].odefault = l - 1;
if (defwind) options[WINDOW].ovalue = defwind;
options[SCROLL].ovalue = options[SCROLL].odefault = HC ? 11 : ((l-1) / 2);
if (i <= 0)
TLINES = 2;
}
void
zap(void)
{
register char *namp;
register bool **fp;
register char ***sp;
int flag;
char *string;
#ifndef UCVISUAL
namp = "ambsdadbeohcinmincnsosulxbxnxtxx";
#else
namp = "ambsdadbeohchzinmincnsosulxbxnxtxx";
#endif
fp = sflags;
do {
flag = tgetflag(namp);
*(*fp++) = flag;
namp += 2;
} while (*namp);
namp = "albcbtcdceclcmcrcsdcdldmdoedeik0k1k2k3k4k5k6k7k8k9hoicimipkdkekhklkrkskullndnlpcrcscsesfsosrtatetiupvbvsveALDLUPDOLERI";
sp = sstrs;
do {
string = tgetstr(namp, &aoftspace);
*(*sp++) = string;
namp += 2;
} while (*namp);
}
char *
gettlongname(register char *bp, char *def)
{
register char *cp;
while (*bp && *bp != ':' && *bp != '|')
bp++;
if (*bp == '|') {
bp++;
cp = bp;
while (*cp && *cp != ':' && *cp != '|')
cp++;
*cp = 0;
return (bp);
}
return (def);
}
char *
fkey(int i)
{
if (0 <= i && i <= 9)
return(*fkeys[i]);
else
return(NOSTR);
}
/*
* cost figures out how much (in characters) it costs to send the string
* str to the terminal. It takes into account padding information, as
* much as it can, for a typical case. (Right now the typical case assumes
* the number of lines affected is the size of the screen, since this is
* mainly used to decide if AL or SR is better, and this always happens
* at the top of the screen. We assume cursor motion (CM) has little
* padding, if any, required, so that case, which is really more important
* than AL vs SR, won't be really affected.)
*/
static int costnum;
int
cost(char *str)
{
if (str == NULL || *str=='O') /* OOPS */
return 10000; /* infinity */
costnum = 0;
tputs(str, TLINES, countnum);
return costnum;
}
/*ARGSUSED*/
int
countnum(int ch)
{
costnum++;
return ch;
}

249
ex_tty.h Normal file
View File

@ -0,0 +1,249 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex_tty.h 7.5.1 (2.11BSD GTE) 12/9/94
*
* @(#)ex_tty.h 1.13 (gritter) 12/1/04
*/
#include "libterm/libterm.h"
/*
* Capabilities from termcap
*
* The description of terminals is a difficult business, and we only
* attempt to summarize the capabilities here; for a full description
* see the paper describing termcap.
*
* Capabilities from termcap are of three kinds - string valued options,
* numeric valued options, and boolean options. The string valued options
* are the most complicated, since they may include padding information,
* which we describe now.
*
* Intelligent terminals often require padding on intelligent operations
* at high (and sometimes even low) speed. This is specified by
* a number before the string in the capability, and has meaning for the
* capabilities which have a P at the front of their comment.
* This normally is a number of milliseconds to pad the operation.
* In the current system which has no true programmible delays, we
* do this by sending a sequence of pad characters (normally nulls, but
* specifiable as "pc"). In some cases, the pad is better computed
* as some number of milliseconds times the number of affected lines
* (to bottom of screen usually, except when terminals have insert modes
* which will shift several lines.) This is specified as '12*' e.g.
* before the capability to say 12 milliseconds per affected whatever
* (currently always line). Capabilities where this makes sense say P*.
*/
#ifndef VMUNIX
var char tspace[256]; /* Space for capability strings */
#else
var char tspace[1024]; /* Space for capability strings */
#endif
var char *aoftspace; /* Address of tspace for relocation */
var char *AL; /* P* Add new blank line */
var char *AL_PARM; /* P* Add n new blank lines */
extern char *BC; /* Back cursor */
var char *BT; /* P Back tab */
var char *CD; /* P* Clear to end of display */
var char *CE; /* P Clear to end of line */
var char *CL; /* P* Clear screen */
var char *CM; /* PG Cursor motion */
var char *xCS; /* PG Change scrolling region (vt100) */
var char *xCR; /* P Carriage return */
var char *DC; /* P* Delete character */
var char *DL; /* P* Delete line sequence */
var char *DL_PARM; /* P* Delete n lines */
var char *DM; /* Delete mode (enter) */
var char *DO; /* Down line sequence */
var char *DOWN_PARM; /* Down n lines */
var char *ED; /* End delete mode */
var char *EI; /* End insert mode */
var char *F0,*F1,*F2,*F3,*F4,*F5,*F6,*F7,*F8,*F9;
/* Strings sent by various function keys */
var char *HO; /* Home cursor */
var char *IC; /* P Insert character */
var char *IM; /* Insert mode (give as ':im=:' if 'ic' */
var char *IP; /* P* Insert pad after char ins'd using IM+IE */
var char *KD; /* Keypad down arrow */
var char *KE; /* Keypad don't xmit */
var char *KH; /* Keypad home key */
var char *KL; /* Keypad left arrow */
var char *KR; /* Keypad right arrow */
var char *KS; /* Keypad start xmitting */
var char *KU; /* Keypad up arrow */
var char *LEFT_PARM; /* Left n chars */
var char *LL; /* Quick to last line, column 0 */
var char *ND; /* Non-destructive space */
var char *RIGHT_PARM; /* Right n spaces */
var char *xNL; /* Line feed (new line) */
extern char PC; /* Pad character */
var char *RC; /* Restore cursor from last SC */
var char *SC; /* Save cursor */
var char *SE; /* Standout end (may leave space) */
var char *SF; /* P Scroll forwards */
var char *SO; /* Stand out begin (may leave space) */
var char *SR; /* P Scroll backwards */
var char *TA; /* P Tab (other than ^I or with padding) */
var char *TE; /* Terminal end sequence */
var char *TI; /* Terminal initial sequence */
extern char *UP; /* Upline */
var char *UP_PARM; /* Up n lines */
var char *VB; /* Visible bell */
var char *VE; /* Visual end sequence */
var char *VS; /* Visual start sequence */
var bool AM; /* Automatic margins */
var bool BS; /* Backspace works */
var bool CA; /* Cursor addressible */
var bool DA; /* Display may be retained above */
var bool DB; /* Display may be retained below */
var bool EO; /* Can erase overstrikes with ' ' */
var bool GT; /* Gtty indicates tabs */
var bool HC; /* Hard copy terminal */
#ifdef UCVISUAL
var bool xHZ; /* Hazeltine ~ braindamage */
#endif
var bool IN; /* Insert-null blessing */
var bool MI; /* can move in insert mode */
var bool NC; /* No Cr - \r snds \r\n then eats \n (dm2500) */
var bool NS; /* No scroll - linefeed at bottom won't scroll */
var bool OS; /* Overstrike works */
var bool UL; /* Underlining works even though !os */
var bool XB; /* Beehive (no escape key, simulate with f1) */
var bool XN; /* A newline gets eaten after wrap (concept) */
var bool XT; /* Tabs are destructive */
var bool XX; /* Tektronix 4025 insert line */
/* X? is reserved for severely nauseous glitches */
/* If there are enough of these we may need bit masks! */
/*
* From the tty modes...
*/
var bool NONL; /* Terminal can't hack linefeeds doing a CR */
#ifdef UCVISUAL
var bool UPPERCASE; /* Ick! */
#endif
extern short TLINES; /* Number of lines on screen */
extern short TCOLUMNS;
var short OCOLUMNS; /* Save TCOLUMNS for a hack in open mode */
#ifdef TIOCGWINSZ
var struct winsize winsz; /* Save window size for stopping comparisons */
#endif
var short outcol; /* Where the cursor is */
var short outline;
var short destcol; /* Where the cursor should be */
var short destline;
var struct termios tty; /* Use this one structure to change modes */
var struct termios normf; /* Restore tty flags to this (someday) */
var bool normtty; /* Have to restore normal mode from normf */
var short costCM; /* # chars to output a typical CM, with padding etc. */
var short costSR; /* likewise for scroll reverse */
var short costAL; /* likewise for insert line */
var short costDP; /* likewise for DOWN_PARM */
var short costLP; /* likewise for LEFT_PARM */
var short costRP; /* likewise for RIGHT_PARM */
#ifdef VMUNIX
# define MAXNOMACS 128 /* max number of macros of each kind */
# define MAXCHARMACS 2048 /* max # of chars total in macros */
#else
# define MAXNOMACS 48 /* max number of macros of each kind */
# define MAXCHARMACS 1536 /* max # of chars total in macros */
#endif
struct maps {
char *cap; /* pressing button that sends this.. */
int *icap; /* same as int */
char *mapto; /* .. maps to this string */
char *descr; /* legible description of key */
bool hadthis; /* did this mapping already (avoid recursion) */
};
var struct maps arrows[MAXNOMACS]; /* macro defs - 1st 5 built in */
var struct maps immacs[MAXNOMACS]; /* for while in insert mode */
var struct maps abbrevs[MAXNOMACS]; /* for word abbreviations */
var int ldisc; /* line discipline for ucb tty driver */
var char mapspace[MAXCHARMACS];
var int imapspace[MAXCHARMACS];
var char *msnext; /* next free location in mapspace */
var int *imsnext; /* next free location in imapspace */
var int maphopcnt; /* check for infinite mapping loops */
var bool anyabbrs; /* true if abbr or unabbr has been done */
var char ttynbuf[255]; /* result of ttyname() */
var int ttymesg; /* original mode of users tty */
extern int map(register int, register struct maps *);
extern void addmac1(register char *, register char *, register char *,
register struct maps *, int);
#define addmac(a, b, c, d) addmac1(a, b, c, d, 0)

225
ex_tune.h Normal file
View File

@ -0,0 +1,225 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex_tune.h 7.8.1 (2.11BSD) 1996/10/23
*
* @(#)ex_tune.h 1.12 (gritter) 12/1/04
*/
/*
* Note: the parameters that are actually tuneable have been moved to
* config.h. Do not make changes here unless you know what you are
* doing! GR
*/
/*
* Definitions of editor parameters and limits
*/
/*
* Pathnames (will be predefined in Makefile).
*/
#ifndef EXRECOVER
#define EXRECOVER "/usr/sbin/exrecover"
#endif
#ifndef EXPRESERVE
#define EXPRESERVE "/usr/sbin/expreserve"
#endif
#ifndef VMUNIX
#ifndef EXSTRINGS
#define EXSTRINGS "/usr/share/misc/exstrings"
#endif
#endif
/*
* If your system believes that tabs expand to a width other than
* 8 then your makefile should cc with -DTABS=whatever, otherwise we use 8.
*/
#ifndef TABS
#define TABS 8
#endif
/*
* Maximums
*
* The definition of LBSIZE should be the same as BUFSIZ (512 usually).
* Most other definitions are quite generous.
*/
/* FNSIZE is also defined in expreserve.c */
#ifdef _POSIX_PATH_MAX
#define FNSIZE _POSIX_PATH_MAX
#else
#define FNSIZE 128 /* File name size */
#endif
#ifdef VMUNIX
#define LBSIZE BUFSIZ /* Line buffer size */
#ifndef ESIZE /* see config.h */
#define ESIZE 512 /* Regular expression buffer size */
#endif
#define CRSIZE BUFSIZ /* Crypt buffer size */
#else /* !VMUNIX */
#ifdef u370
#define LBSIZE 4096
#ifndef ESIZE /* see config.h */
#define ESIZE 512
#endif
#define CRSIZE 4096
#else
#define LBSIZE 512 /* Line length */
#ifndef ESIZE /* see config.h */
#define ESIZE 128 /* Size of compiled re */
#endif
#define CRSIZE 512
#endif
#endif
#define NBRA 9 /* Number of re \( \) pairs */
#define GBSIZE 256 /* Buffer size */
#define UXBSIZE 128 /* Unix command buffer size */
#define VBSIZE 128 /* Partial line max size in visual */
/* LBLKS is also defined in expreserve.c */
#ifndef VMUNIX
#define LBLKS 125 /* Line pointer blocks in temp file */
#define HBLKS 1 /* struct header fits in BUFSIZ*HBLKS */
#else /* VMUNIX */
#ifdef LARGEF
#define LBLKS 20000
#else /* !LARGEF */
#define LBLKS 900
#endif /* !LARGEF */
#define HBLKS (1 + (FNSIZE + LBLKS * sizeof(bloc)) / BUFSIZ)
#endif /* VMUNIX */
#define MAXDIRT 12 /* Max dirtcnt before sync tfile */
/*
* Size of in-core buffers for temporary file. Since this is
* sizeof (char) * (INCORB + 1) * BUFSIZ, it should not be too
* large.
*
* If not defined, no in-core buffers are used.
*/
#ifdef VMUNIX
#if (BUFSIZ - 0) <= 16384
#define INCORB (65536/BUFSIZ)
#else /* Huge-memory systems. */
#define INCORB 4
#endif /* Huge-memory systems. */
#endif /* VMUNIX */
/*
* Except on VMUNIX, these are a ridiculously small due to the
* lousy arglist processing implementation which fixes core
* proportional to them. Argv (and hence NARGS) is really unnecessary,
* and argument character space not needed except when
* arguments exist. Argument lists should be saved before the "zero"
* of the incore line information and could then
* be reasonably large.
*/
#undef NCARGS
#ifndef VMUNIX
#define NARGS 100 /* Maximum number of names in "next" */
#define NCARGS LBSIZE /* Maximum arglist chars in "next" */
#else
#define NCARGS 5120
#define NARGS (NCARGS/6)
#endif
/*
* Output column (and line) are set to this value on cursor addressible
* terminals when we lose track of the cursor to force cursor
* addressing to occur.
*/
#define UKCOL -20 /* Prototype unknown column */
/*
* Attention is the interrupt character (normally 0177 -- delete).
* Quit is the quit signal (normally FS -- control-\) and quits open/visual.
*/
extern int ATTN;
#define QUIT ('\\' & 037)
#define LRGINT INT_MAX /* largest normal length positive integer */
#ifdef LONG_BIT
#if (LONG_BIT > 32)
#define MAXOCT 22 /* Maximum octal digits in a long */
#define BIG 10000000000000000000UL /* largest power of 10 < uns. long */
#define MAXDIGS 20 /* number of digits in BIG */
#else /* LONG_BIT <= 32 */
#define MAXOCT 11 /* Maximum octal digits in a long */
#define BIG 1000000000UL /* largest power of 10 < unsigned long */
#define MAXDIGS 10 /* number of digits in BIG */
#endif /* LONG_BIT <= 32 */
#else /* !LONG_BIT */
#define MAXOCT 11 /* Maximum octal digits in a long */
#define BIG 1000000000 /* largest power of 10 < unsigned long */
#define MAXDIGS 10 /* number of digits in BIG */
#endif /* !LONG_BIT */

450
ex_unix.c Normal file
View File

@ -0,0 +1,450 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_unix.c 1.16 (gritter) 11/23/04";
#endif
#endif
/* from ex_unix.c 7.6 (Berkeley) 10/22/85 */
#include "ex.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include "ex_vis.h"
#include <sys/wait.h>
/*
* Unix escapes, filtering
*/
/*
* First part of a shell escape,
* parse the line, expanding # and % and ! and printing if implied.
*/
void
unix0(int warn)
{
register char *up, *fp;
register short c;
char printub, puxb[UXBSIZE + sizeof (int)];
printub = 0;
CP(puxb, uxb);
c = getchar();
if (c == '\n' || c == EOF)
error(catgets(catd, 1, 192,
"Incomplete shell escape command@- use 'shell' to get a shell"));
up = uxb;
do {
switch (c) {
case '\\':
if (any(peekchar(), "%#!"))
c = getchar();
default:
if (up >= &uxb[UXBSIZE]) {
tunix:
uxb[0] = 0;
error(catgets(catd, 1, 193,
"Command too long"));
}
*up++ = c;
break;
case '!':
fp = puxb;
if (*fp == 0) {
uxb[0] = 0;
error(catgets(catd, 1, 194,
"No previous command@to substitute for !"));
}
printub++;
while (*fp) {
if (up >= &uxb[UXBSIZE])
goto tunix;
*up++ = *fp++;
}
break;
case '#':
fp = altfile;
if (*fp == 0) {
uxb[0] = 0;
error(catgets(catd, 1, 195,
"No alternate filename@to substitute for #"));
}
goto uexp;
case '%':
fp = savedfile;
if (*fp == 0) {
uxb[0] = 0;
error(catgets(catd, 1, 196,
"No filename@to substitute for %%"));
}
uexp:
printub++;
while (*fp) {
if (up >= &uxb[UXBSIZE])
goto tunix;
#ifndef BIT8
*up++ = *fp++ | QUOTE;
#else
*up++ = *fp++;
#endif
}
break;
}
c = getchar();
} while (c == '"' || c == '|' || !endcmd(c));
if (c == EOF)
ungetchar(c);
*up = 0;
if (!inopen)
resetflav();
if (warn)
ckaw();
if (warn && hush == 0 && chng && xchng != chng && value(WARN) && dol > zero) {
xchng = chng;
vnfl();
printf(mesg(catgets(catd, 1, 197,
"[No write]|[No write since last change]")));
noonl();
flush();
} else
warn = 0;
if (printub) {
if (uxb[0] == 0)
error(catgets(catd, 1, 198,
"No previous command@to repeat"));
if (inopen) {
splitw++;
vclean();
vgoto(WECHO, 0);
}
if (warn)
vnfl();
if (hush == 0)
lprintf("!%s", uxb);
if (inopen && Outchar != termchar) {
vclreol();
vgoto(WECHO, 0);
} else
putnl();
flush();
}
}
/*
* Do the real work for execution of a shell escape.
* Mode is like the number passed to open system calls
* and indicates filtering. If input is implied, newstdin
* must have been setup already.
*/
struct termios
unixex(char *opt, char *up, int newstdin, int mode)
{
int pvec[2];
struct termios f;
signal(SIGINT, SIG_IGN);
#ifdef SIGTSTP
if (dosusp)
signal(SIGTSTP, SIG_DFL);
#endif
if (inopen)
f = setty(normf);
if ((mode & 1) && pipe(pvec) < 0) {
/* Newstdin should be io so it will be closed */
if (inopen)
setty(f);
error(catgets(catd, 1, 199, "Can't make pipe for filter"));
}
#ifndef VFORK
pid = fork();
#else
pid = vfork();
#endif
if (pid < 0) {
if (mode & 1) {
close(pvec[0]);
close(pvec[1]);
}
setrupt();
error(catgets(catd, 1, 200, "No more processes"));
}
if (pid == 0) {
if (mode & 2) {
close(0);
dup(newstdin);
close(newstdin);
}
if (mode & 1) {
close(pvec[0]);
close(1);
dup(pvec[1]);
if (inopen) {
close(2);
dup(1);
}
close(pvec[1]);
}
if (io)
close(io);
if (tfile)
close(tfile);
#ifndef VMUNIX
close(erfile);
#endif
signal(SIGHUP, oldhup);
signal(SIGQUIT, oldquit);
#ifdef SIGXFSZ
signal(SIGXFSZ, oldxfsz);
#endif
if (ruptible)
signal(SIGINT, SIG_DFL);
execl(svalue(SHELL), "sh", opt, up, (char *)0);
printf(catgets(catd, 1, 201, "No %s!\n"), svalue(SHELL));
error(NOSTR);
}
if (mode & 1) {
io = pvec[0];
close(pvec[1]);
}
if (newstdin)
close(newstdin);
return (f);
}
/*
* Wait for the command to complete.
* F is for restoration of tty mode if from open/visual.
* C flags suppression of printing.
*/
void
unixwt(int c, struct termios f)
{
waitfor();
#ifdef SIGTSTP
if (dosusp)
signal(SIGTSTP, onsusp);
#endif
if (inopen)
setty(f);
setrupt();
if (!inopen && c && hush == 0) {
printf("!\n");
flush();
termreset();
gettmode();
}
}
/*
* Setup a pipeline for the filtration implied by mode
* which is like a open number. If input is required to
* the filter, then a child editor is created to write it.
* If output is catch it from io which is created by unixex.
*/
void
filter(register int mode)
{
static int pvec[2];
struct termios f; /* mjm: was register */
register int lines = lineDOL();
struct stat statb;
mode++;
if (mode & 2) {
signal(SIGINT, SIG_IGN);
if (pipe(pvec) < 0)
error(catgets(catd, 1, 202, "Can't make pipe"));
pid = fork();
io = pvec[0];
if (pid < 0) {
setrupt();
close(pvec[1]);
error(catgets(catd, 1, 203, "No more processes"));
}
if (pid == 0) {
setrupt();
io = pvec[1];
close(pvec[0]);
putfile(1);
exitex(0);
}
close(pvec[1]);
io = pvec[0];
setrupt();
}
f = unixex("-c", uxb, (mode & 2) ? pvec[0] : 0, mode);
if (mode == 3) {
delete(0);
addr2 = addr1 - 1;
} else if (mode == 1)
deletenone();
if (mode & 1) {
if(FIXUNDO)
undap1 = undap2 = addr2+1;
if (fstat(io, &statb) < 0 || statb.st_blksize > LBSIZE)
bsize = LBSIZE;
else {
bsize = statb.st_blksize;
if (bsize <= 0)
bsize = LBSIZE;
}
ignore(append(getfile, addr2));
#ifdef TRACE
if (trace)
vudump("after append in filter");
#endif
}
close(io);
io = -1;
unixwt(!inopen, f);
netchHAD(lines);
}
/*
* Set up to do a recover, getting io to be a pipe from
* the recover process.
*/
void
recover(void)
{
static int pvec[2];
if (pipe(pvec) < 0)
error(catgets(catd, 1, 204, " Can't make pipe for recovery"));
pid = fork();
io = pvec[0];
if (pid < 0) {
close(pvec[1]);
error(catgets(catd, 1, 205, " Can't fork to execute recovery"));
}
if (pid == 0) {
close(2);
dup(1);
close(1);
dup(pvec[1]);
close(pvec[1]);
execl(EXRECOVER, "exrecover", svalue(DIRECTORY), file, (char *) 0);
close(1);
dup(2);
error(catgets(catd, 1, 206, " No recovery routine"));
}
close(pvec[1]);
}
/*
* Wait for the process (pid an external) to complete.
*/
void
waitfor(void)
{
int stat = 0;
pid_t wpid;
do {
wpid = wait(&stat);
if (wpid == pid) {
status = stat;
rpid = wpid;
}
} while (wpid != -1);
if (status) {
if (WIFEXITED(status))
status = WEXITSTATUS(status);
else
status = 0;
}
}
/*
* The end of a recover operation. If the process
* exits non-zero, force not edited; otherwise force
* a write.
*/
void
revocer(void)
{
waitfor();
if (pid == rpid && status != 0)
edited = 0;
else
change();
}

527
ex_v.c Normal file
View File

@ -0,0 +1,527 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_v.c 1.17 (gritter) 11/27/04";
#endif
#endif
/* from ex_v.c 7.8.1 (2.11BSD GTE) 12/9/94 */
#include "ex.h"
#include "ex_re.h"
#include "ex_tty.h"
#include "ex_vis.h"
/*
* Entry points to open and visual from command mode processor.
* The open/visual code breaks down roughly as follows:
*
* ex_v.c entry points, checking of terminal characteristics
*
* ex_vadj.c logical screen control, use of intelligent operations
* insert/delete line and coordination with screen image;
* updating of screen after changes.
*
* ex_vget.c input of single keys and reading of input lines
* from the echo area, handling of memory for repeated
* commands and small saved texts from inserts and partline
* deletes, notification of multi line changes in the echo
* area.
*
* ex_vmain.c main command decoding, some command processing.
*
* ex_voperate.c decoding of operator/operand sequences and
* contextual scans, implementation of word motions.
*
* ex_vops.c major operator interfaces, undos, motions, deletes,
* changes, opening new lines, shifts, replacements and yanks
* coordinating logical and physical changes.
*
* ex_vops2.c subroutines for operator interfaces in ex_vops.c,
* insert mode, read input line processing at lowest level.
*
* ex_vops3.c structured motion definitions of ( ) { } and [ ] operators,
* indent for lisp routines, () and {} balancing.
*
* ex_vput.c output routines, clearing, physical mapping of logical cursor
* positioning, cursor motions, handling of insert character
* and delete character functions of intelligent and unintelligent
* terminals, visual mode tracing routines (for debugging),
* control of screen image and its updating.
*
* ex_vwind.c window level control of display, forward and backward rolls,
* absolute motions, contextual displays, line depth determination
*/
JMP_BUF venv;
/*
* Enter open mode
*/
#ifdef u370
cell atube[TUBESIZE+LBSIZE];
#endif
void
oop(void)
{
register char *ic;
#ifndef u370
cell atube[TUBESIZE + LBSIZE];
#endif
struct termios f; /* mjm: was register */
int resize;
resize = SETJMP(venv);
if (resize) {
setsize();
initev = (char *)0;
inopen = 0;
addr1 = addr2 = dot;
}
#ifdef SIGWINCH
signal(SIGWINCH, onwinch);
#endif
ovbeg();
if (peekchar() == '/') {
ignore(compile(getchar(), 1));
savere(&scanre);
if (execute(0, dot) == 0)
error(catgets(catd, 1, 207,
"Fail|Pattern not found on addressed line"));
ic = loc1;
if (ic > linebuf && *ic == 0)
ic--;
} else {
getDOT();
ic = vskipwh(linebuf);
}
newline();
/*
* If overstrike then have to HARDOPEN
* else if can move cursor up off current line can use CRTOPEN (~~vi1)
* otherwise (ugh) have to use ONEOPEN (like adm3)
*/
if (OS && !EO)
bastate = HARDOPEN;
else if (CA || UP)
bastate = CRTOPEN;
else
bastate = ONEOPEN;
setwind();
/*
* To avoid bombing on glass-crt's when the line is too long
* pretend that such terminals are 160 columns wide.
* If a line is too wide for display, we will dynamically
* switch to hardcopy open mode.
*/
if (state != CRTOPEN)
WCOLS = TUBECOLS;
if (!inglobal)
savevis();
vok(atube);
if (state != CRTOPEN)
TCOLUMNS = WCOLS;
Outchar = vputchar;
f = ostart();
if (state == CRTOPEN) {
if (outcol == UKCOL)
outcol = 0;
vmoveitup(1, 1);
} else
outline = destline = WBOT;
vshow(dot, NOLINE);
vnline(ic);
vmain();
if (state != CRTOPEN)
vclean();
Command = "open";
ovend(f);
#ifdef SIGWINCH
signal(SIGWINCH, SIG_DFL);
#endif
}
void
ovbeg(void)
{
if (!value(OPEN))
error(catgets(catd, 1, 208,
"Can't use open/visual unless open option is set"));
if (inopen)
error(catgets(catd, 1, 209,
"Recursive open/visual not allowed"));
Vlines = lineDOL();
fixzero();
setdot();
pastwh();
dot = addr2;
}
void
ovend(struct termios f)
{
splitw++;
vgoto(WECHO, 0);
vclreol();
vgoto(WECHO, 0);
holdcm = 0;
splitw = 0;
ostop(f);
setoutt();
undvis();
TCOLUMNS = OCOLUMNS;
inopen = 0;
flusho();
netchHAD(Vlines);
}
/*
* Enter visual mode
*/
void
vop(void)
{
register int c;
#ifndef u370
cell atube[TUBESIZE + LBSIZE];
#endif
struct termios f; /* mjm: was register */
int resize;
if (!CA && UP == NOSTR) {
if (initev) {
toopen:
merror(catgets(catd, 1, 210, "[Using open mode]"));
putNFL();
oop();
return;
}
error(catgets(catd, 1, 211,
"Visual needs addressible cursor or upline capability"));
}
if (OS && !EO) {
if (initev)
goto toopen;
error(catgets(catd, 1, 212,
"Can't use visual on a terminal which overstrikes"));
}
if (!CL) {
if (initev)
goto toopen;
error(catgets(catd, 1, 213,
"Visual requires clear screen capability"));
}
if (NS && !SF) {
if (initev)
goto toopen;
error(catgets(catd, 1, 214, "Visual requires scrolling"));
}
resize = SETJMP(venv);
if (resize) {
setsize();
initev = (char *)0;
inopen = 0;
addr1 = addr2 = dot;
}
#ifdef SIGWINCH
signal(SIGWINCH, onwinch);
#endif
ovbeg();
bastate = VISUAL;
c = 0;
if (any(peekchar(), "+-^."))
c = getchar();
pastwh();
vsetsiz(isdigit(peekchar()) ? getnum() : value(WINDOW));
setwind();
newline();
vok(atube);
if (!inglobal)
savevis();
Outchar = vputchar;
vmoving = 0;
f = ostart();
if (initev == 0) {
vcontext(dot, c);
vnline(NOSTR);
}
vmain();
Command = "visual";
ovend(f);
#ifdef SIGWINCH
signal(SIGWINCH, SIG_DFL);
#endif
}
/*
* Hack to allow entry to visual with
* empty buffer since routines internally
* demand at least one line.
*/
void
fixzero(void)
{
if (dol == zero) {
register bool ochng = chng;
vdoappend("");
if (!ochng)
synced();
fixedzero++;
addr1 = addr2 = one;
} else if (addr2 == zero)
addr2 = one;
}
/*
* Save lines before visual between unddol and truedol.
* Accomplish this by throwing away current [unddol,truedol]
* and then saving all the lines in the buffer and moving
* unddol back to dol. Don't do this if in a global.
*
* If you do
* g/xxx/vi.
* and then do a
* :e xxxx
* at some point, and then quit from the visual and undo
* you get the old file back. Somewhat weird.
*/
void
savevis(void)
{
if (inglobal)
return;
truedol = unddol;
saveall();
unddol = dol;
undkind = UNDNONE;
}
/*
* Restore a sensible state after a visual/open, moving the saved
* stuff back to [unddol,dol], and killing the partial line kill indicators.
*/
void
undvis(void)
{
if (ruptible)
signal(SIGINT, onintr);
squish();
pkill[0] = pkill[1] = 0;
unddol = truedol;
unddel = zero;
undap1 = one;
undap2 = dol + 1;
undkind = UNDALL;
if (undadot <= zero || undadot > dol)
undadot = zero+1;
}
/*
* Set the window parameters based on the base state bastate
* and the available buffer space.
*/
void
setwind(void)
{
WCOLS = TCOLUMNS;
switch (bastate) {
case ONEOPEN:
if (AM)
WCOLS--;
/* fall into ... */
case HARDOPEN:
basWTOP = WTOP = WBOT = WECHO = 0;
ZERO = 0;
holdcm++;
break;
case CRTOPEN:
basWTOP = TLINES - 2;
/* fall into */
case VISUAL:
ZERO = TLINES - TUBESIZE / WCOLS;
if (ZERO < 0)
ZERO = 0;
if (ZERO > basWTOP)
error(catgets(catd, 1, 215,
"Screen too large for internal buffer"));
WTOP = basWTOP; WBOT = TLINES - 2; WECHO = TLINES - 1;
break;
}
state = bastate;
basWLINES = WLINES = WBOT - WTOP + 1;
}
/*
* Can we hack an open/visual on this terminal?
* If so, then divide the screen buffer up into lines,
* and initialize a bunch of state variables before we start.
*/
void
vok(register cell *atube)
{
register int i;
if (WCOLS == 1000)
serror(catgets(catd, 1, 216,
"Don't know enough about your terminal to use %s"), Command);
if (WCOLS > TUBECOLS)
error(catgets(catd, 1, 217, "Terminal too wide"));
if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
error(catgets(catd, 1, 218, "Screen too large"));
vtube0 = atube;
vclrcell(atube, WCOLS * (WECHO - ZERO + 1));
for (i = 0; i < ZERO; i++)
vtube[i] = (cell *) 0;
for (; i <= WECHO; i++)
vtube[i] = atube, atube += WCOLS;
for (; i < TUBELINES; i++)
vtube[i] = (cell *) 0;
vutmp = (char *)atube;
vundkind = VNONE;
vUNDdot = 0;
OCOLUMNS = TCOLUMNS;
inopen = 1;
signal(SIGINT, vintr);
vmoving = 0;
splitw = 0;
doomed = 0;
holdupd = 0;
Peekkey = 0;
vcnt = vcline = 0;
if (vSCROLL == 0)
vSCROLL = value(SCROLL);
/*old vSCROLL = (value(WINDOW)+1)/2;*//* round up so dft=6,11 */
}
void
vintr(int signum)
{
extern JMP_BUF readbuf;
extern int doingread;
signal(SIGINT, vintr);
if (vcatch)
onintr(SIGINT);
ungetkey(ATTN);
draino();
if (doingread) {
doingread = 0;
LONGJMP(readbuf, 1);
}
}
/*
* Set the size of the screen to size lines, to take effect the
* next time the screen is redrawn.
*/
void
vsetsiz(int size)
{
register int b;
if (bastate != VISUAL)
return;
b = TLINES - 1 - size;
if (b >= TLINES - 1)
b = TLINES - 2;
if (b < 0)
b = 0;
basWTOP = b;
basWLINES = WBOT - b + 1;
}
#ifdef SIGWINCH
void
onwinch(int signum)
{
vsave();
setty(normf);
LONGJMP(venv, 1);
}
#endif

1160
ex_vadj.c Normal file

File diff suppressed because it is too large Load Diff

48
ex_vars.h Normal file
View File

@ -0,0 +1,48 @@
/* sccs id @(#)ex_vars.h makeoptions 1.8 (gritter) 7/1/02 */
#define AUTOINDENT 0
#define AUTOPRINT 1
#define AUTOWRITE 2
#define BEAUTIFY 3
#define DIRECTORY 4
#define EDCOMPATIBLE 5
#define ERRORBELLS 6
#define EXRC 7
#define FLASH 8
#define HARDTABS 9
#define IGNORECASE 10
#define LISP 11
#define LIST 12
#define MAGIC 13
#define MESG 14
#define MODELINES 15
#define NUMBER 16
#define OPEN 17
#define OPTIMIZE 18
#define PARAGRAPHS 19
#define PROMPT 20
#define READONLY 21
#define REDRAW 22
#define REMAP 23
#define REPORT 24
#define SCROLL 25
#define SECTIONS 26
#define SHELL 27
#define SHIFTWIDTH 28
#define SHOWMATCH 29
#define SHOWMODE 30
#define SLOWOPEN 31
#define SOURCEANY 32
#define TABSTOP 33
#define TAGLENGTH 34
#define TAGS 35
#define TERM 36
#define TERSE 37
#define TIMEOUT 38
#define TTYTYPE 39
#define WARN 40
#define WINDOW 41
#define WRAPSCAN 42
#define WRAPMARGIN 43
#define WRITEANY 44
#define NOPTS 45

90
ex_version.c Normal file
View File

@ -0,0 +1,90 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* Sccsid @(#)ex_version.c 1.107 (gritter) 12/2/04
*/
#include "ex.h"
static char *versionstring = "@(#)Version 4.0 (gritter) 12/2/04";
void
printver(void)
{
printf("%s%s%s", versionstring + 4,
#ifdef BIT8
"", ""
#else
",", "@(#) 7bit" + 4
#endif
);
}

876
ex_vget.c Normal file
View File

@ -0,0 +1,876 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_vget.c 1.26 (gritter) 11/27/04";
#endif
#endif
/* from ex_vget.c 6.8.1 (2.11BSD GTE) 12/9/94 */
#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
/*
* Input routines for open/visual.
* We handle reading from the echo area here as well as notification on
* large changes which appears in the echo area.
*/
/*
* Return the key.
*/
void
ungetkey (
int c /* mjm: char --> int */
)
{
if (Peekkey != ATTN)
Peekkey = c;
}
/*
* Return a keystroke, but never a ^@.
*/
int
getkey(void)
{
register int c; /* mjm: char --> int */
do {
c = getbr();
if (c==0)
beep();
} while (c == 0);
return (c);
}
/*
* Tell whether next keystroke would be a ^@.
*/
int
peekbr(void)
{
Peekkey = getbr();
return (Peekkey == 0);
}
short precbksl;
JMP_BUF readbuf;
int doingread = 0;
static int
readwc(int fd, int *cp)
{
int c;
char b;
#ifdef MB
if (mb_cur_max > 1) {
static char pbuf[2][MB_LEN_MAX], *pend[2], *pcur[2];
static mbstate_t state[2];
static int incompl[2];
int i, rest;
int idx = fd ? 1 : 0;
wchar_t wc;
size_t sz;
i = 0;
rest = pend[idx] - pcur[idx];
if (rest && pcur[idx] > pbuf[idx]) {
do
pbuf[idx][i] = pcur[idx][i];
while (i++, --rest);
} else if (incompl[idx]) {
pend[idx] = pcur[idx] = NULL;
return -1;
}
if (i == 0) {
if ((c = read(fd, &b, 1)) <= 0) {
pend[idx] = pcur[idx] = NULL;
return c;
}
pbuf[idx][i++] = b;
}
if (pbuf[idx][0] & 0200) {
sz = 1;
while (pbuf[idx][i-1] & 0200 && i < mb_cur_max &&
(sz = mbrtowc(&wc, pbuf[idx], i,
&state[idx])) == (size_t)-2) {
if ((c = read(fd, &b, 1)) <= 0) {
incompl[idx] = 1;
break;
} else
pbuf[idx][i++] = b;
memset(&state[idx], 0, sizeof state[idx]);
}
if (sz == (size_t)-2 || sz == (size_t)-1 ||
!widthok(wc)) {
memset(&state[idx], 0, sizeof state[idx]);
c = 1;
*cp = pbuf[idx][0] | INVBIT;
} else if (sz == 0) {
c = 1;
*cp = wc;
} else {
c = sz;
*cp = wc;
}
} else {
c = 1;
*cp = pbuf[idx][0];
}
pcur[idx] = &pbuf[idx][c];
pend[idx] = &pcur[idx][i-c];
return c;
} else
#endif /* MB */
{
c = read(fd, &b, 1);
*cp = b;
return c;
}
}
/*
* Get a keystroke, including a ^@.
* If an key was returned with ungetkey, that
* comes back first. Next comes unread input (e.g.
* from repeating commands with .), and finally new
* keystrokes.
*/
int
getbr(void)
{
int ch;
register int c;
#ifdef UCVISUAL
register int d;
register char *colp;
#endif
#ifdef BEEHIVE
int cnt;
static char Peek2key;
#endif
extern short slevel, ttyindes;
getATTN:
if (Peekkey) {
c = Peekkey;
Peekkey = 0;
return (c);
}
#ifdef BEEHIVE
if (Peek2key) {
c = Peek2key;
Peek2key = 0;
return (c);
}
#endif
if (vglobp) {
if (*vglobp)
return (lastvgk = *vglobp++);
lastvgk = 0;
return (ESCAPE);
}
if (vmacp) {
if (*vmacp) {
int n;
nextc(ch, vmacp, n);
vmacp += n;
return (ch);
}
/* End of a macro or set of nested macros */
vmacp = 0;
if (inopen == -1) /* don't screw up undo for esc esc */
vundkind = VMANY;
inopen = 1; /* restore old setting now that macro done */
vch_mac = VC_NOTINMAC;
}
flusho();
for (c =0; abbrevs[c].mapto; c++)
abbrevs[c].hadthis = 0;
#ifdef UCVISUAL
again:
#endif
if (SETJMP(readbuf))
goto getATTN;
doingread = 1;
c = readwc(slevel == 0 ? 0 : ttyindes, &ch);
doingread = 0;
if (c < 1) {
if (errno == EINTR)
goto getATTN;
error(catgets(catd, 1, 222, "Input read error"));
}
c = ch & TRIM;
#ifdef BEEHIVE
if (XB && slevel==0 && c == ESCAPE) {
if (readwc(0, &Peek2key) < 1)
goto getATTN;
Peek2key &= TRIM;
switch (Peek2key) {
case 'C': /* SPOW mode sometimes sends \EC for space */
c = ' ';
Peek2key = 0;
break;
case 'q': /* f2 -> ^C */
c = CTRL('c');
Peek2key = 0;
break;
case 'p': /* f1 -> esc */
Peek2key = 0;
break;
}
}
#endif
#ifdef UCVISUAL
/*
* The algorithm here is that of the UNIX kernel.
* See the description in the programmers manual.
*/
if (UPPERCASE) {
if (xisupper(c))
c = xtolower(c);
if (c == '\\') {
if (precbksl < 2)
precbksl++;
if (precbksl == 1)
goto again;
} else if (precbksl) {
d = 0;
if (xislower(c))
d = xtoupper(c);
else {
colp = "({)}!|^~'~";
while (d = *colp++)
if (d == c) {
d = *colp++;
break;
} else
colp++;
}
if (precbksl == 2) {
if (!d) {
Peekkey = c;
precbksl = 0;
c = '\\';
}
} else if (d)
c = d;
else {
Peekkey = c;
precbksl = 0;
c = '\\';
}
}
if (c != '\\')
precbksl = 0;
}
#endif
#ifdef TRACE
if (trace) {
if (!techoin) {
tfixnl();
techoin = 1;
fprintf(trace, "*** Input: ");
}
tracec(c);
}
#endif
lastvgk = 0;
return (c);
}
/*
* Get a key, but if a delete, quit or attention
* is typed return 0 so we will abort a partial command.
*/
int
getesc(void)
{
register int c;
c = getkey();
if (c == ATTN)
goto case_ATTN;
switch (c) {
case CTRL('v'):
case CTRL('q'):
c = getkey();
return (c);
case QUIT:
case_ATTN:
ungetkey(c);
return (0);
case ESCAPE:
return (0);
}
return (c);
}
/*
* Peek at the next keystroke.
*/
int
peekkey(void)
{
Peekkey = getkey();
return (Peekkey);
}
/*
* Read a line from the echo area, with single character prompt c.
* A return value of 1 means the user blewit or blewit away.
*/
int
readecho(int c)
{
register char *sc = cursor;
register void (*OP)(int);
bool waste;
register int OPeek;
if (WBOT == WECHO)
vclean();
else
vclrech(0);
splitw++;
vgoto(WECHO, 0);
putchar(c);
vclreol();
vgoto(WECHO, 1);
cursor = linebuf; linebuf[0] = 0; genbuf[0] = c;
if (peekbr()) {
if (!INS[0] || (INS[0] & (QUOTE|TRIM)) == OVERBUF)
goto blewit;
vglobp = INS;
}
OP = Pline; Pline = normline;
ignore(vgetline(0, genbuf + 1, &waste, c));
if (Outchar == termchar)
putchar('\n');
vscrap();
Pline = OP;
if (Peekkey != ATTN && Peekkey != QUIT && Peekkey != CTRL('h')) {
cursor = sc;
vclreol();
return (0);
}
blewit:
OPeek = Peekkey==CTRL('h') ? 0 : Peekkey; Peekkey = 0;
splitw = 0;
vclean();
vshow(dot, NOLINE);
vnline(sc);
Peekkey = OPeek;
return (1);
}
/*
* A complete command has been defined for
* the purposes of repeat, so copy it from
* the working to the previous command buffer.
*/
void
setLAST(void)
{
if (vglobp || vmacp)
return;
lastreg = vreg;
lasthad = Xhadcnt;
lastcnt = Xcnt;
*lastcp = 0;
cellcpy(lastcmd, workcmd);
}
/*
* Gather up some more text from an insert.
* If the insertion buffer oveflows, then destroy
* the repeatability of the insert.
*/
void
addtext(char *cp)
{
if (vglobp)
return;
addto(INS, cp);
if ((INS[0] & (QUOTE|TRIM)) == OVERBUF)
lastcmd[0] = 0;
}
void
setDEL(void)
{
setBUF(DEL);
}
/*
* Put text from cursor upto wcursor in BUF.
*/
void
setBUF(register cell *BUF)
{
register int c;
register char *wp = wcursor;
c = *wp;
*wp = 0;
BUF[0] = 0;
addto(BUF, cursor);
*wp = c;
}
void
addto(register cell *buf, register char *str)
{
if ((buf[0] & (QUOTE|TRIM)) == OVERBUF)
return;
if (cellen(buf) + strlen(str) + 1 >= VBSIZE) {
buf[0] = OVERBUF;
return;
}
while (*buf)
buf++;
str2cell(buf, str);
}
/*
* Note a change affecting a lot of lines, or non-visible
* lines. If the parameter must is set, then we only want
* to do this for open modes now; return and save for later
* notification in visual.
*/
int
noteit(int must)
{
register int sdl = destline, sdc = destcol;
if (notecnt < 2 || !must && state == VISUAL)
return (0);
splitw++;
if (WBOT == WECHO)
vmoveitup(1, 1);
vigoto(WECHO, 0);
printf(catgets(catd, 1, 223, "%d %sline"), notecnt, notesgn);
if (notecnt > 1)
putchar('s');
if (*notenam) {
printf(" %s", notenam);
if (*(strend(notenam) - 1) != 'e')
putchar('e');
putchar('d');
}
vclreol();
notecnt = 0;
if (state != VISUAL)
vcnt = vcline = 0;
splitw = 0;
if (state == ONEOPEN || state == CRTOPEN)
vup1();
destline = sdl; destcol = sdc;
return (1);
}
/*
* Rrrrringgggggg.
* If possible, use flash (VB).
*/
void
beep(void)
{
if (VB && value(FLASH))
vputp(VB, 0);
else
vputc(CTRL('g'));
}
/*
* Push an integer string as a macro.
*/
static void
imacpush(int *ip, int canundo)
{
char buf[BUFSIZ], *bp = buf;
int n;
do {
n = wctomb(bp, *ip&TRIM);
bp += n;
} while (*ip++);
macpush(buf, canundo);
}
/*
* Map the command input character c,
* for keypads and labelled keys which do cursor
* motions. I.e. on an adm3a we might map ^K to ^P.
* DM1520 for example has a lot of mappable characters.
*/
int
map(register int c, register struct maps *maps)
{
register int d;
register int *p, *q;
int b[10+MB_LEN_MAX]; /* Assumption: no keypad sends string longer than 10 */
/*
* Mapping for special keys on the terminal only.
* BUG: if there's a long sequence and it matches
* some chars and then misses, we lose some chars.
*
* For this to work, some conditions must be met.
* 1) Keypad sends SHORT (2 or 3 char) strings
* 2) All strings sent are same length & similar
* 3) The user is unlikely to type the first few chars of
* one of these strings very fast.
* Note: some code has been fixed up since the above was laid out,
* so conditions 1 & 2 are probably not required anymore.
* However, this hasn't been tested with any first char
* that means anything else except escape.
*/
#ifdef MDEBUG
if (trace)
fprintf(trace,"map(%c): ",c);
#endif
/*
* If c==0, the char came from getesc typing escape. Pass it through
* unchanged. 0 messes up the following code anyway.
*/
if (c==0)
return(0);
b[0] = c;
b[1] = 0;
for (d=0; maps[d].mapto; d++) {
#ifdef MDEBUG
if (trace)
fprintf(trace,"\ntry '%s', ",maps[d].cap);
#endif
if (p = maps[d].icap) {
for (q=b; *p; p++, q++) {
#ifdef MDEBUG
if (trace)
fprintf(trace,"q->b[%d], ",q-b);
#endif
if (*q==0) {
/*
* Is there another char waiting?
*
* This test is oversimplified, but
* should work mostly. It handles the
* case where we get an ESCAPE that
* wasn't part of a keypad string.
*/
if ((c=='#' ? peekkey() : fastpeekkey()) == 0) {
#ifdef MDEBUG
if (trace)
fprintf(trace,"fpk=0: will return '%c'",c);
#endif
/*
* Nothing waiting. Push back
* what we peeked at & return
* failure (c).
*
* We want to be able to undo
* commands, but it's nonsense
* to undo part of an insertion
* so if in input mode don't.
*/
#ifdef MDEBUG
if (trace)
fprintf(trace, "Call macpush, b %d %d %d\n", b[0], b[1], b[2]);
#endif
imacpush(&b[1],maps == arrows);
#ifdef MDEBUG
if (trace)
fprintf(trace, "return %d\n", c);
#endif
return(c);
}
*q = getkey();
q[1] = 0;
}
if (*p != *q)
goto contin;
}
macpush(maps[d].mapto,maps == arrows);
c = getkey();
#ifdef MDEBUG
if (trace)
fprintf(trace,"Success: push(%s), return %c",maps[d].mapto, c);
#endif
return(c); /* first char of map string */
contin:;
}
}
#ifdef MDEBUG
if (trace)
fprintf(trace,"Fail: push(%s), return %c", &b[1], c);
#endif
imacpush(&b[1],0);
return(c);
}
/*
* Push st onto the front of vmacp. This is tricky because we have to
* worry about where vmacp was previously pointing. We also have to
* check for overflow (which is typically from a recursive macro)
* Finally we have to set a flag so the whole thing can be undone.
* canundo is 1 iff we want to be able to undo the macro. This
* is false for, for example, pushing back lookahead from fastpeekkey(),
* since otherwise two fast escapes can clobber our undo.
*/
void
macpush(char *st, int canundo)
{
char tmpbuf[BUFSIZ];
if (st==0 || *st==0)
return;
#ifdef MDEBUG
if (trace)
fprintf(trace, "macpush(%s), canundo=%d\n",st,canundo);
#endif
if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZ)
error(catgets(catd, 1, 224,
"Macro too long@ - maybe recursive?"));
if (vmacp) {
strcpy(tmpbuf, vmacp);
if (!FIXUNDO)
canundo = 0; /* can't undo inside a macro anyway */
}
strcpy(vmacbuf, st);
if (vmacp)
strcat(vmacbuf, tmpbuf);
vmacp = vmacbuf;
/* arrange to be able to undo the whole macro */
if (canundo) {
#ifdef notdef
otchng = tchng;
vsave();
saveall();
inopen = -1; /* no need to save since it had to be 1 or -1 before */
vundkind = VMANY;
#endif
vch_mac = VC_NOCHANGE;
}
}
#ifdef TRACE
void
visdump(char *s)
{
register int i;
if (!trace) return;
fprintf(trace, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n",
s, basWTOP, basWLINES, WTOP, WBOT, WLINES, WCOLS, WECHO);
fprintf(trace, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n",
vcnt, vcline, cursor-linebuf, wcursor-linebuf, wdot-zero);
for (i=0; i<TUBELINES; i++)
if (vtube[i] && *vtube[i])
fprintf(trace, "%d: '%s'\n", i, vtube[i]);
tvliny();
}
void
vudump(char *s)
{
register line *p;
char savelb[1024];
if (!trace) return;
fprintf(trace, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n",
s, undkind, vundkind, lineno(unddel), lineno(undap1), lineno(undap2));
fprintf(trace, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n",
lineno(undadot), lineno(dot), lineno(dol), lineno(unddol), lineno(truedol));
fprintf(trace, " [\n");
CP(savelb, linebuf);
fprintf(trace, "linebuf = '%s'\n", linebuf);
for (p=zero+1; p<=truedol; p++) {
fprintf(trace, "%o ", *p);
getline(*p);
fprintf(trace, "'%s'\n", linebuf);
}
fprintf(trace, "]\n");
CP(linebuf, savelb);
}
#endif
/*
* Get a count from the keyed input stream.
* A zero count is indistinguishable from no count.
*/
int
vgetcnt(void)
{
register int c, cnt;
cnt = 0;
for (;;) {
c = getkey();
if (!xisdigit(c))
break;
cnt *= 10, cnt += c - '0';
}
ungetkey(c);
Xhadcnt = 1;
Xcnt = cnt;
return(cnt);
}
void
trapalarm(int signum) {
alarm(0);
if (vcatch)
LONGJMP(vreslab,1);
}
/*
* fastpeekkey is just like peekkey but insists the character come in
* fast (within 1 second). This will succeed if it is the 2nd char of
* a machine generated sequence (such as a function pad from an escape
* flavor terminal) but fail for a human hitting escape then waiting.
*/
int
fastpeekkey(void)
{
shand Oint;
register int c;
/*
* If the user has set notimeout, we wait forever for a key.
* If we are in a macro we do too, but since it's already
* buffered internally it will return immediately.
* In other cases we force this to die in 1 second.
* This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs,
* but UNIX truncates it to 0 - 1 secs) but due to system delays
* there are times when arrow keys or very fast typing get counted
* as separate. notimeout is provided for people who dislike such
* nondeterminism.
*/
#ifdef MDEBUG
if (trace)
fprintf(trace,"\nfastpeekkey: ",c);
#endif
Oint = signal(SIGINT, trapalarm);
if (value(TIMEOUT) && inopen >= 0) {
signal(SIGALRM, trapalarm);
#ifdef MDEBUG
alarm(10);
if (trace)
fprintf(trace, "set alarm ");
#else
alarm(1);
#endif
}
CATCH
c = peekkey();
#ifdef MDEBUG
if (trace)
fprintf(trace,"[OK]",c);
#endif
alarm(0);
ONERR
c = 0;
#ifdef MDEBUG
if (trace)
fprintf(trace,"[TIMEOUT]",c);
#endif
ENDCATCH
#ifdef MDEBUG
if (trace)
fprintf(trace,"[fpk:%o]",c);
#endif
signal(SIGINT,Oint);
return(c);
}

321
ex_vis.h Normal file
View File

@ -0,0 +1,321 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* from ex_vis.h 7.4 (Berkeley) 5/31/85
*
* @(#)ex_vis.h 1.15 (gritter) 11/27/04
*/
/*
* Ex version 3
* Mark Horton, UCB
* Bill Joy UCB
*
* Open and visual mode definitions.
*
* There are actually 4 major states in open/visual modes. These
* are visual, crt open (where the cursor can move about the screen and
* the screen can scroll and be erased), one line open (on dumb glass-crt's
* like the adm3), and hardcopy open (for everything else).
*
* The basic state is given by bastate, and the current state by state,
* since we can be in pseudo-hardcopy mode if we are on an adm3 and the
* line is longer than 80.
*/
var enum {
VISUAL = 0,
CRTOPEN = 1,
ONEOPEN = 2,
HARDOPEN = 3
} bastate, state;
/*
* The screen in visual and crtopen is of varying size; the basic
* window has top basWTOP and basWLINES lines are thereby implied.
* The current window (which may have grown from the basic size)
* has top WTOP and WLINES lines. The top line of the window is WTOP,
* and the bottom line WBOT. The line WECHO is used for messages,
* search strings and the like. If WBOT==WECHO then we are in ONEOPEN
* or HARDOPEN and there is no way back to the line we were on if we
* go to WECHO (i.e. we will have to scroll before we go there, and
* we can't get back). There are WCOLS columns per line.
* If WBOT!=WECHO then WECHO will be the last line on the screen
* and WBOT is the line before it.
*/
var short basWTOP;
var short basWLINES;
var short WTOP;
var short WBOT;
var short WLINES;
var short WCOLS;
var short WECHO;
/*
* When we are dealing with the echo area we consider the window
* to be "split" and set the variable splitw. Otherwise, moving
* off the bottom of the screen into WECHO causes a screen rollup.
*/
var bool splitw;
/*
* Information about each line currently on the screen includes
* the y coordinate associated with the line, the printing depth
* of the line (0 indicates unknown), and a mask which indicates
* whether the line is "unclean", i.e. whether we should check
* to make sure the line is displayed correctly at the next
* appropriate juncture.
*/
struct vlinfo {
short vliny; /* Y coordinate */ /* mjm: was char */
short vdepth; /* Depth of displayed line */ /*mjm: was char */
short vflags; /* Is line potentially dirty ? */
};
var struct vlinfo vlinfo[TUBELINES + 2];
#define DEPTH(c) (vlinfo[c].vdepth)
#define LINE(c) (vlinfo[c].vliny)
#define FLAGS(c) (vlinfo[c].vflags)
#define VDIRT 1
/*
* Hacks to copy vlinfo structures around
*/
# define vlcopy(i, j) i = j;
/*
* The current line on the screen is represented by vcline.
* There are vcnt lines on the screen, the last being "vcnt - 1".
* Vcline is intimately tied to the current value of dot,
* and when command mode is used as a subroutine fancy footwork occurs.
*/
var short vcline;
var short vcnt;
/*
* To allow many optimizations on output, an exact image of the terminal
* screen is maintained in the space addressed by vtube0. The vtube
* array indexes this space as lines, and is shuffled on scrolls, insert+delete
* lines and the like rather than (more expensively) shuffling the screen
* data itself. It is also rearranged during insert mode across line
* boundaries to make incore work easier.
*/
var cell *vtube[TUBELINES];
var cell *vtube0;
/*
* The current cursor position within the current line is kept in
* cursor. The current line is kept in linebuf. During insertions
* we use the auxiliary array genbuf as scratch area.
* The cursor wcursor and wdot are used in operations within/spanning
* lines to mark the other end of the affected area, or the target
* for a motion.
*/
var char *cursor;
var char *wcursor;
var line *wdot;
/*
* Undo information is saved in a LBSIZE buffer at "vutmp" for changes
* within the current line, or as for command mode for multi-line changes
* or changes on lines no longer the current line.
* The change kind "VCAPU" is used immediately after a U undo to prevent
* two successive U undo's from destroying the previous state.
*/
#define VNONE 0
#define VCHNG 1
#define VMANY 2
#define VCAPU 3
#define VMCHNG 4
#define VMANYINS 5
var short vundkind; /* Which kind of undo - from above */
var char *vutmp; /* Prev line image when "VCHNG" */
/*
* State information for undoing of macros. The basic idea is that
* if the macro does only 1 change or even none, we don't treat it
* specially. If it does 2 or more changes we want to be able to
* undo it as a unit. We remember how many changes have been made
* within the current macro. (Remember macros can be nested.)
*/
#define VC_NOTINMAC 0 /* Not in a macro */
#define VC_NOCHANGE 1 /* In a macro, no changes so far */
#define VC_ONECHANGE 2 /* In a macro, one change so far */
#define VC_MANYCHANGE 3 /* In a macro, at least 2 changes so far */
var short vch_mac; /* Change state - one of the above */
/*
* For U undo's the line is grabbed by "vmove" after it first appears
* on that line. The "vUNDdot" which specifies which line has been
* saved is selectively cleared when changes involving other lines
* are made, i.e. after a 'J' join. This is because a 'JU' would
* lose completely the text of the line just joined on.
*/
var char *vUNDcurs; /* Cursor just before 'U' */
var line *vUNDdot; /* The line address of line saved in vUNDsav */
var line vUNDsav; /* Grabbed initial "*dot" */
#define killU() vUNDdot = NOLINE
/*
* There are a number of cases where special behaviour is needed
* from deeply nested routines. This is accomplished by setting
* the bits of hold, which acts to change the state of the general
* visual editing behaviour in specific ways.
*
* HOLDAT prevents the clreol (clear to end of line) routines from
* putting out @'s or ~'s on empty lines.
*
* HOLDDOL prevents the reopen routine from putting a '$' at the
* end of a reopened line in list mode (for hardcopy mode, e.g.).
*
* HOLDROL prevents spurious blank lines when scrolling in hardcopy
* open mode.
*
* HOLDQIK prevents the fake insert mode during repeated commands.
*
* HOLDPUPD prevents updating of the physical screen image when
* mucking around while in insert mode.
*
* HOLDECH prevents clearing of the echo area while rolling the screen
* backwards (e.g.) in deference to the clearing of the area at the
* end of the scroll (1 time instead of n times). The fact that this
* is actually needed is recorded in heldech, which says that a clear
* of the echo area was actually held off.
*/
var short hold;
var short holdupd; /* Hold off update when echo line is too long */
#define HOLDAT 1
#define HOLDDOL 2
#define HOLDROL 4
#define HOLDQIK 8
#define HOLDPUPD 16
#define HOLDECH 32
#define HOLDWIG 64
/*
* Miscellaneous variables
*/
var short CDCNT; /* Count of ^D's in insert on this line */
var cell DEL[VBSIZE]; /* Last deleted text */
var bool HADUP; /* This insert line started with ^ then ^D */
var bool HADZERO; /* This insert line started with 0 then ^D */
var cell INS[VBSIZE]; /* Last inserted text */
var int Vlines; /* Number of file lines "before" vi command */
var int Xcnt; /* External variable holding last cmd's count */
var bool Xhadcnt; /* Last command had explicit count? */
var short ZERO;
var short dir; /* Direction for search (+1 or -1) */
var short doomed; /* Disply chars right of cursor to be killed */
var bool gobblebl; /* Wrapmargin space generated nl, eat a space */
var bool hadcnt; /* (Almost) internal to vmain() */
var bool heldech; /* We owe a clear of echo area */
var bool insmode; /* Are in character insert mode */
var cell lastcmd[5]; /* Chars in last command */
var int lastcnt; /* Count for last command */
var cell *lastcp; /* Save current command here to repeat */
var bool lasthad; /* Last command had a count? */
var short lastvgk; /* Previous input key, if not from keyboard */
var short lastreg; /* Register with last command */
var char *ncols['z'-'a'+2]; /* Cursor positions of marks */
var char *notenam; /* Name to be noted with change count */
var char *notesgn; /* Change count from last command */
var int op; /* Operation of current command */
var int Peekkey; /* Peek ahead key */
var bool rubble; /* Line is filthy (in hardcopy open), redraw! */
var int vSCROLL; /* Number lines to scroll on ^D/^U */
var cell *vglobp; /* Untyped input (e.g. repeat insert text) */
var char vmacbuf[VBSIZE]; /* Text of visual macro, hence nonnestable */
var char *vmacp; /* Like vglobp but for visual macros */
var char *vmcurs; /* Cursor for restore after undo d), e.g. */
var short vmovcol; /* Column to try to keep on arrow keys */
var bool vmoving; /* Are trying to keep vmovcol */
var short vreg; /* Reg for this command */ /* mjm: was char */
var short wdkind; /* Liberal/conservative words? */
var cell workcmd[5]; /* Temporary for lastcmd */
var char *vcolbp; /* first byte of current character in column */
/*
* Macros
*/
#define INF 30000
#define LASTLINE LINE(vcnt)
#define OVERBUF QUOTE
#define beep obeep
#define cindent() ((outline - vlinfo[vcline].vliny) * WCOLS + outcol)
#define vputp(cp, cnt) tputs(cp, cnt, vputch)
#define vputc(c) putch(c)

1438
ex_vmain.c Normal file

File diff suppressed because it is too large Load Diff

975
ex_voper.c Normal file
View File

@ -0,0 +1,975 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_voper.c 1.23 (gritter) 12/1/04";
#endif
#endif
/* from ex_voper.c 7.4 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_re.h"
#include "ex_tty.h"
#include "ex_vis.h"
#ifdef MB
static int
cblank(char *cp)
{
if (mb_cur_max > 1 && *cp & 0200) {
int c;
return mbtowi(&c, cp, mb_cur_max) > 0 && iswspace(c);
} else
return isspace(*cp&0377);
}
#define blank() cblank(wcursor)
#else /* !MB */
#define cblank(cp) isspace(*cp&0377)
#define blank() xisspace(wcursor[0]&TRIM)
#endif /* !MB */
#define forbid(a) if (a) goto errlab;
cell vscandir[2] = { '/', 0 };
/*
* Decode an operator/operand type command.
* Eventually we switch to an operator subroutine in ex_vops.c.
* The work here is setting up a function variable to point
* to the routine we want, and manipulation of the variables
* wcursor and wdot, which mark the other end of the affected
* area. If wdot is zero, then the current line is the other end,
* and if wcursor is zero, then the first non-blank location of the
* other line is implied.
*/
void
operate(register int c, register int cnt)
{
register int i = 0;
void (*moveop)(int), (*deleteop)(int);
void (*opf)(int);
bool subop = 0;
char *oglobp, *ocurs;
register line *addr;
line *odot;
static int lastFKND, lastFCHR;
short d;
cell nullcell[1], qmarkcell[2], slashcell[2];
CLOBBGRD(opf);
CLOBBGRD(d);
qmarkcell[0] = '?';
slashcell[0] = '/';
nullcell[0] = qmarkcell[1] = slashcell[1] = 0;
moveop = vmove, deleteop = vdelete;
wcursor = cursor;
wdot = NOLINE;
notecnt = 0;
dir = 1;
switch (c) {
/*
* d delete operator.
*/
case 'd':
moveop = vdelete;
deleteop = (void (*)(int))beep;
break;
/*
* s substitute characters, like c\040, i.e. change space.
*/
case 's':
ungetkey(' ');
subop++;
/* fall into ... */
/*
* c Change operator.
*/
case 'c':
if (c == 'c' && workcmd[0] == 'C' || workcmd[0] == 'S')
subop++;
moveop = vchange;
deleteop = (void (*)(int))beep;
break;
/*
* ! Filter through a UNIX command.
*/
case '!':
moveop = vfilter;
deleteop = (void (*)(int))beep;
break;
/*
* y Yank operator. Place specified text so that it
* can be put back with p/P. Also yanks to named buffers.
*/
case 'y':
moveop = vyankit;
deleteop = (void (*)(int))beep;
break;
/*
* = Reformat operator (for LISP).
*/
#ifdef LISPCODE
case '=':
forbid(!value(LISP));
/* fall into ... */
#endif
/*
* > Right shift operator.
* < Left shift operator.
*/
case '<':
case '>':
moveop = vshftop;
deleteop = (void (*)(int))beep;
break;
/*
* r Replace character under cursor with single following
* character.
*/
case 'r':
vmacchng(1);
vrep(cnt);
return;
default:
goto nocount;
}
vmacchng(1);
/*
* Had an operator, so accept another count.
* Multiply counts together.
*/
if (xisdigit(peekkey()) && peekkey() != '0') {
cnt *= vgetcnt();
Xcnt = cnt;
forbid (cnt <= 0);
}
/*
* Get next character, mapping it and saving as
* part of command for repeat.
*/
c = map(getesc(),arrows);
if (c == 0)
return;
if (!subop)
*lastcp++ = c;
nocount:
opf = moveop;
switch (c) {
/*
* b Back up a word.
* B Back up a word, liberal definition.
*/
case 'b':
case 'B':
dir = -1;
/* fall into ... */
/*
* w Forward a word.
* W Forward a word, liberal definition.
*/
case 'W':
case 'w':
wdkind = c & ' ';
forbid(llfind(2, cnt, opf, 0) < 0);
vmoving = 0;
break;
/*
* E to end of following blank/nonblank word
*/
case 'E':
wdkind = 0;
goto ein;
/*
* e To end of following word.
*/
case 'e':
wdkind = 1;
ein:
forbid(llfind(3, cnt - 1, opf, 0) < 0);
vmoving = 0;
break;
/*
* ( Back an s-expression.
*/
case '(':
dir = -1;
/* fall into... */
/*
* ) Forward an s-expression.
*/
case ')':
forbid(llfind(0, cnt, opf, (line *) 0) < 0);
markDOT();
break;
/*
* { Back an s-expression, but don't stop on atoms.
* In text mode, a paragraph. For C, a balanced set
* of {}'s.
*/
case '{':
dir = -1;
/* fall into... */
/*
* } Forward an s-expression, but don't stop on atoms.
* In text mode, back paragraph. For C, back a balanced
* set of {}'s.
*/
case '}':
forbid(llfind(1, cnt, opf, (line *) 0) < 0);
markDOT();
break;
/*
* % To matching () or {}. If not at ( or { scan for
* first such after cursor on this line.
*/
case '%':
vsave();
i = lmatchp((line *) 0);
#ifdef TRACE
if (trace)
fprintf(trace, "after lmatchp in %, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol));
#endif
getDOT();
forbid(!i);
if (opf != vmove)
if (dir > 0)
wcursor += skipright(linebuf, wcursor);
else
cursor += skipright(linebuf, cursor);
else
markDOT();
vmoving = 0;
break;
/*
* [ Back to beginning of defun, i.e. an ( in column 1.
* For text, back to a section macro.
* For C, back to a { in column 1 (~~ beg of function.)
*/
case '[':
dir = -1;
/* fall into ... */
/*
* ] Forward to next defun, i.e. a ( in column 1.
* For text, forward section.
* For C, forward to a } in column 1 (if delete or such)
* or if a move to a { in column 1.
*/
case ']':
if (!vglobp)
forbid(getkey() != c);
forbid (Xhadcnt);
vsave();
i = lbrack(c, opf);
getDOT();
forbid(!i);
markDOT();
if (ospeed > B300)
hold |= HOLDWIG;
break;
/*
* , Invert last find with f F t or T, like inverse
* of ;.
*/
case ',':
forbid (lastFKND == 0);
c = xisupper(lastFKND&TRIM)
? xtolower(lastFKND&TRIM) : xtoupper(lastFKND&TRIM);
i = lastFCHR;
if (vglobp == 0)
vglobp = nullcell;
subop++;
goto nocount;
/*
* 0 To beginning of real line.
*/
case '0':
wcursor = linebuf;
vmoving = 0;
break;
/*
* ; Repeat last find with f F t or T.
*/
case ';':
forbid (lastFKND == 0);
c = lastFKND;
i = lastFCHR;
subop++;
goto nocount;
/*
* F Find single character before cursor in current line.
* T Like F, but stops before character.
*/
case 'F': /* inverted find */
case 'T':
dir = -1;
/* fall into ... */
/*
* f Find single character following cursor in current line.
* t Like f, but stope before character.
*/
case 'f': /* find */
case 't':
if (!subop) {
i = getesc();
if (i == 0)
return;
*lastcp++ = i;
}
if (vglobp == 0)
lastFKND = c, lastFCHR = i;
for (; cnt > 0; cnt--)
forbid (find(i) == 0);
vmoving = 0;
switch (c) {
case 'T':
wcursor += skipright(linebuf, wcursor);
break;
case 't':
wcursor += skipleft(linebuf, wcursor);
case 'f':
fixup:
if (moveop != vmove)
wcursor += skipright(linebuf, wcursor);
break;
}
break;
/*
* | Find specified print column in current line.
*/
case '|':
if (Pline == numbline)
cnt += 8;
vmovcol = cnt;
vmoving = 1;
wcursor = vfindcol(cnt);
break;
/*
* ^ To beginning of non-white space on line.
*/
case '^':
wcursor = vskipwh(linebuf);
vmoving = 0;
break;
/*
* $ To end of line.
*/
case '$':
if (opf == vmove) {
vmoving = 1;
vmovcol = 20000;
} else
vmoving = 0;
if (cnt > 1) {
if (opf == vmove) {
wcursor = 0;
cnt--;
} else
wcursor = linebuf;
/* This is wrong at EOF */
wdot = dot + cnt;
break;
}
if (linebuf[0]) {
wcursor = strend(linebuf) - 1;
goto fixup;
}
wcursor = linebuf;
break;
/*
* h Back a character.
* ^H Back a character.
*/
case 'h':
case CTRL('h'):
dir = -1;
/* fall into ... */
/*
* space Forward a character.
*/
case 'l':
case ' ':
forbid (margin() || opf == vmove && edge());
while (cnt > 0 && !margin()) {
wcursor += dir>0 ? skipright(linebuf, wcursor) :
skipleft(linebuf, wcursor);
cnt--;
}
if (margin() && opf == vmove || wcursor < linebuf)
wcursor -= dir;
vmoving = 0;
break;
/*
* D Delete to end of line, short for d$.
*/
case 'D':
cnt = INF;
goto deleteit;
/*
* X Delete character before cursor.
*/
case 'X':
dir = -1;
/* fall into ... */
deleteit:
/*
* x Delete character at cursor, leaving cursor where it is.
*/
case 'x':
if (margin())
goto errlab;
vmacchng(1);
while (cnt > 0 && !margin()) {
wcursor += skipright(linebuf, wcursor);
cnt--;
}
opf = deleteop;
vmoving = 0;
break;
default:
/*
* Stuttered operators are equivalent to the operator on
* a line, thus turn dd into d_.
*/
if (opf == vmove || c != workcmd[0]) {
errlab:
beep();
vmacp = 0;
return;
}
/* fall into ... */
/*
* _ Target for a line or group of lines.
* Stuttering is more convenient; this is mostly
* for aesthetics.
*/
case '_':
wdot = dot + cnt - 1;
vmoving = 0;
wcursor = 0;
break;
/*
* H To first, home line on screen.
* Count is for count'th line rather than first.
*/
case 'H':
wdot = (dot - vcline) + cnt - 1;
if (opf == vmove)
markit(wdot);
vmoving = 0;
wcursor = 0;
break;
/*
* - Backwards lines, to first non-white character.
*/
case '-':
wdot = dot - cnt;
vmoving = 0;
wcursor = 0;
break;
/*
* ^P To previous line same column. Ridiculous on the
* console of the VAX since it puts console in LSI mode.
*/
case 'k':
case CTRL('p'):
wdot = dot - cnt;
if (vmoving == 0)
vmoving = 1, vmovcol = column(cursor);
wcursor = 0;
break;
/*
* L To last line on screen, or count'th line from the
* bottom.
*/
case 'L':
wdot = dot + vcnt - vcline - cnt;
if (opf == vmove)
markit(wdot);
vmoving = 0;
wcursor = 0;
break;
/*
* M To the middle of the screen.
*/
case 'M':
wdot = dot + ((vcnt + 1) / 2) - vcline - 1;
if (opf == vmove)
markit(wdot);
vmoving = 0;
wcursor = 0;
break;
/*
* + Forward line, to first non-white.
*
* CR Convenient synonym for +.
*/
case '+':
case CR:
wdot = dot + cnt;
vmoving = 0;
wcursor = 0;
break;
/*
* ^N To next line, same column if possible.
*
* LF Linefeed is a convenient synonym for ^N.
*/
case CTRL('n'):
case 'j':
case NL:
wdot = dot + cnt;
if (vmoving == 0)
vmoving = 1, vmovcol = column(cursor);
wcursor = 0;
break;
/*
* n Search to next match of current pattern.
*/
case 'n':
vglobp = vscandir;
c = *vglobp++;
goto nocount;
/*
* N Like n but in reverse direction.
*/
case 'N':
vglobp = vscandir[0] == '/' ? qmarkcell : slashcell;
c = *vglobp++;
goto nocount;
/*
* ' Return to line specified by following mark,
* first white position on line.
*
* ` Return to marked line at remembered column.
*/
case '\'':
case '`':
d = c;
c = getesc();
if (c == 0)
return;
c = markreg(c);
forbid (c == 0);
wdot = getmark(c);
forbid (wdot == NOLINE);
forbid (Xhadcnt);
vmoving = 0;
wcursor = d == '`' ? ncols[c - 'a'] : 0;
if (opf == vmove && (wdot != dot || (d == '`' && wcursor != cursor)))
markDOT();
if (wcursor) {
vsave();
getline(*wdot);
if (wcursor > strend(linebuf))
wcursor = 0;
getDOT();
}
if (ospeed > B300)
hold |= HOLDWIG;
break;
/*
* G Goto count'th line, or last line if no count
* given.
*/
case 'G':
if (!Xhadcnt)
cnt = lineDOL();
wdot = zero + cnt;
forbid (wdot < one || wdot > dol);
if (opf == vmove)
markit(wdot);
vmoving = 0;
wcursor = 0;
break;
/*
* / Scan forward for following re.
* ? Scan backward for following re.
*/
case '/':
case '?':
forbid (Xhadcnt);
vsave();
ocurs = cursor;
odot = dot;
wcursor = 0;
if (readecho(c))
return;
if (!vglobp)
vscandir[0] = genbuf[0];
oglobp = globp;
CP(vutmp, genbuf);
globp = vutmp;
d = peekc;
fromsemi:
ungetchar(0);
fixech();
CATCH
addr = address(cursor);
ONERR
slerr:
globp = oglobp;
dot = odot;
cursor = ocurs;
ungetchar(d);
splitw = 0;
vclean();
vjumpto(dot, ocurs, 0);
return;
ENDCATCH
if (globp == 0)
globp = "";
else if (peekc)
--globp;
if (*globp == ';') {
/* /foo/;/bar/ */
globp++;
dot = addr;
cursor = loc1;
goto fromsemi;
}
dot = odot;
ungetchar(d);
c = 0;
if (*globp == 'z')
globp++, c = '\n';
if (any(*globp, "^+-."))
c = *globp++;
i = 0;
while (xisdigit(*globp&TRIM))
i = i * 10 + *globp++ - '0';
if (any(*globp, "^+-."))
c = *globp++;
if (*globp) {
/* random junk after the pattern */
beep();
goto slerr;
}
globp = oglobp;
splitw = 0;
vmoving = 0;
wcursor = loc1;
if (i != 0)
vsetsiz(i);
if (opf == vmove) {
if (state == ONEOPEN || state == HARDOPEN)
outline = destline = WBOT;
if (addr != dot || loc1 != cursor)
markDOT();
if (loc1 > linebuf && *loc1 == 0)
loc1--;
if (c)
vjumpto(addr, loc1, c);
else {
vmoving = 0;
if (loc1) {
vmoving++;
vmovcol = column(loc1);
}
getDOT();
if (state == CRTOPEN && addr != dot)
vup1();
vupdown(addr - dot, NOSTR);
}
return;
}
lastcp[-1] = 'n';
getDOT();
wdot = addr;
break;
}
/*
* Apply.
*/
if (vreg && wdot == 0)
wdot = dot;
(*opf)(c);
wdot = NOLINE;
}
/*
* Find single character c, in direction dir from cursor.
*/
int
find(int c)
{
for(;;) {
if (edge())
return (0);
wcursor += dir>0 ? skipright(linebuf, wcursor) :
skipleft(linebuf, wcursor-1);
if (samechar(wcursor, c))
return (1);
}
}
/*
* Do a word motion with operator op, and cnt more words
* to go after this.
*/
int
word(register void (*op)(int), int cnt)
{
register int which = 0;
register char *iwc;
register line *iwdot = wdot;
if (dir == 1) {
iwc = wcursor;
which = wordch(wcursor);
while (wordof(which, wcursor)) {
if (cnt == 1 && op != vmove &&
wcursor[skipright(linebuf, wcursor)]
== 0) {
wcursor++;
break;
}
if (!lnext())
return (0);
if (wcursor == linebuf)
break;
}
/* Unless last segment of a change skip blanks */
if (op != vchange || cnt > 1)
while (!margin() && blank())
wcursor += skipright(linebuf, wcursor);
else
if (wcursor == iwc && iwdot == wdot && *iwc)
wcursor += skipright(linebuf, wcursor);
if (op == vmove && margin()) {
if (wcursor == linebuf)
wcursor--;
else if (!lnext())
return (0);
}
} else {
if (!lnext())
return (0);
while (blank())
if (!lnext())
return (0);
if (!margin()) {
which = wordch(wcursor);
while (!margin() && wordof(which, wcursor))
wcursor--;
}
if (wcursor < linebuf || !wordof(which, wcursor))
wcursor += skipright(linebuf, wcursor);
}
return (1);
}
/*
* To end of word, with operator op and cnt more motions
* remaining after this.
*/
void
eend(register void (*op)(int))
{
register int which;
if (!lnext())
return;
while (blank())
if (!lnext())
return;
which = wordch(wcursor);
while (wordof(which, wcursor)) {
if (wcursor[1] == 0) {
wcursor++;
break;
}
if (!lnext())
return;
}
if (op != vchange && op != vdelete && wcursor > linebuf)
wcursor--;
}
/*
* Wordof tells whether the character at *wc is in a word of
* kind which (blank/nonblank words are 0, conservative words 1).
*/
int
wordof(int which, register char *wc)
{
if (cblank(wc))
return (0);
return (!wdkind || wordch(wc) == which);
}
/*
* Wordch tells whether character at *wc is a word character
* i.e. an alfa, digit, or underscore.
*/
int
wordch(char *wc)
{
int c;
#ifdef MB
if (mb_cur_max > 0 && *wc & 0200) {
mbtowi(&c, wc, mb_cur_max);
if (c & INVBIT)
return 1;
} else
#endif
c = wc[0]&0377;
return (xisalnum(c) || c == '_'
#ifdef BIT8
#ifdef ISO8859_1
/*
* We consider all ISO 8859-1 characters except for
* no-break-space as word characters.
*/
|| c&0200 && (!(c&QUOTE) && (c&TRIM) != 0240)
#endif
#endif
);
}
/*
* Edge tells when we hit the last character in the current line.
*/
int
edge(void)
{
if (linebuf[0] == 0)
return (1);
if (dir == 1)
return (wcursor[1] == 0);
else
return (wcursor == linebuf);
}
/*
* Margin tells us when we have fallen off the end of the line.
*/
int
margin(void)
{
return (wcursor < linebuf || wcursor[0] == 0);
}

1053
ex_vops.c Normal file

File diff suppressed because it is too large Load Diff

1097
ex_vops2.c Normal file

File diff suppressed because it is too large Load Diff

731
ex_vops3.c Normal file
View File

@ -0,0 +1,731 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_vops3.c 1.18 (gritter) 11/27/04";
#endif
#endif
/* from ex_vops3.c 7.3 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
/*
* Routines to handle structure.
* Operations supported are:
* ( ) { } [ ]
*
* These cover: LISP TEXT
* ( ) s-exprs sentences
* { } list at same paragraphs
* [ ] defuns sections
*
* { and } for C used to attempt to do something with matching {}'s, but
* I couldn't find definitions which worked intuitively very well, so I
* scrapped this.
*
* The code here is very hard to understand.
*/
line *llimit;
void (*lf)(int);
bool wasend;
/*
* Find over structure, repeated count times.
* Don't go past line limit. F is the operation to
* be performed eventually. If pastatom then the user said {}
* rather than (), implying past atoms in a list (or a paragraph
* rather than a sentence.
*/
int
llfind(bool pastatom, int cnt, void (*f)(int), line *limit)
{
#ifdef LISPCODE
register int c;
#endif
register int rc = 0;
char save[LBSIZE];
/*
* Initialize, saving the current line buffer state
* and computing the limit; a 0 argument means
* directional end of file.
*/
wasend = 0;
lf = f;
strcpy(save, linebuf);
if (limit == 0)
limit = dir < 0 ? one : dol;
llimit = limit;
wdot = dot;
wcursor = cursor;
if (pastatom >= 2) {
while (cnt > 0 && word(f, cnt))
cnt--;
if (pastatom == 3)
eend(f);
if (dot == wdot) {
wdot = 0;
if (cursor == wcursor)
rc = -1;
}
}
#ifdef LISPCODE
else if (!value(LISP)) {
#else
else {
#endif
char *icurs;
line *idot;
if (linebuf[0] == 0) {
do
if (!lnext())
goto ret;
while (linebuf[0] == 0);
if (dir > 0) {
wdot--;
linebuf[0] = 0;
wcursor = linebuf;
/*
* If looking for sentence, next line
* starts one.
*/
if (!pastatom) {
icurs = wcursor;
idot = wdot;
goto begin;
}
}
}
icurs = wcursor;
idot = wdot;
/*
* Advance so as to not find same thing again.
*/
if (dir > 0) {
if (!lnext()) {
rc = -1;
goto ret;
}
} else
ignore(lskipa1(""));
/*
* Count times find end of sentence/paragraph.
*/
begin:
for (;;) {
while (!endsent(pastatom))
if (!lnext())
goto ret;
if (!pastatom || wcursor == linebuf && endPS())
if (--cnt <= 0)
break;
if (linebuf[0] == 0) {
do
if (!lnext())
goto ret;
while (linebuf[0] == 0);
} else
if (!lnext())
goto ret;
}
/*
* If going backwards, and didn't hit the end of the buffer,
* then reverse direction.
*/
if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
dir = 1;
llimit = dot;
/*
* Empty line needs special treatement.
* If moved to it from other than begining of next line,
* then a sentence starts on next line.
*/
if (linebuf[0] == 0 && !pastatom &&
(wdot != dot - 1 || cursor != linebuf)) {
lnext();
goto ret;
}
}
/*
* If we are not at a section/paragraph division,
* advance to next.
*/
if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
ignore(lskipa1(""));
}
#ifdef LISPCODE
else {
c = *wcursor;
/*
* Startup by skipping if at a ( going left or a ) going
* right to keep from getting stuck immediately.
*/
if (dir < 0 && c == '(' || dir > 0 && c == ')') {
if (!lnext()) {
rc = -1;
goto ret;
}
}
/*
* Now chew up repitition count. Each time around
* if at the beginning of an s-exp (going forwards)
* or the end of an s-exp (going backwards)
* skip the s-exp. If not at beg/end resp, then stop
* if we hit a higher level paren, else skip an atom,
* counting it unless pastatom.
*/
while (cnt > 0) {
c = *wcursor;
if (dir < 0 && c == ')' || dir > 0 && c == '(') {
if (!lskipbal("()"))
goto ret;
/*
* Unless this is the last time going
* backwards, skip past the matching paren
* so we don't think it is a higher level paren.
*/
if (dir < 0 && cnt == 1)
goto ret;
if (!lnext() || !ltosolid())
goto ret;
--cnt;
} else if (dir < 0 && c == '(' || dir > 0 && c == ')')
/* Found a higher level paren */
goto ret;
else {
if (!lskipatom())
goto ret;
if (!pastatom)
--cnt;
}
}
}
#endif
ret:
strcLIN(save);
return (rc);
}
/*
* Is this the end of a sentence?
*/
int
endsent(bool pastatom)
{
register char *cp = wcursor;
register int c, d;
/*
* If this is the beginning of a line, then
* check for the end of a paragraph or section.
*/
if (cp == linebuf)
return (endPS());
/*
* Sentences end with . ! ? not at the beginning
* of the line, and must be either at the end of the line,
* or followed by 2 spaces. Any number of intervening ) ] ' "
* characters are allowed.
*/
if (!any(c = *cp, ".!?"))
goto tryps;
do
if ((d = *++cp) == 0)
return (1);
while (any(d, ")]'"));
if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
return (1);
tryps:
if (cp[1] == 0)
return (endPS());
return (0);
}
/*
* End of paragraphs/sections are respective
* macros as well as blank lines and form feeds.
*/
int
endPS(void)
{
return (linebuf[0] == 0 ||
isa(svalue(PARAGRAPHS)) || isa(svalue(SECTIONS)));
}
#ifdef LISPCODE
int
lindent(line *addr)
{
register int i;
char *swcurs = wcursor;
line *swdot = wdot;
again:
if (addr > one) {
register char *cp;
register int cnt = 0;
addr--;
getline(*addr);
for (cp = linebuf; *cp; cp++)
if (*cp == '(')
cnt++;
else if (*cp == ')')
cnt--;
cp = vpastwh(linebuf);
if (*cp == 0)
goto again;
if (cnt == 0)
return (whitecnt(linebuf));
addr++;
}
wcursor = linebuf;
linebuf[0] = 0;
wdot = addr;
dir = -1;
llimit = one;
lf = (void (*)(int))lindent;
if (!lskipbal("()"))
i = 0;
else if (wcursor == linebuf)
i = 2;
else {
register char *wp = wcursor;
dir = 1;
llimit = wdot;
if (!lnext() || !ltosolid() || !lskipatom()) {
wcursor = wp;
i = 1;
} else
i = 0;
i += column(wcursor) - 1;
if (!inopen)
i--;
}
wdot = swdot;
wcursor = swcurs;
return (i);
}
#endif
int
lmatchp(line *addr)
{
register int i;
register char *parens, *cp;
for (cp = cursor; !any(*cp, "({[)}]");)
if (*cp++ == 0)
return (0);
lf = 0;
parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}";
if (*cp == parens[1]) {
dir = -1;
llimit = one;
} else {
dir = 1;
llimit = dol;
}
if (addr)
llimit = addr;
if (splitw)
llimit = dot;
wcursor = cp;
wdot = dot;
i = lskipbal(parens);
return (i);
}
void
lsmatch(char *cp)
{
char save[LBSIZE];
register char *sp = save;
register char *scurs = cursor;
wcursor = cp;
strcpy(sp, linebuf);
*wcursor = 0;
strcpy(cursor, genbuf);
cursor = strend(linebuf) - 1;
if (lmatchp(dot - vcline)) {
register int i = insmode;
register int c = outcol;
register int l = outline;
if (!MI)
endim();
vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
flush();
sleep(1);
vgoto(l, c);
if (i)
goim();
}
else {
strcLIN(sp);
strcpy(scurs, genbuf);
if (!lmatchp((line *) 0))
beep();
}
strcLIN(sp);
wdot = 0;
wcursor = 0;
cursor = scurs;
}
int
ltosolid(void)
{
return (ltosol1("()"));
}
int
ltosol1(register char *parens)
{
register char *cp;
if (*parens && !*wcursor && !lnext())
return (0);
while (isspace(*wcursor&0377) || (*wcursor == 0 && *parens))
if (!lnext())
return (0);
if (any(*wcursor, parens) || dir > 0)
return (1);
for (cp = wcursor; cp > linebuf; cp--)
if (isspace(cp[-1]&0377) || any(cp[-1], parens))
break;
wcursor = cp;
return (1);
}
int
lskipbal(register char *parens)
{
register int level = dir;
register int c;
do {
if (!lnext()) {
wdot = NOLINE;
return (0);
}
c = *wcursor;
if (c == parens[1])
level--;
else if (c == parens[0])
level++;
} while (level);
return (1);
}
int
lskipatom(void)
{
return (lskipa1("()"));
}
int
lskipa1(register char *parens)
{
register int c;
for (;;) {
if (dir < 0 && wcursor == linebuf) {
if (!lnext())
return (0);
break;
}
c = *wcursor;
if (c && (isspace(c) || any(c, parens)))
break;
if (!lnext())
return (0);
if (dir > 0 && wcursor == linebuf)
break;
}
return (ltosol1(parens));
}
int
lnext(void)
{
if (dir > 0) {
if (*wcursor)
wcursor += skipright(linebuf, wcursor);
if (*wcursor)
return (1);
if (wdot >= llimit) {
if (lf == vmove && wcursor > linebuf)
wcursor += skipleft(linebuf, wcursor);
return (0);
}
wdot++;
getline(*wdot);
wcursor = linebuf;
return (1);
} else {
wcursor += skipleft(linebuf, wcursor);
if (wcursor >= linebuf)
return (1);
#ifdef LISPCODE
if (lf == (void (*)(int))lindent && linebuf[0] == '(')
llimit = wdot;
#endif
if (wdot <= llimit) {
wcursor = linebuf;
return (0);
}
wdot--;
getline(*wdot);
wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1;
return (1);
}
}
int
lbrack(register int c, void (*f)(int))
{
register line *addr;
addr = dot;
for (;;) {
addr += dir;
if (addr < one || addr > dol) {
addr -= dir;
break;
}
getline(*addr);
if (linebuf[0] == '{' ||
#ifdef LISPCODE
value(LISP) && linebuf[0] == '(' ||
#endif
isa(svalue(SECTIONS))) {
if (c == ']' && f != vmove) {
addr--;
getline(*addr);
}
break;
}
if (c == ']' && f != vmove && linebuf[0] == '}')
break;
}
if (addr == dot)
return (0);
if (f != vmove)
wcursor = c == ']' ? strend(linebuf) : linebuf;
else
wcursor = 0;
wdot = addr;
vmoving = 0;
return (1);
}
int
isa(register char *cp)
{
if (linebuf[0] != '.')
return (0);
for (; cp[0] && cp[1]; cp += 2)
if (linebuf[1] == cp[0]) {
if (linebuf[2] == cp[1])
return (1);
if (linebuf[2] == 0 && cp[1] == ' ')
return (1);
}
return (0);
}
static int
cswitch(char *dst, const char *src)
{
int c, n;
#ifdef MB
if (mb_cur_max > 1) {
nextc(c, src, n);
if (c & INVBIT) {
*dst = *src;
n = 1;
} else {
if (iswupper(c))
c = towlower(c);
else if (iswlower(c))
c = towupper(c);
if (wctomb(dst, c) != n) {
*dst = *src;
n = 1;
}
}
} else
#endif /* MB */
{
c = *src & 0377;
if (isupper(c))
*dst = tolower(c);
else if (islower(c))
*dst = toupper(c);
else
*dst = c;
n = 1;
}
return n;
}
void
vswitch(int cnt)
{
if (cnt <= 1) {
char mbuf[MB_LEN_MAX+4];
int n;
setLAST();
mbuf[0] = 'r';
n = cswitch(&mbuf[1], cursor);
if (cursor[n] != '\0')
mbuf[1+n++] = ' ';
mbuf[1+n] = '\0';
macpush(mbuf, 1);
} else { /* cnt > 1 */
char *mbuf = malloc(MAXDIGS + cnt*(mb_cur_max+1) + 5);
register char *p = &mbuf[MAXDIGS + 1];
register int num, n, m;
setLAST();
*p++ = 's';
for (num = 0, m = 0; num < cnt && cursor[m] != '\0'; num++) {
*p++ = CTRL('v');
n = cswitch(p, &cursor[m]);
p += n;
m += n;
}
*p++ = ESCAPE;
if (cursor[m])
*p++ = ' ';
*p++ = '\0';
macpush(p_dconv((long)num, mbuf), 1);
lastvgk = 0;
free(mbuf);
}
}
#ifdef MB
int
wskipleft(char *lp, char *pos)
{
int c, n;
do {
nextc(c, lp, n);
lp += n;
} while (lp < pos);
return -n;
}
int
wskipright(char *line, char *pos)
{
int c, n;
nextc(c, pos, n);
return n;
}
int
wsamechar(char *cp, int d)
{
int c;
if (mbtowi(&c, cp, mb_cur_max) >= 0 && c == d)
return 1;
return 0;
}
#endif /* MB */

1577
ex_vput.c Normal file

File diff suppressed because it is too large Load Diff

500
ex_vwind.c Normal file
View File

@ -0,0 +1,500 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_vwind.c 1.9 (gritter) 11/23/04";
#endif
#endif
/* from ex_vwind.c 7.3 (Berkeley) 6/7/85 */
#include "ex.h"
#include "ex_tty.h"
#include "ex_vis.h"
/*
* Routines to adjust the window, showing specified lines
* in certain positions on the screen, and scrolling in both
* directions. Code here is very dependent on mode (open versus visual).
*/
/*
* Move in a nonlocal way to line addr.
* If it isn't on screen put it in specified context.
* New position for cursor is curs.
* Like most routines here, we vsave().
*/
void
vmoveto(register line *addr, char *curs, int context)
{
markit(addr);
vsave();
vjumpto(addr, curs, context);
}
/*
* Vjumpto is like vmoveto, but doesn't mark previous
* context or save linebuf as current line.
*/
void
vjumpto(register line *addr, char *curs, int context)
{
noteit(0);
if (context != 0)
vcontext(addr, context);
else
vshow(addr, NOLINE);
noteit(1);
vnline(curs);
}
/*
* Go up or down cnt (negative is up) to new position curs.
*/
void
vupdown(register int cnt, char *curs)
{
if (cnt > 0)
vdown(cnt, 0, 0);
else if (cnt < 0)
vup(-cnt, 0, 0);
if (vcnt == 0)
vrepaint(curs);
else
vnline(curs);
}
/*
* Go up cnt lines, afterwards preferring to be ind
* logical lines from the top of the screen.
* If scroll, then we MUST use a scroll.
* Otherwise clear and redraw if motion is far.
*/
void
vup(register int cnt, register int ind, int scroll)
{
register int i, tot;
if (dot == one) {
beep();
return;
}
vsave();
i = lineDOT() - 1;
if (cnt > i) {
ind -= cnt - i;
if (ind < 0)
ind = 0;
cnt = i;
}
if (!scroll && cnt <= vcline) {
vshow(dot - cnt, NOLINE);
return;
}
cnt -= vcline, dot -= vcline, vcline = 0;
if (hold & HOLDWIG)
goto contxt;
if (state == VISUAL && !AL && !SR &&
cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
goto okr;
tot = WECHO - ZERO;
if (state != VISUAL || (!AL && !SR) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
if (ind > basWLINES / 2)
ind = basWLINES / 3;
contxt:
vcontext(dot + ind - cnt, '.');
return;
}
okr:
vrollR(cnt);
if (scroll) {
vcline += ind, dot += ind;
if (vcline >= vcnt)
dot -= vcline - vcnt + 1, vcline = vcnt - 1;
getDOT();
}
}
/*
* Like vup, but scrolling down.
*/
void
vdown(register int cnt, register int ind, int scroll)
{
register int i, tot;
if (dot == dol) {
beep();
return;
}
vsave();
i = dol - dot;
if (cnt > i) {
ind -= cnt - i;
if (ind < 0)
ind = 0;
cnt = i;
}
i = vcnt - vcline - 1;
if (!scroll && cnt <= i) {
vshow(dot + cnt, NOLINE);
return;
}
cnt -= i, dot += i, vcline += i;
if (hold & HOLDWIG)
goto dcontxt;
if (!scroll) {
tot = WECHO - ZERO;
if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
dcontxt:
vcontext(dot + cnt, '.');
return;
}
}
if (cnt > 0)
vroll(cnt);
if (state == VISUAL && scroll) {
vcline -= ind, dot -= ind;
if (vcline < 0)
dot -= vcline, vcline = 0;
getDOT();
}
}
/*
* Show line addr in context where on the screen.
* Work here is in determining new top line implied by
* this placement of line addr, since we always draw from the top.
*/
void
vcontext(register line *addr, int where)
{
register line *top;
getline(*addr);
if (state != VISUAL)
top = addr;
else switch (where) {
case '^':
addr = vback(addr, basWLINES - vdepth());
getline(*addr);
/* fall into ... */
case '-':
top = vback(addr, basWLINES - vdepth());
getline(*addr);
break;
case '.':
top = vback(addr, basWLINES / 2 - vdepth());
getline(*addr);
break;
default:
top = addr;
break;
}
if (state == ONEOPEN && LINE(0) == WBOT)
vup1();
vcnt = vcline = 0;
vclean();
if (state == CRTOPEN)
vup1();
vshow(addr, top);
}
/*
* Get a clean line. If we are in a hard open
* we may be able to reuse the line we are on
* if it is blank. This is a real win.
*/
void
vclean(void)
{
if (state != VISUAL && state != CRTOPEN) {
destcol = 0;
if (!ateopr())
vup1();
vcnt = 0;
}
}
/*
* Show line addr with the specified top line on the screen.
* Top may be 0; in this case have vcontext compute the top
* (and call us recursively). Eventually, we clear the screen
* (or its open mode equivalent) and redraw.
*/
void
vshow(line *addr, line *top)
{
register int cnt = addr - dot;
register int i = vcline + cnt;
short oldhold = hold;
if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
dot = addr;
getDOT();
vcline = i;
return;
}
if (state != VISUAL) {
dot = addr;
vopen(dot, WBOT);
return;
}
if (top == 0) {
vcontext(addr, '.');
return;
}
dot = top;
oldhold = hold;
hold |= HOLDAT;
vclear();
vreset(0);
vredraw(WTOP);
/* error if vcline >= vcnt ! */
vcline = addr - top;
dot = addr;
getDOT();
hold = oldhold;
vsync(LASTLINE);
}
/*
* reset the state.
* If inecho then leave us at the beginning of the echo
* area; we are called this way in the middle of a :e escape
* from visual, e.g.
*/
void
vreset(int inecho)
{
vcnt = vcline = 0;
WTOP = basWTOP;
WLINES = basWLINES;
if (inecho)
splitw = 1, vgoto(WECHO, 0);
}
/*
* Starting from which line preceding tp uses almost (but not more
* than) cnt physical lines?
*/
line *
vback(register line *tp, register int cnt)
{
register int d;
if (cnt > 0)
for (; tp > one; tp--) {
getline(tp[-1]);
d = vdepth();
if (d > cnt)
break;
cnt -= d;
}
return (tp);
}
/*
* How much scrolling will it take to roll cnt lines starting at tp?
*/
int
vfit(register line *tp, int cnt)
{
register int j;
j = 0;
while (cnt > 0) {
cnt--;
getline(tp[cnt]);
j += vdepth();
}
if (tp > dot)
j -= WBOT - LASTLINE;
return (j);
}
/*
* Roll cnt lines onto the screen.
*/
void
vroll(register int cnt)
{
short oldhold = hold;
#ifdef ADEBUG
if (trace)
tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
#endif
if (state != VISUAL)
hold |= HOLDAT|HOLDROL;
if (WBOT == WECHO) {
vcnt = 0;
if (state == ONEOPEN)
vup1();
}
for (; cnt > 0 && Peekkey != ATTN; cnt--) {
dot++, vcline++;
vopen(dot, LASTLINE);
vscrap();
}
hold = oldhold;
if (state == HARDOPEN)
sethard();
vsyncCL();
}
/*
* Roll backwards (scroll up).
*/
void
vrollR(register int cnt)
{
short oldhold = hold;
#ifdef ADEBUG
if (trace)
tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
#endif
if (WBOT == WECHO)
vcnt = 0;
heldech = 0;
hold |= HOLDAT|HOLDECH;
for (; cnt > 0 && Peekkey != ATTN; cnt--) {
dot--;
vopen(dot, WTOP);
vscrap();
}
hold = oldhold;
if (heldech)
vclrech(0);
vsync(LINE(vcnt-1));
}
/*
* Go into cooked mode (allow interrupts) during
* a scroll if we are at less than 1200 baud and not
* a 'vi' command, of if we are in a 'vi' command and the
* scroll is more than 2 full screens.
*
* BUG: An interrupt during a scroll in this way
* dumps to command mode.
*/
int
vcookit(register int cnt)
{
return (cnt > 1 && (ospeed < B1200 && !initev || cnt > TLINES * 2));
}
/*
* Determine displayed depth of current line.
*/
int
vdepth(void)
{
register int d;
d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + IN) / WCOLS;
#ifdef ADEBUG
if (trace)
tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
#endif
return (d == 0 ? 1 : d);
}
/*
* Move onto a new line, with cursor at position curs.
*/
void
vnline(char *curs)
{
if (curs)
wcursor = curs;
else if (vmoving)
wcursor = vfindcol(vmovcol);
else
wcursor = vskipwh(linebuf);
cursor = linebuf;
vmove(0);
}

555
expreserve.c Normal file
View File

@ -0,0 +1,555 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifdef __GNUC__
#define UNUSED __attribute__ ((unused))
#else
#define UNUSED
#endif
#ifndef lint
#ifdef DOSCCS
char *copyright =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif
static char sccsid[] UNUSED = "@(#)expreserve.c 1.23 (gritter) 11/27/04";
#endif
/* from expreserve.c 7.13.2 (2.11BSD GTE) 1996/10/26 */
#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <dirent.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <time.h>
#include "config.h"
#ifdef LANGMSG
#include <nl_types.h>
#include <locale.h>
nl_catd catd;
#else
#define catgets(a, b, c, d) (d)
#endif
#ifdef BUFSIZ
#undef BUFSIZ
#endif
#ifdef LINE_MAX
#define BUFSIZ LINE_MAX /* POSIX line size */
#else /* !LINE_MAX */
#ifdef VMUNIX
#define BUFSIZ 1024
#else /* !VMUNIX */
#ifdef u370
#define BUFSIZ 4096
#else /* !u370 */
#define BUFSIZ 512
#endif /* !u370 */
#endif
#endif /* !VMUNIX */
#ifdef LARGEF
typedef off_t bloc;
#else
typedef short bloc;
#endif
#ifdef VMUNIX
#ifdef LARGEF
typedef off_t bbloc;
#else
typedef int bbloc;
#endif
#else
typedef short bbloc;
#endif
#ifdef notdef
#define TMP "/tmp"
#else
#define TMP "/var/tmp"
#endif
#ifndef VMUNIX
#define LBLKS 125
#else
#ifdef LARGEF
#define LBLKS 20000
#else
#define LBLKS 900
#endif
#endif
#ifdef _POSIX_PATH_MAX
#define FNSIZE _POSIX_PATH_MAX
#else
#define FNSIZE 128
#endif
#ifdef VMUNIX
#define HBLKS (1 + (FNSIZE + LBLKS * sizeof(bloc)) / BUFSIZ)
#else
#define HBLKS 1
#endif
char xstr[1]; /* make loader happy */
extern void notify(uid_t, char *, int, time_t);
extern int copyout(char *);
extern void mkdigits(char *);
extern void mknext(char *);
/*
* Expreserve - preserve a file in /usr/preserve
* Bill Joy UCB November 13, 1977
*
* This routine is very naive - it doesn't remove anything from
* /usr/preserve... this may mean that we leave
* stuff there... the danger in doing anything with /usr/preserve
* is that the clock may be screwed up and we may get confused.
*
* We are called in two ways - first from the editor with no argumentss
* and the standard input open on the temp file. Second with an argument
* to preserve the entire contents of /tmp (root only).
*
* BUG: should do something about preserving Rx... (register contents)
* temporaries.
*/
struct header {
time_t Time; /* Time temp file last updated */
uid_t Uid;
bbloc Flines; /* Number of lines in file */
char Savedfile[FNSIZE]; /* The current file name */
bloc Blocks[LBLKS]; /* Blocks where line pointers stashed */
} H;
#define ignore(a) a
#define ignorl(a) a
#define eq(a, b) (strcmp(a, b) == 0)
int
main(int argc, char **argv)
{
register DIR *tf;
struct dirent *dirent;
struct stat stbuf;
#ifdef LANGMSG
setlocale(LC_MESSAGES, "");
catd = catopen(CATNAME, NL_CAT_LOCALE);
#endif
/*
* If only one argument, then preserve the standard input.
*/
if (argc == 1) {
if (copyout((char *) 0))
exit(1);
exit(0);
}
/*
* If not super user, then can only preserve standard input.
*/
if (getuid()) {
fprintf(stderr, catgets(catd, 3, 1, "NOT super user\n"));
exit(1);
}
/*
* ... else preserve all the stuff in /tmp, removing
* it as we go.
*/
if (chdir(TMP) < 0) {
perror(TMP);
exit(1);
}
tf = opendir(".");
if (tf == NULL) {
perror(TMP);
exit(1);
}
while ((dirent = readdir(tf)) != NULL) {
/* Ex temporaries must begin with Ex. */
if (dirent->d_name[0] != 'E' || dirent->d_name[1] != 'x')
continue;
if (stat(dirent->d_name, &stbuf))
continue;
if ((stbuf.st_mode & S_IFMT) != S_IFREG)
continue;
/*
* Save the bastard.
*/
ignore(copyout(dirent->d_name));
}
closedir(tf);
return 0;
}
#ifdef notdef
char pattern[] = "/usr/preserve/Exaa`XXXXX";
#else
char pattern[] = "/var/preserve/Exa`XXXXXXXXXX";
#endif
/*
* Notify user uid that his file fname has been saved.
*/
void
notify(uid_t uid, char *fname, int flag, time_t time)
{
struct passwd *pp = getpwuid(uid);
register FILE *mf;
char cmd[BUFSIZ];
struct utsname ut;
char *hostname;
char croak[128];
char *timestamp;
if (pp == NULL)
return;
uname(&ut);
hostname = ut.nodename;
timestamp = ctime(&time);
timestamp[16] = 0; /* blast from seconds on */
putenv("MAILRC=/dev/null");
sprintf(cmd, "/bin/mail %s", pp->pw_name);
setuid(getuid());
mf = popen(cmd, "w");
if (mf == NULL)
return;
setbuf(mf, cmd);
/*
* flag says how the editor croaked:
* "the editor was killed" is perhaps still not an ideal
* error message. Usually, either it was forcably terminated
* or the phone was hung up, but we don't know which.
*/
sprintf(croak, flag
? catgets(catd, 3, 2, "the system went down")
: catgets(catd, 3, 3, "the editor was killed"));
if (fname[0] == 0) {
fname = "LOST";
fprintf(mf, catgets(catd, 3, 4,
"Subject: editor saved ``LOST''\n"));
fprintf(mf, catgets(catd, 3, 5,
"You were editing a file without a name\n"));
fprintf(mf, catgets(catd, 3, 6,
"at <%s> on the machine ``%s'' when %s.\n"),
timestamp, hostname, croak);
fprintf(mf, catgets(catd, 3, 7,
"Since the file had no name, it has been named \"LOST\".\n"));
} else {
fprintf(mf, catgets(catd, 3, 8,
"Subject: editor saved ``%s''\n"), fname);
fprintf(mf, catgets(catd, 3, 9,
"You were editing the file \"%s\"\n"), fname);
fprintf(mf, catgets(catd, 3, 10,
"at <%s> on the machine ``%s''\n"),
timestamp, hostname);
fprintf(mf, catgets(catd, 3, 11, "when %s.\n"), croak);
}
fprintf(mf, catgets(catd, 3, 12,
"\nYou can retrieve most of your changes to this file\n"));
fprintf(mf, catgets(catd, 3, 13,
"using the \"recover\" command of the editor.\n"));
fprintf(mf, catgets(catd, 3, 14,
"An easy way to do this is to give the command \"vi -r %s\".\n"), fname);
fprintf(mf, catgets(catd, 3, 15,
"This method also works using \"ex\" and \"edit\".\n"));
pclose(mf);
}
/*
* Copy file name into /usr/preserve/...
* If name is (char *) 0, then do the standard input.
* We make some checks on the input to make sure it is
* really an editor temporary, generate a name for the
* file (this is the slowest thing since we must stat
* to find a unique name), and finally copy the file.
*/
int
copyout(char *name)
{
int i;
char buf[BUFSIZ];
static int reenter;
/*
* The first time we put in the digits of our
* process number at the end of the pattern.
*/
if (reenter == 0) {
mkdigits(pattern);
reenter++;
}
/*
* If a file name was given, make it the standard
* input if possible.
*/
if (name != 0) {
ignore(close(0));
/*
* Need read/write access for arcane reasons
* (see below).
*/
if (open(name, O_RDWR) < 0)
return (-1);
}
/*
* Get the header block.
*/
ignorl(lseek(0, (off_t) 0, SEEK_SET));
if (read(0, (char *) &H, sizeof H) != sizeof H) {
format:
if (name == 0)
fprintf(stderr, catgets(catd, 3, 16,
"Buffer format error\t"));
return (-1);
}
/*
* Consistency checsks so we don't copy out garbage.
*/
if (H.Flines < 0) {
#ifdef DEBUG
fprintf(stderr, "Negative number of lines\n");
#endif
goto format;
}
if (H.Blocks[0] != HBLKS || H.Blocks[1] != HBLKS+1) {
#ifdef DEBUG
fprintf(stderr, "Blocks %d %d\n", H.Blocks[0], H.Blocks[1]);
#endif
goto format;
}
if (name == 0 && H.Uid != getuid()) {
#ifdef DEBUG
fprintf(stderr, "Wrong user-id\n");
#endif
goto format;
}
if (lseek(0, (off_t) 0, SEEK_SET)) {
#ifdef DEBUG
fprintf(stderr, "Negative number of lines\n");
#endif
goto format;
}
/*
* If no name was assigned to the file, then give it the name
* LOST, by putting this in the header.
*/
if (H.Savedfile[0] == 0) {
strcpy(H.Savedfile, "LOST");
ignore(write(0, (char *) &H, sizeof H));
H.Savedfile[0] = 0;
lseek(0, (off_t) 0, SEEK_SET);
}
/*
* File is good. Get a name and create a file for the copy.
*/
mknext(pattern);
ignore(close(1));
if (open(pattern, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC
#ifdef O_NOFOLLOW
|O_NOFOLLOW
#endif /* O_NOFOLLOW */
, 0600) < 0) {
if (name == 0)
perror(pattern);
return (1);
}
/*
* Make the target be owned by the owner of the file.
*/
ignore(chown(pattern, H.Uid, 0));
/*
* Copy the file.
*/
for (;;) {
i = read(0, buf, BUFSIZ);
if (i < 0) {
if (name)
perror(catgets(catd, 3, 17,
"Buffer read error"));
ignore(unlink(pattern));
return (-1);
}
if (i == 0) {
if (name)
ignore(unlink(name));
notify(H.Uid, H.Savedfile, name != 0, H.Time);
return (0);
}
if (write(1, buf, i) != i) {
if (name == 0)
perror(pattern);
unlink(pattern);
return (-1);
}
}
}
/*
* Blast the last 5 characters of cp to be the process number.
*/
void
mkdigits(char *cp)
{
register pid_t i;
register int j;
#ifdef notdef
for (i = getpid(), j = 5, cp += strlen(cp); j > 0; i /= 10, j--)
*--cp = i % 10 | '0';
#else
for (i = getpid(), j = 10, cp += strlen(cp); j > 0; i /= 10, j--)
*--cp = i % 10 | '0';
#endif
}
/*
* Make the name in cp be unique by clobbering up to
* three alphabetic characters into a sequence of the form 'aab', 'aac', etc.
* Mktemp gets weird names too quickly to be useful here.
*/
void
mknext(char *cp)
{
char *dcp;
struct stat stb;
dcp = cp + strlen(cp) - 1;
while (isdigit(*dcp & 0377))
dcp--;
whoops:
if (dcp[0] == 'z') {
dcp[0] = 'a';
if (dcp[-1] == 'z') {
#ifdef notdef
dcp[-1] = 'a';
if (dcp[-2] == 'z')
#endif
fprintf(stderr, catgets(catd, 3, 18,
"Can't find a name\t"));
#ifdef notdef
dcp[-2]++;
#endif
} else
dcp[-1]++;
} else
dcp[0]++;
if (stat(cp, &stb) == 0)
goto whoops;
}
/*
* people making love
* never exactly the same
* just like a snowflake
*/
#ifdef lint
void
Ignore(int a)
{
a = a;
}
void
Ignorl(long a)
{
a = a;
}
#endif

902
exrecover.c Normal file
View File

@ -0,0 +1,902 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifdef __GNUC__
#define UNUSED __attribute__ ((unused))
#else
#define UNUSED
#endif
#ifndef lint
#ifdef DOSCCS
char *copyright =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif
static char sccsid[] UNUSED = "@(#)exrecover.c 1.21 (gritter) 11/27/04";
#endif
/* from exrecover.c 7.9.2 (2.11BSD) 1996/10/26 */
#include <stdarg.h>
#ifdef notdef /* GR */
#include <stdio.h> /* mjm: BUFSIZ: stdio = 512, VMUNIX = 1024 */
#undef BUFSIZ /* mjm: BUFSIZ different */
#undef EOF /* mjm: EOF and NULL effectively the same */
#undef NULL
#else
#define xstderr (int*)0
typedef int xFILE;
extern void perror(const char *);
extern int vsprintf(char *, const char *, va_list);
#endif
#define var
#include "ex.h"
#include "ex_temp.h"
#include "ex_tty.h"
#include <dirent.h>
#include <time.h>
#ifndef MAXNAMLEN
#ifdef FNSIZE
#define MAXNAMLEN FNSIZE
#else
#ifdef NAME_MAX
#define MAXNAMLEN NAME_MAX
#else
#define MAXNAMLEN 255
#endif
#endif
#endif
#define TMP "/var/tmp"
#ifdef LANGMSG
nl_catd catd;
#endif
char xstr[1]; /* make loader happy */
int tfile = -1; /* ditto */
/*
*
* This program searches through the specified directory and then
* the directory /usr/preserve looking for an instance of the specified
* file from a crashed editor or a crashed system.
* If this file is found, it is unscrambled and written to
* the standard output.
*
* If this program terminates without a "broken pipe" diagnostic
* (i.e. the editor doesn't die right away) then the buffer we are
* writing from is removed when we finish. This is potentially a mistake
* as there is not enough handshaking to guarantee that the file has actually
* been recovered, but should suffice for most cases.
*/
/*
* Here we save the information about files, when
* you ask us what files we have saved for you.
* We buffer file name, number of lines, and the time
* at which the file was saved.
*/
struct svfile {
char sf_name[FNSIZE + 1];
int sf_lines;
char sf_entry[MAXNAMLEN + 1];
time_t sf_time;
};
#define ignorl(a) a
/*
* This directory definition also appears (obviously) in expreserve.c.
* Change both if you change either.
*/
#ifdef notdef
char mydir[] = "/usr/preserve";
#else
char mydir[] = "/var/preserve";
#endif
/*
* Limit on the number of printed entries
* when an, e.g. ``ex -r'' command is given.
*/
#define NENTRY 50
char nb[BUFSIZ];
int vercnt; /* Count number of versions of file found */
extern void error(char *, ...);
extern void listfiles(char *);
extern void enter(struct svfile *, char *, int);
extern int qucmp(struct svfile *, struct svfile *);
extern void findtmp(char *);
extern void searchdir(char *);
extern int yeah(char *);
extern int preserve(void);
extern void scrapbad(void);
extern void putfile(int);
extern void wrerror(void);
extern void clrstats(void);
extern void getline(line);
extern char *getblock(line, int);
extern void blkio(bloc, char *, ssize_t (*)(int, void *, size_t));
extern void syserror(void);
extern void xvfprintf(xFILE *, char *, va_list);
extern void xfprintf(xFILE *, char *, ...);
int
main(int argc, char *argv[])
{
register char *cp;
register int b, i;
/*
* Initialize the built-in memory allocator.
*/
#ifdef VMUNIX
poolsbrk(0);
#endif
#ifdef LANGMSG
setlocale(LC_MESSAGES, "");
catd = catopen(CATNAME, NL_CAT_LOCALE);
#endif
/*
* Initialize as though the editor had just started.
*/
fendcore = (line *) sbrk(0);
dot = zero = dol = fendcore;
one = zero + 1;
endcore = fendcore - 2;
iblock = oblock = -1;
/*
* If given only a -r argument, then list the saved files.
*/
if (argc == 2 && strcmp(argv[1], "-r") == 0) {
listfiles(mydir);
listfiles(TMP);
exit(0);
}
if (argc != 3)
error(catgets(catd, 2, 1,
" Wrong number of arguments to exrecover"), 0);
strcpy(file, argv[2]);
/*
* Search for this file.
*/
findtmp(argv[1]);
/*
* Got (one of the versions of) it, write it back to the editor.
*/
cp = ctime(&H.Time);
cp[19] = 0;
xfprintf(xstderr, catgets(catd, 2, 2, " [Dated: %s"), cp);
xfprintf(xstderr, vercnt > 1 ? catgets(catd, 2, 3,
", newest of %d saved]")
: catgets(catd, 2, 4, "]"), vercnt);
H.Flines++;
/*
* Allocate space for the line pointers from the temp file.
*/
if ((char *) sbrk(H.Flines * sizeof (line)) == (char *) -1)
/*
* Good grief.
*/
error(catgets(catd, 1, 5, " Not enough core for lines"), 0);
#ifdef DEBUG
xfprintf(xstderr, "%d lines\n", H.Flines);
#endif
/*
* Now go get the blocks of seek pointers which are scattered
* throughout the temp file, reconstructing the incore
* line pointers at point of crash.
*/
b = 0;
while (H.Flines > 0) {
ignorl(lseek(tfile, (off_t) ((blocks[b] & BLKMSK) * BUFSIZ),
SEEK_SET));
i = H.Flines < BUFSIZ / sizeof (line) ?
H.Flines * sizeof (line) : BUFSIZ;
if (read(tfile, (char *) dot, i) != i) {
perror(nb);
exit(1);
}
dot += i / sizeof (line);
H.Flines -= i / sizeof (line);
b++;
}
dot--; dol = dot;
/*
* Sigh... due to sandbagging some lines may really not be there.
* Find and discard such. This shouldn't happen much.
*/
scrapbad();
/*
* Now if there were any lines in the recovered file
* write them to the standard output.
*/
if (dol > zero) {
addr1 = one; addr2 = dol; io = 1;
putfile(0);
}
/*
* Trash the saved buffer.
* Hopefully the system won't crash before the editor
* syncs the new recovered buffer; i.e. for an instant here
* you may lose if the system crashes because this file
* is gone, but the editor hasn't completed reading the recovered
* file from the pipe from us to it.
*
* This doesn't work if we are coming from an non-absolute path
* name since we may have chdir'ed but what the hay, noone really
* ever edits with temporaries in "." anyways.
*/
if (nb[0] == '/')
ignore(unlink(nb));
/*
* Adieu.
*/
exit(0);
}
/*
* Print an error message (notably not in error
* message file). If terminal is in RAW mode, then
* we should be writing output for "vi", so don't print
* a newline which would screw up the screen.
*/
/*VARARGS2*/
void
error(char *str, ...)
{
va_list ap;
va_start(ap, str);
xvfprintf(xstderr, str, ap);
va_end(ap);
tcgetattr(2, &tty);
if (tty.c_lflag & ICANON)
xfprintf(xstderr, "\n");
exit(1);
}
void
listfiles(char *dirname)
{
register DIR *dir;
struct dirent *dirent;
int ecount;
register int f;
char *cp;
struct svfile *fp, svbuf[NENTRY];
/*
* Open /usr/preserve, and go there to make things quick.
*/
dir = opendir(dirname);
if (dir == NULL) {
perror(dirname);
return;
}
if (chdir(dirname) < 0) {
perror(dirname);
return;
}
xfprintf(xstderr, "%s:\n", dirname);
/*
* Look at the candidate files in /usr/preserve.
*/
fp = &svbuf[0];
ecount = 0;
while ((dirent = readdir(dir)) != NULL) {
if (dirent->d_name[0] != 'E')
continue;
#ifdef DEBUG
xfprintf(xstderr, "considering %s\n", dirent->d_name);
#endif
/*
* Name begins with E; open it and
* make sure the uid in the header is our uid.
* If not, then don't bother with this file, it can't
* be ours.
*/
f = open(dirent->d_name, O_RDONLY);
if (f < 0) {
#ifdef DEBUG
xfprintf(xstderr, "open failed\n");
#endif
continue;
}
if (read(f, (char *) &H, sizeof H) != sizeof H) {
#ifdef DEBUG
xfprintf(xstderr, "culdnt read hedr\n");
#endif
ignore(close(f));
continue;
}
ignore(close(f));
if (getuid() != H.Uid) {
#ifdef DEBUG
xfprintf(xstderr, "uid wrong\n");
#endif
continue;
}
/*
* Saved the day!
*/
enter(fp++, dirent->d_name, ecount);
ecount++;
#ifdef DEBUG
xfprintf(xstderr, "entered file %s\n", dirent->d_name);
#endif
}
ignore(closedir(dir));
/*
* If any files were saved, then sort them and print
* them out.
*/
if (ecount == 0) {
xfprintf(xstderr, catgets(catd, 2, 6, "No files saved.\n"));
return;
}
qsort(&svbuf[0], ecount, sizeof svbuf[0], (int(*)()) qucmp);
for (fp = &svbuf[0]; fp < &svbuf[ecount]; fp++) {
cp = ctime(&fp->sf_time);
cp[10] = 0;
xfprintf(xstderr, catgets(catd, 2, 7, "On %s at "), cp);
cp[16] = 0;
xfprintf(xstderr, &cp[11]);
xfprintf(xstderr, catgets(catd, 2, 8,
" saved %d lines of file \"%s\"\n"),
fp->sf_lines, fp->sf_name);
}
}
/*
* Enter a new file into the saved file information.
*/
void
enter(struct svfile *fp, char *fname, int count)
{
register char *cp, *cp2;
register struct svfile *f, *fl;
time_t curtime, itol();
f = 0;
if (count >= NENTRY) {
/*
* My god, a huge number of saved files.
* Would you work on a system that crashed this
* often? Hope not. So lets trash the oldest
* as the most useless.
*
* (I wonder if this code has ever run?)
*/
fl = fp - count + NENTRY - 1;
curtime = fl->sf_time;
for (f = fl; --f > fp-count; )
if (f->sf_time < curtime)
curtime = f->sf_time;
for (f = fl; --f > fp-count; )
if (f->sf_time == curtime)
break;
fp = f;
}
/*
* Gotcha.
*/
fp->sf_time = H.Time;
fp->sf_lines = H.Flines;
cp2 = fp->sf_name, cp = savedfile;
while (*cp2++ = *cp++);
for (cp2 = fp->sf_entry, cp = fname; *cp && cp-fname < 14;)
*cp2++ = *cp++;
*cp2++ = 0;
}
/*
* Do the qsort compare to sort the entries first by file name,
* then by modify time.
*/
int
qucmp(struct svfile *p1, struct svfile *p2)
{
register int t;
if (t = strcmp(p1->sf_name, p2->sf_name))
return(t);
if (p1->sf_time > p2->sf_time)
return(-1);
return(p1->sf_time < p2->sf_time);
}
/*
* Scratch for search.
*/
char bestnb[BUFSIZ]; /* Name of the best one */
long besttime; /* Time at which the best file was saved */
int bestfd; /* Keep best file open so it dont vanish */
/*
* Look for a file, both in the users directory option value
* (i.e. usually /tmp) and in /usr/preserve.
* Want to find the newest so we search on and on.
*/
void
findtmp(char *dir)
{
/*
* No name or file so far.
*/
bestnb[0] = 0;
bestfd = -1;
/*
* Search /usr/preserve and, if we can get there, /tmp
* (actually the users "directory" option).
*/
searchdir(dir);
if (chdir(mydir) == 0)
searchdir(mydir);
if (bestfd != -1) {
/*
* Gotcha.
* Put the file (which is already open) in the file
* used by the temp file routines, and save its
* name for later unlinking.
*/
tfile = bestfd;
strcpy(nb, bestnb);
ignorl(lseek(tfile, (off_t) 0, SEEK_SET));
/*
* Gotta be able to read the header or fall through
* to lossage.
*/
if (read(tfile, (char *) &H, sizeof H) == sizeof H)
return;
}
/*
* Extreme lossage...
*/
error(catgets(catd, 2, 9, " File not found"), 0);
}
/*
* Search for the file in directory dirname.
*
* Don't chdir here, because the users directory
* may be ".", and we would move away before we searched it.
* Note that we actually chdir elsewhere (because it is too slow
* to look around in /usr/preserve without chdir'ing there) so we
* can't win, because we don't know the name of '.' and if the path
* name of the file we want to unlink is relative, rather than absolute
* we won't be able to find it again.
*/
void
searchdir(char *dirname)
{
struct dirent *dirent;
register DIR *dir;
/* char dbuf[BUFSIZ]; */
dir = opendir(dirname);
if (dir == NULL)
return;
while ((dirent = readdir(dir)) != NULL) {
if (dirent->d_name[0] != 'E')
continue;
/*
* Got a file in the directory starting with E...
* Save a consed up name for the file to unlink
* later, and check that this is really a file
* we are looking for.
*/
ignore(strcat(strcat(strcpy(nb, dirname), "/"), dirent->d_name));
if (yeah(nb)) {
/*
* Well, it is the file we are looking for.
* Is it more recent than any version we found before?
*/
if (H.Time > besttime) {
/*
* A winner.
*/
ignore(close(bestfd));
bestfd = dup(tfile);
besttime = H.Time;
strcpy(bestnb, nb);
}
/*
* Count versions so user can be told there are
* ``yet more pages to be turned''.
*/
vercnt++;
}
ignore(close(tfile));
}
ignore(closedir(dir));
}
/*
* Given a candidate file to be recovered, see
* if its really an editor temporary and of this
* user and the file specified.
*/
int
yeah(char *name)
{
tfile = open(name, O_RDWR);
if (tfile < 0)
return (0);
if (read(tfile, (char *) &H, sizeof H) != sizeof H) {
nope:
ignore(close(tfile));
return (0);
}
if (strcmp(savedfile, file))
goto nope;
if (getuid() != H.Uid)
goto nope;
/*
* This is old and stupid code, which
* puts a word LOST in the header block, so that lost lines
* can be made to point at it.
*/
ignorl(lseek(tfile, (off_t) (BUFSIZ*HBLKS-8), SEEK_SET));
ignore(write(tfile, "LOST", 5));
return (1);
}
int
preserve(void)
{
return 0;
}
/*
* Find the true end of the scratch file, and ``LOSE''
* lines which point into thin air. This lossage occurs
* due to the sandbagging of i/o which can cause blocks to
* be written in a non-obvious order, different from the order
* in which the editor tried to write them.
*
* Lines which are lost are replaced with the text LOST so
* they are easy to find. We work hard at pretty formatting here
* as lines tend to be lost in blocks.
*
* This only seems to happen on very heavily loaded systems, and
* not very often.
*/
void
scrapbad(void)
{
register line *ip;
struct stat stbuf;
off_t size, maxt;
bbloc bno, cnt = 0, bad, was;
char bk[BUFSIZ];
ignore(fstat(tfile, &stbuf));
size = stbuf.st_size;
maxt = (size >> SHFT) | (BNDRY-1);
bno = (maxt >> OFFBTS) & BLKMSK;
#ifdef DEBUG
xfprintf(xstderr, "size %ld, maxt %o, bno %d\n", size, maxt, bno);
#endif
/*
* Look for a null separating two lines in the temp file;
* if last line was split across blocks, then it is lost
* if the last block is.
*/
while (bno > 0) {
ignorl(lseek(tfile, (off_t) (BUFSIZ * (bno & BLKMSK)),
SEEK_SET));
cnt = read(tfile, (char *) bk, BUFSIZ);
while (cnt > 0)
if (bk[--cnt] == 0)
goto null;
bno--;
}
null:
/*
* Magically calculate the largest valid pointer in the temp file,
* consing it up from the block number and the count.
*/
maxt = ((bno << OFFBTS) | (cnt >> SHFT)) & ~1;
#ifdef DEBUG
xfprintf(xstderr, "bno %d, cnt %d, maxt %o\n", bno, cnt, maxt);
#endif
/*
* Now cycle through the line pointers,
* trashing the Lusers.
*/
was = bad = 0;
for (ip = one; ip <= dol; ip++)
if (*ip > maxt) {
#ifdef DEBUG
xfprintf(xstderr, "%d bad, %o > %o\n", ip - zero, *ip, maxt);
#endif
if (was == 0)
was = ip - zero;
*ip = ((HBLKS*BUFSIZ)-8) >> SHFT;
} else if (was) {
if (bad == 0)
xfprintf(xstderr, catgets(catd, 2, 10,
" [Lost line(s):"));
xfprintf(xstderr, catgets(catd, 2, 11,
" %d"), was);
if ((ip - 1) - zero > was)
xfprintf(xstderr, catgets(catd, 2, 12, "-%d"),
(int) ((ip - 1) - zero));
bad++;
was = 0;
}
if (was != 0) {
if (bad == 0)
xfprintf(xstderr, catgets(catd, 2, 13,
" [Lost line(s):"));
xfprintf(xstderr, catgets(catd, 2, 14, " %d"), was);
if (dol - zero != was)
xfprintf(xstderr, catgets(catd, 2, 15,
"-%d"), (int) (dol - zero));
bad++;
}
if (bad)
xfprintf(xstderr, catgets(catd, 2, 16, "]"));
}
int cntch, cntln, cntodd, cntnull;
/*
* Following routines stolen mercilessly from ex.
*/
void
putfile(int unused)
{
line *a1;
register char *fp, *lp;
register int nib;
a1 = addr1;
clrstats();
cntln = addr2 - a1 + 1;
if (cntln == 0)
return;
nib = BUFSIZ;
fp = genbuf;
do {
getline(*a1++);
lp = linebuf;
for (;;) {
if (--nib < 0) {
nib = fp - genbuf;
if (write(io, genbuf, nib) != nib)
wrerror();
cntch += nib;
nib = MAXBSIZE - 1 /* 511 */;
fp = genbuf;
}
if ((*fp++ = *lp++) == 0) {
fp[-1] = '\n';
break;
}
}
} while (a1 <= addr2);
nib = fp - genbuf;
if (write(io, genbuf, nib) != nib)
wrerror();
cntch += nib;
}
void
wrerror(void)
{
syserror();
}
void
clrstats(void)
{
ninbuf = 0;
cntch = 0;
cntln = 0;
cntnull = 0;
cntodd = 0;
}
#define READ 0
#define WRITE 1
void
getline(line tl)
{
register char *bp, *lp;
register int nl;
lp = linebuf;
bp = getblock(tl, READ);
nl = nleft;
tl &= ~OFFMSK;
while (*lp++ = *bp++)
if (--nl == 0) {
bp = getblock(tl += INCRMT, READ);
nl = nleft;
}
}
char *
getblock(line atl, int iof)
{
register bbloc bno, off;
bno = (atl >> OFFBTS) & BLKMSK;
off = (atl << SHFT) & LBTMSK;
if (bno >= NMBLKS)
error(catgets(catd, 2, 17, " Tmp file too large"));
nleft = BUFSIZ - off;
if (bno == iblock) {
ichanged |= iof;
return (ibuff + off);
}
if (bno == oblock)
return (obuff + off);
if (iof == READ) {
if (ichanged)
blkio(iblock, ibuff, (ssize_t(*)())write);
ichanged = 0;
iblock = bno;
blkio(bno, ibuff, (ssize_t(*)())read);
return (ibuff + off);
}
if (oblock >= 0)
blkio(oblock, obuff, (ssize_t(*)())write);
oblock = bno;
return (obuff + off);
}
void
blkio(bloc b, char *buf, ssize_t (*iofcn)(int, void *, size_t))
{
lseek(tfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET);
if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
syserror();
}
void
syserror(void)
{
dirtcnt = 0;
write(2, " ", 1);
error("%s", strerror(errno));
exit(1);
}
/*
* Must avoid stdio because expreserve uses sbrk to do memory
* allocation and stdio uses malloc.
*/
/*
* I do not know whether vsprintf() uses malloc() or not.
* So this may be fail, too.
*/
void
xvfprintf(xFILE *fp, char *fmt, va_list ap)
{
char buf[BUFSIZ];
if (fp != xstderr)
return;
vsprintf(buf, fmt, ap);
write(2, buf, strlen(buf));
}
void
xfprintf(xFILE *fp, char *fmt, ...)
{
va_list ap;
if (fp != xstderr)
return;
va_start(ap, fmt);
xvfprintf(fp, fmt, ap);
va_end(ap);
}

64
libterm/Makefile Normal file
View File

@ -0,0 +1,64 @@
#
# This code contains changes by
# Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
#
# Conditions 1, 2, and 4 and the no-warranty notice below apply
# to these changes.
#
#
# Copyright (c) 1980, 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.
#
# from Makefile 5.1 (Berkeley) 6/5/85
#
# Sccsid @(#)Makefile 1.2 (gritter) 2/4/02
#
DEFS = -DCM_N -DCM_GT -DCM_B -DCM_D
# COPT comes from ex.
CFLAGS = $(DEFS) $(COPT)
SRCS = termcap.c tgoto.c tputs.c
OBJS = termcap.o tgoto.o tputs.o
.c.o: ; $(CC) $(CFLAGS) -c $<
all: libtermlib.a
libtermlib.a: $(OBJS)
ar cr libtermlib.a $(OBJS)
clean:
rm -f libtermlib.a $(OBJS) core
# DO NOT DELETE
termcap.o: libterm.h
tgoto.o: libterm.h
tputs.o: libterm.h

56
libterm/libterm.h Normal file
View File

@ -0,0 +1,56 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Header for termcap routines derived from 2.11 BSD.
*
* Sccsid @(#)libterm.h 1.4 (gritter) 11/23/04
*/
/*
* Size of the capability buffer string.
*/
#define TCBUFSIZE 2048
int tgetent(char *, const char *);
int tgetnum(char *);
int tgetflag(char *);
char *tgetstr(char *, char **);
char *tgoto(char *, int, int);
int tputs(const char *, int, int (*)(int));

410
libterm/termcap.c Normal file
View File

@ -0,0 +1,410 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*/
#ifndef lint
#ifdef DOSCCS
static char *sccsid = "@(#)termcap.c 1.7 (gritter) 11/23/04";
#endif
#endif
/* from termcap.c 5.1 (Berkeley) 6/5/85 */
#if 0 /* GR */
#define TCBUFSIZE 1024
#else
#include "libterm.h"
#endif
#define E_TERMCAP "/etc/termcap"
#define MAXHOP 32 /* max number of tc= indirections */
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
/*
* termcap - routines for dealing with the terminal capability data base
*
* BUG: Should use a "last" pointer in tbuf, so that searching
* for capabilities alphabetically would not be a n**2/2
* process when large numbers of capabilities are given.
* Note: If we add a last pointer now we will screw up the
* tc capability. We really should compile termcap.
*
* Essentially all the work here is scanning and decoding escapes
* in string capabilities. We don't use stdio because the editor
* doesn't, and because living w/o it is not hard.
*/
static char *tbuf;
static int hopcount; /* detect infinite loops in termcap, init 0 */
static int tnamatch(const char *);
static int tnchktc(void);
static char *tskip(register const char *);
static char *tdecode(register char *, char **);
/*
* Tnamatch deals with name matching. The first field of the termcap
* entry is a sequence of names separated by |'s, so we compare
* against each such name. The normal : terminator after the last
* name (before the first field) stops us.
*/
static int
tnamatch(const char *np)
{
register const char *Np;
register char *Bp;
Bp = tbuf;
if (*Bp == '#')
return(0);
for (;;) {
for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
continue;
if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
return (1);
while (*Bp && *Bp != ':' && *Bp != '|')
Bp++;
if (*Bp == 0 || *Bp == ':')
return (0);
Bp++;
}
}
/*
* tnchktc: check the last entry, see if it's tc=xxx. If so,
* recursively find xxx and append that entry (minus the names)
* to take the place of the tc=xxx entry. This allows termcap
* entries to say "like an HP2621 but doesn't turn on the labels".
* Note that this works because of the left to right scan.
*/
static int
tnchktc(void)
{
register char *p, *q;
char tcname[16]; /* name of similar terminal */
char tcbuf[TCBUFSIZE];
char rmbuf[TCBUFSIZE];
char *holdtbuf = tbuf, *holdtc;
int l;
p = tbuf;
while (*p) {
holdtc = p = tskip(p);
if (!*p)
break;
if (*p++ != 't' || *p == 0 || *p++ != 'c')
continue;
if (*p++ != '=') {
bad: write(2, "Bad termcap entry\n", 18);
return (0);
}
for (q = tcname; *p && *p != ':'; p++) {
if (q >= &tcname[sizeof tcname - 1])
goto bad;
*q++ = *p;
}
*q = '\0';
if (++hopcount > MAXHOP) {
write(2, "Infinite tc= loop\n", 18);
return (0);
}
if (tgetent(tcbuf, tcname) != 1) {
hopcount = 0; /* unwind recursion */
return(0);
}
hopcount--;
tbuf = holdtbuf;
strcpy(rmbuf, &p[1]);
for (q=tcbuf; *q != ':'; q++)
;
l = holdtc - holdtbuf + strlen(rmbuf) + strlen(q);
if (l > TCBUFSIZE) {
write(2, "Termcap entry too long\n", 23);
break;
}
q++;
for (p = holdtc; *q; q++)
*p++ = *q;
strcpy(p, rmbuf);
p = holdtc;
}
return(1);
}
/*
* Get an entry for terminal name in buffer bp,
* from the termcap file. Parse is very rudimentary;
* we just notice escaped newlines.
*/
int
tgetent(char *bp, const char *name)
{
register char *cp;
register int c;
register int i = 0, cnt = 0;
char ibuf[TCBUFSIZE];
int tf;
tbuf = bp;
tf = -1;
#ifndef V6
cp = getenv("TERMCAP");
/*
* TERMCAP can have one of two things in it. It can be the
* name of a file to use instead of /etc/termcap. In this
* case it better start with a "/". Or it can be an entry to
* use so we don't have to read the file. In this case it
* has to already have the newlines crunched out.
*/
if (cp && *cp) {
if (*cp == '/') {
tf = open(cp, 0);
} else {
tbuf = cp;
c = tnamatch(name);
tbuf = bp;
if (c) {
strcpy(bp,cp);
return(tnchktc());
}
}
}
if (tf < 0)
tf = open(E_TERMCAP, 0);
#else
tf = open(E_TERMCAP, 0);
#endif
if (tf < 0)
return (-1);
for (;;) {
cp = bp;
for (;;) {
if (i == cnt) {
cnt = read(tf, ibuf, TCBUFSIZE);
if (cnt <= 0) {
close(tf);
return (0);
}
i = 0;
}
c = ibuf[i++];
if (c == '\n') {
if (cp > bp && cp[-1] == '\\'){
cp--;
continue;
}
break;
}
if (cp >= bp+TCBUFSIZE) {
write(2,"Termcap entry too long\n", 23);
break;
} else
*cp++ = c;
}
*cp = 0;
/*
* The real work for the match.
*/
if (tnamatch(name)) {
close(tf);
return(tnchktc());
}
}
}
/*
* Skip to the next field. Notice that this is very dumb, not
* knowing about \: escapes or any such. If necessary, :'s can be put
* into the termcap file in octal.
*/
static char *
tskip(register const char *bp)
{
while (*bp && *bp != ':')
bp++;
if (*bp == ':')
bp++;
return (char *)bp;
}
/*
* Return the (numeric) option id.
* Numeric options look like
* li#80
* i.e. the option string is separated from the numeric value by
* a # character. If the option is not found we return -1.
* Note that we handle octal numbers beginning with 0.
*/
int
tgetnum(char *id)
{
register int i, base;
register char *bp = tbuf;
for (;;) {
bp = tskip(bp);
if (*bp == 0)
return (-1);
if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
continue;
if (*bp == '@')
return(-1);
if (*bp != '#')
continue;
bp++;
base = 10;
if (*bp == '0')
base = 8;
i = 0;
while (isdigit((*bp & 0377)))
i *= base, i += *bp++ - '0';
return (i);
}
}
/*
* Handle a flag option.
* Flag options are given "naked", i.e. followed by a : or the end
* of the buffer. Return 1 if we find the option, or 0 if it is
* not given.
*/
int
tgetflag(char *id)
{
register char *bp = tbuf;
for (;;) {
bp = tskip(bp);
if (!*bp)
return (0);
if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
if (!*bp || *bp == ':')
return (1);
else if (*bp == '@')
return(0);
}
}
}
/*
* Get a string valued option.
* These are given as
* cl=^Z
* Much decoding is done on the strings, and the strings are
* placed in area, which is a ref parameter which is updated.
* No checking on area overflow.
*/
char *
tgetstr(char *id, char **area)
{
register char *bp = tbuf;
for (;;) {
bp = tskip(bp);
if (!*bp)
return (0);
if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
continue;
if (*bp == '@')
return(0);
if (*bp != '=')
continue;
bp++;
return (tdecode(bp, area));
}
}
/*
* Tdecode does the grung work to decode the
* string capability escapes.
*/
static char *
tdecode(register char *str, char **area)
{
register char *cp;
register int c;
register char *dp;
int i;
cp = *area;
while ((c = *str++) && c != ':') {
switch (c) {
case '^':
c = *str++ & 037;
break;
case '\\':
dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
c = *str++;
nextc:
if (*dp++ == c) {
c = *dp++;
break;
}
dp++;
if (*dp)
goto nextc;
if (isdigit(c)) {
c -= '0', i = 2;
do
c <<= 3, c |= *str++ - '0';
while (--i && isdigit(*str & 0377));
}
break;
}
*cp++ = c;
}
*cp++ = 0;
str = *area;
*area = cp;
return (str);
}
/*
*/
static const char sccssl[] = "@(#)libterm.sl 1.7 (gritter) 11/23/04";

222
libterm/tgoto.c Normal file
View File

@ -0,0 +1,222 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*/
#ifndef lint
#ifdef DOSCCS
static char *sccsid = "@(#)tgoto.c 1.3 (gritter) 11/23/04";
#endif
#endif
/* from tgoto.c 5.1 (Berkeley) 6/5/85 */
#include "libterm.h"
#define CTRL(c) (c & 037)
#define MAXRETURNSIZE 64
#ifdef __STDC__
#include <string.h>
#endif
char *UP;
char *BC;
/*
* Routine to perform cursor addressing.
* CM is a string containing printf type escapes to allow
* cursor addressing. We start out ready to print the destination
* line, and switch each time we print row or column.
* The following escapes are defined for substituting row/column:
*
* %d as in printf
* %2 like %2d
* %3 like %3d
* %. gives %c hacking special case characters
* %+x like %c but adding x first
*
* The codes below affect the state but don't use up a value.
*
* %>xy if value > x add y
* %r reverses row/column
* %i increments row/column (for one origin indexing)
* %% gives %
* %B BCD (2 decimal digits encoded in one byte)
* %D Delta Data (backwards bcd)
*
* all other characters are ``self-inserting''.
*/
char *
tgoto(char *CM, int destcol, int destline)
{
static char result[MAXRETURNSIZE];
static char added[10];
char *cp = CM;
register char *dp = result;
register int c;
int oncol = 0;
register int which = destline;
if (cp == 0) {
toohard:
/*
* ``We don't do that under BOZO's big top''
*/
return ("OOPS");
}
added[0] = 0;
while (c = *cp++) {
if (c != '%') {
*dp++ = c;
continue;
}
switch (c = *cp++) {
#ifdef CM_N
case 'n':
destcol ^= 0140;
destline ^= 0140;
goto setwhich;
#endif
case 'd':
if (which < 10)
goto one;
if (which < 100)
goto two;
/* fall into... */
case '3':
*dp++ = (which / 100) | '0';
which %= 100;
/* fall into... */
case '2':
two:
*dp++ = which / 10 | '0';
one:
*dp++ = which % 10 | '0';
swap:
oncol = 1 - oncol;
setwhich:
which = oncol ? destcol : destline;
continue;
#ifdef CM_GT
case '>':
if (which > *cp++)
which += *cp++;
else
cp++;
continue;
#endif
case '+':
which += *cp++;
/* fall into... */
case '.':
/* casedot: */
/*
* This code is worth scratching your head at for a
* while. The idea is that various weird things can
* happen to nulls, EOT's, tabs, and newlines by the
* tty driver, arpanet, and so on, so we don't send
* them if we can help it.
*
* Tab is taken out to get Ann Arbors to work, otherwise
* when they go to column 9 we increment which is wrong
* because bcd isn't continuous. We should take out
* the rest too, or run the thing through more than
* once until it doesn't make any of these, but that
* would make termlib (and hence pdp-11 ex) bigger,
* and also somewhat slower. This requires all
* programs which use termlib to stty tabs so they
* don't get expanded. They should do this anyway
* because some terminals use ^I for other things,
* like nondestructive space.
*/
if (which == 0 || which == CTRL('d') || /* which == '\t' || */ which == '\n') {
if (oncol || UP) /* Assumption: backspace works */
/*
* Loop needed because newline happens
* to be the successor of tab.
*/
do {
strcat(added, oncol ? (BC ? BC : "\b") : UP);
which++;
} while (which == '\n');
}
*dp++ = which;
goto swap;
case 'r':
oncol = 1;
goto setwhich;
case 'i':
destcol++;
destline++;
which++;
continue;
case '%':
*dp++ = c;
continue;
#ifdef CM_B
case 'B':
which = (which/10 << 4) + which%10;
continue;
#endif
#ifdef CM_D
case 'D':
which = which - 2 * (which%16);
continue;
#endif
default:
goto toohard;
}
}
strcpy(dp, added);
return (result);
}

134
libterm/tputs.c Normal file
View File

@ -0,0 +1,134 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*/
#ifndef lint
#ifdef DOSCCS
static char *sccsid = "@(#)tputs.c 1.4 (gritter) 11/23/04";
#endif
#endif
/* from tputs.c 5.1 (Berkeley) 6/5/85 */
#include <ctype.h>
#include "libterm.h"
/*
* The following array gives the number of tens of milliseconds per
* character for each speed as returned by gtty. Thus since 300
* baud returns a 7, there are 33.3 milliseconds per char at 300 baud.
*/
static
short tmspc10[] = {
0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
};
short ospeed;
char PC;
/*
* Put the character string cp out, with padding.
* The number of affected lines is affcnt, and the routine
* used to output one character is outc.
*/
int
tputs(const char *cp, int affcnt, int (*outc)(int))
{
register int i = 0;
register int mspc10;
if (cp == 0)
return 1;
/*
* Convert the number representing the delay.
*/
if (isdigit(*cp & 0377)) {
do
i = i * 10 + *cp++ - '0';
while (isdigit(*cp & 0377));
}
i *= 10;
if (*cp == '.') {
cp++;
if (isdigit(*cp & 0377))
i += *cp - '0';
/*
* Only one digit to the right of the decimal point.
*/
while (isdigit(*cp & 0377))
cp++;
}
/*
* If the delay is followed by a `*', then
* multiply by the affected lines count.
*/
if (*cp == '*')
cp++, i *= affcnt;
/*
* The guts of the string.
*/
while (*cp)
(*outc)(*cp++);
/*
* If no delay needed, or output speed is
* not comprehensible, then don't try to delay.
*/
if (i == 0)
return 1;
if (ospeed <= 0 || ospeed >= (sizeof tmspc10 / sizeof tmspc10[0]))
return 1;
/*
* Round up by a half a character frame,
* and then do the delay.
* Too bad there are no user program accessible programmed delays.
* Transmitting pad characters slows many
* terminals down and also loads the system.
*/
mspc10 = tmspc10[ospeed];
i += mspc10 / 2;
for (i /= mspc10; i > 0; i--)
(*outc)(PC);
return 1;
}

123
makeoptions Normal file
View File

@ -0,0 +1,123 @@
#!/bin/sh
#
# This code contains changes by
# Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
#
# Conditions 1, 2, and 4 and the no-warranty notice below apply
# to these changes.
#
#
# Copyright (c) 1980, 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.
#
#
# Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# Redistributions of source code and documentation must retain the
# above copyright notice, this list of conditions and the following
# disclaimer.
# 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.
# All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed or owned by Caldera
# International, Inc.
# Neither the name of Caldera International, Inc. nor the names of
# other contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
# INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
#
# from makeoptions 6.4 (Berkeley) 5/31/85
#
# @(#)makeoptions 1.8 (gritter) 7/1/02
#
#
# remake options -- this isn't necessary unless you add/delete options
#
trap "rm -f /tmp/ex_foo$$.c /tmp/ex_bar$$.c" 0
trap '' 2
cat < ex_data.c > /tmp/ex_bar$$.c
ex -s /tmp/ex_bar$$.c <<\!
g/^#include/d
w
q
!
cc -E ${@+"$@"} /tmp/ex_bar$$.c >/tmp/ex_foo$$.c
ex -s /tmp/ex_foo$$.c <<\!
" delete all preprocessor output (# line, etc)
g/^# /d
set sh=/bin/sh
" delete junk (all but data lines)
g/^[ ]*$/d
1,/option options/d
/};/-1,$d
" get rid of all of line but option name
1,$s/[ ]*{[ ]*"//
1,$s/".*//
" begin kludge since options start at 0 but nl starts at 1
" move first to end and later move it back and renumber
1m$
%!nl
$t0
1s/[0-9][0-9]*/0/
" end kludge
" make #define lines
1,$s/[ ]*\([0-9][0-9]*\)[ ]*\(.*\)/#define \U\2\L \1/
" filter through expand to make it line up nice
%!expand -8\,24
" blank line and number of options.
$i
.
$s/e[ ].*[ ]/e NOPTS /
0a
/* sccs id @(#)ex_vars.h makeoptions 1.8 (gritter) 7/1/02 */
.
w! ex_vars.h
q
!

352
malloc.c Normal file
View File

@ -0,0 +1,352 @@
/*
* AT&T Unix 7th Edition memory allocation routines.
*
* Modified for ex by Gunnar Ritter, Freiburg i. Br., Germany,
* July 2000.
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*
* @(#)malloc.c 1.17 (gritter) 11/26/04
*/
#ifdef VMUNIX
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include "config.h"
#ifdef LANGMSG
#include <nl_types.h>
extern nl_catd catd;
#else
#define catgets(a, b, c, d) (d)
#endif
/*
* Since ex makes use of sbrk(), the C library's version of malloc()
* must be avoided.
*
* In ex, malloc() calls sbrk() only one time with an argument of
* POOL. Ex itselves never uses malloc() internally, so POOL
* must be sufficient for library calls like setlocale() only.
*
* Known problem: If linking against ncurses, changing the terminal
* type repeatedly outruns the pool. Even that is not really a
* problem since the work continues with the old terminal type, so
* there is no need for a large pool here.
*/
#define POOL 32768
#ifdef debug
#define ASSERT(p) if(!(p))botch("p");else
int
botch(char *s)
{
printf("assertion botched: %s\n",s);
abort();
}
#else
#define ASSERT(p)
#endif
/* avoid break bug */
#ifdef pdp11
#define GRANULE 64
#else
#define GRANULE 0
#endif
/* C storage allocator
* circular first-fit strategy
* works with noncontiguous, but monotonically linked, arena
* each block is preceded by a ptr to the (pointer of)
* the next following block
* blocks are exact number of words long
* aligned to the data type requirements of ALIGN
* pointers to blocks must have BUSY bit 0
* bit in ptr is 1 for busy, 0 for idle
* gaps in arena are merely noted as busy blocks
* last block of arena (pointed to by alloct) is empty and
* has a pointer to first
* idle blocks are coalesced during space search
*
* a different implementation may need to redefine
* ALIGN, NALIGN, BLOCK, BUSY, INT
* where INT is integer type to which a pointer can be cast
*/
#define INT intptr_t
#define ALIGN intptr_t
#define NALIGN 1
#define WORD sizeof (union store)
#define BLOCK 1024 /* a multiple of WORD*/
#define BUSY 1
#ifdef NULL
#undef NULL
#endif
#define NULL 0
#define testbusy(p) ((INT)(p)&BUSY)
#define setbusy(p) (union store *)((INT)(p)|BUSY)
#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
union store { union store *ptr;
ALIGN dummy[NALIGN];
/*int calloc;*/ /*calloc clears an array of integers*/
};
static union store allocs[2]; /*initial arena*/
static union store *allocp; /*search ptr*/
static union store *alloct; /*arena top*/
static union store *allocx; /*for benefit of realloc*/
extern int error(char *, ...);
char *
poolsbrk(intptr_t inc)
{
static char *pool;
static intptr_t ps;
intptr_t os, ns;
if (pool == NULL)
if ((pool = sbrk(POOL)) == (char *)-1)
error(catgets(catd, 1, 241,
"No memory pool"));
if (inc == 0)
return pool;
os = ps;
ns = ps + inc;
if (ns >= POOL)
error(catgets(catd, 1, 242,
"Memory pool exhausted"));
ps = ns;
return pool + os;
}
char *
malloc(size_t nbytes)
{
register union store *p, *q;
register nw;
static temp; /*coroutines assume no auto*/
if(allocs[0].ptr==0) { /*first time*/
allocs[0].ptr = setbusy(&allocs[1]);
allocs[1].ptr = setbusy(&allocs[0]);
alloct = &allocs[1];
allocp = &allocs[0];
}
nw = (nbytes+WORD+WORD-1)/WORD;
ASSERT(allocp>=allocs && allocp<=alloct);
ASSERT(allock());
for(p=allocp; ; ) {
for(temp=0; ; ) {
if(!testbusy(p->ptr)) {
while(!testbusy((q=p->ptr)->ptr)) {
ASSERT(q>p&&q<alloct);
p->ptr = q->ptr;
}
if(q>=p+nw && p+nw>=p)
goto found;
}
q = p;
p = clearbusy(p->ptr);
if(p>q)
ASSERT(p<=alloct);
else if(q!=alloct || p!=allocs) {
ASSERT(q==alloct&&p==allocs);
errno = ENOMEM;
return(NULL);
} else if(++temp>1)
break;
}
temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD);
q = (union store *)poolsbrk(0);
if(q+temp+GRANULE < q) {
errno = ENOMEM;
return(NULL);
}
q = (union store *)poolsbrk(temp*WORD);
if((INT)q == -1) {
errno = ENOMEM;
return(NULL);
}
ASSERT(q>alloct);
alloct->ptr = q;
if(q!=alloct+1)
alloct->ptr = setbusy(alloct->ptr);
alloct = q->ptr = q+temp-1;
alloct->ptr = setbusy(allocs);
}
found:
allocp = p + nw;
ASSERT(allocp<=alloct);
if(q>allocp) {
allocx = allocp->ptr;
allocp->ptr = p->ptr;
}
p->ptr = setbusy(allocp);
return((char *)(p+1));
}
/* freeing strategy tuned for LIFO allocation
*/
int
free(register char *ap)
{
register union store *p = (union store *)ap;
ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct);
ASSERT(allock());
allocp = --p;
ASSERT(testbusy(p->ptr));
p->ptr = clearbusy(p->ptr);
ASSERT(p->ptr > allocp && p->ptr <= alloct);
}
/* realloc(p, nbytes) reallocates a block obtained from malloc()
* and freed since last call of malloc()
* to have new size nbytes, and old content
* returns new location, or 0 on failure
*/
char *
realloc(register union store *p, size_t nbytes)
{
register union store *q;
union store *s, *t;
register size_t nw;
size_t onw;
if (p == NULL)
return malloc(nbytes);
if (nbytes == 0) {
free(p);
return NULL;
}
if(testbusy(p[-1].ptr))
free((char *)p);
onw = p[-1].ptr - p;
q = (union store *)malloc(nbytes);
if(q==NULL || q==p)
return((char *)q);
s = p;
t = q;
nw = (nbytes+WORD-1)/WORD;
if(nw<onw)
onw = nw;
while(onw--!=0)
*t++ = *s++;
if(q<p && q+nw>=p)
(q+(q+nw-p))->ptr = allocx;
return((char *)q);
}
#ifdef debug
int
allock(void)
{
#ifdef longdebug
register union store *p;
int x;
x = 0;
for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) {
if(p==allocp)
x++;
}
ASSERT(p==alloct);
return(x==1|p==allocp);
#else
return(1);
#endif
}
#endif
/* calloc - allocate and clear memory block
*/
#define CHARPERINT (sizeof(INT)/sizeof(char))
char *
calloc(size_t num, size_t size)
{
register char *mp;
register INT *q;
register m;
num *= size;
mp = malloc(num);
if(mp == NULL)
return(NULL);
q = (INT *) mp;
m = (num+CHARPERINT-1)/CHARPERINT;
while(--m >= 0)
*q++ = 0;
return(mp);
}
/*ARGSUSED*/
int
cfree(char *p, size_t num, size_t size)
{
free(p);
}
#ifdef notdef
/*
* Just in case ...
*/
char *
memalign(size_t alignment, size_t size)
{
return NULL;
}
char *
valloc(size_t size)
{
return NULL;
}
char *
mallinfo(void)
{
return NULL;
}
int
mallopt(void)
{
return -1;
}
#endif /* notdef */
#endif /* VMUNIX */

570
mapmalloc.c Normal file
View File

@ -0,0 +1,570 @@
/*
* Memory allocation routines using mmap().
*
* Derived from mm-1.1.3 by Gunnar Ritter, Freiburg i. Br., Germany,
* September 2001.
*/
/* Sccsid @(#)mapmalloc.c 1.14 (gritter) 11/26/04 */
/* ====================================================================
* Copyright (c) 1999-2000 Ralf S. Engelschall. 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 acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com>."
*
* 4. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by
* Ralf S. Engelschall <rse@engelschall.com>."
*
* THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
* EXPRESSED 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 RALF S. ENGELSCHALL OR
* ITS 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.
* ====================================================================
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#ifdef __GLIBC__
/*
* Broken GNU libc will include stdlib.h with conflicting
* malloc() types otherwise.
*/
#ifndef __NO_STRING_INLINES
#define __NO_STRING_INLINES
#endif /* !__NO_STRING_INLINES */
#endif /* __GLIBC__ */
#include <string.h>
#include "config.h"
#ifdef LANGMSG
#include <nl_types.h>
extern nl_catd catd;
#else
#define catgets(a, b, c, d) (d)
#endif
#ifndef min_of
#define min_of(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max_of
#define max_of(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MAP_ANON
#ifdef MAP_ANONYMOUS
#define MAP_ANON MAP_ANONYMOUS
#endif
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((char *)-1)
#endif
#define MM_ALLOC_MINSIZE 8192
/*
* Define a union with types which are likely to have the longest
* *relevant* CPU-specific memory word alignment restrictions...
*/
union mem_word {
char (*mw_fp)(int);
char *mw_cp;
long mw_l;
double mw_d;
intptr_t mw_it;
};
typedef union mem_word mem_word;
#define SIZEOF_mem_word (sizeof(mem_word))
/*
* Define the structure used for memory chunks
*/
union mem_chunk_mc_u {
struct mem_chunk *mc_next; /* really used when it's free */
mem_word mc_base;/* virtually used when it's allocated */
};
struct mem_chunk {
size_t mc_size; /* physical size */
size_t mc_usize; /* user known size */
struct mem_pool *mc_pool;
union mem_chunk_mc_u mc_u;
};
typedef struct mem_chunk mem_chunk;
#define SIZEOF_mem_chunk (sizeof(mem_chunk)-sizeof(union mem_chunk_mc_u))
/*
* Define the structure describing a memory pool
*/
struct mem_pool {
struct mem_pool *mp_prev;
struct mem_pool *mp_next;
size_t mp_size;
size_t mp_offset;
int mp_users;
mem_chunk mp_freechunks;
mem_word mp_base;
};
typedef struct mem_pool mem_pool;
#define SIZEOF_mem_pool (sizeof(mem_pool)-SIZEOF_mem_word)
/*
* Define the structure describing a shared memory core area
* (the actual contents depends on the shared memory and
* semaphore/mutex type and is stripped down to a minimum
* required)
*/
struct mem_core {
size_t mo_size;
size_t mo_usize;
mem_word mo_base;
};
typedef struct mem_core mem_core;
#define SIZEOF_mem_core (sizeof(mem_core)-SIZEOF_mem_word)
typedef mem_pool MM;
static MM *mm_global = NULL;
#ifndef MAP_ANON
static int zerofd = -1;
#endif
extern int error(char *, ...);
/*
* Determine memory page size of OS
*/
static size_t
mm_core_pagesize(void)
{
static int pagesize = 0;
if (pagesize == 0)
#ifdef _SC_PAGESIZE
pagesize = sysconf(_SC_PAGESIZE);
#else
pagesize = 8192;
#endif
return pagesize;
}
/*
* Align a size to the next page or word boundary
*/
static size_t
mm_core_align2page(size_t size)
{
int psize = mm_core_pagesize();
return ((size) % (psize) > 0 ?
((size) / (psize) + 1) * (psize) : (size));
}
static size_t
mm_core_align2word(size_t size)
{
return ((1 + ((size - 1) / SIZEOF_mem_word)) * SIZEOF_mem_word);
}
/*
* Create a shared memory area
*/
static char
*mm_core_create(size_t usersize)
{
mem_core *mo;
char *area = ((char *)-1);
size_t size;
if (usersize <= 0) {
errno = EINVAL;
return NULL;
}
size = mm_core_align2page(usersize + SIZEOF_mem_core);
#ifdef MAP_ANON
if ((area = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0)) == (char *)MAP_FAILED)
error(catgets(catd, 1, 243,
"failed to memory map anonymous area"));
#else /* !MAP_ANON */
if (zerofd == -1 && ((zerofd = open("/dev/zero", O_RDWR)) == -1
#ifdef F_SETFD
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif /* !FD_CLOEXEC */
|| fcntl(zerofd, F_SETFD, FD_CLOEXEC) == -1
#endif /* F_SETFD */
))
error(catgets(catd, 1, 244,
"failed to open /dev/zero"));
if ((area = (char *)mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE, zerofd, (off_t)0)) == (char *)MAP_FAILED)
error(catgets(catd, 1, 245,
"failed to memory map /dev/zero"));
#endif /* !MAP_ANON */
/*
* Configure the memory core parameters
*/
mo = (mem_core *)area;
mo->mo_size = size;
mo->mo_usize = usersize;
/*
* Return successfully established core
*/
return ((char *)&(mo->mo_base.mw_cp));
}
/*
* Create a memory pool
*/
static MM *
mm_create(MM *mmPrev, size_t usize)
{
MM *mm = NULL;
char *core;
size_t size;
/*
* defaults
*/
if (usize < MM_ALLOC_MINSIZE)
usize = MM_ALLOC_MINSIZE;
/*
* determine size
*/
size = usize + SIZEOF_mem_pool;
/*
* get a shared memory area
*/
if ((core = mm_core_create(size)) == NULL)
return NULL;
/*
* fill in the memory pool structure
*/
mm = (MM *)core;
mm->mp_prev = mmPrev;
mm->mp_next = NULL;
mm->mp_size = size;
mm->mp_offset = SIZEOF_mem_pool;
mm->mp_users = 0;
/*
* first element of list of free chunks counts existing chunks
*/
mm->mp_freechunks.mc_size = 0; /* has to be 0 forever */
mm->mp_freechunks.mc_usize = 0; /* counts chunks */
mm->mp_freechunks.mc_u.mc_next = NULL;
return mm;
}
/*
* Insert a chunk to the list of free chunks. Algorithm used is:
* Insert in sorted manner to the list and merge with previous
* and/or next chunk when possible to form larger chunks out of
* smaller ones.
*/
static void
mm_insert_chunk(MM *mm, mem_chunk *mcInsert)
{
mem_chunk *mc;
mem_chunk *mcPrev;
mem_chunk *mcNext;
mc = &(mm->mp_freechunks);
while (mc->mc_u.mc_next != NULL &&
(char *)(mc->mc_u.mc_next) < (char *)mcInsert)
mc = mc->mc_u.mc_next;
mcPrev = mc;
mcNext = mc->mc_u.mc_next;
if (mcPrev == mcInsert || mcNext == mcInsert)
error(catgets(catd, 1, 246,
"chunk of memory already in free list"));
if ((char *)mcPrev + (mcPrev->mc_size) == (char *)mcInsert &&
(mcNext != NULL &&
(char *)mcInsert + (mcInsert->mc_size) ==
(char *)mcNext)) {
/*
* merge with previous and next chunk
*/
mcPrev->mc_size += mcInsert->mc_size + mcNext->mc_size;
mcPrev->mc_u.mc_next = mcNext->mc_u.mc_next;
mm->mp_freechunks.mc_usize -= 1;
} else if ((char *)mcPrev + (mcPrev->mc_size) ==
(char *)mcInsert) {
/*
* merge with previous chunk
*/
mcPrev->mc_size += mcInsert->mc_size;
} else if (mcNext != NULL &&
(char *)mcInsert + (mcInsert->mc_size) ==
(char *)mcNext) {
/*
* merge with next chunk
*/
mcInsert->mc_size += mcNext->mc_size;
mcInsert->mc_u.mc_next = mcNext->mc_u.mc_next;
mcPrev->mc_u.mc_next = mcInsert;
} else {
/*
* no merging possible, so insert as new chunk
*/
mcInsert->mc_u.mc_next = mcNext;
mcPrev->mc_u.mc_next = mcInsert;
mm->mp_freechunks.mc_usize += 1;
}
}
/*
* Retrieve a chunk from the list of free chunks. Algorithm used
* is: Search for minimal-sized chunk which is larger or equal
* than the request size. But when the retrieved chunk is still a
* lot larger than the requested size, split out the requested
* size to not waste memory.
*/
static mem_chunk *
mm_retrieve_chunk(MM *mm, size_t size)
{
mem_chunk *mc;
mem_chunk **pmcMin;
mem_chunk *mcRes;
size_t sMin;
size_t s;
if (size == 0)
return NULL;
if (mm->mp_freechunks.mc_usize == 0)
return NULL;
/*
* find best-fitting chunk
*/
pmcMin = NULL;
sMin = mm->mp_size; /* initialize with maximum possible */
mc = &(mm->mp_freechunks);
while (mc->mc_u.mc_next != NULL) {
s = mc->mc_u.mc_next->mc_size;
if (s >= size && s < sMin) {
pmcMin = &(mc->mc_u.mc_next);
sMin = s;
if (s == size)
break;
}
mc = mc->mc_u.mc_next;
}
/*
* create result chunk
*/
if (pmcMin == NULL)
mcRes = NULL;
else {
mcRes = *pmcMin;
if (mcRes->mc_size >= (size + min_of(2 * size, 128))) {
/*
* split out in part
*/
s = mcRes->mc_size - size;
mcRes->mc_size = size;
/*
* add back remaining chunk part as new chunk
*/
mc = (mem_chunk *)((char *)mcRes + size);
mc->mc_size = s;
mc->mc_u.mc_next = mcRes->mc_u.mc_next;
*pmcMin = mc;
} else {
/*
* split out as a whole
*/
*pmcMin = mcRes->mc_u.mc_next;
mm->mp_freechunks.mc_usize--;
}
}
return mcRes;
}
/*
* Allocate a chunk of memory
*/
char *
malloc(size_t usize)
{
MM *mm;
mem_chunk *mc;
size_t size;
size = mm_core_align2word(SIZEOF_mem_chunk + usize);
if (mm_global == NULL && (mm_global = mm_create(NULL, size)) == NULL)
return NULL;
mm = mm_global;
nextpool:
if ((mc = mm_retrieve_chunk(mm, size)) != NULL) {
mc->mc_usize = usize;
mc->mc_pool = mm;
mm->mp_users++;
return (char *)&(mc->mc_u.mc_base.mw_cp);
}
if ((mm->mp_size - mm->mp_offset) < size) {
if (mm->mp_next != NULL ||
(mm->mp_next = mm_create(mm, size)) != NULL) {
mm = mm->mp_next;
goto nextpool;
}
error(catgets(catd, 1, 247, "out of memory"));
errno = ENOMEM;
return NULL;
}
mc = (mem_chunk *)((char *)mm + mm->mp_offset);
mc->mc_size = size;
mc->mc_usize = usize;
mc->mc_pool = mm;
mm->mp_offset += size;
mm->mp_users++;
return (char *)&(mc->mc_u.mc_base.mw_cp);
}
/*
* Free a chunk of memory
*/
void
free(char *ptr)
{
MM *mm;
mem_chunk *mc;
if (mm_global == NULL || ptr == NULL)
return;
mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);
mm = mc->mc_pool;
mm_insert_chunk(mm, mc);
if (--mm->mp_users == 0) {
mem_core *mo = (mem_core *)((char *)mm - SIZEOF_mem_core);
if (mm == mm_global)
mm_global = mm->mp_next;
if (mm->mp_prev != NULL)
mm->mp_prev->mp_next = mm->mp_next;
if (mm->mp_next != NULL)
mm->mp_next->mp_prev = mm->mp_prev;
munmap((char *)mo, mo->mo_size);
}
}
/*
* Reallocate a chunk of memory
*/
char *
realloc(char *ptr, size_t usize)
{
size_t size;
mem_chunk *mc;
char *vp;
if (ptr == NULL)
return malloc(usize); /* POSIX.1 semantics */
mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk);
if (usize <= mc->mc_usize) {
mc->mc_usize = usize;
return ptr;
}
size = mm_core_align2word(SIZEOF_mem_chunk + usize);
if (size <= mc->mc_size) {
mc->mc_usize = usize;
return ptr;
}
if ((vp = malloc(usize)) == NULL)
return NULL;
memcpy(vp, ptr, usize);
free(ptr);
return vp;
}
/*
* Allocate and initialize a chunk of memory
*/
char *
calloc(size_t number, size_t usize)
{
char *vp;
if ((vp = malloc(number * usize)) == NULL)
return NULL;
memset(vp, 0, number * usize);
return vp;
}
/*ARGSUSED*/
void
cfree(char *p, size_t num, size_t size)
{
free(p);
}
#ifdef notdef
/*ARGSUSED*/
char *
memalign(size_t alignment, size_t size)
{
return NULL;
}
/*ARGSUSED*/
char *
valloc(size_t size)
{
return NULL;
}
char *
mallinfo(void)
{
return NULL;
}
int
mallopt(void)
{
return -1;
}
#endif /* notdef */
/*ARGSUSED*/
char *
poolsbrk(intptr_t val)
{
return NULL;
}

440
printf.c Normal file
View File

@ -0,0 +1,440 @@
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 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.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* 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.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. 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 CALDERA INTERNATIONAL, INC. 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.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)printf.c 1.15 (gritter) 12/1/04";
#endif
#endif
/* from printf.c 7.3 (Berkeley) 6/7/85 */
/* The pwb version this is based on */
/* from printf.c:2.2 6/5/79 */
#include "ex.h"
/*
* This version of printf is compatible with the Version 7 C
* printf. The differences are only minor except that this
* printf assumes it is to print through putchar. Version 7
* printf is more general (and is much larger) and includes
* provisions for floating point.
*/
static int width, sign, fill;
int vprintf(const char *, va_list);
char *p_dconv(long, char *);
static int p_emit(char *, char *);
int
printf(const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vprintf(fmt, ap);
va_end(ap);
return ret;
}
int
vprintf(const char *fmt, va_list ap)
{
int cnt = 0;
int fcode;
int prec;
int length,mask1,nbits,n,m;
long int mask2, num;
register char *bptr;
char *ptr;
char buf[134];
for (;;) {
/* process format string first */
while (nextc(fcode,fmt,m), fmt+=m, fcode!='%') {
/* ordinary (non-%) character */
if (fcode=='\0')
return cnt;
putchar(fcode);
cnt += m;
}
/* length modifier: -1 for h, 1 for l, 0 for none */
length = 0;
/* check for a leading - sign */
sign = 0;
if (*fmt == '-') {
sign++;
fmt++;
}
/* a '0' may follow the - sign */
/* this is the requested fill character */
fill = 1;
if (*fmt == '0') {
fill--;
fmt++;
}
/* Now comes a digit string which may be a '*' */
if (*fmt == '*') {
width = va_arg(ap, int);
if (width < 0) {
width = -width;
sign = !sign;
}
fmt++;
}
else {
width = 0;
while (*fmt>='0' && *fmt<='9')
width = width * 10 + (*fmt++ - '0');
}
/* maybe a decimal point followed by more digits (or '*') */
if (*fmt=='.') {
if (*++fmt == '*') {
prec = va_arg(ap, int);
fmt++;
}
else {
prec = 0;
while (*fmt>='0' && *fmt<='9')
prec = prec * 10 + (*fmt++ - '0');
}
}
else
prec = -1;
/*
* At this point, "sign" is nonzero if there was
* a sign, "fill" is 0 if there was a leading
* zero and 1 otherwise, "width" and "prec"
* contain numbers corresponding to the digit
* strings before and after the decimal point,
* respectively, and "fmt" addresses the next
* character after the whole mess. If there was
* no decimal point, "prec" will be -1.
*/
switch (*fmt) {
case 'L':
case 'l':
length = 2;
/* no break!! */
case 'h':
case 'H':
length--;
fmt++;
break;
}
/*
* At exit from the following switch, we will
* emit the characters starting at "bptr" and
* ending at "ptr"-1, unless fcode is '\0'.
*/
switch (nextc(fcode, fmt, m), fmt += m, fcode) {
/* process characters and strings first */
case 'c':
buf[0] = va_arg(ap, int);
ptr = bptr = &buf[0];
if (buf[0] != '\0')
ptr++;
break;
case 's':
bptr = va_arg(ap,char *);
if (bptr==0)
bptr = catgets(catd, 1, 248,
"(null pointer)");
if (prec < 0)
prec = LRGINT;
for (n=0; *bptr++ && n < prec; n++) ;
ptr = --bptr;
bptr -= n;
break;
case 'O':
length = 1;
fcode = 'o';
/* no break */
case 'o':
case 'X':
case 'x':
if (length > 0)
num = va_arg(ap,long);
else
num = (unsigned)va_arg(ap,int);
if (fcode=='o') {
mask1 = 0x7;
mask2 = 0x1fffffffL;
nbits = 3;
}
else {
mask1 = 0xf;
mask2 = 0x0fffffffL;
nbits = 4;
}
n = (num!=0);
bptr = buf + MAXOCT + 3;
/* shift and mask for speed */
do
if (((int) num & mask1) < 10)
*--bptr = ((int) num & mask1) + 060;
else
*--bptr = ((int) num & mask1) + 0127;
while (num = (num >> nbits) & mask2);
if (fcode=='o') {
if (n)
*--bptr = '0';
}
else
if (!sign && fill <= 0) {
putchar('0');
putchar(fcode);
width -= 2;
}
else {
*--bptr = fcode;
*--bptr = '0';
}
ptr = buf + MAXOCT + 3;
break;
case 'D':
case 'U':
case 'I':
length = 1;
fcode = fcode + 'a' - 'A';
/* no break */
case 'd':
case 'i':
case 'u':
if (length > 0)
num = va_arg(ap,long);
else {
n = va_arg(ap,int);
if (fcode=='u')
num = (unsigned) n;
else
num = (long) n;
}
if (n = (fcode != 'u' && num < 0))
num = -num;
/* now convert to digits */
bptr = p_dconv(num, buf);
if (n)
*--bptr = '-';
if (fill == 0)
fill = -1;
ptr = buf + MAXDIGS + 1;
break;
default:
/* not a control character,
* print it.
*/
ptr = bptr = (char *)&fmt[-m];
ptr++;
break;
}
if (fcode != '\0')
cnt += p_emit(bptr,ptr);
}
}
/* p_dconv converts the unsigned long integer "value" to
* printable decimal and places it in "buffer", right-justified.
* The value returned is the address of the first non-zero character,
* or the address of the last character if all are zero.
* The result is NOT null terminated, and is MAXDIGS characters long,
* starting at buffer[1] (to allow for insertion of a sign).
*
* This program assumes it is running on 2's complement machine
* with reasonable overflow treatment.
*/
char *
p_dconv(long value, char *buffer)
{
register char *bp;
register int svalue;
int n;
long lval;
bp = buffer;
/* zero is a special case */
if (value == 0) {
bp += MAXDIGS;
*bp = '0';
return(bp);
}
/* develop the leading digit of the value in "n" */
n = 0;
while (value < 0) {
value -= BIG; /* will eventually underflow */
n++;
}
while (value >= BIG && (lval = value - BIG) >= 0) {
value = lval;
n++;
}
/* stash it in buffer[1] to allow for a sign */
bp[1] = n + '0';
/*
* Now develop the rest of the digits. Since speed counts here,
* we do it in two loops. The first gets "value" down until it
* is no larger than LRGINT. The second one uses integer divides
* rather than long divides to speed it up.
*/
bp += MAXDIGS + 1;
while (value > LRGINT) {
*--bp = (int)(value % 10) + '0';
value /= 10;
}
/* cannot lose precision */
svalue = value;
while (svalue > 0) {
*--bp = (svalue % 10) + '0';
svalue /= 10;
}
/* fill in intermediate zeroes if needed */
if (buffer[1] != '0') {
while (bp > buffer + 2)
*--bp = '0';
--bp;
}
return(bp);
}
/*
* This program sends string "s" to putchar. The character after
* the end of "s" is given by "send". This allows the size of the
* field to be computed; it is stored in "alen". "width" contains the
* user specified length. If width<alen, the width will be taken to
* be alen. "sign" is zero if the string is to be right-justified
* in the field, nonzero if it is to be left-justified. "fill" is
* 0 if the string is to be padded with '0', positive if it is to be
* padded with ' ', and negative if an initial '-' should appear before
* any padding in right-justification (to avoid printing "-3" as
* "000-3" where "-0003" was intended).
*/
static int
p_emit(register char *s, char *send)
{
char cfill;
register int alen;
int npad;
int cnt = 0;
int c, m;
alen = send - s;
if (alen > width)
width = alen;
cfill = fill>0? ' ': '0';
/* we may want to print a leading '-' before anything */
if (*s == '-' && fill < 0) {
putchar(*s++);
cnt++;
alen--;
width--;
}
npad = width - alen;
/* emit any leading pad characters */
if (!sign)
while (--npad >= 0) {
putchar(cfill);
cnt++;
}
/* emit the string itself */
while (--alen >= 0) {
nextc(c, s, m);
s += m;
putchar(c);
cnt += m;
alen -= m-1;
}
/* emit trailing pad characters */
if (sign)
while (--npad >= 0) {
putchar(cfill);
cnt++;
}
return cnt;
}

1025
vi.1 Normal file

File diff suppressed because it is too large Load Diff