mirror of https://github.com/tildeclub/ex-vi.git
Initial revision
This commit is contained in:
commit
92e4e9fdf7
|
@ -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).
|
|
@ -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.
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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"
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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}
|
|
@ -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();
|
||||
}
|
|
@ -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 *);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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, }
|
||||
};
|
|
@ -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"
|
|
@ -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);
|
||||
}
|
|
@ -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 *);
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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 = ®rbuf;
|
||||
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();
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
|
@ -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 */
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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)
|
File diff suppressed because it is too large
Load Diff
|
@ -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"E) && (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);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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));
|
|
@ -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";
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
!
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue