incorporated alm's update of elvis to 1.7

This commit is contained in:
cgd 1993-04-08 02:22:57 +00:00
parent 744d9dbe75
commit 18969c77a9
38 changed files with 2477 additions and 769 deletions

View File

@ -1,6 +1,8 @@
PROG= elvispreserve
CFLAGS= -I${.CURDIR}/../../usr.bin/elvis
BINOWN= root
BINMODE=4755
MAN8=elvispreserve.0
.include <bsd.prog.mk>

View File

@ -1,15 +1,15 @@
.TH ELVISPRESERVE 8
.TH ELVPRSV 1
.SH NAME
elvispreserve - Preserve the the modified version of a file after a crash.
elvprsv - Preserve the the modified version of a file after a crash.
.SH SYNOPSIS
.nf
\fB\fBelvispreserve\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
\fB\fBelvispreserve\fP -R /tmp/\fIfilename\fP...
\fB\fBelvprsv\fP ["-\fIwhy elvis died\fP"] /tmp/\fIfilename\fP...
\fB\fBelvprsv\fP -R /tmp/\fIfilename\fP...
.fi
.SH DESCRIPTION
.PP
\fIelvispreserve\fP preserves your edited text after \fIelvis\fP dies.
The text can be recovered later, via the \fIelvispreserve\fP program.
\fIelvprsv\fP preserves your edited text after \fIelvis\fP dies.
The text can be recovered later, via the \fIelvprsv\fP program.
.PP
For UNIX-like systems,
you should never need to run this program from the command line.
@ -17,35 +17,35 @@ It is run automatically when \fIelvis\fP is about to die,
and it should be run (via /etc/rc) when the computer is booted.
THAT'S ALL!
.PP
For non-UNIX systems such as MS-DOS, you can either use \fIelvispreserve\fP
For non-UNIX systems such as MS-DOS, you can either use \fIelvprsv\fP
the same way as under UNIX systems (by running it from your AUTOEXEC.BAT file),
or you can run it separately with the "-R" flag to recover the files
in one step.
.PP
If you're editing a file when \fIelvis\fP dies
(due to a bug, system crash, power failure, etc.)
then \fIelvispreserve\fP will preserve the most recent version of your text.
then \fIelvprsv\fP will preserve the most recent version of your text.
The preserved text is stored in a special directory; it does NOT overwrite
your text file automatically.
.PP
\fIelvispreserve\fP will send mail to any user whose work it preserves,
\fIelvprsv\fP will send mail to any user whose work it preserves,
if your operating system normally supports mail.
.SH FILES
.IP /tmp/elv*
The temporary file that \fIelvis\fP was using when it died.
.IP /usr/preserve/p*
The text that is preserved by \fIelvispreserve\fP.
The text that is preserved by \fIelvprsv\fP.
.IP /usr/preserve/Index
A text file which lists the names of all preserved files, and the names
of the /usr/preserve/p* files which contain their preserved text.
.SH BUGS
.PP
Due to the permissions on the /usr/preserve directory, on UNIX systems
\fIelvispreserve\fP must be run as superuser.
This is accomplished by making the \fIelvispreserve\fP executable be owned by "root"
\fIelvprsv\fP must be run as superuser.
This is accomplished by making the \fIelvprsv\fP executable be owned by "root"
and turning on its "set user id" bit.
.PP
If you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvispreserve\fP will pretend
If you're editing a nameless buffer when \fIelvis\fP dies, then \fIelvprsv\fP will pretend
that the file was named "foo".
.SH AUTHOR
.nf

View File

