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