@ -53,6 +53,17 @@
#include "config.h"
#include "vi.h"
/* We include ctype.c here (instead of including just ctype.h and linking
* with ctype.o) because on some systems ctype.o will have been compiled in
* "large model" and the elvprsv program is to be compiled in "small model"
* You can't mix models. By including ctype.c here, we can avoid linking
* with ctype.o.
*/
#include "ctype.c"
void preserve P_((char *, char *));
void main P_((int, char **));
#if AMIGA
BLK tmpblk;
# include "amiwild.c"
@ -121,7 +132,7 @@ void preserve(tname, when)
|| read(infd, name.c, BLKSIZE) != BLKSIZE)
{
/* something wrong with the file - sorry */
fprintf(stderr, "%s: trucated header blocks\n", tname);
fprintf(stderr, "%s: truncated header blocks\n", tname);
close(infd);
return;
}
@ -138,6 +149,16 @@ void preserve(tname, when)
return;
}
/* If there are no text blocks in the file, then we must've never
* really started editing. Discard the file.
*/
if (hdr.n[1] == 0)
{
close(infd);
unlink(tname);
return;
}
if (rewrite_now)
{
/* we don't need to open the index file */
@ -147,7 +168,8 @@ void preserve(tname, when)
for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
{
lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
if (read(infd, buf.c, BLKSIZE) != BLKSIZE
|| buf.c[0] == '\0')
{
/* messed up header */
fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
@ -172,9 +194,12 @@ void preserve(tname, when)
if (!index)
{
perror(PRSVINDEX);
exit(1);
exit(2);
}
/* should be at the end of the file already, but MAKE SURE */
fseek(index, 0L, 2);
/* create the recovery file in the PRESVDIR directory */
#if AMIGA
prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
@ -199,7 +224,8 @@ void preserve(tname, when)
for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
{
lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
if (read(infd, buf.c, BLKSIZE) != BLKSIZE
|| buf.c[0] == '\0')
{
/* messed up header */
fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
@ -242,7 +268,7 @@ void preserve(tname, when)
}
}
main(argc, argv)
void main(argc, argv)
int argc;
char **argv;
{
@ -251,10 +277,11 @@ main(argc, argv)
#if MSDOS || TOS
/* expand any wildcards in the command line */
_ct_init("");
argv = wildexpand(&argc, argv);
#endif
/* do we have a "when" argument? */
/* do we have a "-c", "-R", or "-when elvis died" argument? */
i = 1;
if (argc >= i + 1 && !strcmp(argv[i], "-R"))
{

View File

@ -1,6 +1,6 @@
# @(#)Makefile 5.8.1.1 (Berkeley) 5/8/91
#
# $Header: /cvsroot/src/usr.bin/Makefile,v 1.7 1993/04/04 20:14:43 cgd Exp $
# $Header: /cvsroot/src/usr.bin/Makefile,v 1.8 1993/04/08 02:22:57 cgd Exp $
# BROKEN: tn3270 rcs
@ -13,7 +13,7 @@ SUBDIR= ar awk biff basename cal calendar \
login logname lorder m4 machine mail make man mesg mkdep mkfifo \
mkstr more netstat nfsstat nice nm nohup pagesize \
passwd paste pr printenv printf ranlib \
rdist renice rlogin rpcgen rpcinfo rsh ruptime rwall rwho \
rdist ref renice rlogin rpcgen rpcinfo rsh ruptime rwall rwho \
script sed shar showmount size soelim sort split strings \
strip su symorder tail talk tar tee telnet tftp time \
tip touch tput tr true tsort tty ul unexpand unifdef uniq \

View File

@ -38,6 +38,9 @@ static struct _blkbuf
void blkflush P_((REG struct _blkbuf *this));
/* This function wipes out all buffers */
@ -72,7 +75,7 @@ BLK *blkget(logical)
/* see if we have that block in mem already */
for (this = blk; this < &blk[NBUFS]; this++)
{
if (this->logical == logical)
if (this->logical == (unsigned)logical)
{
newtoo = toonew;
toonew = this;
@ -162,6 +165,7 @@ void blkflush(this)
if (write(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
{
msg("Trouble writing to tmp file");
deathtrap(0);
}
this->dirty = FALSE;
@ -243,7 +247,7 @@ void blkdirty(bp)
k = blk[i].logical;
for (j = 0; j < NBUFS; j++)
{
if (blk[j].logical >= k)
if (blk[j].logical >= (unsigned)k)
{
blk[j].logical--;
}
@ -268,8 +272,21 @@ void blkdirty(bp)
BLK *blkadd(logical)
int logical; /* where to insert the new block */
{
static long chg;
REG int i;
/* if we're approaching the limit, then give a warning */
if (hdr.n[MAXBLKS - 10] && chg != changes)
{
chg = changes;
msg("WARNING: The edit buffer will overflow soon.");
}
if (hdr.n[MAXBLKS - 2])
{
msg("BAD NEWS: edit buffer overflow -- GOOD NEWS: text preserved");
deathtrap(0);
}
/* adjust hdr and lnum[] */
for (i = MAXBLKS - 1; i > logical; i--)
{
@ -282,7 +299,7 @@ BLK *blkadd(logical)
/* adjust the cache */
for (i = 0; i < NBUFS; i++)
{
if (blk[i].logical >= logical)
if (blk[i].logical >= (unsigned)logical)
{
blk[i].logical++;
}
@ -343,7 +360,8 @@ void beforedo(forundo)
lseek(tmpfd, 0L, 0);
if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) != BLKSIZE)
{
msg("Trouble writing header to tmp file ");
msg("Trouble writing header to tmp file");
deathtrap(0);
}
/* copy or swap oldnlines <--> nlines, oldlnum <--> lnum */

View File

@ -17,6 +17,19 @@
#include "vi.h"
#include "regexp.h"
#ifndef NO_TAGSTACK
/* These describe the current state of the tag related commands */
#define MAXTAGS 15
struct Tag_item {
MARK tag_mark;
char *tag_file;
};
static struct Tag_item tag_stack[MAXTAGS];
static int curr_tag = -1;
#endif /* !NO_TAGSTACK */
#ifdef DEBUG
/* print the selected lines with info on the blocks */
/*ARGSUSED*/
@ -197,7 +210,7 @@ void cmd_write(frommark, tomark, cmd, bang, extra)
}
/* either the file must not exist, or we must have a ! or be appending */
if (access(extra, 0) == 0 && !bang && !append)
if (*extra && access(extra, 0) == 0 && !bang && !append)
{
msg("File already exists - Use :w! to overwrite");
return;
@ -337,7 +350,7 @@ void cmd_global(frommark, tomark, cmd, bang, extra)
}
/* make sure we got a search pattern */
if (*extra != '/' && *extra != '?')
if (*extra == ' ' || *extra == '\n')
{
msg("Usage: %c /regular expression/ command", cmd == CMD_GLOBAL ? 'g' : 'v');
return;
@ -395,7 +408,7 @@ void cmd_global(frommark, tomark, cmd, bang, extra)
doingglobal = FALSE;
/* free the regexp */
free(re);
_free_(re);
/* Reporting...*/
rptlines = nchanged;
@ -421,9 +434,9 @@ void cmd_file(frommark, tomark, cmd, bang, extra)
if (cmd == CMD_FILE)
{
#ifndef CRUNCH
msg("\"%s\" %s%s%s %ld lines, line %ld [%ld%%]",
msg("\"%s\" %s%s%s line %ld of %ld [%ld%%]",
#else
msg("\"%s\" %s%s %ld lines, line %ld [%ld%%]",
msg("\"%s\" %s%s line %ld of %ld [%ld%%]",
#endif
*origname ? origname : "[NO FILE]",
tstflag(file, MODIFIED) ? "[MODIFIED]" : "",
@ -431,8 +444,8 @@ void cmd_file(frommark, tomark, cmd, bang, extra)
tstflag(file, NOTEDITED) ?"[NOT EDITED]":"",
#endif
tstflag(file, READONLY) ? "[READONLY]" : "",
nlines,
markline(frommark),
nlines,
markline(frommark) * 100 / nlines);
}
#ifndef CRUNCH
@ -590,8 +603,8 @@ void cmd_next(frommark, tomark, cmd, bang, extra)
}
}
/* also called from :wq -- always writes back in this case */
/* also called for :wq -- always writes back in this case */
/* also called for :q -- never writes back in that case */
/*ARGSUSED*/
void cmd_xit(frommark, tomark, cmd, bang, extra)
MARK frommark, tomark;
@ -602,45 +615,40 @@ void cmd_xit(frommark, tomark, cmd, bang, extra)
static long whenwarned; /* when the user was last warned of extra files */
int oldflag;
/* if there are more files to edit, then warn user */
if (argno >= 0 && argno + 1 < nargs && whenwarned != changes && (!bang || cmd != CMD_QUIT))
/* Unless the command is ":q", save the file if it has been modified */
if (cmd != CMD_QUIT
&& (cmd == CMD_WQUIT || tstflag(file, MODIFIED))
&& !tmpsave((char *)0, FALSE) && !bang)
{
msg("Could not save file -- use quit! to abort changes, or w filename");
return;
}
/* If there are more files to edit, then warn user */
if (argno >= 0 && argno + 1 < nargs /* more args */
&& whenwarned != changes /* user not already warned */
&& (!bang || cmd != CMD_QUIT)) /* command not ":q!" */
{
msg("More files to edit -- Use \":n\" to go to next file");
whenwarned = changes;
return;
}
if (cmd == CMD_QUIT)
/* Discard the temp file. Note that we should already have saved the
* the file, unless the command is ":q", so the only way that tmpabort
* could fail would be if you did a ":q" on a modified file.
*/
oldflag = *o_autowrite;
*o_autowrite = FALSE;
if (tmpabort(bang))
{
oldflag = *o_autowrite;
*o_autowrite = FALSE;
if (tmpabort(bang))
{
mode = MODE_QUIT;
}
else
{
msg("Use q! to abort changes, or wq to save changes");
}
*o_autowrite = oldflag;
mode = MODE_QUIT;
}
else
{
/* else try to save this file */
oldflag = tstflag(file, MODIFIED);
if (cmd == CMD_WQUIT)
setflag(file, MODIFIED);
if (tmpend(bang))
{
mode = MODE_QUIT;
}
else
{
msg("Could not save file -- use quit! to abort changes, or w filename");
}
if (!oldflag)
clrflag(file, MODIFIED);
msg("Use q! to abort changes, or wq to save changes");
}
*o_autowrite = oldflag;
}
@ -746,8 +754,6 @@ void cmd_cd(frommark, tomark, cmd, bang, extra)
int bang;
char *extra;
{
char *getenv();
#ifndef CRUNCH
/* if current file is modified, and no '!' was given, then error */
if (tstflag(file, MODIFIED) && !bang)
@ -759,7 +765,7 @@ void cmd_cd(frommark, tomark, cmd, bang, extra)
/* default directory name is $HOME */
if (!*extra)
{
extra = getenv("HOME");
extra = gethome((char *)0);
if (!extra)
{
msg("environment variable $HOME not set");
@ -928,7 +934,14 @@ void cmd_tag(frommark, tomark, cmd, bang, extra)
#ifdef INTERNAL_TAGS
char *cmp; /* char of tag name we're comparing, or NULL */
char *end; /* marks the end of chars in tmpblk.c */
char file[128]; /* name of file containing tag */
int found; /* whether the tag has been found */
int file_exists; /* whether any tag file exists */
char *s, *t;
#else
# ifndef NO_TAGSTACK
char *s;
# endif
int i;
#endif
#ifndef NO_MAGIC
@ -971,66 +984,96 @@ void cmd_tag(frommark, tomark, cmd, bang, extra)
*scan = '\0';
/* close the pipe. abort if error */
if (rpclose(fd) != 0 || scan < tmpblk.c + 3)
if (rpclose(fd) != 0)
{
msg("Trouble running \"ref\" -- Can't do tag lookup");
return;
}
else if (scan < tmpblk.c + 3)
{
msg("tag \"%s\" not found", extra);
return;
}
#else /* use internal code to look up the tag */
/* open the tags file */
fd = open(TAGS, O_RDONLY);
if (fd < 0)
{
found = 0;
file_exists = 0;
s = o_tags;
while (!found && *s != 0) {
while (isspace(*s)) s++;
for(t = file; s && *s && !isspace(*s); s++)
*t++ = *s;
*t = '\0';
/* open the next tags file */
fd = open(file, O_RDONLY);
if (fd < 0)
continue;
else
file_exists = 1;
/* Hmmm... this would have been a lot easier with <stdio.h> */
/* find the line with our tag in it */
for(scan = end = tmpblk.c, cmp = extra; ; scan++)
{
/* read a block, if necessary */
if (scan >= end)
{
end = tmpblk.c + tread(fd, tmpblk.c, BLKSIZE);
scan = tmpblk.c;
if (scan >= end)
{
close(fd);
break;
}
}
/* if we're comparing, compare... */
if (cmp)
{
/* matched??? wow! */
if (!*cmp && *scan == '\t')
{
if ((s = strrchr(file, '/')) != 0 ||
(s = strrchr(file, '\\')) != 0)
++s;
else
s = file;
*s = '\0';
found = 1;
break;
}
if (*cmp++ != *scan)
{
/* failed! skip to newline */
cmp = (char *)0;
}
}
/* if we're skipping to newline, do it fast! */
if (!cmp)
{
while (scan < end && *scan != '\n')
{
scan++;
}
if (scan < end)
{
cmp = extra;
}
}
}
}
if (!file_exists) {
msg("No tags file");
return;
}
/* Hmmm... this would have been a lot easier with <stdio.h> */
/* find the line with our tag in it */
for(scan = end = tmpblk.c, cmp = extra; ; scan++)
{
/* read a block, if necessary */
if (scan >= end)
{
end = tmpblk.c + tread(fd, tmpblk.c, BLKSIZE);
scan = tmpblk.c;
if (scan >= end)
{
msg("tag \"%s\" not found", extra);
close(fd);
return;
}
}
/* if we're comparing, compare... */
if (cmp)
{
/* matched??? wow! */
if (!*cmp && *scan == '\t')
{
break;
}
if (*cmp++ != *scan)
{
/* failed! skip to newline */
cmp = (char *)0;
}
}
/* if we're skipping to newline, do it fast! */
if (!cmp)
{
while (scan < end && *scan != '\n')
{
scan++;
}
if (scan < end)
{
cmp = extra;
}
}
if (!found) {
msg("tag \"%s\" not found", extra);
return;
}
/* found it! get the rest of the line into memory */
@ -1062,7 +1105,32 @@ void cmd_tag(frommark, tomark, cmd, bang, extra)
return;
}
tmpstart(tmpblk.c);
#ifdef NO_TAGSTACK
}
#else /* tagstack enabled */
s = prevorig;
}
else
s = origname;
if (frommark != MARK_UNSET && *s && *o_tagstack)
{
curr_tag++;
if (curr_tag >= MAXTAGS)
{
/* discard the oldest tag position */
free(tag_stack[0].tag_file);
for (curr_tag = 0; curr_tag < MAXTAGS - 1; curr_tag++)
{
tag_stack[curr_tag] = tag_stack[curr_tag + 1];
}
/* at this point, curr_tag = MAXTAGS-1 */
}
tag_stack[curr_tag].tag_file = (char *) malloc(strlen(s) + 1);
strcpy(tag_stack[curr_tag].tag_file, s);
tag_stack[curr_tag].tag_mark = frommark;
}
#endif
/* move to the desired line (or to line 1 if that fails) */
#ifndef NO_MAGIC
@ -1082,6 +1150,44 @@ void cmd_tag(frommark, tomark, cmd, bang, extra)
}
#ifndef NO_TAGSTACK
/*ARGSUSED*/
void cmd_pop(frommark, tomark, cmd, bang, extra)
MARK frommark, tomark;
CMD cmd;
int bang;
char *extra;
{
char buf[8];
if (!*o_tagstack)
{
msg("Tagstack not enabled");
return;
}
if (curr_tag < 0)
msg("Tagstack empty");
else
{
if (strcmp(origname, tag_stack[curr_tag].tag_file) != 0)
{
if (!tmpabort(bang))
{
msg("Use :pop! to abort changes, or :w to save changes");
return;
}
tmpstart(tag_stack[curr_tag].tag_file);
}
cursor = tag_stack[curr_tag].tag_mark;
if (cursor < MARK_FIRST || cursor > MARK_LAST + BLKSIZE)
{
cursor = MARK_FIRST;
}
free(tag_stack[curr_tag--].tag_file);
}
}
#endif
@ -1247,7 +1353,7 @@ static char *parse_errmsg(text)
}
/* if the number is part of a larger word, then ignore this line */
if (*text && isalpha(text[-1]))
if (*text && (isalpha(text[-1]) || text[-1] == '_'))
{
return (char *)0;
}
@ -1451,15 +1557,38 @@ void cmd_make(frommark, tomark, cmd, bang, extra)
errfd = -3;
}
#if MINT
/* I guess MiNT can't depend on the shell for redirection? */
close(creat(ERRLIST, 0666));
if ((fd = open(ERRLIST, O_RDWR)) == -1)
{
unlink(ERRLIST);
return;
}
suspend_curses();
old2 = dup(2);
dup2(fd, 2);
system(buf.c);
dup2(old2, 2);
close(old2);
close(fd);
#else
/* run the command, with curses temporarily disabled */
suspend_curses();
system(buf.c);
#endif
resume_curses(mode == MODE_EX);
if (mode == MODE_COLON)
mode = MODE_VI;
/* ':' hit instead of CR, so let him escape... -nox */
return;
/* run the "errlist" command */
cmd_errlist(MARK_UNSET, MARK_UNSET, cmd, bang, ERRLIST);
/* avoid spurious `Hit <RETURN>' after 1st error message -nox */
/* (which happened when cmd_errlist didn't have to change files...) */
if (mode == MODE_VI)
refresh();
}
#endif
@ -1738,9 +1867,9 @@ void cmd_suspend(frommark, tomark, cmd, bang, extra)
int bang;
char *extra;
{
void (*func)(); /* stores the previous setting of SIGTSTP */
SIGTYPE (*func)(); /* stores the previous setting of SIGTSTP */
#if !defined(__386BSD__) && defined(ANY_UNIX)
#if ANY_UNIX
/* the Bourne shell can't handle ^Z */
if (!strcmp(o_shell, "/bin/sh"))
{
@ -1749,11 +1878,6 @@ void cmd_suspend(frommark, tomark, cmd, bang, extra)
}
#endif
func = signal(SIGTSTP, SIG_DFL);
if ( func == SIG_IGN ) {
msg("SIGTSTP is being ignored, you may not suspend the editor", func);
return;
}
move(LINES - 1, 0);
if (tstflag(file, MODIFIED))
{
@ -1764,7 +1888,7 @@ void cmd_suspend(frommark, tomark, cmd, bang, extra)
}
refresh();
suspend_curses();
/* was here func = signal(SIGTSTP, SIG_DFL); /* races ??? */
func = signal(SIGTSTP, SIG_DFL);
kill (0, SIGTSTP);
/* the process stops and resumes here */

View File

@ -76,7 +76,7 @@ void cmd_substitute(frommark, tomark, cmd, bang, extra)
else /* CMD_SUBSTITUTE */
{
/* make sure we got a search pattern */
if (*extra != '/' && *extra != '?')
if (*extra == ' ' || *extra == '\n')
{
msg("Usage: s/regular expression/new text/");
return;
@ -253,7 +253,7 @@ Continue:
}
/* free the regexp */
free(re);
_free_(re);
/* if done from within a ":g" command, then finish silently */
if (doingglobal)
@ -447,7 +447,7 @@ void cmd_join(frommark, tomark, cmd, bang, extra)
}
/* see if the line will fit */
if (strlen(scan) + len + 3 > BLKSIZE)
if (strlen(scan) + len + 3 > (unsigned)BLKSIZE)
{
msg("Can't join -- the resulting line would be too long");
return;
@ -461,10 +461,14 @@ void cmd_join(frommark, tomark, cmd, bang, extra)
if (tmpblk.c[len - 1] == '.'
|| tmpblk.c[len - 1] == '?'
|| tmpblk.c[len - 1] == '!')
{
tmpblk.c[len++] = ' ';
tmpblk.c[len++] = ' ';
}
else if (tmpblk.c[len - 1] != ' ')
{
tmpblk.c[len++] = ' ';
}
tmpblk.c[len++] = ' ';
}
}
strcpy(tmpblk.c + len, scan);
@ -769,7 +773,7 @@ void cmd_print(frommark, tomark, cmd, bang, extra)
col++;
} while (col % *o_tabstop != 0);
}
else if (*scan > 0 && *scan < ' ' || *scan == '\177')
else if (*scan >= 1 && *scan < ' ' || *scan == '\177')
{
qaddch('^');
qaddch(*scan ^ 0x40);
@ -801,6 +805,9 @@ void cmd_print(frommark, tomark, cmd, bang, extra)
addch('\n');
exrefresh();
}
/* leave the cursor on the last line printed */
cursor = tomark;
}

View File

@ -1,28 +1,225 @@
/*
* vi configuration file
* We try to automatically configure to various compilers and operating
* systems. Extend the autoconf section as needed.
*/
# define BSD 1
#ifndef _CONFIG_H
# define _CONFIG_H
/*************************** autoconf section ************************/
/* Commodore-Amiga */
#ifdef amiga
# define AMIGA 1
# define COMPILED_BY "Manx Aztec C 5.2b"
# define TINYSTACK 1
#endif
/* standard unix V (?) */
#ifdef M_SYSV
# define UNIXV 1
# ifdef M_XENIX
# ifndef M_I386
# define TINYSTACK 1
# endif
# endif
# undef COHERENT
#endif
/* xelos system, University of Ulm */
#ifdef xelos
# define UNIXV 1
#endif
/* BSD UNIX? */
#ifdef bsd
# define BSD 1
#else
# ifdef sun
# ifndef M_SYSV
# define BSD 1
# endif
# endif
#endif
/* Microsoft C: sorry, Watcom does the same thing */
#ifdef M_I86
# ifndef M_SYSV
# define MSDOS 1
# ifdef IBMC2
# define COMPILED_BY "IBM C/2 1.00"
# else
# define MICROSOFT 1
# define COMPILED_BY "Microsoft C 5.10"
# endif
# define TINYSTACK 1
# endif
#endif
/* Borland's Turbo C */
#ifdef __TURBOC__
# define MSDOS 1
# define TURBOC 1
# ifdef __BORLANDC__
# define COMPILED_BY "Borland C 2.00"
# else
# define COMPILED_BY (__TURBOC__ >= 661 ? "Turbo C++ 1.00" : "Turbo C 2.00")
# endif
# define TINYSTACK 1
#endif
/* Tos Mark-Williams */
#ifdef M68000
# define TOS 1
# define COMPILED_BY "Mark Williams C"
# define TINYSTACK 1
#endif
/* Tos GNU-C */
#ifdef __atarist__
# ifdef __gem__
# define TOS 1
# define COMPILED_BY "GNU-C " __VERSION__
# define TINYSTACK 1
# endif
#endif
/* OS9/68000 */
#ifdef OSK
# define COMPILED_BY "Microware C V2.3 Edition 40"
# define TINYSTACK 1
#endif
/* DEC Rainbow, running MS-DOS (handled by earlier MS-DOS tests) */
/* (would need -DRAINBOW in CFLAGS to compile a Rainbow-compatible .EXE) */
#ifdef VMS
# define COMPILED_BY "VAX/VMS VAXC compiler"
# undef VMS
# define VMS 1
#endif
#ifdef COHERENT
# ifdef _I386
# define COH_386 1
# define COH_286 0
# else
# define COH_386 0
# define COH_286 1
# endif
# undef COHERENT
# define COHERENT 1
#endif
/*************************** end of autoconf section ************************/
/* All undefined symbols are defined to zero here, to allow for older */
/* compilers which dont understand #if defined() or #if UNDEFINED_SYMBOL */
# define UNIXV 0 /* UNIX - AT&T SYSV */
# define UNIX7 0 /* UNIX - version 7 */
# define MSDOS 0 /* PC */
# define TOS 0 /* Atari ST */
# define AMIGA 0 /* Commodore Amiga */
# define OSK 0 /* OS-9 / 68k */
# define COHERENT 0 /* Coherent */
# define MINIX 0
/*************************** operating systems *****************************/
#ifndef BSD
# define BSD 0 /* UNIX - Berkeley 4.x */
#endif
#ifndef UNIXV
# define UNIXV 0 /* UNIX - AT&T SYSV */
#endif
#ifndef UNIX7
# define UNIX7 0 /* UNIX - version 7 */
#endif
#ifndef MSDOS
# define MSDOS 0 /* PC */
#endif
#ifndef TOS
# define TOS 0 /* Atari ST */
#endif
#ifndef AMIGA
# define AMIGA 0 /* Commodore Amiga */
#endif
#ifndef OSK
# define OSK 0 /* OS-9 / 68k */
#endif
#ifndef COHERENT
# define COHERENT 0 /* Coherent */
#endif
#ifndef RAINBOW /* DEC Rainbow support, under MS-DOS */
# define RAINBOW 0
#endif
#ifndef VMS
# define VMS 0 /* VAX/VMS */
#endif
/* Minix has no predefines */
#if !BSD && !UNIXV && !UNIX7 && !MSDOS && !TOS && !AMIGA && !OSK && !COHERENT && !VMS
# define MINIX 1
#else
# define MINIX 0
#endif
/* generic combination of Unices */
#if UNIXV || UNIX7 || BSD || MINIX || COHERENT
# define ANY_UNIX 1
#else
# define ANY_UNIX 0
#endif
#ifndef TINYSTACK
# define TINYSTACK 0
#endif
/*************************** compilers **************************************/
#ifndef AZTEC_C
# define AZTEC_C 0
#endif
#ifndef MICROSOFT
# define MICROSOFT 0
#endif
#ifndef TURBOC
# define TURBOC 0
#endif
/* Should we use "new style" ANSI C prototypes? */
#ifdef __STDC__
# define NEWSTYLE 1
#endif
#ifdef __cplusplus
# define NEWSTYLE 1
#endif
#ifndef NEWSTYLE
# define NEWSTYLE 0
#endif
#if NEWSTYLE
# define P_(s) s
#else
# define P_(s) ()
#endif
/******************************* Credit ************************************/
#if MSDOS
# define CREDIT "Ported to MS-DOS by Guntram Blohm & Martin Patzel"
# if RAINBOW
# define CREDIT2 "Rainbow support added by Willett Kempton"
# endif
#endif
#if AMIGA
# define CREDIT "Ported to AmigaDOS 2.04 by Mike Rieser & Dale Rahn"
#endif
#if TOS
@ -37,39 +234,130 @@
# define CREDIT "Ported to Coherent by Esa Ahola"
#endif
#if VMS
# define CREDIT "Ported to VAX/VMS by John Campbell"
#endif
/*************************** functions depending on OS *********************/
extern char *strchr();
#define tread(fd,buf,n) read(fd,buf,(unsigned)(n))
#define twrite(fd,buf,n) write(fd,buf,(unsigned)(n))
#define ttywrite(buf, len) write(1, buf, (unsigned)(len)) /* raw write */
extern void *malloc();
/* Most compilers could benefit from using the "register" storage class */
#if 1
# define REG register
/* There are two terminal-related functions that we need: ttyread() and
* ttywrite(). The ttyread() function implements read-with-timeout and is
* a true function on all systems. The ttywrite() function is almost always
* just a macro...
*/
#if !TOS && !AMIGA
# define ttywrite(buf, len) write(1, buf, (unsigned)(len)) /* raw write */
#endif
typedef unsigned char uchar;
#define UCHAR(s) ((unsigned char) (s))
/* The strchr() function is an official standard now, so everybody has it
* except Unix version 7 (which is old) and BSD Unix (which is academic).
* Those guys use something called index() to do the same thing.
*/
#if BSD || UNIX7 || OSK
# define strchr index
# define strrchr rindex
#endif
#if !NEWSTYLE
extern char *strchr();
#endif
/* BSD uses bcopy() instead of memcpy() */
#if BSD
# define memcpy(dest, src, siz) bcopy(src, dest, siz)
#endif
/* BSD uses getwd() instead of getcwd(). The arguments are a little different,
* but we'll ignore that and hope for the best; adding arguments to the macro
* would mess up an "extern" declaration of the function.
*
* Also, the Coherent-286 uses getwd(), but Coherent-386 uses getcwd()
*/
#if BSD
#ifndef __386BSD__
# define getcwd getwd
#endif
#endif
#if COH_286
# define getcwd getwd
#endif
extern char *getcwd();
/* text versa binary mode for read/write */
#if !TOS
#define tread(fd,buf,n) read(fd,buf,(unsigned)(n))
#define twrite(fd,buf,n) write(fd,buf,(unsigned)(n))
#endif
/**************************** Compiler quirks *********************************/
/* the UNIX version 7 and (some) TOS compilers, don't allow "void" */
#if UNIX7 || TOS
# define void int
#endif
/* as far as I know, all compilers except version 7 support unsigned char */
/* NEWFLASH: the Minix-ST compiler has subtle problems with unsigned char */
#if UNIX7 || MINIX
# define UCHAR(c) ((c) & 0xff)
# define uchar char
#else
# define UCHAR(c) ((unsigned char)(c))
# define uchar unsigned char
#endif
/* Some compilers prefer to have malloc declared as returning a (void *) */
/* ANSI, on the other hand, needs the arguments to free() to be cast */
#ifndef __STDC__
# if BSD || AMIGA || MINIX
extern void *malloc();
# define _free_(ptr) free((void *)ptr)
# else
extern char *malloc();
# define _free_(ptr) free((char *)ptr)
# endif
#else
# define _free_(ptr) free((void *)ptr)
#endif /* __STDC__ */
/* everybody but Amiga wants lseek declared here */
#if !AMIGA
extern long lseek();
#endif
/* ANSI C has getenv() declared in stdlib.h, which we've already included.
* Other compilers will need it declared here, though.
*/
#ifndef __STDC__
extern char *getenv();
#endif
/* Signal handler functions used to return an int value, which was ignored.
* On newer systems, signal handlers are void functions. Here, we try to
* guess the proper return type for this system.
*/
#ifdef __STDC__
# define SIGTYPE void
#else
# if MSDOS
# define SIGTYPE void
# else
# if UNIXV
# define SIGTYPE void /* Note: This is wrong for SCO Xenix. */
# endif
# endif
#endif
#ifndef SIGTYPE
# define SIGTYPE int
#endif
/******************* Names of files and environment vars **********************/
#define TMPDIR "/var/tmp"
#define TMPNAME "%s/elvis%04x%03x" /* temp file */
#define CUTNAME "%s/elvis_%04x%03x" /* cut buffer's temp file */
# ifndef EXRC
# define EXRC ".exrc" /* init file in current directory */
# endif
# define SCRATCHOUT "%s/soXXXXXX" /* temp file used as input to filter */
# ifndef EXINIT
# define EXINIT "EXINIT"
# endif
# ifndef SHELL
# define SHELL "/bin/sh" /* default shell */
#if ANY_UNIX
# ifndef TMPDIR
# if MINIX
# define TMPDIR "/usr/tmp" /* Keep elvis' temp files off RAM disk! */
# else
# define TMPDIR "/var/tmp" /* directory where temp files live */
# endif
# endif
# ifndef PRSVDIR
# define PRSVDIR "/var/preserve" /* directory where preserved file live */
@ -77,9 +365,200 @@ typedef unsigned char uchar;
# ifndef PRSVINDEX
# define PRSVINDEX "/var/preserve/Index" /* index of files in PRSVDIR */
# endif
# ifndef EXRC
# define EXRC ".exrc" /* init file in current directory */
# endif
# define SCRATCHOUT "%s/soXXXXXX" /* temp file used as input to filter */
# ifndef SHELL
# define SHELL "/bin/sh" /* default shell */
# endif
# if COHERENT
# ifndef REDIRECT
# define REDIRECT ">" /* Coherent CC writes errors to stdout */
# endif
# endif
# define gethome(x) getenv("HOME")
#endif
#if AMIGA /* Specify AMIGA environment */
# ifndef CC_COMMAND
# define CC_COMMAND "cc" /* generic C compiler */
# endif
# ifndef COLON
# define COLON ':' /* Amiga files can also end in `:' */
# endif
# ifndef SYSEXRC
# define SYSEXRC "S:" EXRC /* name of ".exrc" file in system dir */
# endif
# ifndef MAXRCLEN
# define MAXRCLEN 2048 /* max size of a .exrc file */
# endif
# ifndef NBUFS
# define NBUFS 10 /* must be at least 3 -- more is better */
# endif
# ifndef NEEDSYNC
# define NEEDSYNC TRUE /* assume ":se sync" by default */
# endif
# ifndef PRSVDIR
# define PRSVDIR "Elvis:" /* directory where preserved file live */
# endif
# ifndef PRSVINDEX
# define PRSVINDEX "Elvis:Index" /* index of files in PRSVDIR */
# endif
# ifndef REDIRECT
# define REDIRECT ">" /* Amiga writes errors to stdout */
# endif
# ifndef SCRATCHIN
# define SCRATCHIN "%sSIXXXXXX"
# endif
# ifndef SCRATCHOUT
# define SCRATCHOUT "%sSOXXXXXX"
# endif
# ifndef SHELL
# define SHELL "newshell" /* default shell */
# endif
# ifndef TERMTYPE
# define TERMTYPE "amiga" /* default termtype */
# endif
# ifndef TMPDIR /* for AMIGA should end in `:' or `/' */
# define TMPDIR "T:" /* directory where temp files live */
# endif
# ifndef TMPNAME
# define TMPNAME "%selv_%x.%x" /* format of names for temp files */
# endif
# define gethome(x) getenv("HOME")
#endif
#if MSDOS || TOS
/* do not change TMPNAME and SCRATCH*: they MUST begin with '%s\\'! */
# ifndef TMPDIR
# define TMPDIR "C:\\tmp" /* directory where temp files live */
# endif
# ifndef PRSVDIR
# define PRSVDIR "C:\\preserve" /* directory where preserved file live */
# endif
# ifndef PRSVINDEX
# define PRSVINDEX "C:\\preserve\\Index" /* index of files in PRSVDIR */
# endif
# define TMPNAME "%s\\elv_%x.%x" /* temp file */
# if MSDOS
# if MICROSOFT
# define CC_COMMAND "cl -c" /* C compiler */
# else
# if __BORLANDC__ /* Borland C */
# define CC_COMMAND "bcc" /* C compiler */
# else
# if TURBOC /* Turbo C */
# define CC_COMMAND "tcc" /* C compiler */
# endif /* TURBOC */
# endif /* BORLANDC */
# endif /* MICROSOFT */
# endif /* MSDOS */
# define SCRATCHIN "%s\\siXXXXXX" /* DOS ONLY - output of filter program */
# define SCRATCHOUT "%s\\soXXXXXX" /* temp file used as input to filter */
# define SLASH '\\'
# ifndef SHELL
# if TOS
# define SHELL "shell.ttp" /* default shell */
# else
# define SHELL "command.com" /* default shell */
# endif
# endif
# define NEEDSYNC TRUE /* assume ":se sync" by default */
# if TOS && __GNUC__ /* probably on other systems, too */
# define REDIRECT "2>" /* GNUC reports on 2, others on 1 */
# define CC_COMMAND "gcc -c"
# else
# define REDIRECT ">" /* shell's redirection of stderr */
# endif
#endif
#if VMS
/* do not change TMPNAME, and SCRATCH*: they MUST begin with '%s\\'! */
# ifndef TMPDIR
# define TMPDIR "sys$scratch:" /* directory where temp files live */
# endif
# define TMPNAME "%selv_%x.%x;1" /* temp file */
# define SCRATCHIN "%ssiXXXXXX" /* DOS ONLY - output of filter program */
# define SCRATCHOUT "%ssoXXXXXX" /* temp file used as input to filter */
# define SLASH '\:' /* Worry point... jdc */
# ifndef SHELL
# define SHELL "" /* default shell */
# endif
# define REDIRECT ">" /* shell's redirection of stderr */
# define tread(fd,buf,n) vms_read(fd,buf,(unsigned)(n))
# define close vms_close
# define lseek vms_lseek
# define unlink vms_delete
# define delete __delete /* local routine conflicts w/VMS rtl routine. */
# define rpipe vms_rpipe
# define rpclose vms_rpclose
# define ttyread vms_ttyread
# define gethome(x) getenv("HOME")
/* There is no sync() on vms */
# define sync()
/* jdc -- seems VMS external symbols are case insensitive */
# define m_fWord m_fw_ord
# define m_bWord m_bw_ord
# define m_eWord m_ew_ord
# define m_Nsrch m_n_srch
# define m_Fch m_f_ch
# define m_Tch m_t_ch
# define v_Xchar v_x_char
/* jdc -- also, braindead vms curses always found by linker. */
# define LINES elvis_LINES
# define COLS elvis_COLS
# define curscr elvis_curscr
# define stdscr elvis_stdscr
# define initscr elvis_initscr
# define endwin elvis_endwin
# define wrefresh elvis_wrefresh
#endif
#if OSK
# ifndef TMPDIR
# define TMPDIR "/dd/tmp" /* directory where temp files live */
# endif
# ifndef PRSVDIR
# define PRSVDIR "/dd/usr/preserve" /* directory where preserved file live */
# endif
# ifndef PRSVINDEX
# define PRSVINDEX "/dd/usr/preserve/Index" /* index of files in PRSVDIR */
# endif
# ifndef CC_COMMAND
# define CC_COMMAND "cc -r" /* name of the compiler */
# endif
# ifndef EXRC
# define EXRC ".exrc" /* init file in current directory */
# endif
# define SCRATCHOUT "%s/soXXXXXX" /* temp file used as input to filter */
# ifndef SHELL
# define SHELL "shell" /* default shell */
# endif
# define FILEPERMS (S_IREAD|S_IWRITE) /* file permissions used for creat() */
# define REDIRECT ">>-" /* shell's redirection of stderr */
# define sync() /* OS9 doesn't need a sync() */
# define gethome(x) getenv("HOME")
#endif
#ifndef TAGS
# define TAGS "tags" /* tags file */
# define TAGS "tags" /* name of the tags file */
#endif
#ifndef TMPNAME
# define TMPNAME "%s/elv_%x.%x" /* format of names for temp files */
#endif
#ifndef EXINIT
# define EXINIT "EXINIT" /* name of EXINIT environment variable */
#endif
#ifndef EXRC
# define EXRC "elvis.rc" /* name of ".exrc" file in current dir */
#endif
#ifndef HMEXRC
# define HMEXRC EXRC /* name of ".exrc" file in home dir */
#endif
#ifndef KEYWORDPRG
@ -92,7 +571,7 @@ typedef unsigned char uchar;
#endif
#ifndef ERRLIST
# define ERRLIST "errlist"
# define ERRLIST "errs"
#endif
#ifndef SLASH
@ -104,7 +583,7 @@ typedef unsigned char uchar;
#endif
#ifndef REG
# define REG
# define REG register
#endif
#ifndef NEEDSYNC
@ -115,6 +594,10 @@ typedef unsigned char uchar;
# define FILEPERMS 0666
#endif
#ifndef PRESERVE
# define PRESERVE "/usr/libexec/elvispreserve" /* name of the "preserve" program */
#endif
#ifndef CC_COMMAND
# define CC_COMMAND "cc -c"
#endif
@ -127,18 +610,6 @@ typedef unsigned char uchar;
# define REDIRECT "2>"
#endif
#ifndef PRESERVE
# define PRESERVE "/usr/libexec/elvispreserve" /* name of the "preserve" program */
#endif
#if !defined(CRUNCH) && defined(LETS_GET_SMALL)
#define CRUNCH
#endif
#if defined(CRUNCH) && !defined(LETS_GET_SMALL)
#define LETS_GET_SMALL
#endif
#ifndef BLKSIZE
# ifdef CRUNCH
# define BLKSIZE 1024
@ -151,16 +622,12 @@ typedef unsigned char uchar;
# define KEYBUFSIZE 1000
#endif
#ifdef LETS_GET_SMALL
#define NO_CHARATTR
#define NO_DIGRAPH
#define NO_SENTENCE
#define NO_EXTENSIONS
#define NO_MAGIC
#define NO_ERRLIST
#define NO_MODELINE
#define NO_SHOWMATCH
#define NO_SHOWMODE
#define NO_OPTCOLS
#define NO_MKEXRC
#ifndef MAILER
# define MAILER "mail"
#endif
#ifndef gethome
extern char *gethome();
#endif
#endif /* ndef _CONFIG_H */

View File

@ -7,6 +7,8 @@
#include "config.h"
#include "ctype.h"
void _ct_init P_((uchar *));
uchar _ct_toupper[256];
uchar _ct_tolower[256];
uchar _ct_ctypes[256];

View File

@ -18,15 +18,17 @@
#include "vi.h"
#if ANY_UNIX
# if UNIXV
# if UNIXV || COH_386
# ifdef TERMIOS
# include <termios.h>
# else
# include <termio.h>
# endif
# ifdef S5WINSIZE
# include <sys/stream.h> /* winsize struct defined in one of these? */
# include <sys/ptem.h>
# ifndef NO_S5WINSIZE
# ifndef _SEQUENT_
# include <sys/stream.h> /* winsize struct defined in one of these? */
# include <sys/ptem.h>
# endif
# else
# undef TIOCGWINSZ /* we can't handle it correctly yet */
# endif
@ -48,7 +50,6 @@ extern int VMS_read_raw; /* Set in initscr() */
#endif
extern char *getenv();
static void starttcap();
/* variables, publicly available & used in the macros */
@ -89,8 +90,8 @@ char *SR_; /* :sr=: scroll reverse */
#else
char *SR; /* :sr=: scroll reverse */
#endif
char *KS = ""; /* :ks=: init string for cursor */
char *KE = ""; /* :ke=: restore string for cursor */
char *KS = ""; /* :ks=: switch keypad to application mode */
char *KE = ""; /* :ke=: switch keypad to system mode */
char *KU; /* :ku=: key sequence sent by up arrow */
char *KD; /* :kd=: key sequence sent by down arrow */
char *KL; /* :kl=: key sequence sent by left arrow */
@ -127,25 +128,25 @@ char *CR = ""; /* :cR=: cursor used for VI replace mode */
char *aend = ""; /* end an attribute -- either UE or ME */
char ERASEKEY; /* backspace key taken from ioctl structure */
#ifndef NO_COLOR
char normalcolor[16];
char SOcolor[16];
char SEcolor[16];
char UScolor[16];
char UEcolor[16];
char MDcolor[16];
char MEcolor[16];
char AScolor[16];
char AEcolor[16];
char normalcolor[24];
char SOcolor[24];
char SEcolor[24];
char UScolor[24];
char UEcolor[24];
char MDcolor[24];
char MEcolor[24];
char AScolor[24];
char AEcolor[24];
# ifndef NO_POPUP
char POPUPcolor[16];
char POPUPcolor[24];
# endif
# ifndef NO_VISIBLE
char VISIBLEcolor[16];
char VISIBLEcolor[24];
# endif
#endif
#if ANY_UNIX
# if UNIXV
# if UNIXV || COH_386
# ifdef TERMIOS
static struct termios oldtermio; /* original tty mode */
static struct termios newtermio; /* cbreak/noecho tty mode */
@ -210,11 +211,11 @@ void initscr()
{
#if ANY_UNIX
write(2, "Environment variable TERM must be set\n", (unsigned)38);
exit(1);
exit(2);
#endif
#if OSK
writeln(2, "Environment variable TERM must be set\n", (unsigned)38);
exit(1);
exit(2);
#endif
#if AMIGA
termtype = TERMTYPE;
@ -229,7 +230,7 @@ void initscr()
#endif
#if VMS
write(2, "UNKNOWN terminal: define ELVIS_TERM\n", (unsigned)36);
exit(1);
exit(2);
#endif
}
else
@ -246,7 +247,7 @@ void initscr()
/* change the terminal mode to cbreak/noecho */
#if ANY_UNIX
# if UNIXV
# if UNIXV || COH_386
# ifdef TERMIOS
tcgetattr(2, &oldtermio);
# else
@ -281,10 +282,12 @@ void endwin()
static int curses_active = FALSE;
extern int oldcurs;
/* Send any required termination strings. Turn off "raw" mode. */
void suspend_curses()
{
#if ANY_UNIX && !UNIXV
#if ANY_UNIX && !(UNIXV || COH_386)
struct tchars tbuf;
# ifdef TIOCSLTC
struct ltchars ltbuf;
@ -294,6 +297,7 @@ void suspend_curses()
if (has_CQ)
{
do_CQ();
oldcurs = 0;
}
#endif
if (has_TE) /* GB */
@ -311,8 +315,8 @@ void suspend_curses()
/* change the terminal mode back the way it was */
#if ANY_UNIX
# if UNIXV
# if TERMIOS
# if (UNIXV || COH_386)
# ifdef TERMIOS
tcsetattr(2, TCSADRAIN, &oldtermio);
# else
ioctl(2, TCSETAW, &oldtermio);
@ -360,7 +364,7 @@ void resume_curses(quietly)
{
/* change the terminal mode to cbreak/noecho */
#if ANY_UNIX
# if UNIXV
# if UNIXV || COH_386
ospeed = (oldtermio.c_cflag & CBAUD);
ERASEKEY = oldtermio.c_cc[VERASE];
newtermio = oldtermio;
@ -381,7 +385,7 @@ void resume_curses(quietly)
# else
ioctl(2, TCSETAW, &newtermio);
# endif
# else /* BSD or V7 or Coherent or Minix */
# else /* BSD, V7, Coherent-286, or Minix */
struct tchars tbuf;
# ifdef TIOCSLTC
struct ltchars ltbuf;
@ -438,6 +442,12 @@ void resume_curses(quietly)
ERASEKEY = '\177'; /* Accept <DEL> as <^H> for VMS */
#endif
curses_active = TRUE;
}
/* If we're supposed to quit quietly, then we're done */
if (quietly)
{
if (has_TI) /* GB */
{
do_TI();
@ -447,12 +457,6 @@ void resume_curses(quietly)
do_KS();
}
curses_active = TRUE;
}
/* If we're supposed to quit quietly, then we're done */
if (quietly)
{
return;
}
@ -468,6 +472,10 @@ void resume_curses(quietly)
do_SE();
refresh();
ttyread(kbuf, 20, 0); /* in RAW mode, so <20 is very likely */
if (has_TI)
{
do_TI();
}
if (kbuf[0] == ':')
{
mode = MODE_COLON;
@ -481,11 +489,7 @@ void resume_curses(quietly)
}
exwrote = FALSE;
#if TURBOC || __GNUC__
signal(SIGINT, (void(*)()) trapint);
#else
signal(SIGINT, trapint);
#endif
}
/* This function fetches an optional string from termcap */
@ -517,7 +521,7 @@ static void musthave(T, s)
#if OSK
write(2, "\l", 1);
#endif
exit(1);
exit(2);
}
}
@ -615,11 +619,16 @@ static void starttcap(term)
getsize(0);
/* Key sequences */
pair(&KS, &KE, "ks", "ke");
pair(&KS, &KE, "ks", "ke"); /* keypad enable/disable */
mayhave(&KU, "ku"); /* up */
mayhave(&KD, "kd"); /* down */
mayhave(&KL, "kl"); /* left */
mayhave(&KR, "kr"); /* right */
mayhave(&KL, "kl"); /* left */
if (KL && KL[0]=='\b' && !KL[1])
{
/* never use '\b' as a left arrow! */
KL = (char *)0;
}
mayhave(&PU, "kP"); /* PgUp */
mayhave(&PD, "kN"); /* PgDn */
mayhave(&HM, "kh"); /* Home */
@ -913,8 +922,8 @@ void wqrefresh()
/* This function is called during termination. It resets color modes */
int ansiquit()
{
/* if ANSI color terminal, then reset the colors */
if (!strcmp(UP, "\033[A"))
/* if ANSI terminal & colors were set, then reset the colors */
if (!strcmp(UP, "\033[A") && strcmp(SOcolor, SO))
{
tputs("\033[37;40m\033[m", 1, faddch);
clrtoeol();
@ -931,21 +940,33 @@ int ansicolor(cmode, attrbyte)
int cmode; /* mode to set, e.g. A_NORMAL */
int attrbyte; /* IBM PC attribute byte */
{
char temp[16]; /* hold the new mode string */
char temp[24]; /* hold the new mode string */
/* if not ANSI-ish, then fail */
if (strcmp(UP, "\033[A") && strcmp(UP, "\033OA"))
{
msg("Don't know how to set colors for this terminal");
return 0;
/* Only give an error message if we're editing a file.
* (I.e., if we're *NOT* currently doing a ".exrc")
*/
if (tmpfd >= 0)
msg("Don't know how to set colors for this terminal");
return FALSE;
}
/* construct the color string */
#ifdef MWC /* either Coherent-286 ("COHERENT"), or Coherent-386 ("M_SYSV") */
sprintf(temp, "\033[m\033[3%cm\033[4%cm%s%s",
"04261537"[attrbyte & 0x07],
"04261537"[(attrbyte >> 4) & 0x07],
(attrbyte & 0x08) ? "\033[1m" : "",
(attrbyte & 0x80) ? "\033[5m" : "");
#else
sprintf(temp, "\033[m\033[3%c;4%c%s%sm",
"04261537"[attrbyte & 0x07],
"04261537"[(attrbyte >> 4) & 0x07],
(attrbyte & 0x08) ? ";1" : "",
(attrbyte & 0x80) ? ";5" : "");
#endif
/* stick it in the right place */
switch (cmode)
@ -997,7 +1018,7 @@ int ansicolor(cmode, attrbyte)
#endif
}
return 1;
return TRUE;
}
@ -1006,6 +1027,7 @@ int ansicolor(cmode, attrbyte)
* yet, this is one of the termcap strings; for color terminals that really
* have had colors defined, we just the "normal color" escape sequence.
*/
int
endcolor()
{
if (aend == ME)

View File

@ -150,7 +150,7 @@ static void cutfree(buf)
msg("cutfree() tried to free a NULL buf->phys pointer.");
else
#endif
free((char *)buf->phys);
_free_((char *)buf->phys);
/* maybe delete the temp file */
maybezap(num);
@ -666,7 +666,7 @@ int cb2str(name, buf, size)
}
/* if too big, return the size now, without doing anything */
if (cb->end - cb->start >= size)
if ((unsigned)(cb->end - cb->start) >= size)
{
return cb->end - cb->start;
}

View File

@ -72,6 +72,58 @@ is executed as a series of \fIex\fR commands.
A file by the same name may be executed in the current directory, too.
On non-UNIX systems, ".exrc" is usually an invalid file name;
there, the initialization file is called "elvis.rc" instead.
.SH ENVIRONMENT
.IP TERM
This is the name of your terminal's entry in the termcap or terminfo
database.
The list of legal values varies from one system to another.
.IP TERMCAP
Optional.
If your system uses termcap, and the TERMCAP variable is unset, then
\*E will read your terminal's definition from \fB/etc/termcap\fR.
If TERMCAP is set to the full pathname of a file (starting with a '/')
then \*E will look in the named file instead of \fB/etc/termcap\fR.
If TERMCAP is set to a value which doesn't start with a '/',
then its value is assumed to be the full termcap entry for your terminal.
.IP TERMINFO
Optional.
If your system uses terminfo, and the TERMINFO variable is unset, then
\*E will read your terminal's definition from the database in the
\fB/usr/lib/terminfo\fR database.
If TERMINFO is set, then its value is used as the database name to use
instead of \fB/usr/lib/terminfo\fR.
.IP "LINES, COLUMNS"
Optional.
These variables, if set, will override the screen size values given in
the termcap/terminfo for your terminal.
On windowing systems such as X, \*E has other ways of determining the
screen size, so you should probably leave these variables unset.
.IP EXINIT
Optional.
This variable can hold EX commands which will be executed before any .exrc
files.
.IP SHELL
Optional.
The SHELL variable sets the default value for the "shell" option,
which determines which shell program is used to perform wildcard
expansion in file names, and also which is used to execute filters
or external programs.
The default value on UNIX systems is "/bin/sh".
.IP
Note: Under MS-DOS, this variable is called COMSPEC instead of SHELL.
.IP HOME
This variable should be set to the name of your home directory.
\*E looks for its initialization file there;
if HOME is unset then the initialization file will not be executed.
.IP TAGPATH
Optional.
This variable is used by the "ref" program, which is invoked by the shift-K,
control-], and :tag commands.
See "ref" for more information.
.IP "TMP, TEMP"
These optional environment variables are only used in non-UNIX versions
of \*E.
They allow you to supply a directory name to be used for storing temporary files.
.SH "SEE ALSO"
ctags(1), ref(1), virec(1)
.PP

View File

@ -5,14 +5,6 @@
* 14407 SW Teal Blvd. #C
* Beaverton, OR 97005
* kirkenda@cs.pdx.edu
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00043
* -------------------- ----- ----------------------
*
* 27 Nov 1992 Felix Gaehtgens Fixed <ESC>:wq!
*
*/
@ -60,6 +52,8 @@ static struct
}
cmdnames[] =
{ /* cmd name cmd code function arguments */
{"print", CMD_PRINT, cmd_print, RANGE+NL },
{"append", CMD_APPEND, cmd_append, FROM+ZERO+BANG },
#ifdef DEBUG
{"bug", CMD_DEBUG, cmd_debug, RANGE+BANG+EXTRA+NL},
@ -76,7 +70,6 @@ static struct
{"move", CMD_MOVE, cmd_move, RANGE+EXTRA },
{"next", CMD_NEXT, cmd_next, BANG+NAMEDFS },
{"Next", CMD_PREVIOUS, cmd_next, BANG },
{"print", CMD_PRINT, cmd_print, RANGE+NL },
{"quit", CMD_QUIT, cmd_xit, BANG },
{"read", CMD_READ, cmd_read, FROM+ZERO+NAMEDF},
{"substitute", CMD_SUBSTITUTE, cmd_substitute, RANGE+EXTRA },
@ -118,6 +111,9 @@ static struct
{"mkexrc", CMD_MKEXRC, cmd_mkexrc, NAMEDF },
#endif
{"number", CMD_NUMBER, cmd_print, RANGE+NL },
#ifndef NO_TAGSTACK
{"pop", CMD_POP, cmd_pop, BANG+WORD1 },
#endif
{"put", CMD_PUT, cmd_put, FROM+ZERO+WORD1 },
{"set", CMD_SET, cmd_set, EXRCOK+EXTRA },
{"shell", CMD_SHELL, cmd_shell, NL },
@ -128,7 +124,7 @@ static struct
{"tag", CMD_TAG, cmd_tag, BANG+WORD1 },
{"version", CMD_VERSION, cmd_version, EXRCOK+NONE },
{"visual", CMD_VISUAL, cmd_edit, BANG+NAMEDF },
{"wq", CMD_WQUIT, cmd_xit, BANG+NL },
{"wq", CMD_WQUIT, cmd_xit, NL },
#ifdef DEBUG
{"debug", CMD_DEBUG, cmd_debug, RANGE+BANG+EXTRA+NL},
@ -392,8 +388,8 @@ void doexcmd(cmdbuf)
}
else if (*scan == '0')
{
frommark = tomark = MARK_UNSET;
scan++;
frommark = tomark = (*scan ? MARK_UNSET : MARK_FIRST);
}
else
{
@ -424,16 +420,23 @@ void doexcmd(cmdbuf)
scan++;
}
/* if no command, then just move the cursor to the mark */
/* Figure out how long the command name is. If no command, then the
* length is 0, which will match the "print" command.
*/
if (!*scan)
{
if (tomark != MARK_UNSET)
cursor = tomark;
return;
/* if not in ex mode, and both endpoints are at the line,
* then just move to the start of that line without printing
*/
if (mode != MODE_EX && frommark == tomark)
{
if (tomark != MARK_UNSET)
cursor = tomark;
return;
}
cmdlen = 0;
}
/* figure out how long the command name is */
if (!isalpha(*scan))
else if (!isalpha(*scan))
{
cmdlen = 1;
}
@ -672,23 +675,60 @@ int doexrc(filename)
int fd; /* file descriptor */
int len; /* length of the ".exrc" file */
#ifdef CRUNCH
/* small address space - we need to conserve space */
/* !!! kludge: we use U_text as the buffer. This has the side-effect
* of interfering with the shift-U visual command. Disable shift-U.
*/
U_line = 0L;
#else
# if TINYSTACK
# if TOS || MINT
/* small stack, but big heap. Allocate buffer from heap */
char *U_text = (char *)malloc(4096);
if (!U_text)
{
return 0;
}
# else
/* small stack - we need to conserve space */
/* !!! kludge: we use U_text as the buffer. This has the side-effect
* of interfering with the shift-U visual command. Disable shift-U.
*/
U_line = 0L;
# endif
# else
/* This is how we would *like* to do it -- with a large buffer on the
* stack, so we can handle large .exrc files and also recursion.
*/
char U_text[4096];
# endif
#endif
/* open the file, read it, and close */
fd = open(filename, O_RDONLY);
if (fd < 0)
{
#if TINYSTACK && (TOS || MINT)
free(U_text);
#endif
return 0;
}
len = tread(fd, U_text, BLKSIZE);
#if TINYSTACK && (TOS || MINT)
len = tread(fd, U_text, 4096);
#else
len = tread(fd, U_text, sizeof U_text);
#endif
close(fd);
/* execute the string */
exstring(U_text, len, ctrl('V'));
#if TINYSTACK && (TOS || MINT)
free(U_text);
#endif
return 1;
}

View File

@ -28,8 +28,8 @@ static struct _DIG
} *digs;
char digraph(key1, key2)
char key1; /* the underlying character */
char key2; /* the second character */
int key1; /* the underlying character */
int key2; /* the second character */
{
int newkey;
REG struct _DIG *dp;
@ -158,7 +158,7 @@ void do_digraph(bang, extra)
prev->next = dp->next;
else
digs = dp->next;
free(dp);
_free_(dp);
return;
}
@ -211,11 +211,11 @@ void savedigs(fd)
* chunk of text with typed-in text. It returns the MARK of the last character
* that the user typed in.
*/
MARK input(from, to, when, above)
MARK input(from, to, when, delta)
MARK from; /* where to start inserting text */
MARK to; /* extent of text to delete */
int when; /* either WHEN_VIINP or WHEN_VIREP */
int above; /* boolean: take indentation from lower line? */
int delta; /* 1 to take indent from lower line, -1 for upper, 0 for none */
{
char key[2]; /* key char followed by '\0' char */
char *build; /* used in building a newline+indent string */
@ -287,8 +287,8 @@ MARK input(from, to, when, above)
/* handle autoindent of the first line, maybe */
cursor = from;
m = (above ? (cursor + BLKSIZE) : (cursor - BLKSIZE));
if (*o_autoindent && markidx(m) == 0
m = cursor + MARK_AT_LINE(delta);
if (delta != 0 && *o_autoindent && markidx(m) == 0
&& markline(m) >= 1L && markline(m) <= nlines)
{
/* Only autoindent blank lines. */
@ -307,7 +307,7 @@ MARK input(from, to, when, above)
{
*build = '\0';
add(cursor, tmpblk.c);
cursor += (build - tmpblk.c);
cursor += (int)(build - tmpblk.c);
if (cursor > to)
to = cursor;
}
@ -329,7 +329,7 @@ MARK input(from, to, when, above)
build = ptext;
if (pline == markline(from))
build += markidx(from);
for (scan = ptext + markidx(cursor); --scan >= build && isalnum(*scan); )
for (scan = ptext + markidx(cursor); --scan >= build && !isspace(*scan); )
{
}
scan++;
@ -338,7 +338,7 @@ MARK input(from, to, when, above)
key[0] = getkey(when);
#endif
#ifndef NO_VISIBLE
if (key[0] != '\0' && V_from != MARK_UNSET)
if (key[0] != ctrl('O') && V_from != MARK_UNSET)
{
msg("Can't modify text during a selection");
beep();
@ -375,10 +375,11 @@ MARK input(from, to, when, above)
* warpmargin, then change the last whitespace
* characters on line into a newline
*/
if (*o_wrapmargin != 0)
if (*o_wrapmargin)
{
pfetch(markline(cursor));
if (idx2col(cursor, ptext, TRUE) > COLS - (*o_wrapmargin & 0xff))
if (plen == idx2col(cursor, ptext, TRUE)
&& plen > COLS - (*o_wrapmargin & 0xff))
{
build = tmpblk.c;
*build++ = '\n';
@ -401,11 +402,15 @@ MARK input(from, to, when, above)
continue;
/*break up line, and we do autoindent if needed*/
change(m + (scan - ptext), m + (scan - ptext) + 1, tmpblk.c);
cursor = (cursor & ~(BLKSIZE - 1))
+ BLKSIZE
+ strlen(tmpblk.c) - 1
+ plen - (scan - ptext) - 1;
change(m + (int)(scan - ptext), m + (int)(scan - ptext) + 1, tmpblk.c);
/* NOTE: for some reason, MSC 5.10 doesn't
* like for these lines to be combined!!!
*/
cursor = (cursor & ~(BLKSIZE - 1));
cursor += BLKSIZE;
cursor += strlen(tmpblk.c) - 1;
cursor += plen - (int)(scan - ptext) - 1;
/*remove trailing spaces on previous line*/
pfetch(markline(m));
@ -416,7 +421,7 @@ MARK input(from, to, when, above)
if (*scan != ' ' && *scan != '\t')
break;
}
delete(m + (scan-ptext) + 1, m + plen);
delete(m + (int)(scan - ptext) + 1, m + plen);
break;
}
@ -559,7 +564,7 @@ MARK input(from, to, when, above)
V_from = MARK_UNSET;
ChangeText
{
m = from = to = cursor = paste(cursor, (*key == 'p'), FALSE);
m = paste(cursor, (*key == 'p'), FALSE);
}
break;
# endif /* !NO_VISIBLE */
@ -569,8 +574,8 @@ MARK input(from, to, when, above)
/* adjust the moved cursor */
if (m != cursor)
{
m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? 0x20 : 0));
if (*key == '$' || (*key == 'l' && m <= cursor))
m = adjmove(cursor, m, (*key == 'j' || *key == 'k' ? NCOL|FINL : FINL));
if (plen && (*key == '$' || (*key == 'l' && m <= cursor)))
{
m++;
}
@ -696,11 +701,21 @@ MARK input(from, to, when, above)
}
/* remove indent from this line, if blank */
if ((scan - ptext) >= markidx(cursor) && plen > 0)
if ((int)(scan - ptext) >= markidx(cursor) && plen > 0)
{
to = cursor &= ~(BLKSIZE - 1);
delete(cursor, cursor + plen);
delete(cursor, cursor + (int)(scan - ptext));
}
#if 0
/* advance "to" past whitespace at the cursor */
if (to >= cursor)
{
for (scan = ptext + markidx(cursor), to = cursor; *scan == ' ' || *scan == '\t'; scan++, to++)
{
}
}
#endif
}
*build = 0;
if (cursor >= to && when != WHEN_VIREP)
@ -727,7 +742,11 @@ MARK input(from, to, when, above)
{
cutname('.');
}
to = cursor = paste(cursor, FALSE, TRUE) + 1L;
m = paste(cursor, FALSE, TRUE);
if (m != MARK_UNSET)
{
to = cursor = m + 1L;
}
break;
case ctrl('V'):

View File

@ -20,8 +20,7 @@
#include <setjmp.h>
#include "vi.h"
extern trapint(); /* defined below */
extern char *getenv();
extern SIGTYPE trapint(); /* defined below */
jmp_buf jmpenv;
#ifndef NO_DIGRAPH
@ -89,33 +88,33 @@ void main(argc, argv)
/* arrange for deadly signals to be caught */
# ifdef SIGHUP
signal(SIGHUP, (void(*)()) deathtrap);
signal(SIGHUP, deathtrap);
# endif
# ifndef DEBUG
# ifdef SIGILL
signal(SIGILL, (void(*)()) deathtrap);
signal(SIGILL, deathtrap);
# endif
# ifdef SIGBUS
signal(SIGBUS, (void(*)()) deathtrap);
signal(SIGBUS, deathtrap);
# endif
# ifdef SIGSEGV
signal(SIGSEGV, (void(*)()) deathtrap);
signal(SIGSEGV, deathtrap);
# endif
# ifdef SIGSYS
signal(SIGSYS, (void(*)()) deathtrap);
signal(SIGSYS, deathtrap);
# endif
# endif /* !DEBUG */
# ifdef SIGPIPE
signal(SIGPIPE, (void(*)()) deathtrap);
signal(SIGPIPE, deathtrap);
# endif
# ifdef SIGTERM
signal(SIGTERM, (void(*)()) deathtrap);
signal(SIGTERM, deathtrap);
# endif
# ifdef SIGUSR1
signal(SIGUSR1, (void(*)()) deathtrap);
signal(SIGUSR1, deathtrap);
# endif
# ifdef SIGUSR2
signal(SIGUSR2, (void(*)()) deathtrap);
signal(SIGUSR2, deathtrap);
# endif
/* initialize the options - must be done after initscr(), so that
@ -187,11 +186,11 @@ void main(argc, argv)
case 'L':
case 'r': /* recover */
msg("Use the `elvisrecover` program to recover lost files");
msg("Use the `elvrec` program to recover lost files");
endmsgs();
refresh();
endwin();
exit(0);
exit(1);
break;
case 't': /* tag */
@ -309,7 +308,7 @@ void main(argc, argv)
doexrc(SYSEXRC);
#endif
#ifdef HMEXRC
str = getenv("HOME");
str = gethome(argv[0]);
if (str && *str)
{
strcpy(tmpblk.c, str);
@ -346,7 +345,7 @@ void main(argc, argv)
blkinit();
if (tag)
{
cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
cmd_tag(MARK_UNSET, MARK_FIRST, CMD_TAG, 0, tag);
}
#ifndef NO_ERRLIST
else if (err)
@ -386,7 +385,7 @@ void main(argc, argv)
/* Maybe we just aborted a change? */
abortdo();
}
signal(SIGINT, (void(*)()) trapint);
signal(SIGINT, trapint);
switch (mode)
{
@ -419,13 +418,13 @@ void main(argc, argv)
refresh();
endwin();
exit(0);
exit(exitcode);
/*NOTREACHED*/
}
/*ARGSUSED*/
int trapint(signo)
SIGTYPE trapint(signo)
int signo;
{
beep();
@ -434,16 +433,11 @@ int trapint(signo)
#if OSK
sigmask(-1);
#endif
#if TURBOC || __GNUC__
signal(signo, (void (*)())trapint);
#else
signal(signo, trapint);
#endif
doingglobal = FALSE;
longjmp(jmpenv, 1);
return 0;
/*NOTREACHED*/
}
@ -502,7 +496,7 @@ static char digtable[][4] =
""
};
static init_digraphs()
static int init_digraphs()
{
int i;

View File

@ -378,7 +378,7 @@ void add(atmark, newtext)
{
/* hey, we probably can! Get the following block & see... */
following = blkget(blkno + 1);
if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
if (strlen(following->c) + (build - blk->c) < (unsigned)(BLKSIZE - 1))
{
/* we can! Copy text from following to blk */
for (scan = following->c; *scan; )

View File

@ -17,7 +17,7 @@
MARK m_updnto(m, cnt, cmd)
MARK m; /* movement is relative to this mark */
long cnt; /* a numeric argument */
char cmd; /* the command character */
int cmd; /* the command character */
{
DEFAULT(cmd == 'G' ? nlines : 1L);
@ -245,6 +245,10 @@ MARK m_sentence(m, cnt, cmd)
{
REG char *text;
REG long l;
#ifndef CRUNCH
/* figure out where the paragraph boundary is */
MARK pp = m_paragraph(m, 1L, cmd=='(' ? '{' : '}');
#endif
DEFAULT(1);
@ -277,9 +281,9 @@ MARK m_sentence(m, cnt, cmd)
/* move forward, wrap at end of line */
if (!text[0])
{
if (l >= nlines)
if (l == nlines)
{
return MARK_UNSET;
goto BreakBreak;
}
l++;
pfetch(l);
@ -297,9 +301,9 @@ MARK m_sentence(m, cnt, cmd)
{
do
{
if (l <= 1)
if (l == 1L)
{
return MARK_FIRST;
goto BreakBreak;
}
l--;
pfetch(l);
@ -313,12 +317,25 @@ MARK m_sentence(m, cnt, cmd)
}
} while (!isperiod(text));
}
BreakBreak:
/* construct a mark for this location */
m = buildmark(text);
/* move forward to the first word of the next sentence */
m = m_fword(m, 1L, 'w', '\0');
if (m == MARK_UNSET)
{
m = MARK_EOF;
}
#ifndef CRUNCH
/* don't cross the paragraph boundary */
if (pp && ((cmd=='(') ? (m<pp) : (m>pp)))
{
m = pp;
}
#endif
return m;
}
@ -334,11 +351,15 @@ MARK m_paragraph(m, cnt, cmd)
long l, ol; /* current line number, original line number */
int dir; /* -1 if we're moving up, or 1 if down */
char col0; /* character to expect in column 0 */
long limit; /* line where searching must stop */
#ifndef NO_SENTENCE
# define SENTENCE(x) (x)
char *list; /* either o_sections or o_paragraph */
#else
# define SENTENCE(x)
#endif
#ifndef CRUNCH
MARK ss;
#endif
DEFAULT(1);
@ -350,12 +371,26 @@ MARK m_paragraph(m, cnt, cmd)
dir = -1;
col0 = '\0';
SENTENCE(list = o_paragraphs);
#ifndef CRUNCH
ss = m_paragraph(m, 1L, '<');
if (ss)
limit = markline(ss);
else
#endif
limit = 1L;
break;
case '}':
dir = 1;
col0 = '\0';
SENTENCE(list = o_paragraphs);
#ifndef CRUNCH
ss = m_paragraph(m, 1L, '>');
if (ss)
limit = markline(ss);
else
#endif
limit = nlines;
break;
case '[':
@ -363,9 +398,12 @@ MARK m_paragraph(m, cnt, cmd)
{
return MARK_UNSET;
}
/* fall through... */
case '<':
dir = -1;
col0 = '{';
SENTENCE(list = o_sections);
limit = 1L;
break;
case ']':
@ -373,18 +411,21 @@ MARK m_paragraph(m, cnt, cmd)
{
return MARK_UNSET;
}
/* fall through... */
case '>':
dir = 1;
col0 = '{';
SENTENCE(list = o_sections);
limit = nlines;
break;
}
ol = l = markline(m);
/* for each paragraph that we want to travel through... */
while (l > 0 && l <= nlines && cnt-- > 0)
while (l != limit && cnt-- > 0)
{
/* skip blank lines between paragraphs */
while (l > 0 && l <= nlines && col0 == *(text = fetchline(l)))
while (l != limit && col0 == *(text = fetchline(l)))
{
l += dir;
}
@ -407,22 +448,14 @@ MARK m_paragraph(m, cnt, cmd)
}
#endif
l += dir;
} while (l > 0 && l <= nlines && col0 != *(text = fetchline(l)));
} while (l != limit && col0 != *(text = fetchline(l)));
BreakBreak: ;
}
if (l > nlines)
{
m = MARK_LAST;
}
else if (l <= 0)
{
m = MARK_FIRST;
}
else
{
m = MARK_AT_LINE(l);
}
m = MARK_AT_LINE(l);
#ifdef DEBUG2
debout("m_paragraph() returning %ld.%d\n", markline(m), markidx(m));
#endif
return m;
}

View File

@ -44,37 +44,50 @@ MARK m_wsrch(word, m, cnt)
}
#endif
MARK m_nsrch(m)
MARK m_nsrch(m, cnt, cmd)
MARK m; /* where to start searching */
long cnt; /* number of searches to do */
int cmd; /* command character -- 'n' or 'N' */
{
if (prevsf)
int oldprevsf; /* original value of prevsf, so we can fix any changes */
DEFAULT(1L);
/* clear the bottom line. In particular, we want to loose any
* "(wrapped)" notice.
*/
move(LINES - 1, 0);
clrtoeol();
/* if 'N' command, then invert the "prevsf" variable */
oldprevsf = prevsf;
if (cmd == 'N')
{
m = m_fsrch(m, (char *)0);
prevsf = TRUE;
prevsf = !prevsf;
}
else
/* search forward if prevsf -- i.e., if previous search was forward */
while (--cnt >= 0L && m != MARK_UNSET)
{
m = m_bsrch(m, (char *)0);
prevsf = FALSE;
if (prevsf)
{
m = m_fsrch(m, (char *)0);
}
else
{
m = m_bsrch(m, (char *)0);
}
}
/* restore the old value of prevsf -- if cmd=='N' then it was inverted,
* and the m_fsrch() and m_bsrch() functions force it to a (possibly
* incorrect) value. The value of prevsf isn't supposed to be changed
* at all here!
*/
prevsf = oldprevsf;
return m;
}
MARK m_Nsrch(m)
MARK m; /* where to start searching */
{
if (prevsf)
{
m = m_bsrch(m, (char *)0);
prevsf = TRUE;
}
else
{
m = m_fsrch(m, (char *)0);
prevsf = FALSE;
}
return m;
}
MARK m_fsrch(m, ptrn)
MARK m; /* where to start searching */
@ -104,7 +117,7 @@ MARK m_fsrch(m, ptrn)
ptrn++;
/* free the previous pattern */
if (re) free(re);
if (re) _free_(re);
/* compile the pattern */
re = regcomp(ptrn);
@ -214,7 +227,7 @@ MARK m_bsrch(m, ptrn)
ptrn++;
/* free the previous pattern, if any */
if (re) free(re);
if (re) _free_(re);
/* compile the pattern */
re = regcomp(ptrn);

View File

@ -21,7 +21,7 @@ static char prev_key; /* sought cvhar from previous [fFtT] */
MARK m__ch(m, cnt, cmd)
MARK m; /* current position */
long cnt;
char cmd; /* command: either ',' or ';' */
int cmd; /* command: either ',' or ';' */
{
MARK (*tmp)();
@ -52,7 +52,7 @@ MARK m__ch(m, cnt, cmd)
MARK m_fch(m, cnt, key)
MARK m; /* where to search from */
long cnt;
char key; /* what to search for */
int key; /* what to search for */
{
REG char *text;
@ -83,7 +83,7 @@ MARK m_fch(m, cnt, key)
MARK m_Fch(m, cnt, key)
MARK m; /* where to search from */
long cnt;
char key; /* what to search for */
int key; /* what to search for */
{
REG char *text;
@ -114,50 +114,32 @@ MARK m_Fch(m, cnt, key)
MARK m_tch(m, cnt, key)
MARK m; /* where to search from */
long cnt;
char key; /* what to search for */
int key; /* what to search for */
{
/* skip the adjacent char */
pfetch(markline(m));
if (plen <= markidx(m))
{
return MARK_UNSET;
}
m++;
m = m_fch(m, cnt, key);
if (m == MARK_UNSET)
if (m != MARK_UNSET)
{
return MARK_UNSET;
prevfwdfn = m_tch;
prevrevfn = m_Tch;
m--;
}
prevfwdfn = m_tch;
prevrevfn = m_Tch;
return m - 1;
return m;
}
/* move backward within this line almost to previous occurrence of key */
MARK m_Tch(m, cnt, key)
MARK m; /* where to search from */
long cnt;
char key; /* what to search for */
int key; /* what to search for */
{
/* skip the adjacent char */
if (markidx(m) == 0)
{
return MARK_UNSET;
}
m--;
m = m_Fch(m, cnt, key);
if (m == MARK_UNSET)
{
return MARK_UNSET;
prevfwdfn = m_Tch;
prevrevfn = m_tch;
m++;
}
prevfwdfn = m_Tch;
prevrevfn = m_tch;
return m + 1;
return m;
}
#endif

View File

@ -136,6 +136,12 @@ MARK m_scroll(m, cnt, key)
int key; /* keystroke that causes this movement */
{
MARK tmp; /* a temporary mark, used as arg to redraw() */
#ifndef CRUNCH
int savenearscroll;
savenearscroll = *o_nearscroll;
*o_nearscroll = LINES;
#endif
/* adjust cnt, and maybe *o_scroll, depending of key */
switch (key)
@ -207,5 +213,8 @@ MARK m_scroll(m, cnt, key)
break;
}
#ifndef CRUNCH
*o_nearscroll = savenearscroll;
#endif
return m;
}

View File

@ -36,7 +36,7 @@ MARK m_fword(m, cnt, cmd, prevkey)
*/
if (cnt == 1L && prevkey == 'c' && isspace(*text))
{
return m + 1L;
return m;
}
#endif

View File

@ -18,7 +18,6 @@
#ifndef NULL
#define NULL (char *)0
#endif
extern char *getenv();
/* maximum width to permit for strings, including ="" */
#define MAXWIDTH 20
@ -28,7 +27,7 @@ char o_autoindent[1] = {FALSE};
char o_autoprint[1] = {TRUE};
char o_autotab[1] = {TRUE};
char o_autowrite[1] = {FALSE};
char o_columns[3] = {80, 32, 255};
char o_columns[3] = {80, 32, ~0};
char o_directory[30] = TMPDIR;
char o_edcompatible[1] = {FALSE};
char o_equalprg[80] = {"fmt"};
@ -45,7 +44,7 @@ char o_remap[1] = {TRUE};
char o_report[3] = {5, 1, 127};
char o_scroll[3] = {12, 1, 127};
char o_shell[60] = SHELL;
char o_shiftwidth[3] = {8, 1, 255};
char o_shiftwidth[3] = {8, 1, ~0};
char o_sidescroll[3] = {8, 1, 40};
char o_sync[1] = {NEEDSYNC};
char o_tabstop[3] = {8, 1, 40};
@ -59,12 +58,14 @@ char o_beautify[1] = {FALSE};
char o_exrc[1] = {FALSE};
char o_mesg[1] = {TRUE};
char o_more[1] = {TRUE};
char o_nearscroll[3] = {15, 0, ~0};
char o_novice[1] = {FALSE};
char o_prompt[1] = {TRUE};
char o_taglength[3] = {0, 0, 30};
char o_tags[256] = {"tags"};
char o_terse[1] = {FALSE};
char o_window[3] = {0, 1, 24};
char o_wrapmargin[3] = {0, 0, 255};
char o_wrapmargin[3] = {0, 0, ~0};
char o_writeany[1] = {FALSE};
#endif
@ -123,6 +124,11 @@ char o_showmatch[1] = {FALSE};
char o_smd[1] = {FALSE};
#endif
#ifndef NO_TAGSTACK
char o_tagstack[1] = {TRUE};
#endif
/* The following describes the names & types of all options */
#define BOOL 0
@ -199,6 +205,7 @@ struct
#endif
#ifndef CRUNCH
{ "more", "mo", BOOL, CANSET, o_more },
{ "nearscroll", "ns", NUM, CANSET, o_nearscroll },
{ "novice", "nov", BOOL, CANSET, o_novice },
#endif
{ "number", "nu", BOOL, CANSET|MR, o_number },
@ -234,6 +241,10 @@ struct
{ "tabstop", "ts", NUM, CANSET|MR, o_tabstop },
#ifndef CRUNCH
{ "taglength", "tl", NUM, CANSET, o_taglength },
{ "tags", "tag", STR, CANSET, o_tags },
#endif
#ifndef NO_TAGSTACK
{ "tagstack", "tgs", BOOL, CANSET, o_tagstack },
#endif
{ "term", "te", STR, SET, o_term },
#ifndef CRUNCH
@ -304,6 +315,7 @@ void initopts()
{
o_window[0] = o_window[2] = *o_lines;
}
*o_nearscroll = *o_lines;
#endif
/* disable the flash option if we don't know how to do a flash */
@ -685,7 +697,11 @@ void setopts(assignments)
/* change the variable */
if (!opts[i].name)
{
msg("invalid option name \"%s\"", name);
/* only complain about unknown options if we're editing
* a file; i.e., if we're not executing the .exrc now.
*/
if (tmpfd >= 0)
msg("invalid option name \"%s\"", name);
}
else if ((opts[i].flags & CANSET) != CANSET)
{

View File

@ -180,4 +180,31 @@ dbfree(ptr, file, line)
}
free(ptr - sizeof(long));
}
dbcheckmem(file, line)
char *file;
int line;
{
int i, j;
for (i = j = 0; i < MAXALLOC && allocated[i]; i++)
{
if (((long *)allocated[i])[-1] != MEMMAGIC)
{
if (!j) endwin();
fprintf(stderr, "\r\n%s(%d): underflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
j++;
}
if (((long *)allocated[i])[sizes[i]] != MEMMAGIC)
{
if (!j) endwin();
fprintf(stderr, "\r\n%s(%d): overflowed malloc space, allocated at %s(%d)\n", file, line, fromfile[i], fromline[i]);
j++;
}
}
if (j)
{
abort();
}
}
#endif

View File

@ -19,6 +19,11 @@
#include "config.h"
#include "vi.h"
#ifdef CRUNCH
# define NEAR LINES
#else
# define NEAR (*o_nearscroll&0xff)
#endif
/* This variable contains the line number that smartdrawtext() knows best */
static long smartlno;
@ -367,7 +372,7 @@ static void drawtext(text, lno, clr)
/* show the line number, if necessary */
if (*o_number)
{
sprintf(numstr, "%6ld |", lno);
sprintf(numstr, "%6ld ", lno);
qaddstr(numstr);
}
@ -494,7 +499,7 @@ static void drawtext(text, lno, clr)
{
qaddch(' ');
col++;
} while (col < i);
} while (col < i && col < limitcol);
}
else
#endif /* !NO_VISIBLE */
@ -522,11 +527,16 @@ static void drawtext(text, lno, clr)
{
qaddch(' ');
col++;
} while (col < i);
} while (col < i && col < limitcol);
}
}
else /* tab ending after screen? next line! */
{
#ifdef CRUNCH
/* needed at least when scrolling the screen right -nox */
if (clr && col < limitcol)
clrtoeol();
#endif
col = limitcol;
if (has_AM)
{
@ -798,7 +808,7 @@ static void smartdrawtext(text, lno, showit)
/* show the line number, if necessary */
if (*o_number)
{
sprintf(numstr, "%6ld |", lno);
sprintf(numstr, "%6ld ", lno);
qaddstr(numstr);
}
@ -980,7 +990,7 @@ void redraw(curs, inputting)
smartdrawtext(text, l, (chgs != changes));
}
}
else if (l < topline && l > topline - LINES && (has_SR || has_AL))
else if (l < topline && l >= topline - NEAR && (has_SR || has_AL))
{
/* near top - scroll down */
if (!mustredraw)
@ -1012,7 +1022,7 @@ void redraw(curs, inputting)
redrawrange(0L, INFINITY, INFINITY);
}
}
else if (l > topline && l < botline + LINES)
else if (l > topline && l <= botline + NEAR)
{
/* near bottom -- scroll up */
if (!mustredraw)
@ -1038,12 +1048,13 @@ void redraw(curs, inputting)
else
{
/* distant line - center it & force a redraw */
topline = l - (LINES / 2) - 1;
topline = l - (LINES - 1) / 2;
if (topline < 1)
{
topline = 1;
}
redrawrange(0L, INFINITY, INFINITY);
smartlno = 0L;
changes++;
}

View File

@ -93,6 +93,8 @@ static char *makeclass(text, bmap)
int complement = 0;
checkmem();
/* zero the bitmap */
for (i = 0; bmap && i < 32; i++)
{
@ -119,7 +121,7 @@ static char *makeclass(text, bmap)
}
/* add each character in the span to the bitmap */
for (i = text[0]; bmap && i <= text[2]; i++)
for (i = UCHAR(text[0]); bmap && (unsigned)i <= UCHAR(text[2]); i++)
{
bmap[i >> 3] |= (1 << (i & 7));
}
@ -133,7 +135,7 @@ static char *makeclass(text, bmap)
i = *text++;
if (bmap)
{
bmap[i >> 3] |= (1 << (i & 7));
bmap[UCHAR(i) >> 3] |= (1 << (UCHAR(i) & 7));
}
}
}
@ -153,6 +155,8 @@ static char *makeclass(text, bmap)
}
}
checkmem();
return text;
}
@ -171,6 +175,10 @@ static int gettoken(sptr, re)
int c;
c = **sptr;
if (!c)
{
return c;
}
++*sptr;
if (c == '\\')
{
@ -353,21 +361,30 @@ regexp *regcomp(exp)
int token;
int peek;
char *build;
#if __STDC__
volatile
#endif
regexp *re;
#ifndef CRUNCH
int from;
int to;
int digit;
#endif
#ifdef DEBUG
int calced;
#endif
checkmem();
/* prepare for error handling */
re = (regexp *)0;
if (setjmp(errorhandler))
{
checkmem();
if (re)
{
free(re);
_free_(re);
}
return (regexp *)0;
}
@ -384,20 +401,26 @@ regexp *regcomp(exp)
else /* non-empty regexp given, so remember it */
{
if (previous)
free(previous);
_free_(previous);
previous = (char *)malloc((unsigned)(strlen(exp) + 1));
if (previous)
strcpy(previous, exp);
}
/* allocate memory */
checkmem();
class_cnt = 0;
start_cnt = 1;
end_sp = 0;
retext = exp;
#ifdef DEBUG
calced = calcsize(exp);
size = calced + sizeof(regexp);
#else
size = calcsize(exp) + sizeof(regexp) + 10; /* !!! 10 bytes for slop */
#endif
#ifdef lint
re = ((regexp *)0) + size;
re = (regexp *)0;
#else
re = (regexp *)malloc((unsigned)size);
#endif
@ -405,6 +428,7 @@ regexp *regcomp(exp)
{
FAIL("Not enough memory for this RE");
}
checkmem();
/* compile it */
build = &re->program[1 + 32 * class_cnt];
@ -541,6 +565,7 @@ regexp *regcomp(exp)
*build++ = token;
}
}
checkmem();
/* end it with a \) which MUST MATCH the opening \( */
ADD_META(build, M_END(0));
@ -549,6 +574,15 @@ regexp *regcomp(exp)
FAIL("Not enough \\)s");
}
#ifdef DEBUG
if ((int)(build - re->program) != calced)
{
msg("regcomp error: calced=%d, actual=%d", calced, (int)(build - re->program));
getkey(0);
}
#endif
checkmem();
return re;
}
@ -577,7 +611,7 @@ int match1(re, ch, token)
}
else if (IS_CLASS(token))
{
if (re->program[1 + 32 * (token - M_CLASS(0)) + (ch >> 3)] & (1 << (ch & 7)))
if (re->program[1 + 32 * (token - M_CLASS(0)) + (UCHAR(ch) >> 3)] & (1 << (UCHAR(ch) & 7)))
return 0;
}
else if (ch == token || *o_ignorecase && tolower(ch) == tolower(token))
@ -733,6 +767,8 @@ int regexec(re, str, bol)
int len; /* length of the string */
REG char *here;
checkmem();
/* if must start at the beginning of a line, and this isn't, then fail */
if (re->bol && !bol)
{
@ -780,6 +816,7 @@ int regexec(re, str, bol)
}
/* if we didn't fail, then we must have succeeded */
checkmem();
return 1;
}

View File

@ -56,6 +56,7 @@ void regsub(re, src, dst)
}
/* allocate memory for the ~ed version of src */
checkmem();
start = cpy = (char *)malloc((unsigned)(len + 1));
if (!cpy)
{
@ -94,10 +95,11 @@ void regsub(re, src, dst)
msg("Bug in regsub.c! Predicted length = %d, Actual length = %d", len, (int)(cpy - start));
}
#endif
checkmem();
/* remember this as the "previous" for next time */
if (prev)
free(prev);
_free_(prev);
prev = src = start;
#endif /* undef CRUNCH */

View File

@ -22,7 +22,9 @@
#include "config.h"
#include "vi.h"
#ifndef XDOS
extern char **environ;
#endif
#if ANY_UNIX
@ -30,6 +32,9 @@ extern char **environ;
* between this one and the library one is: this one uses the o_shell option.
*/
int system(cmd)
#ifdef __STDC__
const
#endif
char *cmd; /* a command to run */
{
int pid; /* process ID of child */
@ -73,11 +78,7 @@ int system(cmd)
{
status = -1;
}
#if __GNUC__
signal(SIGINT, (void (*)()) trapint);
#else
signal(SIGINT, trapint);
#endif
}
return status;
@ -168,11 +169,7 @@ int rpclose(fd)
close(fd);
wait(&status);
#if __GNUC__
signal(SIGINT, (void (*)()) trapint);
#else
signal(SIGINT, trapint);
#endif
return status;
}
@ -372,13 +369,13 @@ int filter(from, to, cmd, back)
}
#endif
}
}
/* delete old text, if any */
if (to)
{
cut(from, to);
delete(from, to);
/* delete old text, if any */
if (to)
{
cut(from, to);
delete(from, to);
}
}
}
else

View File

@ -14,10 +14,11 @@
#include "vi.h"
#include "ctype.h"
static int showmsg P_((void));
/* This function reads in a line from the terminal. */
int vgets(prompt, buf, bsize)
char prompt; /* the prompt character, or '\0' for none */
int prompt; /* the prompt character, or '\0' for none */
char *buf; /* buffer into which the string is read */
int bsize; /* size of the buffer */
{
@ -57,7 +58,7 @@ int vgets(prompt, buf, bsize)
else
{
/* maybe expand an abbreviation while getting key */
for (word = len; --word >= 0 && isalnum(buf[word]); )
for (word = len; --word >= 0 && !isspace(buf[word]); )
{
}
word++;
@ -74,8 +75,10 @@ int vgets(prompt, buf, bsize)
#endif
/* some special conversions */
#if 0
if (ch == ctrl('D') && len == 0)
ch = ctrl('[');
#endif
#ifndef NO_DIGRAPH
if (*o_digraph && erased != 0 && ch != '\b')
{
@ -99,9 +102,10 @@ int vgets(prompt, buf, bsize)
quoted = TRUE;
break;
case ctrl('['):
case ctrl('D'):
return -1;
case ctrl('['):
case '\n':
#if OSK
case '\l':
@ -111,6 +115,21 @@ int vgets(prompt, buf, bsize)
clrtoeol();
goto BreakBreak;
#ifndef CRUNCH
case ctrl('U'):
while (len > 0)
{
len--;
while (widths[len]-- > 0)
{
qaddch('\b');
qaddch(' ');
qaddch('\b');
}
}
break;
#endif
case '\b':
if (len > 0)
{
@ -235,14 +254,24 @@ void endmsgs()
* msg("") - clears the message line
* msg("%s %d", ...) - does a printf onto the message line
*/
/*VARARGS1*/
#ifdef __STDC__
void msg (char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
#else
void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
char *fmt;
long arg1, arg2, arg3, arg4, arg5, arg6, arg7;
{
#endif
if (mode != MODE_VI)
{
#ifdef __STDC__
vsprintf (pmsg, fmt, ap);
#else
sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
#endif
qaddstr(pmsg);
addch('\n');
exrefresh();
@ -256,12 +285,19 @@ void msg(fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
}
/* real message */
#ifdef __STDC__
vsprintf (pmsg, fmt, ap);
#else
sprintf(pmsg, fmt, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
#endif
if (*fmt)
{
manymsgs = TRUE;
}
}
#ifdef __STDC__
va_end (ap);
#endif
}
@ -330,7 +366,7 @@ void beep()
}
else if (*o_errorbells)
{
ttywrite("\007", 1);
tputs("\007", 1, faddch);
}
/* discard any buffered input, and abort macros */
@ -426,6 +462,10 @@ void execmap(rawlen, cookedstr, visual)
#endif
}
#ifndef NO_CURSORSHAPE
/* made global so that suspend_curses() can reset it. -nox */
int oldcurs;
#endif
/* This function calls ttyread(). If necessary, it will also redraw the screen,
* change the cursor shape, display the mode, and update the ruler. If the
* number of characters read is 0, and we didn't time-out, then it exits because
@ -443,9 +483,6 @@ static int fillkeybuf(when, timeout)
static long oldnlines;
char *str;
#endif
#ifndef NO_CURSORSHAPE
static int oldcurs;
#endif
#ifdef DEBUG
watch();
@ -480,7 +517,10 @@ static int fillkeybuf(when, timeout)
redraw(cursor, !(when & WHEN_VICMD));
/* now the "topline" test should be valid */
if (when != oldwhen || topline != oldtop || leftcol != oldleft || nlines != oldnlines)
if (when != oldwhen
|| topline != oldtop
|| leftcol != oldleft
|| nlines != oldnlines)
{
oldwhen = when;
oldtop = topline;
@ -490,9 +530,9 @@ static int fillkeybuf(when, timeout)
if (when & WHEN_VICMD) str = "Command";
else if (when & WHEN_VIINP) str = " Input ";
else if (when & WHEN_VIREP) str = "Replace";
else if (when & WHEN_REP1) str = " Rep 1 ";
else if (when & WHEN_CUT) str = "BufName";
else if (when & WHEN_MARK) str = "Mark AZ";
else if (when & WHEN_REP1) str = "Replc 1";
else if (when & WHEN_CUT) str = "Buffer ";
else if (when & WHEN_MARK) str = " Mark ";
else if (when & WHEN_CHAR) str = "Dest Ch";
else str = (char *)0;
@ -539,7 +579,7 @@ static int fillkeybuf(when, timeout)
clrtoeol();
refresh();
endwin();
exit(1);
exit(exitcode);
}
cend += nkeys;
@ -592,7 +632,12 @@ static int countmatch(when)
/* No, it wouldn't. But check for partial match */
if (!strncmp(map->rawin, &keybuf[next], cend - next))
{
count++;
/* increment by 2 instead of 1 so that, in the
* event that we have a partial match with a
* single map, we don't mistakenly assume we
* have resolved the map yet.
*/
count += 2;
}
}
}
@ -612,7 +657,7 @@ static void expandabbr(word, wlen)
MAP *abbr;
/* if the next character wouldn't end the word, then don't expand */
if (isalnum(keybuf[next]) || keybuf[next] == ctrl('V'))
if (isalnum(keybuf[next]) || keybuf[next] == ctrl('V') || keybuf[next] == '\b')
{
return;
}
@ -696,7 +741,7 @@ int getabkey(when, word, wlen)
}
/* try to map the key, unless already mapped and not ":set noremap" */
if (next >= user || *o_remap)
if (next <= user || *o_remap)
{
do
{
@ -713,6 +758,12 @@ int getabkey(when, word, wlen)
} while (*o_remap && matches == 1);
}
/* ERASEKEY should always be mapped to '\b'. */
if (keybuf[next] == ERASEKEY)
{
keybuf[next] = '\b';
}
#ifndef NO_ABBR
/* try to expand an abbreviation, except in visual command mode */
if (wlen > 0 && (mode & (WHEN_EX|WHEN_VIINP|WHEN_VIREP)) != 0)
@ -721,12 +772,6 @@ int getabkey(when, word, wlen)
}
#endif
/* ERASEKEY should always be mapped to '\b'. */
if (keybuf[next] == ERASEKEY)
{
keybuf[next] = '\b';
}
/* return the next key */
return keybuf[next++];
}
@ -735,7 +780,7 @@ int getabkey(when, word, wlen)
void mapkey(rawin, cooked, when, name)
char *rawin; /* the input key sequence, before mapping */
char *cooked;/* after mapping -- or NULL to remove map */
short when; /* bitmap of when mapping should happen */
int when; /* bitmap of when mapping should happen */
char *name; /* name of the key, NULL for no name, "abbr" for abbr */
{
MAP **head; /* head of list of maps or abbreviations */
@ -751,7 +796,7 @@ void mapkey(rawin, cooked, when, name)
/* try to find the map in the list */
for (scan = *head, prev = (MAP *)0;
scan && (strcmp(rawin, scan->rawin) ||
scan && (strcmp(rawin, scan->rawin) && strcmp(rawin, scan->cooked) ||
!(scan->flags & when & (WHEN_EX|WHEN_VICMD|WHEN_VIINP|WHEN_VIREP)));
prev = scan, scan = scan->next)
{
@ -778,7 +823,7 @@ void mapkey(rawin, cooked, when, name)
{
scan = (MAP *)malloc(sizeof(MAP));
scan->len = strlen(rawin);
scan->rawin = malloc(scan->len + 1);
scan->rawin = malloc((unsigned)(scan->len + 1));
strcpy(scan->rawin, rawin);
scan->flags = when;
scan->label = name;
@ -794,9 +839,9 @@ void mapkey(rawin, cooked, when, name)
}
else /* recycle old structure */
{
free(scan->cooked);
_free_(scan->cooked);
}
scan->cooked = malloc(strlen(cooked) + 1);
scan->cooked = malloc((unsigned)(strlen(cooked) + 1));
strcpy(scan->cooked, cooked);
}
else /* unmapping */
@ -818,9 +863,9 @@ void mapkey(rawin, cooked, when, name)
}
/* free it, and the strings that it refers to */
free(scan->rawin);
free(scan->cooked);
free(scan);
_free_(scan->rawin);
_free_(scan->cooked);
_free_(scan);
}
}
@ -924,7 +969,7 @@ void dumpkey(when, abbr)
#ifndef NO_MKEXRC
static safequote(str)
static void safequote(str)
char *str;
{
char *build;
@ -949,15 +994,14 @@ static safequote(str)
* :abbr dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE);
* :abbr! dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE);
*/
void
savemaps(fd, abbr)
int fd; /* file descriptor of an open file to write to */
int abbr; /* boolean: do abbr table? (else do map table) */
{
MAP *scan;
char *str;
int bang;
int when;
int len;
# ifndef NO_ABBR
for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)

View File

@ -5,13 +5,6 @@
* 14407 SW Teal Blvd. #C
* Beaverton, OR 97005
* kirkenda@cs.pdx.edu
*
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00041
* -------------------- ----- ----------------------
*
* 12 Aug 92 Bob Wilcox Fixed named yank buffer problem
*/
@ -153,11 +146,15 @@ int tmpstart(filename)
((getuid() >> 16) == 0 ? S_IOWRITE | S_IWRITE :
((statb.st_gid != (getuid() >> 16) ? S_IOWRITE : S_IWRITE)))))
#endif
#if AMIGA || MSDOS || (TOS && defined(__GNUC__))
#if AMIGA || MSDOS
if (*o_readonly || !(statb.st_mode & S_IWRITE))
#endif
#if TOS && !defined(__GNUC__)
#if TOS
# ifdef __GNUC__
if (*o_readonly || !(statb.st_mode & S_IWRITE))
# else
if (*o_readonly || (statb.st_mode & S_IJRON))
# endif
#endif
#if ANY_UNIX
if (*o_readonly || !(statb.st_mode &
@ -185,25 +182,36 @@ int tmpstart(filename)
}
/* make a name for the tmp file */
tmpnum++;
#if MSDOS || TOS
/* MS-Dos doesn't allow multiple slashes, but supports drives
* with current directories.
* This relies on TMPNAME beginning with "%s\\"!!!!
*/
strcpy(tmpname, o_directory);
if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
tmpname[i++]=SLASH;
sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
#else
sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
#endif
/* make sure nobody else is editing the same file */
if (access(tmpname, 0) == 0)
do
{
FAIL("Temp file \"%s\" already exists?", tmpname);
}
tmpnum++;
#if MSDOS || TOS
/* MS-Dos doesn't allow multiple slashes, but supports drives
* with current directories.
* This relies on TMPNAME beginning with "%s\\"!!!!
*/
strcpy(tmpname, o_directory);
if ((i = strlen(tmpname)) && !strchr(":/\\", tmpname[i-1]))
tmpname[i++]=SLASH;
sprintf(tmpname+i, TMPNAME+3, getpid(), tmpnum);
#else
sprintf(tmpname, TMPNAME, o_directory, getpid(), tmpnum);
#endif
} while (access(tmpname, 0) == 0);
/* !!! RACE CONDITION HERE - some other process with the same PID could
* create the temp file between the access() call and the creat() call.
* This could happen in a couple of ways:
* - different workstation may share the same temp dir via NFS. Each
* workstation could have a process with the same number.
* - The DOS version may be running multiple times on the same physical
* machine in different virtual machines. The DOS pid number will
* be the same on all virtual machines.
*
* This race condition could be fixed by replacing access(tmpname, 0)
* with open(tmpname, O_CREAT|O_EXCL, 0600), if we could only be sure
* that open() *always* used modern UNIX semantics.
*/
/* create the temp file */
#if ANY_UNIX
@ -219,8 +227,11 @@ int tmpstart(filename)
}
/* allocate space for the header in the file */
write(tmpfd, hdr.c, (unsigned)BLKSIZE);
write(tmpfd, tmpblk.c, (unsigned)BLKSIZE);
if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) < BLKSIZE
|| write(tmpfd, tmpblk.c, (unsigned)BLKSIZE) < BLKSIZE)
{
FAIL("Error writing headers to \"%s\"", tmpname);
}
#ifndef NO_RECYCLE
/* initialize the block allocator */
@ -292,7 +303,7 @@ int tmpstart(filename)
this->c[j++] = 0x80;
}
#ifndef CRUNCH
else if (*o_beautify && this->c[k] < ' ' && this->c[k] > 0)
else if (*o_beautify && this->c[k] < ' ' && this->c[k] >= 1)
{
if (this->c[k] == '\t'
|| this->c[k] == '\n'
@ -345,6 +356,10 @@ int tmpstart(filename)
}
/* allocate next buffer */
if (i >= MAXBLKS - 2)
{
FAIL("File too big. Limit is approx %ld kbytes.", MAXBLKS * BLKSIZE / 1024L);
}
next = blkget(++i);
/* move fragmentary last line to next buffer */
@ -475,11 +490,7 @@ int tmpsave(filename, bang)
}
/* can't rewrite a READONLY file */
#if AMIGA
if (!strcmp(filename, origname) && tstflag(file, READONLY) && !bang)
#else
if (!strcmp(filename, origname) && *o_readonly && !bang)
#endif
{
msg("\"%s\" [READONLY] -- NOT WRITTEN", filename);
return FALSE;
@ -552,6 +563,10 @@ int tmpsave(filename, bang)
/* reset the "modified" flag, but not the "undoable" flag */
clrflag(file, MODIFIED);
significant = FALSE;
if (!strcmp(origname, filename))
{
exitcode &= ~1;
}
/* report lines & characters */
#if MSDOS || TOS
@ -601,11 +616,6 @@ int tmpabort(bang)
blkinit();
nlines = 0;
initflags();
#ifdef BROKEN_YANK_BUFFERS /* 12 Aug 92*/
close(tmpfd);
tmpfd = -1;
unlink(tmpname);
#endif /* BROKEN_YANK_BUFFERS*/
return TRUE;
}
@ -652,6 +662,7 @@ sync()
* to store the arguments to a command, so we can't use it here. Instead,
* we'll borrow the buffer that is used for "shift-U".
*/
int
storename(name)
char *name; /* the name of the file - normally origname */
{
@ -669,7 +680,11 @@ storename(name)
U_text[1] = 127;
}
#ifndef CRUNCH
# if TOS || MINT || MSDOS || AMIGA
else if (*name != '/' && *name != '\\' && !(*name && name[1] == ':'))
# else
else if (*name != SLASH)
# endif
{
/* get the directory name */
ptr = getcwd(U_text, BLKSIZE);
@ -696,7 +711,10 @@ storename(name)
{
/* write the name out to second block of the temp file */
lseek(tmpfd, (long)BLKSIZE, 0);
write(tmpfd, U_text, (unsigned)BLKSIZE);
if (write(tmpfd, U_text, (unsigned)BLKSIZE) < BLKSIZE)
{
FAIL("Error stuffing name \"%s\" into temp file", U_text);
}
}
return 0;
}
@ -706,7 +724,7 @@ storename(name)
/* This function handles deadly signals. It restores sanity to the terminal
* preserves the current temp file, and deletes any old temp files.
*/
int deathtrap(sig)
SIGTYPE deathtrap(sig)
int sig; /* the deadly signal that we caught */
{
char *why;
@ -730,8 +748,10 @@ int deathtrap(sig)
# ifdef SIGBUS
case SIGBUS: why = "-Elvis had a bus error"; break;
# endif
# if defined(SIGSEGV) && !defined(TOS)
# ifdef SIGSEGV
# if !TOS
case SIGSEGV: why = "-Elvis had a segmentation violation"; break;
# endif
# endif
# ifdef SIGSYS
case SIGSYS: why = "-Elvis munged a system call"; break;

View File

@ -79,6 +79,9 @@ int ttyread(buf, len, time)
case -1: /* assume we got an EINTR because of SIGWINCH */
if (*o_lines != LINES || *o_columns != COLS)
{
#ifndef CRUNCH
*o_nearscroll =
#endif
*o_lines = LINES;
*o_columns = COLS;
#ifndef CRUNCH
@ -106,10 +109,10 @@ int ttyread(buf, len, time)
}
# else
# if M_SYSV
/* For System-V or Coherent, we use VMIN/VTIME to implement the timeout.
* For no timeout, VMIN should be 1 and VTIME should be 0; for timeout,
* VMIN should be 0 and VTIME should be the timeout value.
# if UNIXV || COH_386
/* For System-V, we use VMIN/VTIME to implement the timeout. For no timeout,
* VMIN should be 1 and VTIME should be 0; for timeout, VMIN should be 0 and
* VTIME should be the timeout value.
*/
# include <termio.h>
int ttyread(buf, len, time)
@ -135,7 +138,7 @@ int ttyread(buf, len, time)
ioctl(0, TCSETA, &tio);
/* Perform the read. Loop if EINTR error happens */
while ((bytes = read(0, buf, len)) < 0)
while ((bytes = read(0, buf, (unsigned)len)) < 0)
{
/* probably EINTR error because a SIGWINCH was received */
if (*o_lines != LINES || *o_columns != COLS)
@ -145,6 +148,7 @@ int ttyread(buf, len, time)
#ifndef CRUNCH
if (!wset)
{
*o_nearscroll = LINES;
*o_window = LINES - 1;
}
#endif
@ -178,7 +182,7 @@ int ttyread(buf, len, time)
static jmp_buf env;
/*ARGSUSED*/
int dummy(signo)
SIGTYPE dummy(signo)
int signo;
{
longjmp(env, 1);
@ -189,17 +193,13 @@ int ttyread(buf, len, time)
int time; /* maximum time to allow for reading */
{
/* arrange for timeout */
#if __GNUC__
signal(SIGALRM, (void (*)()) dummy);
#else
signal(SIGALRM, dummy);
#endif
alarm(time);
/* perform the blocking read */
if (setjmp(env) == 0)
{
len = read(0, buf, len);
len = read(0, buf, (unsigned)len);
}
else /* I guess we timed out */
{
@ -216,7 +216,7 @@ int ttyread(buf, len, time)
return len;
}
# endif /* !(M_SYSV || COHERENT) */
# endif /* M_SYSV */
# endif /* !BSD */
#endif /* ANY_UNIX */

View File

@ -51,6 +51,7 @@ int bavar; /* used only in BeforeAfter macros */
/* used to detect changes that invalidate cached text/blocks */
long changes; /* incremented when file is changed */
int significant; /* boolean: was a *REAL* change made? */
int exitcode = 1; /* 0=overwritten, 1=not updated, else error */
/* used to support the pfetch() macro */
int plen; /* length of the line */

View File

@ -264,7 +264,7 @@ MARK v_overtype(m)
/* Normally, we input starting here, in replace mode */
ChangeText
{
end = input(m, m, WHEN_VIREP, FALSE);
end = input(m, m, WHEN_VIREP, 0);
}
/* if we ended on the same line we started on, then this
@ -361,14 +361,13 @@ MARK v_insert(m, cnt, key)
{
int wasdot;
long reps;
int above; /* boolean: new line going above old line? */
int delta = 0;/* 1 to take autoindent from line below, -1 for above */
DEFAULT(1);
ChangeText
{
/* tweak the insertion point, based on command key */
above = FALSE;
switch (key)
{
case 'i':
@ -394,19 +393,20 @@ MARK v_insert(m, cnt, key)
case 'O':
m &= ~(BLKSIZE - 1);
add(m, "\n");
above = TRUE;
delta = 1;
break;
case 'o':
m = (m & ~(BLKSIZE - 1)) + BLKSIZE;
add(m, "\n");
delta = -1;
break;
}
/* insert the same text once or more */
for (reps = cnt, wasdot = doingdot; reps > 0; reps--, doingdot = TRUE)
{
m = input(m, m, WHEN_VIINP, above) + 1;
m = input(m, m, WHEN_VIINP, delta) + 1;
}
if (markidx(m) > 0)
{
@ -455,7 +455,7 @@ MARK v_change(m, n)
ChangeText
{
cut(m, n);
m = input(m, n, WHEN_VIINP, FALSE);
m = input(m, n, WHEN_VIINP, 0);
}
return m;
@ -479,7 +479,7 @@ MARK v_subst(m, cnt)
ChangeText
{
cut(m, m + cnt);
m = input(m, m + cnt, WHEN_VIINP, FALSE);
m = input(m, m + cnt, WHEN_VIINP, 0);
}
return m;
}
@ -964,12 +964,24 @@ MARK v_popup(m, n)
break;
}
/* arrange for the menu to be erased (except that "chg from kbd"
* already erased it, and "save & exit" doesn't care)
/* arrange for the menu to be erased (except "save & exit" doesn't care)
*/
if (sel != 5 && sel != 9)
if (mode == MODE_VI)
redraw(MARK_UNSET, FALSE);
return m;
}
#endif /* undef NO_POPUP */
#ifndef NO_TAGSTACK
MARK v_pop(m, cnt, cmd)
MARK m; /* original cursor position (ignored) */
long cnt; /* number of levels to pop */
int cmd; /* command key -- ^T (ignored) */
{
DEFAULT(1L);
sprintf(tmpblk.c, "%ld", cnt);
cmd_pop(m, m, CMD_POP, FALSE, tmpblk.c);
return cursor;
}
#endif

View File

@ -73,7 +73,11 @@ static struct keystru
/* ^Q not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
/* ^R redraw screen */ {v_redraw, NO_ARGS, NO_FLAGS|VIZ},
/* ^S not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
#ifndef NO_TAGSTACK
/* ^T pop tagstack */ {v_pop, CURSOR, NO_FLAGS},
#else
/* ^T not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
#endif
/* ^U scroll up 1/2page*/ {m_scroll, CURSOR, NCOL|VIZ},
/* ^V not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
/* ^W not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
@ -87,7 +91,7 @@ static struct keystru
/* ESC not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
/* ^\ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
/* ^] keyword is tag */ {v_tag, KEYWORD, NO_FLAGS},
/* ^^ previous file */ {v_switch, CURSOR, NO_FLAGS},
/* ^^ previous file */ {v_switch, CURSOR, FRNT},
/* ^_ not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
/* SPC move right,like l*/ {m_right, CURSOR, MVMT|INCL|VIZ},
/* ! run thru filter */ {v_filter, CURSOR_MOVED, FRNT|LNMD|INCL|VIZ},
@ -168,7 +172,7 @@ static struct keystru
#endif
/* L move to last row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},
/* M move to mid row */ {m_row, CURSOR, MVMT|LNMD|FRNT|VIZ|INCL},
/* N reverse prev srch*/ {m_Nsrch, CURSOR, MVMT|NREL|VIZ},
/* N reverse prev srch*/ {m_nsrch, CURSOR, MVMT|NREL|VIZ},
/* O insert above line*/ {v_insert, CURSOR, SDOT},
/* P paste before */ {v_paste, CURSOR, SDOT},
/* Q quit to EX mode */ {v_quit, NO_ARGS, NO_FLAGS},
@ -185,7 +189,7 @@ static struct keystru
#else
/* V not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
#endif
/* W move forward Word*/ {m_fword, CURSOR, MVMT|INCL|VIZ},
/* W move forward Word*/ {m_fword, CURSOR, MVMT|INCL|NWRP|VIZ},
/* X delete to left */ {v_xchar, CURSOR, SDOT},
/* Y yank text */ {v_yank, CURSOR_MOVED, NCOL},
/* Z save file & exit */ {v_xit, CURSOR_CNT_KEY, NO_FLAGS},
@ -233,13 +237,13 @@ static struct keystru
#else
/* v not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS},
#endif
/* w move fwd word */ {m_fword, CURSOR, MVMT|INCL|VIZ},
/* w move fwd word */ {m_fword, CURSOR, MVMT|INCL|NWRP|VIZ},
/* x delete character */ {v_xchar, CURSOR, SDOT},
/* y yank text */ {v_yank, CURSOR_MOVED, NCOL|VIZ},
/* z adjust scrn row */ {m_z, CURSOR_CNT_KEY, NCOL|VIZ},
/* { back paragraph */ {m_paragraph, CURSOR, MVMT|LNMD|VIZ},
/* { back paragraph */ {m_paragraph, CURSOR, MVMT|VIZ},
/* | move to column */ {m_tocol, CURSOR, MVMT|NREL|VIZ},
/* } fwd paragraph */ {m_paragraph, CURSOR, MVMT|LNMD|VIZ},
/* } fwd paragraph */ {m_paragraph, CURSOR, MVMT|VIZ},
/* ~ upper/lowercase */ {v_ulcase, CURSOR, SDOT},
/* DEL not defined */ {NO_FUNC, NO_ARGS, NO_FLAGS}
};
@ -316,6 +320,9 @@ void vi()
key = getkey(WHEN_VICMD);
} while (key < 0 || key > 127);
}
#ifdef DEBUG2
debout("\nkey='%c'\n", key);
#endif
/* Convert a doubled-up operator such as "dd" into "d_" */
if (prevkey && key == prevkey)
@ -551,7 +558,8 @@ void vi()
do
{
text[0] = key;
if (vgets(key, text + 1, sizeof text - 1) >= 0)
text[1] = '\0';
if (doingdot || vgets(key, text + 1, sizeof text - 1) >= 0)
{
/* reassure user that <CR> was hit */
qaddch('\r');
@ -583,16 +591,25 @@ void vi()
}
/* now move the cursor, as appropriate */
if (keyptr->args == CURSOR_MOVED)
if (prevkey && ((keyptr->flags & MVMT)
#ifndef NO_VISIBLE
|| V_from
#endif
) && count == 0L)
{
/* movements used as targets are less strict */
tcurs = adjmove(cursor, tcurs, (int)(keyptr->flags | force_flags));
}
else if (keyptr->args == CURSOR_MOVED)
{
/* the < and > keys have FRNT,
* but it shouldn't be applied yet
*/
tcurs = adjmove(cursor, tcurs, 0);
tcurs = adjmove(cursor, tcurs, FINL);
}
else
{
tcurs = adjmove(cursor, tcurs, (int)keyptr->flags | force_flags);
tcurs = adjmove(cursor, tcurs, (int)(keyptr->flags | force_flags | FINL));
}
/* was that the end of a d/c/y/</>/! command? */
@ -629,7 +646,7 @@ void vi()
* to the front of a line. Instead, they should take
* us only to the end of the preceding line.
*/
if ((keyptr->flags & (MVMT|NREL|LNMD|FRNT|INCL)) == MVMT
if ((keyptr->flags & NWRP) == NWRP
&& markline(range) < markline(tcurs)
&& (markline(tcurs) > nlines || tcurs == m_front(tcurs, 0L)))
{
@ -660,8 +677,8 @@ void vi()
tcurs = (*vikeys[prevkey].func)(range, tcurs);
if (mode == MODE_VI)
{
(void)adjmove(cursor, cursor, 0);
cursor = adjmove(cursor, tcurs, (int)vikeys[prevkey].flags);
(void)adjmove(cursor, cursor, FINL);
cursor = adjmove(cursor, tcurs, (int)(vikeys[prevkey].flags | FINL));
}
/* cleanup */
@ -688,6 +705,9 @@ MARK adjmove(old, new, flags)
REG char *text; /* used to scan through the line's text */
REG int i;
#ifdef DEBUG2
debout("adjmove(%ld.%d, %ld.%d, 0x%x)\n", markline(old), markidx(old), markline(new), markidx(new), flags);
#endif
#ifdef DEBUG
watch();
#endif
@ -695,8 +715,12 @@ MARK adjmove(old, new, flags)
/* if the command failed, bag it! */
if (new == MARK_UNSET)
{
beep();
return old;
if (flags & FINL)
{
beep();
return old;
}
return new;
}
/* if this is a non-relative movement, set the '' mark */
@ -712,6 +736,10 @@ MARK adjmove(old, new, flags)
}
else if (markline(new) > nlines)
{
if (!(flags & FINL))
{
return MARK_EOF;
}
new = MARK_LAST;
}

View File

@ -7,13 +7,14 @@
* kirkenda@cs.pdx.edu
*/
#define VERSION "ELVIS 1.5, by Steve Kirkendall (23 March 1992)"
#define VERSION "ELVIS 1.7, by Steve Kirkendall (30 December 1992)"
#define COPYING "This version of ELVIS is freely redistributable."
#include <errno.h>
extern int errno;
#if TOS && !defined(__GNUC__)
#define ENOENT (-AEFILNF)
#if TOS
# ifndef __GNUC__
# define ENOENT (-AEFILNF)
# endif
#endif
#if TOS || VMS
@ -33,8 +34,10 @@ extern int errno;
# define ENOENT E_PNNF
# define sprintf Sprintf
# else
# include <sys/types.h>
# if COHERENT
# if !AMIGA
# include <sys/types.h>
# endif
# if COH_286
# include <sys/fcntl.h>
# else
# include <fcntl.h>
@ -49,6 +52,16 @@ extern int errno;
#include "curses.h"
#include <signal.h>
#ifdef __STDC__
# include <stdio.h> /* for [v]sprintf prototype */
# include <string.h> /* for str* prototypes */
# include <stdlib.h> /* for atoi, system, malloc, free */
# include <stdarg.h> /* for vararg definitions */
# if ANY_UNIX
# include <unistd.h> /* for read, write, ... prototypes */
# include <sys/wait.h> /* for wait prototype */
# endif
#endif
/*------------------------------------------------------------------------*/
/* Miscellaneous constants. */
@ -74,8 +87,8 @@ typedef union
/* These are used manipulate BLK buffers. */
extern BLK hdr; /* buffer for the header block */
extern BLK *blkget(); /* given index into hdr.c[], reads block */
extern BLK *blkadd(); /* inserts a new block into hdr.c[] */
extern BLK *blkget P_((int)); /* given index into hdr.c[], reads block */
extern BLK *blkadd P_((int)); /* inserts a new block into hdr.c[] */
/*------------------------------------------------------------------------*/
/* These are used to keep track of various flags */
@ -138,9 +151,11 @@ extern char o_beautify[1];
extern char o_exrc[1];
extern char o_mesg[1];
extern char o_more[1];
extern char o_nearscroll[3];
extern char o_novice[1];
extern char o_prompt[1];
extern char o_taglength[3];
extern char o_tags[256];
extern char o_terse[1];
extern char o_window[3];
extern char o_wrapmargin[3];
@ -195,6 +210,10 @@ extern char o_showmatch[1];
extern char o_smd[1];
#endif
#ifndef NO_TAGSTACK
extern char o_tagstack[1];
#endif
/*------------------------------------------------------------------------*/
/* These help support the single-line multi-change "undo" -- shift-U */
@ -210,6 +229,7 @@ typedef long MARK;
#define MARK_UNSET ((MARK)0)
#define MARK_FIRST ((MARK)BLKSIZE)
#define MARK_LAST ((MARK)(nlines * BLKSIZE))
#define MARK_EOF ((MARK)((nlines + 1) * BLKSIZE))
#define MARK_AT_LINE(x) ((MARK)(x) * BLKSIZE)
#define NMARKS 29
@ -227,78 +247,101 @@ extern long prevline; /* line number from preceding file */
/*------------------------------------------------------------------------*/
/* misc housekeeping variables & functions */
extern int tmpfd; /* fd used to access the tmp file */
extern int tmpnum; /* counter used to generate unique filenames */
extern long lnum[MAXBLKS]; /* last line# of each block */
extern long nlines; /* number of lines in the file */
extern char args[BLKSIZE]; /* file names given on the command line */
extern int argno; /* the current element of args[] */
extern int nargs; /* number of filenames in args */
extern long changes; /* counts changes, to prohibit short-cuts */
extern int significant; /* boolean: was a *REAL* change made? */
extern BLK tmpblk; /* a block used to accumulate changes */
extern long topline; /* file line number of top line */
extern int leftcol; /* column number of left col */
extern int tmpfd; /* fd used to access the tmp file */
extern int tmpnum; /* counter used to generate unique filenames */
extern long lnum[MAXBLKS]; /* last line# of each block */
extern long nlines; /* number of lines in the file */
extern char args[BLKSIZE]; /* file names given on the command line */
extern int argno; /* the current element of args[] */
extern int nargs; /* number of filenames in args */
extern long changes; /* counts changes, to prohibit short-cuts */
extern int significant; /* boolean: was a *REAL* change made? */
extern int exitcode; /* 0=not updated, 1=overwritten, else error */
extern BLK tmpblk; /* a block used to accumulate changes */
extern long topline; /* file line number of top line */
extern int leftcol; /* column number of left col */
#define botline (topline + LINES - 2)
#define rightcol (leftcol + COLS - (*o_number ? 9 : 1))
extern int physcol; /* physical column number that cursor is on */
extern int physrow; /* physical row number that cursor is on */
extern int exwrote; /* used to detect verbose ex commands */
extern int doingdot; /* boolean: are we doing the "." command? */
extern int doingglobal; /* boolean: are doing a ":g" command? */
extern long rptlines; /* number of lines affected by a command */
extern char *rptlabel; /* description of how lines were affected */
extern char *fetchline(); /* read a given line from tmp file */
extern char *parseptrn(); /* isolate a regexp in a line */
extern MARK paste(); /* paste from cut buffer to a given point */
extern char *wildcard(); /* expand wildcards in filenames */
extern MARK input(); /* inserts characters from keyboard */
extern char *linespec(); /* finds the end of a /regexp/ string */
extern int physcol; /* physical column number that cursor is on */
extern int physrow; /* physical row number that cursor is on */
extern int exwrote; /* used to detect verbose ex commands */
extern int doingdot; /* boolean: are we doing the "." command? */
extern int doingglobal; /* boolean: are doing a ":g" command? */
extern long rptlines; /* number of lines affected by a command */
extern char *rptlabel; /* description of how lines were affected */
extern char *fetchline P_((long)); /* read a given line from tmp file */
extern char *parseptrn P_((REG char *)); /* isolate a regexp in a line */
extern MARK paste P_((MARK, int, int)); /* paste from cut buffer to a given point */
extern char *wildcard P_((char *)); /* expand wildcards in filenames */
extern MARK input P_((MARK, MARK, int, int)); /* inserts characters from keyboard */
extern char *linespec P_((REG char *, MARK *)); /* finds the end of a /regexp/ string */
#define ctrl(ch) ((ch)&037)
#ifndef NO_RECYCLE
extern long allocate(); /* allocate a free block of the tmp file */
extern long allocate P_((void)); /* allocate a free block of the tmp file */
#endif
extern int trapint(); /* trap handler for SIGINT */
extern int deathtrap(); /* trap handler for deadly signals */
extern void blkdirty(); /* marks a block as being "dirty" */
extern void blkflush(); /* writes a single dirty block to the disk */
extern void blksync(); /* forces all "dirty" blocks to disk */
extern void blkinit(); /* resets the block cache to "empty" state */
extern void beep(); /* rings the terminal's bell */
extern void exrefresh(); /* writes text to the screen */
extern void msg(); /* writes a printf-style message to the screen */
extern void endmsgs(); /* if "manymsgs" is set, then scroll up 1 line */
extern void garbage(); /* reclaims any garbage blocks */
extern void redraw(); /* updates the screen after a change */
extern void resume_curses();/* puts the terminal in "cbreak" mode */
extern void beforedo(); /* saves current revision before a new change */
extern void afterdo(); /* marks end of a beforedo() change */
extern void abortdo(); /* like "afterdo()" followed by "undo()" */
extern int undo(); /* restores file to previous undo() */
extern void dumpkey(); /* lists key mappings to the screen */
extern void mapkey(); /* defines a new key mapping */
extern void savekeys(); /* lists key mappings to a file */
extern void redrawrange(); /* records clues from modify.c */
extern void cut(); /* saves text in a cut buffer */
extern void delete(); /* deletes text */
extern void add(); /* adds text */
extern void change(); /* deletes text, and then adds other text */
extern void cutswitch(); /* updates cut buffers when we switch files */
extern void do_abbr(); /* defines or lists abbreviations */
extern void do_digraph(); /* defines or lists digraphs */
extern void exstring(); /* execute a string as EX commands */
extern void dumpopts();
extern void setopts();
extern void saveopts();
extern void savedigs();
extern void saveabbr();
extern void savecolor();
extern void cutname();
extern void cutname();
extern void initopts();
extern void cutend();
extern SIGTYPE trapint P_((int)); /* trap handler for SIGINT */
extern SIGTYPE deathtrap P_((int)); /* trap handler for deadly signals */
extern void blkdirty P_((BLK *)); /* marks a block as being "dirty" */
extern void blksync P_((void)); /* forces all "dirty" blocks to disk */
extern void blkinit P_((void)); /* resets the block cache to "empty" state */
extern void beep P_((void)); /* rings the terminal's bell */
extern void exrefresh P_((void)); /* writes text to the screen */
#ifdef __STDC__
extern void msg (char *, ...); /* writes a printf-style message to the screen */
#else
extern void msg (); /* writes a printf-style message to the screen */
#endif
extern void endmsgs P_((void)); /* if "manymsgs" is set, then scroll up 1 line */
extern void garbage P_((void)); /* reclaims any garbage blocks */
extern void redraw P_((MARK, int)); /* updates the screen after a change */
extern void resume_curses P_((int)); /* puts the terminal in "cbreak" mode */
extern void beforedo P_((int)); /* saves current revision before a new change */
extern void afterdo P_((void)); /* marks end of a beforedo() change */
extern void abortdo P_((void)); /* like "afterdo()" followed by "undo()" */
extern int undo P_((void)); /* restores file to previous undo() */
extern void dumpkey P_((int, int)); /* lists key mappings to the screen */
extern void mapkey P_((char *, char *, int, char *)); /* defines a new key mapping */
extern void redrawrange P_((long, long, long)); /* records clues from modify.c */
extern void cut P_((MARK, MARK)); /* saves text in a cut buffer */
extern void delete P_((MARK, MARK)); /* deletes text */
extern void add P_((MARK, char *)); /* adds text */
extern void change P_((MARK, MARK, char *));/* deletes text, and then adds other text */
extern void cutswitch P_((void)); /* updates cut buffers when we switch files */
extern void do_digraph P_((int, char [])); /* defines or lists digraphs */
extern void exstring P_((char *, int, int));/* execute a string as EX commands */
extern void dumpopts P_((int)); /* display current option settings on the screen */
extern void setopts P_((char *)); /* assign new values to options */
extern void saveopts P_((int)); /* save current option values to a given fd */
extern void savedigs P_((int)); /* save current non-standard digraphs to fd */
extern void savecolor P_((int)); /* save current color settings (if any) to fd */
extern void cutname P_((int)); /* select cut buffer for next cut/paste */
extern void initopts P_((void)); /* initialize options */
extern void cutend P_((void)); /* free all cut buffers & delete temp files */
extern int storename P_((char *)); /* stamp temp file with pathname of text file */
extern int tmpstart P_((char *)); /* load a text file into edit buffer */
extern int tmpsave P_((char *, int)); /* write edit buffer out to text file */
extern int tmpend P_((int)); /* call tmpsave(), and then tmpabort */
extern int tmpabort P_((int)); /* abandon the current edit buffer */
extern void savemaps P_((int, int)); /* write current :map or :ab commands to fd */
extern int ansicolor P_((int, int)); /* emit ANSI color command to terminal */
extern int filter P_((MARK, MARK, char *, int)); /* I/O though another program */
extern int getkey P_((int)); /* return a keystroke, interpretting maps */
extern int vgets P_((int, char *, int)); /* read a single line from keyboard */
extern int doexrc P_((char *)); /* execute a string as a sequence of EX commands */
extern int cb2str P_((int, char *, unsigned));/* return a string containing cut buffer's contents */
extern int ansiquit P_((void)); /* neutralize previous ansicolor() call */
extern int ttyread P_((char *, int, int)); /* read from keyboard with optional timeout */
extern int tgetent P_((char *, char *)); /* start termcap */
extern int tgetnum P_((char *)); /* get a termcap number */
extern int tgetflag P_((char *)); /* get a termcap boolean */
extern int getsize P_((int)); /* determine how big the screen is */
extern int endcolor P_((void)); /* used during color output */
extern int getabkey P_((int, char *, int));/* like getkey(), but also does abbreviations */
extern int idx2col P_((MARK, REG char *, int)); /* returns column# of a given MARK */
extern int cutneeds P_((BLK *)); /* returns bitmap of blocks needed to hold cutbuffer text */
extern void execmap P_((int, char *, int)); /* replaces "raw" keys with "mapped" keys */
#ifndef CRUNCH
extern int wset; /* boolean: has the "window" size been set? */
extern int wset; /* boolean: has the "window" size been set? */
#endif
/*------------------------------------------------------------------------*/
@ -313,42 +356,41 @@ extern int bavar; /* used only in BeforeAfter macros */
/* These are the movement commands. Each accepts a mark for the starting */
/* location & number and returns a mark for the destination. */
extern MARK m_updnto(); /* k j G */
extern MARK m_right(); /* h */
extern MARK m_left(); /* l */
extern MARK m_tocol(); /* | */
extern MARK m_front(); /* ^ */
extern MARK m_rear(); /* $ */
extern MARK m_fword(); /* w */
extern MARK m_bword(); /* b */
extern MARK m_eword(); /* e */
extern MARK m_paragraph(); /* { } [[ ]] */
extern MARK m_match(); /* % */
extern MARK m_updnto P_((MARK, long, int)); /* k j G */
extern MARK m_right P_((MARK, long, int, int)); /* h */
extern MARK m_left P_((MARK, long)); /* l */
extern MARK m_tocol P_((MARK, long, int)); /* | */
extern MARK m_front P_((MARK, long)); /* ^ */
extern MARK m_rear P_((MARK, long)); /* $ */
extern MARK m_fword P_((MARK, long, int, int)); /* w */
extern MARK m_bword P_((MARK, long, int)); /* b */
extern MARK m_eword P_((MARK, long, int)); /* e */
extern MARK m_paragraph P_((MARK, long, int)); /* { } [[ ]] */
extern MARK m_match P_((MARK, long)); /* % */
#ifndef NO_SENTENCE
extern MARK m_sentence(); /* ( ) */
extern MARK m_sentence P_((MARK, long, int)); /* ( ) */
#endif
extern MARK m_tomark(); /* 'm */
extern MARK m_tomark P_((MARK, long, int)); /* 'm */
#ifndef NO_EXTENSIONS
extern MARK m_wsrch(); /* ^A */
extern MARK m_wsrch P_((char *, MARK, int)); /* ^A */
#endif
extern MARK m_nsrch(); /* n */
extern MARK m_Nsrch(); /* N */
extern MARK m_fsrch(); /* /regexp */
extern MARK m_bsrch(); /* ?regexp */
extern MARK m_nsrch P_((MARK, long, int)); /* n */
extern MARK m_fsrch P_((MARK, char *)); /* /regexp */
extern MARK m_bsrch P_((MARK, char *)); /* ?regexp */
#ifndef NO_CHARSEARCH
extern MARK m__ch(); /* ; , */
extern MARK m_fch(); /* f */
extern MARK m_tch(); /* t */
extern MARK m_Fch(); /* F */
extern MARK m_Tch(); /* T */
extern MARK m__ch P_((MARK, long, int)); /* ; , */
extern MARK m_fch P_((MARK, long, int)); /* f */
extern MARK m_tch P_((MARK, long, int)); /* t */
extern MARK m_Fch P_((MARK, long, int)); /* F */
extern MARK m_Tch P_((MARK, long, int)); /* T */
#endif
extern MARK m_row(); /* H L M */
extern MARK m_z(); /* z */
extern MARK m_scroll(); /* ^B ^F ^E ^Y ^U ^D */
extern MARK m_row P_((MARK, long, int)); /* H L M */
extern MARK m_z P_((MARK, long, int)); /* z */
extern MARK m_scroll P_((MARK, long, int)); /* ^B ^F ^E ^Y ^U ^D */
/* Some stuff that is used by movement functions... */
extern MARK adjmove(); /* a helper fn, used by move fns */
extern MARK adjmove P_((MARK, REG MARK, int)); /* a helper fn, used by move fns */
/* This macro is used to set the default value of cnt */
#define DEFAULT(val) if (cnt < 1) cnt = (val)
@ -358,8 +400,8 @@ extern int plen; /* length of the line */
extern long pline; /* line number that len refers to */
extern long pchgs; /* "changes" level that len refers to */
extern char *ptext; /* text of previous line, if valid */
extern void pfetch();
extern char digraph();
extern void pfetch P_((long));
extern char digraph P_((int, int));
/* This is used to build a MARK that corresponds to a specific point in the
* line that was most recently pfetch'ed.
@ -370,169 +412,174 @@ extern char digraph();
/*------------------------------------------------------------------------*/
/* These are used to handle EX commands. */
#define CMD_NULL 0 /* NOT A VALID COMMAND */
#define CMD_ABBR 1 /* "define an abbreviation" */
#define CMD_ARGS 2 /* "show me the args" */
#define CMD_APPEND 3 /* "insert lines after this line" */
#define CMD_AT 4 /* "execute a cut buffer's contents via EX" */
#define CMD_BANG 5 /* "run a single shell command" */
#define CMD_CC 6 /* "run `cc` and then do CMD_ERRLIST" */
#define CMD_CD 7 /* "change directories" */
#define CMD_CHANGE 8 /* "change some lines" */
#define CMD_COLOR 9 /* "change the default colors" */
#define CMD_COPY 10 /* "copy the selected text to a given place" */
#define CMD_DELETE 11 /* "delete the selected text" */
#define CMD_DIGRAPH 12 /* "add a digraph, or display them all" */
#define CMD_EDIT 13 /* "switch to a different file" */
#define CMD_EQUAL 14 /* "display a line number" */
#define CMD_ERRLIST 15 /* "locate the next error in a list" */
#define CMD_FILE 16 /* "show the file's status" */
#define CMD_GLOBAL 17 /* "globally search & do a command" */
#define CMD_INSERT 18 /* "insert lines before the current line" */
#define CMD_JOIN 19 /* "join the selected line & the one after" */
#define CMD_LIST 20 /* "print lines, making control chars visible" */
#define CMD_MAKE 21 /* "run `make` and then do CMD_ERRLIST" */
#define CMD_MAP 22 /* "adjust the keyboard map" */
#define CMD_MARK 23 /* "mark this line" */
#define CMD_MKEXRC 24 /* "make a .exrc file" */
#define CMD_MOVE 25 /* "move the selected text to a given place" */
#define CMD_NEXT 26 /* "switch to next file in args" */
#define CMD_NUMBER 27 /* "print lines from the file w/ line numbers" */
#define CMD_PRESERVE 28 /* "act as though vi crashed" */
#define CMD_PREVIOUS 29 /* "switch to the previous file in args" */
#define CMD_PRINT 30 /* "print the selected text" */
#define CMD_PUT 31 /* "insert any cut lines before this line" */
#define CMD_QUIT 32 /* "quit without writing the file" */
#define CMD_READ 33 /* "append the given file after this line */
#define CMD_RECOVER 34 /* "recover file after vi crashes" - USE -r FLAG */
#define CMD_REWIND 35 /* "rewind to first file" */
#define CMD_SET 36 /* "set a variable's value" */
#define CMD_SHELL 37 /* "run some lines through a command" */
#define CMD_SHIFTL 38 /* "shift lines left" */
#define CMD_SHIFTR 39 /* "shift lines right" */
#define CMD_SOURCE 40 /* "interpret a file's contents as ex commands" */
#define CMD_STOP 41 /* same as CMD_SUSPEND */
#define CMD_SUBAGAIN 42 /* "repeat the previous substitution" */
#define CMD_SUBSTITUTE 43 /* "substitute text in this line" */
#define CMD_SUSPEND 44 /* "suspend the vi session" */
#define CMD_TR 45 /* "transliterate chars in the selected lines" */
#define CMD_TAG 46 /* "go to a particular tag" */
#define CMD_UNABBR 47 /* "remove an abbreviation definition" */
#define CMD_UNDO 48 /* "undo the previous command" */
#define CMD_UNMAP 49 /* "remove a key sequence map */
#define CMD_VERSION 50 /* "describe which version this is" */
#define CMD_VGLOBAL 51 /* "apply a cmd to lines NOT containing an RE" */
#define CMD_VISUAL 52 /* "go into visual mode" */
#define CMD_WQUIT 53 /* "write this file out (any case) & quit" */
#define CMD_WRITE 54 /* "write the selected(?) text to a given file" */
#define CMD_XIT 55 /* "write this file out (if modified) & quit" */
#define CMD_YANK 56 /* "copy the selected text into the cut buffer" */
#ifdef DEBUG
# define CMD_DEBUG 57 /* access to internal data structures */
# define CMD_VALIDATE 58 /* check for internal consistency */
#endif
#define CMD_NULL 0 /* NOT A VALID COMMAND */
#define CMD_ABBR 1 /* "define an abbreviation" */
#define CMD_ARGS 2 /* "show me the args" */
#define CMD_APPEND 3 /* "insert lines after this line" */
#define CMD_AT 4 /* "execute a cut buffer's contents via EX" */
#define CMD_BANG 5 /* "run a single shell command" */
#define CMD_CC 6 /* "run `cc` and then do CMD_ERRLIST" */
#define CMD_CD 7 /* "change directories" */
#define CMD_CHANGE 8 /* "change some lines" */
#define CMD_COLOR 9 /* "change the default colors" */
#define CMD_COPY 10 /* "copy the selected text to a given place" */
#define CMD_DELETE 11 /* "delete the selected text" */
#define CMD_DIGRAPH 12 /* "add a digraph, or display them all" */
#define CMD_EDIT 13 /* "switch to a different file" */
#define CMD_EQUAL 14 /* "display a line number" */
#define CMD_ERRLIST 15 /* "locate the next error in a list" */
#define CMD_FILE 16 /* "show the file's status" */
#define CMD_GLOBAL 17 /* "globally search & do a command" */
#define CMD_INSERT 18 /* "insert lines before the current line" */
#define CMD_JOIN 19 /* "join the selected line & the one after" */
#define CMD_LIST 20 /* "print lines, making control chars visible" */
#define CMD_MAKE 21 /* "run `make` and then do CMD_ERRLIST" */
#define CMD_MAP 22 /* "adjust the keyboard map" */
#define CMD_MARK 23 /* "mark this line" */
#define CMD_MKEXRC 24 /* "make a .exrc file" */
#define CMD_MOVE 25 /* "move the selected text to a given place" */
#define CMD_NEXT 26 /* "switch to next file in args" */
#define CMD_NUMBER 27 /* "print lines from the file w/ line numbers" */
#define CMD_POP 28 /* "pop a position off the tagstack" */
#define CMD_PRESERVE 29 /* "act as though vi crashed" */
#define CMD_PREVIOUS 30 /* "switch to the previous file in args" */
#define CMD_PRINT 31 /* "print the selected text" */
#define CMD_PUT 32 /* "insert any cut lines before this line" */
#define CMD_QUIT 33 /* "quit without writing the file" */
#define CMD_READ 34 /* "append the given file after this line */
#define CMD_RECOVER 35 /* "recover file after vi crashes" - USE -r FLAG */
#define CMD_REWIND 36 /* "rewind to first file" */
#define CMD_SET 37 /* "set a variable's value" */
#define CMD_SHELL 38 /* "run some lines through a command" */
#define CMD_SHIFTL 39 /* "shift lines left" */
#define CMD_SHIFTR 40 /* "shift lines right" */
#define CMD_SOURCE 41 /* "interpret a file's contents as ex commands" */
#define CMD_STOP 42 /* same as CMD_SUSPEND */
#define CMD_SUBAGAIN 43 /* "repeat the previous substitution" */
#define CMD_SUBSTITUTE 44 /* "substitute text in this line" */
#define CMD_SUSPEND 45 /* "suspend the vi session" */
#define CMD_TR 46 /* "transliterate chars in the selected lines" */
#define CMD_TAG 47 /* "go to a particular tag" */
#define CMD_UNABBR 48 /* "remove an abbreviation definition" */
#define CMD_UNDO 49 /* "undo the previous command" */
#define CMD_UNMAP 50 /* "remove a key sequence map */
#define CMD_VERSION 51 /* "describe which version this is" */
#define CMD_VGLOBAL 52 /* "apply a cmd to lines NOT containing an RE" */
#define CMD_VISUAL 53 /* "go into visual mode" */
#define CMD_WQUIT 54 /* "write this file out (any case) & quit" */
#define CMD_WRITE 55 /* "write the selected(?) text to a given file" */
#define CMD_XIT 56 /* "write this file out (if modified) & quit" */
#define CMD_YANK 57 /* "copy the selected text into the cut buffer" */
#define CMD_DEBUG 58 /* access to internal data structures */
#define CMD_VALIDATE 59 /* check for internal consistency */
typedef int CMD;
extern void ex();
extern void vi();
extern void doexcmd();
extern void ex P_((void));
extern void vi P_((void));
extern void doexcmd P_((char *));
extern void cmd_append();
extern void cmd_args();
extern void cmd_append P_((MARK, MARK, CMD, int, char *));
extern void cmd_args P_((MARK, MARK, CMD, int, char *));
#ifndef NO_AT
extern void cmd_at();
extern void cmd_at P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_cd();
extern void cmd_cd P_((MARK, MARK, CMD, int, char *));
#ifndef NO_COLOR
extern void cmd_color();
extern void cmd_color P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_delete();
extern void cmd_delete P_((MARK, MARK, CMD, int, char *));
#ifndef NO_DIGRAPH
extern void cmd_digraph();
extern void cmd_digraph P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_edit();
extern void cmd_edit P_((MARK, MARK, CMD, int, char *));
#ifndef NO_ERRLIST
extern void cmd_errlist();
extern void cmd_errlist P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_file();
extern void cmd_global();
extern void cmd_join();
extern void cmd_mark();
extern void cmd_file P_((MARK, MARK, CMD, int, char *));
extern void cmd_global P_((MARK, MARK, CMD, int, char *));
extern void cmd_join P_((MARK, MARK, CMD, int, char *));
extern void cmd_mark P_((MARK, MARK, CMD, int, char *));
#ifndef NO_ERRLIST
extern void cmd_make();
extern void cmd_make P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_map();
extern void cmd_map P_((MARK, MARK, CMD, int, char *));
#ifndef NO_MKEXRC
extern void cmd_mkexrc();
extern void cmd_mkexrc P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_next();
extern void cmd_print();
extern void cmd_put();
extern void cmd_read();
extern void cmd_set();
extern void cmd_shell();
extern void cmd_shift();
extern void cmd_source();
extern void cmd_substitute();
extern void cmd_tag();
extern void cmd_undo();
extern void cmd_version();
extern void cmd_write();
extern void cmd_xit();
extern void cmd_move();
extern void cmd_next P_((MARK, MARK, CMD, int, char *));
#ifndef NO_TAGSTACK
extern void cmd_pop P_((MARK, MARK, CMD, int, char *));
#endif
extern void cmd_print P_((MARK, MARK, CMD, int, char *));
extern void cmd_put P_((MARK, MARK, CMD, int, char *));
extern void cmd_read P_((MARK, MARK, CMD, int, char *));
extern void cmd_set P_((MARK, MARK, CMD, int, char *));
extern void cmd_shell P_((MARK, MARK, CMD, int, char *));
extern void cmd_shift P_((MARK, MARK, CMD, int, char *));
extern void cmd_source P_((MARK, MARK, CMD, int, char *));
extern void cmd_substitute P_((MARK, MARK, CMD, int, char *));
extern void cmd_tag P_((MARK, MARK, CMD, int, char *));
extern void cmd_undo P_((MARK, MARK, CMD, int, char *));
extern void cmd_version P_((MARK, MARK, CMD, int, char *));
extern void cmd_write P_((MARK, MARK, CMD, int, char *));
extern void cmd_xit P_((MARK, MARK, CMD, int, char *));
extern void cmd_move P_((MARK, MARK, CMD, int, char *));
#ifdef DEBUG
extern void cmd_debug();
extern void cmd_validate();
extern void cmd_debug P_((MARK, MARK, CMD, int, char *));
extern void cmd_validate P_((MARK, MARK, CMD, int, char *));
#endif
#ifdef SIGTSTP
extern void cmd_suspend();
extern void cmd_suspend P_((MARK, MARK, CMD, int, char *));
#endif
/*----------------------------------------------------------------------*/
/* These are used to handle VI commands */
extern MARK v_1ex(); /* : */
extern MARK v_mark(); /* m */
extern MARK v_quit(); /* Q */
extern MARK v_redraw(); /* ^L ^R */
extern MARK v_ulcase(); /* ~ */
extern MARK v_undo(); /* u */
extern MARK v_xchar(); /* x X */
extern MARK v_replace(); /* r */
extern MARK v_overtype(); /* R */
extern MARK v_selcut(); /* " */
extern MARK v_paste(); /* p P */
extern MARK v_yank(); /* y Y */
extern MARK v_delete(); /* d D */
extern MARK v_join(); /* J */
extern MARK v_insert(); /* a A i I o O */
extern MARK v_change(); /* c C */
extern MARK v_subst(); /* s */
extern MARK v_lshift(); /* < */
extern MARK v_rshift(); /* > */
extern MARK v_reformat(); /* = */
extern MARK v_filter(); /* ! */
extern MARK v_status(); /* ^G */
extern MARK v_switch(); /* ^^ */
extern MARK v_tag(); /* ^] */
extern MARK v_xit(); /* ZZ */
extern MARK v_undoline(); /* U */
extern MARK v_again(); /* & */
extern MARK v_1ex P_((MARK, char *)); /* : */
extern MARK v_mark P_((MARK, long, int)); /* m */
extern MARK v_quit P_((void)); /* Q */
extern MARK v_redraw P_((void)); /* ^L ^R */
extern MARK v_ulcase P_((MARK, long)); /* ~ */
extern MARK v_undo P_((MARK)); /* u */
extern MARK v_xchar P_((MARK, long, int)); /* x X */
extern MARK v_replace P_((MARK, long, int));/* r */
extern MARK v_overtype P_((MARK)); /* R */
extern MARK v_selcut P_((MARK, long, int)); /* " */
extern MARK v_paste P_((MARK, long, int)); /* p P */
extern MARK v_yank P_((MARK, MARK)); /* y Y */
extern MARK v_delete P_((MARK, MARK)); /* d D */
extern MARK v_join P_((MARK, long)); /* J */
extern MARK v_insert P_((MARK, long, int)); /* a A i I o O */
extern MARK v_change P_((MARK, MARK)); /* c C */
extern MARK v_subst P_((MARK, long)); /* s */
extern MARK v_lshift P_((MARK, MARK)); /* < */
extern MARK v_rshift P_((MARK, MARK)); /* > */
extern MARK v_reformat P_((MARK, MARK)); /* = */
extern MARK v_filter P_((MARK, MARK)); /* ! */
extern MARK v_status P_((void)); /* ^G */
extern MARK v_switch P_((void)); /* ^^ */
extern MARK v_tag P_((char *, MARK, long)); /* ^] */
extern MARK v_xit P_((MARK, long, int)); /* ZZ */
extern MARK v_undoline P_((MARK)); /* U */
extern MARK v_again P_((MARK, MARK)); /* & */
#ifndef NO_EXTENSIONS
extern MARK v_keyword(); /* K */
extern MARK v_increment(); /* * */
extern MARK v_keyword P_((char *, MARK, long)); /* K */
extern MARK v_increment P_((char *, MARK, long)); /* * */
#endif
#ifndef NO_ERRLIST
extern MARK v_errlist(); /* * */
extern MARK v_errlist P_((MARK)); /* * */
#endif
#ifndef NO_AT
extern MARK v_at(); /* @ */
extern MARK v_at P_((MARK, long, int)); /* @ */
#endif
#ifdef SIGTSTP
extern MARK v_suspend(); /* ^Z */
extern MARK v_suspend P_((void)); /* ^Z */
#endif
#ifndef NO_POPUP
extern MARK v_popup(); /* \ */
extern MARK v_popup P_((MARK, MARK)); /* \ */
#endif
#ifndef NO_TAGSTACK
extern MARK v_pop P_((MARK, long, int)); /* ^T */
#endif
/*----------------------------------------------------------------------*/
@ -546,8 +593,10 @@ extern MARK v_again(); /* & */
#define NCOL 0x20 /* this command can't change the column# */
#define NREL 0x40 /* this is "non-relative" -- set the '' mark */
#define SDOT 0x80 /* set the "dot" variables, for the "." cmd */
#define FINL 0x100 /* final testing, more strict! */
#define NWRP 0x200 /* no line-wrap (used for 'w' and 'W') */
#ifndef NO_VISIBLE
# define VIZ 0x100 /* commands which can be used with 'v' */
# define VIZ 0x400 /* commands which can be used with 'v' */
#else
# define VIZ 0
#endif
@ -586,11 +635,14 @@ extern int mode;
#ifndef NO_VISIBLE
extern MARK V_from;
extern int V_linemd;
extern MARK v_start();
extern MARK v_start P_((MARK m, long cnt, int cmd));
#endif
#ifdef DEBUG
# define malloc(size) dbmalloc(size, __FILE__, __LINE__)
# define free(ptr) dbfree(ptr, __FILE__, __LINE__)
extern char *dbmalloc();
# define checkmem() dbcheckmem(__FILE__, __LINE__)
extern char *dbmalloc P_((int, char *, int));
#else
# define checkmem()
#endif

View File

@ -14,6 +14,10 @@
#include "config.h"
#include "vi.h"
void recover P_((char *, char *));
void main P_((int, char **));
void recover(basename, outname)
char *basename; /* the name of the file to recover */
char *outname; /* the name of the file to write to */
@ -164,6 +168,7 @@ void recover(basename, outname)
#endif
}
void
main(argc, argv)
int argc;
char **argv;
@ -172,7 +177,7 @@ main(argc, argv)
if (argc > 3)
{
fprintf(stderr, "usage: %s [preserved_file [recovery_file]]\n", argv[0]);
exit(1);
exit(2);
}
/* recover the requested file, or list recoverable files */

7
usr.bin/ref/Makefile Normal file
View File

@ -0,0 +1,7 @@
PROG= ref
CFLAGS+=-I${.CURDIR}/../elvis
SRCS= ref.c
.include <bsd.prog.mk>
.PATH: ${.CURDIR}/../elvis

88
usr.bin/ref/ref.1 Normal file
View File

@ -0,0 +1,88 @@
.TH REF 1
.SH NAME
ref - Display a C function header
.SH SYNOPSIS
\fBref\fR [-t] [-c \fIclass\fR]... [-f \fIfile\fR]... \fItag\fR
.SH DESCRIPTION
\fIref\fP quickly locates and displays the header of a function.
To do this, \fIref\fR
looks in the "tags" file for the line that describes the function, and then
scans the source file for the function.
When it locates the function, it displays an introductory comment
(if there is one), the function's declaration, and the declarations of all
arguments.
.SH "SEARCH METHOD"
.PP
\fIref\fR uses a fairly sophisticated tag look-up algorithm.
If you supply a filename via \fB-f\fR \fIfile\fR, then elvis first scans
the tags file for a static tag from that file.
This search is limited to the tags file in the current directory.
.PP
If you supply a classname via \fB-c\fR \fIclass\fR, then elvis searches
for a tag from that class.
This search is not limited to the current directory;
You can supply a list of directories in the environment variable \fITAGPATH\fR,
and \fIref\fR will search through the "tags" file in each directory until it finds
a tag in the desired class.
.PP
If that fails, \fIref\fR will then try to look up an ordinary global tag.
This search checks all of the directories listed in \fITAGPATH\fR, too.
.PP
If you've given the \fB-t\fR flag, then \fIref\fR will simply output the tag line that
it found, and then exit.
Without \fB-t\fR, though, \fIref\fR will search for the tag line.
It will try to open the source file, which should be in the same directory
as the tags file where the tag was discovered.
If the source file doesn't exist, or is unreadable, then \fIref\fR will try to open
a file called "\fIrefs\fR" in that directory.
Either way, \fIref\fR will try to locate the tag, and display whatever it finds.
.SH "INTERACTION WITH ELVIS"
.PP
\fIref\fP is used by \fIelvis\fR' shift-K command.
If the cursor is located on a word such as "splat", in the file "foo.c",
then \fIelvis\fR will invoke \fIref\fR with the command "ref -f foo.c splat".
.PP
If \fIelvis\fR has been compiled with the -DEXTERNAL_TAGS flag, then \fIelvis\fR will
use \fIref\fR \fB\fRto scan the tags files.
This is slower than the built-in tag searching, but it allows \fIelvis\fR to access
the more sophisticated tag lookup provided by \fIref\fR.
Other than that, external tags should act exactly like internal tags.
.SH OPTIONS
.IP \fB-t\fR
Output tag info, instead of the function header.
.IP "\fB-f\fR \fIfile\fR"
The tag might be a static function in \fIfile\fR.
You can use several -f flags to have \fIref\fR consider static tags from more than one file.
.IP "\fB-c\fR \fIclass\fR"
The tag might be a member of class \fIclass\fR.
You can use several -c flags to have \fIref\fR consider tags from more than one class.
.SH FILES
.IP \fBtags\fR
List of function names and their locations, generated by \fIctags\fR.
.IP \fBrefs\fR
Function headers extracted from source files (optional).
.SH ENVIRONMENT
.IP \fBTAGPATH\fR
List of directories to be searched.
The elements in the list are separated by either
semicolons (for MS-DOS, Atari TOS, and AmigaDos), or
by colons (every other operating system).
For each operating system, \fIref\fR has a built-in default which is probably
adequate.
.SH NOTES
.PP
You might want to generate a "tags" file the directory that contains the
source code for standard C library on your system.
If licensing restrictions prevent you from making the library source readable
by everybody, then you can have \fIctags\fR generate a "refs" file,
and make "refs" readable by everybody.
.PP
If your system doesn't come with the library source code, then perhaps you
can produce something workable from the \fIlint\fR libraries.
.SH "SEE ALSO"
elvis(1), ctags(1)
.SH AUTHOR
.nf
Steve Kirkendall
kirkenda@cs.pdx.edu
.fi

550
usr.bin/ref/ref.c Normal file
View File

@ -0,0 +1,550 @@
/* ref2.c */
/* This is a totally rewritten version of ref. This version looks for the
* desired function name in the "tags" file, and then reads the header out
* from the source file. There is no longer any need for a "refs" file.
*
* Usage: ref [-t] [-f file] [-c class] tag
* Options: -t output tag info, not the description
* -f file default filename for static functions
* -c class default class names for class functions
*/
#ifdef __STDC__
# include <string.h>
# include <stdlib.h>
#endif
#include <stdio.h>
#include "config.h"
extern char *cktagdir P_((char *, char *));
extern int getline P_((char *, int, FILE *));
extern int lookup P_((char *, char *));
extern int find P_((char *));
extern void usage P_((void));
extern int countcolons P_((char *));
extern void main P_((int, char **));
/* This is the default path that is searched for tags */
#if OSK
# define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
#else
# if ANY_UNIX
# define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
# else
# if MSDOS || TOS
# define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
# define SEP ';'
# else
# if AMIGA
# define DEFTAGPATH ".;Include:;Include:sys"
# define SEP ';'
# else /* any other OS */
# define DEFTAGPATH "."
# endif
# endif
# endif
#endif
#ifndef SEP
# define SEP ':'
#endif
/* These variables reflect the command-line options given by the user. */
int taginfo; /* boolean: give only the tag info? (not header?) */
char *def_file; /* default filename for static functions */
char *def_class; /* default classname for class members */
int colons; /* #colons in tag: 0=normal, 1=static, 2=member */
/* This function checks for a tag in the "tags" file of given directory.
* If the tag is found, then it returns a pointer to a static buffer which
* contains the filename, a tab character, and a linespec for finding the
* the tag. If the tag is not found in the "tags" file, or if the "tags"
* file cannot be opened or doesn't exist, then this function returns NULL.
*/
char *cktagdir(tag, dir)
char *tag; /* name of the tag to look for */
char *dir; /* name of the directory to check */
{
char buf[BLKSIZE];
static char found[BLKSIZE];
FILE *tfile;
int len;
#if AMIGA
if (dir[strlen(dir) - 1] == COLON)
sprintf(buf, "%s%s", dir, TAGS); /* no slash after colon. */
else
#endif
/* construct the name of the "tags" file in this directory */
sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
/* Try to open the tags file. Return NULL if can't open */
#if AMIGA
if (buf[0] == '.' && buf[1] == SLASH)
tfile = fopen(&buf[2], "r");
else
#endif
tfile = fopen(buf, "r");
if (!tfile)
{
return (char *)0;
}
/* compute the length of the tagname once */
len = strlen(tag);
/* read lines until we get the one for this tag */
found[0] = '\0';
while (fgets(buf, sizeof buf, tfile))
{
/* is this the one we want? */
if (!strncmp(buf, tag, len) && buf[len] == '\t')
{
/* we've found a match -- remember it */
strcpy(found, buf);
/* if there is no default file, or this match is in
* the default file, then we've definitely found the
* one we want. Break out of the loop now.
*/
if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
{
break;
}
}
}
/* we're through reading */
fclose(tfile);
/* if there's anything in found[], use it */
if (found[0])
{
return &found[len + 1];
}
/* else we didn't find it */
return (char *)0;
}
/* This function reads a single textline from a binary file. It returns
* the number of bytes read, or 0 at EOF.
*/
int getline(buf, limit, fp)
char *buf; /* buffer to read into */
int limit; /* maximum characters to read */
FILE *fp; /* binary stream to read from */
{
int bytes; /* number of bytes read so far */
int ch; /* single character from file */
for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
{
#if MSDOS || TOS
/* since this is a binary file, we'll need to manually strip CR's */
if (ch == '\r')
{
continue;
}
#endif
*buf++ = ch;
}
*buf = '\0';
return bytes;
}
/* This function reads a source file, looking for a given tag. If it finds
* the tag, then it displays it and returns TRUE. Otherwise it returns FALSE.
* To display the tag, it attempts to output any introductory comment, the
* tag line itself, and any arguments. Arguments are assumed to immediately
* follow the tag line, and start with whitespace. Comments are assumed to
* start with lines that begin with "/*", "//", "(*", or "--", and end at the
* tag line or at a blank line.
*/
int lookup(dir, entry)
char *dir; /* name of the directory that contains the source */
char *entry; /* source filename, <Tab>, linespec */
{
char *name; /* basename of source file */
char buf[BLKSIZE]; /* pathname of source file */
long lnum; /* desired line number */
long thislnum; /* current line number */
long here; /* seek position where current line began */
long comment; /* seek position of introductory comment, or -1L */
FILE *sfile; /* used for reading the source file */
int len; /* length of string */
int noargs = 0; /* boolean: don't show lines after tag line? */
char *ptr;
/* construct the pathname of the source file */
name = entry;
strcpy(buf, dir);
ptr = buf + strlen(buf);
#if AMIGA
if (ptr[-1] != COLON)
#endif
*ptr++ = SLASH;
while (*entry != '\t')
{
*ptr++ = *entry++;
}
*entry++ = *ptr = '\0';
/* searching for string or number? */
if (*entry >= '0' && *entry <= '9')
{
/* given a specific line number */
lnum = atol(entry);
entry = (char *)0;
noargs = 1;
}
else
{
/* given a string -- strip off "/^" and "$/\n" */
entry += 2;
len = strlen(entry) - 2;
if (entry[len - 1] == '$')
{
entry[len - 1] = '\n';
}
if (!strchr(entry, '('))
{
noargs = 1;
}
lnum = 0L;
}
/* Open the file. Note that we open the file in binary mode even
* though we know it is a text file, because ftell() and fseek()
* don't work on text files.
*/
#if MSDOS || TOS
sfile = fopen(buf, "rb");
#else
# if AMIGA
if (buf[0] == '.' && buf[1] == SLASH)
sfile = fopen(&buf[2], "r");
else
# endif
sfile = fopen(buf, "r");
#endif
if (!sfile)
{
/* can't open the real source file. Try "refs" instead */
#if AMIGA
if (dir[strlen(dir) - 1] == COLON)
sprintf(buf, "%srefs", dir);
else
#endif
sprintf(buf, "%s%crefs", dir, SLASH);
#if MSDOS || TOS
sfile = fopen(buf, "rb");
#else
# if AMIGA
if (buf[0] == '.' && buf[1] == SLASH)
sfile = fopen(&buf[2], "r");
else
# endif
sfile = fopen(buf, "r");
#endif
if (!sfile)
{
/* failed! */
return 0;
}
name = "refs";
}
/* search the file */
for (comment = -1L, thislnum = 0; here = ftell(sfile), thislnum++, getline(buf, BLKSIZE, sfile) > 0; )
{
/* Is this the start/end of a comment? */
if (comment == -1L)
{
/* starting a comment? */
if (buf[0] == '/' && buf[1] == '*'
|| buf[0] == '/' && buf[1] == '/'
|| buf[0] == '(' && buf[1] == '*'
|| buf[0] == '-' && buf[1] == '-')
{
comment = here;
}
}
else
{
/* ending a comment? */
if (buf[0] == '\n' || buf[0] == '#')
{
comment = -1L;
}
}
/* is this the tag line? */
if (lnum == thislnum || (entry && !strncmp(buf, entry, len)))
{
/* display the filename & line number where found */
if (strcmp(dir, "."))
printf("%s%c%s, line %ld:\n", dir, SLASH, name, thislnum);
else
printf("%s, line %ld:\n", name, thislnum);
/* if there were introductory comments, show them */
if (comment != -1L)
{
fseek(sfile, comment, 0);
while (comment != here)
{
getline(buf, BLKSIZE, sfile);
fputs(buf, stdout);
comment = ftell(sfile);
}
/* re-fetch the tag line */
fgets(buf, BLKSIZE, sfile);
}
/* show the tag line */
fputs(buf, stdout);
/* are we expected to show argument lines? */
if (!noargs)
{
/* show any argument lines */
while (getline(buf, BLKSIZE, sfile) > 0
&& buf[0] != '#'
&& strchr(buf, '{') == (char *)0)
{
fputs(buf, stdout);
}
}
/* Done! Close the file, and return TRUE */
fclose(sfile);
return 1;
}
}
/* not found -- return FALSE */
return 0;
}
/* This function searches through the entire search path for a given tag.
* If it finds the tag, then it displays the info and returns TRUE;
* otherwise it returns FALSE.
*/
int find(tag)
char *tag; /* the tag to look up */
{
char *tagpath;
char dir[80];
char *ptr;
int len;
if (colons == 1)
{
/* looking for static function -- only look in current dir */
tagpath = ".";
}
else
{
/* get the tagpath from the environment. Default to DEFTAGPATH */
tagpath = getenv("TAGPATH");
if (!tagpath)
{
tagpath = DEFTAGPATH;
}
}
/* for each entry in the path... */
while (*tagpath)
{
/* Copy the entry into the dir[] buffer */
for (ptr = dir; *tagpath && *tagpath != SEP; tagpath++)
{
*ptr++ = *tagpath;
}
if (*tagpath == SEP)
{
tagpath++;
}
/* if the entry ended with "/tags", then strip that off */
len = strlen(TAGS);
if (&dir[len] < ptr && ptr[-len - 1] == SLASH && !strncmp(&ptr[-len], TAGS, len))
{
ptr -= len + 1;
}
/* if the entry is now an empty string, then assume "." */
if (ptr == dir)
{
*ptr++ = '.';
}
*ptr = '\0';
/* look for the tag in this path. If found, then display it
* and exit.
*/
ptr = cktagdir(tag, dir);
if (ptr)
{
/* just supposed to display tag info? */
if (taginfo)
{
/* then do only that! */
if (strcmp(dir, "."))
{
printf("%s%c%s", dir, SLASH, ptr);
}
else
{
/* avoid leading "./" if possible */
fputs(ptr, stdout);
}
return 1;
}
else
{
/* else look up the declaration of the thing */
return lookup(dir, ptr);
}
}
}
/* if we get here, then the tag wasn't found anywhere */
return 0;
}
void usage()
{
fputs("usage: ref [-t] [-c class] [-f file] tag\n", stderr);
fputs(" -t output tag info, instead of the function header\n", stderr);
fputs(" -f File tag might be a static function in File\n", stderr);
fputs(" -c Class tag might be a member of class Class\n", stderr);
exit(2);
}
int countcolons(str)
char *str;
{
while (*str != ':' && *str)
{
str++;
}
if (str[0] != ':')
{
return 0;
}
else if (str[1] != ':')
{
return 1;
}
return 2;
}
void main(argc, argv)
int argc;
char **argv;
{
char def_tag[100]; /* used to build tag name with default file/class */
int i;
/* parse flags */
for (i = 1; i < argc && argv[i][0] == '-'; i++)
{
switch (argv[i][1])
{
case 't':
taginfo = 1;
break;
case 'f':
if (argv[i][2])
{
def_file = &argv[i][2];
}
else if (++i < argc)
{
def_file = argv[i];
}
else
{
usage();
}
break;
case 'c':
if (argv[i][2])
{
def_class = &argv[i][2];
}
else if (++i < argc)
{
def_class = argv[i];
}
else
{
usage();
}
break;
default:
usage();
}
}
/* if no tag was given, complain */
if (i + 1 != argc)
{
usage();
}
/* does the tag have an explicit class or file? */
colons = countcolons(argv[i]);
/* if not, then maybe try some defaults */
if (colons == 0)
{
/* try a static function in the file first */
if (def_file)
{
sprintf(def_tag, "%s:%s", def_file, argv[i]);
colons = 1;
if (find(def_tag))
{
exit(0);
}
}
/* try a member function for a class */
if (def_class)
{
sprintf(def_tag, "%s::%s", def_class, argv[i]);
colons = 2;
if (find(def_tag))
{
exit(0);
}
}
/* oh, well */
colons = 0;
}
/* find the tag */
if (find(argv[i]))
{
exit(0);
}
/* Give up. If doing tag lookup then exit(0), else exit(1) */
exit(!taginfo);
/*NOTREACHED*/
}