summaryrefslogtreecommitdiff
path: root/usr.bin/vi/ex
diff options
context:
space:
mode:
authormichaels <michaels@cvs.openbsd.org>1996-08-16 17:58:49 +0000
committermichaels <michaels@cvs.openbsd.org>1996-08-16 17:58:49 +0000
commit418c0bbade1dcb322b7abdbed4064993de8086c2 (patch)
tree4bad4d39a1f432f68cae3d673074f4b724aba879 /usr.bin/vi/ex
parent445816164da4c953591f89549fdd9bc8825aa8c8 (diff)
nvi 1.73
Diffstat (limited to 'usr.bin/vi/ex')
-rw-r--r--usr.bin/vi/ex/ex.c61
-rw-r--r--usr.bin/vi/ex/ex_args.c12
-rw-r--r--usr.bin/vi/ex/ex_argv.c169
-rw-r--r--usr.bin/vi/ex/ex_cmd.c4
-rw-r--r--usr.bin/vi/ex/ex_cscope.c99
-rw-r--r--usr.bin/vi/ex/ex_file.c4
-rw-r--r--usr.bin/vi/ex/ex_init.c11
-rw-r--r--usr.bin/vi/ex/ex_perl.c130
-rw-r--r--usr.bin/vi/ex/ex_read.c4
-rw-r--r--usr.bin/vi/ex/ex_shell.c10
-rw-r--r--usr.bin/vi/ex/ex_source.c4
-rw-r--r--usr.bin/vi/ex/ex_subst.c18
-rw-r--r--usr.bin/vi/ex/ex_version.c4
-rw-r--r--usr.bin/vi/ex/ex_write.c6
-rw-r--r--usr.bin/vi/ex/version.h2
15 files changed, 307 insertions, 231 deletions
diff --git a/usr.bin/vi/ex/ex.c b/usr.bin/vi/ex/ex.c
index f4a5bfb3a47..ca6872b332b 100644
--- a/usr.bin/vi/ex/ex.c
+++ b/usr.bin/vi/ex/ex.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex.c 10.50 (Berkeley) 6/30/96";
+static const char sccsid[] = "@(#)ex.c 10.53 (Berkeley) 8/11/96";
#endif /* not lint */
#include <sys/types.h>
@@ -617,15 +617,9 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
* :s/a/b/|s/c/d|set
*
* was also legal, i.e. the historic ex parser (using the word loosely,
- * since "parser" implies some regularity) delimited the RE's based on
- * its delimiter and not anything so irretrievably vulgar as a command
- * syntax.
- *
- * One thing that makes this easier is that we can ignore most of the
- * command termination conditions for the commands that want to take
- * the command up to the next newline. None of them are legal in .exrc
- * files, so if we're here, we only dealing with a single line, and we
- * can just eat it.
+ * since "parser" implies some regularity of syntax) delimited the RE's
+ * based on its delimiter and not anything so irretrievably vulgar as a
+ * command syntax.
*
* Anyhow, the following code makes this all work. First, for the
* special cases we move past their special argument(s). Then, we
@@ -657,9 +651,8 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
* The historic implementation ignored all escape characters
* so there was no way to put a space or newline into the +cmd
* field. We do a simplistic job of fixing it by moving to the
- * first whitespace character that isn't escaped by a literal
- * next character. The literal next characters are stripped
- * as they're no longer useful.
+ * first whitespace character that isn't escaped. The escaping
+ * characters are stripped as no longer useful.
*/
if (ecp->clen > 0 && *ecp->cp == '+') {
++ecp->cp;
@@ -667,8 +660,8 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
for (arg1 = p = ecp->cp;
ecp->clen > 0; --ecp->clen, ++ecp->cp) {
ch = *ecp->cp;
- if (IS_ESCAPE(sp,
- ecp, ch) && ecp->clen > 1) {
+ if (IS_ESCAPE(sp, ecp, ch) &&
+ ecp->clen > 1) {
--ecp->clen;
ch = *++ecp->cp;
} else if (isblank(ch))
@@ -682,22 +675,30 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
}
} else if (ecp->cmd == &cmds[C_BANG] ||
ecp->cmd == &cmds[C_GLOBAL] || ecp->cmd == &cmds[C_V]) {
- ecp->cp += ecp->clen;
- ecp->clen = 0;
+ for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (ecp->cp[0] == '\n')
+ break;
} else if (ecp->cmd == &cmds[C_READ] || ecp->cmd == &cmds[C_WRITE]) {
/*
- * Move to the next character. If it's a '!', it's a filter
- * command and we want to eat it all, otherwise, we're done.
+ * For write commands, if the next character is a <blank>, and
+ * the next non-blank character is a '!', it's a filter command
+ * and we want to eat everything up to the <newline>. For read
+ * commands, if the next non-blank character is a '!', it's a
+ * filter command and we want to eat everything up to the next
+ * <newline>. Otherwise, we're done.
*/
- for (; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
+ for (tmp = 0; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
ch = *ecp->cp;
- if (!isblank(ch))
+ if (isblank(ch))
+ tmp = 1;
+ else
break;
}
- if (ecp->clen > 0 && ch == '!') {
- ecp->cp += ecp->clen;
- ecp->clen = 0;
- }
+ if (ecp->clen > 0 && ch == '!' &&
+ (ecp->cmd == &cmds[C_READ] || tmp))
+ for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
+ if (ecp->cp[0] == '\n')
+ break;
} else if (ecp->cmd == &cmds[C_SUBSTITUTE]) {
/*
* Move to the next non-whitespace character, we'll use it as
@@ -812,7 +813,7 @@ skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
* case where the 0 address is only valid if it's a default address.
*
* Also, set a flag if we set the default addresses. Some commands
- * (ex: z) care if the user specified an address of if we just used
+ * (ex: z) care if the user specified an address or if we just used
* the current cursor.
*/
switch (F_ISSET(ecp, E_ADDR1 | E_ADDR2 | E_ADDR2_ALL | E_ADDR2_NONE)) {
@@ -1202,7 +1203,7 @@ usage: msgq(sp, M_ERR, "086|Usage: %s", ecp->cmd->usage);
/*
* Verify that the addresses are legal. Check the addresses here,
* because this is a place where all ex addresses pass through.
- * (They don't all pass through ep_line(), for instance.) We're
+ * (They don't all pass through ex_line(), for instance.) We're
* assuming that any non-existent line doesn't exist because it's
* past the end-of-file. That's a pretty good guess.
*
@@ -1408,9 +1409,9 @@ addr_verify:
}
/*
- * If the command was successful may want to display a line based on
- * the autoprint option or an explicit print flag. (Make sure that
- * there's a line to display.) Also, the autoprint edit option is
+ * If the command executed successfully, we may want to display a line
+ * based on the autoprint option or an explicit print flag. (Make sure
+ * that there's a line to display.) Also, the autoprint edit option is
* turned off for the duration of global commands.
*/
if (F_ISSET(sp, SC_EX) && sp->ep != NULL && sp->lno != 0) {
diff --git a/usr.bin/vi/ex/ex_args.c b/usr.bin/vi/ex/ex_args.c
index ba3e7801549..bc37109fc13 100644
--- a/usr.bin/vi/ex/ex_args.c
+++ b/usr.bin/vi/ex/ex_args.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_args.c 10.14 (Berkeley) 4/27/96";
+static const char sccsid[] = "@(#)ex_args.c 10.16 (Berkeley) 7/13/96";
#endif /* not lint */
#include <sys/types.h>
@@ -99,6 +99,9 @@ ex_next(sp, cmdp)
if ((frp = file_add(sp, *sp->cargv)) == NULL)
return (1);
noargs = 0;
+
+ /* Display a file count with the welcome message. */
+ F_SET(sp, SC_STATUS_CNT);
} else {
if ((frp = file_add(sp, sp->cargv[1])) == NULL)
return (1);
@@ -149,6 +152,9 @@ ex_N_next(sp, cmdp)
/* The arguments are a replacement file list. */
new->cargv = new->argv = ex_buildargv(sp, cmdp, NULL);
+ /* Display a file count with the welcome message. */
+ F_SET(new, SC_STATUS_CNT);
+
/* Set up the switch. */
sp->nextdisp = new;
F_SET(sp, SC_SSWITCH);
@@ -237,7 +243,9 @@ ex_rew(sp, cmdp)
(FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
return (1);
- F_SET(sp, SC_FSWITCH);
+ /* Switch and display a file count with the welcome message. */
+ F_SET(sp, SC_FSWITCH | SC_STATUS_CNT);
+
return (0);
}
diff --git a/usr.bin/vi/ex/ex_argv.c b/usr.bin/vi/ex/ex_argv.c
index f62b081eb40..e2cbfd61246 100644
--- a/usr.bin/vi/ex/ex_argv.c
+++ b/usr.bin/vi/ex/ex_argv.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_argv.c 10.19 (Berkeley) 3/30/96";
+static const char sccsid[] = "@(#)ex_argv.c 10.23 (Berkeley) 8/11/96";
#endif /* not lint */
#include <sys/types.h>
@@ -18,6 +18,7 @@ static const char sccsid[] = "@(#)ex_argv.c 10.19 (Berkeley) 3/30/96";
#include <bitstring.h>
#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
@@ -29,7 +30,9 @@ static const char sccsid[] = "@(#)ex_argv.c 10.19 (Berkeley) 3/30/96";
static int argv_alloc __P((SCR *, size_t));
static int argv_fexp __P((SCR *, EXCMD *,
- char *, size_t, char *, size_t *, char **, size_t *, int));
+ char *, size_t, char *, size_t *, char **, size_t *, int));
+static int argv_prefix __P((SCR *,
+ char *, char *, char **, size_t *, size_t *));
static int argv_sexp __P((SCR *, char **, size_t *, size_t *));
/*
@@ -183,25 +186,58 @@ argv_exp2(sp, excp, cmd, cmdlen)
for (p = mp = O_STR(sp, O_SHELLMETA); *p != '\0'; ++p)
if (isblank(*p) || isalnum(*p))
break;
+ p = bp + SHELLOFFSET;
+ n = len - SHELLOFFSET;
if (*p != '\0') {
- for (p = bp, n = len; n > 0; --n, ++p)
+ for (; n > 0; --n, ++p)
if (strchr(mp, *p) != NULL)
break;
} else
- for (p = bp, n = len; n > 0; --n, ++p)
+ for (; n > 0; --n, ++p)
if (!isblank(*p) &&
!isalnum(*p) && strchr(mp, *p) != NULL)
break;
}
- if (n > 0) {
+
+ /*
+ * If we found a meta character in the string, fork a shell to expand
+ * it. Unfortunately, this is comparatively slow. Historically, it
+ * didn't matter much, since users don't enter meta characters as part
+ * of pathnames that frequently. The addition of filename completion
+ * broke that assumption because it's easy to use. As a result, lots
+ * folks have complained that the expansion code is too slow. So, we
+ * detect filename completion as a special case, and do it internally.
+ * Note that this code assumes that the <asterisk> character is the
+ * match-anything meta character. That feels safe -- if anyone writes
+ * a shell that doesn't follow that convention, I'd suggest giving them
+ * a festive hot-lead enema.
+ */
+ switch (n) {
+ case 0:
+ p = bp + SHELLOFFSET;
+ len -= SHELLOFFSET;
+ break;
+ case 1:
+ if (*p == '*') {
+ *p++ = '\0';
+ n = p - bp;
+ if (argv_prefix(sp,
+ bp + SHELLOFFSET, p, &bp, &blen, &len)) {
+ rval = 1;
+ goto err;
+ }
+ p = bp + n;
+ len -= n;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
if (argv_sexp(sp, &bp, &blen, &len)) {
rval = 1;
goto err;
}
p = bp;
- } else {
- p = bp + SHELLOFFSET;
- len -= SHELLOFFSET;
+ break;
}
#if defined(DEBUG) && 0
@@ -472,6 +508,116 @@ argv_free(sp)
}
/*
+ * argv_prefix --
+ * Find all file names matching the prefix and append them to the
+ * buffer.
+ */
+static int
+argv_prefix(sp, path, wp, bpp, blenp, lenp)
+ SCR *sp;
+ char *path, *wp, **bpp;
+ size_t *blenp, *lenp;
+{
+ DIR *dirp;
+ struct dirent *dp;
+ size_t blen, clen, dlen, doffset, len, nlen;
+ char *bp, *dname, *name, *p;
+
+ /*
+ * Open the directory, set up the name and length for comparison,
+ * the prepended directory and length.
+ */
+ if ((p = strrchr(path, '/')) == NULL) {
+ dlen = 0;
+ dname = ".";
+ name = path;
+ } else {
+ if (p == path) {
+ dname = "/";
+ dlen = 0;
+ } else {
+ *p = '\0';
+ dname = path;
+ dlen = strlen(path);
+ }
+ name = p + 1;
+ }
+ nlen = strlen(name);
+
+ if ((dirp = opendir(dname)) == NULL) {
+ msgq_str(sp, M_SYSERR, dname, "%s");
+ return (1);
+ }
+
+ /* Local copies of the buffer variables. */
+ bp = *bpp;
+ blen = *blenp;
+
+ /*
+ * We're passed a pointer to the name (after the echo command at
+ * the start of the buffer) and a pointer to the place to start
+ * writing. Set a pointer to the start of the write area, and a
+ * value for the amount of space we have to write.
+ */
+ p = wp;
+ len = wp - bp;
+ blen -= len;
+
+ /*
+ * Read the directory, checking for files with a matching prefix.
+ *
+ * XXX
+ * We don't use the d_namlen field, it's not portable enough; we
+ * assume that d_name is nul terminated, instead.
+ */
+ while ((dp = readdir(dirp)) != NULL) {
+ clen = strlen(dp->d_name);
+ if (nlen == 0 ||
+ (clen >= nlen && !memcmp(dp->d_name, name, nlen))) {
+ if (blen < clen + dlen + 5) {
+ doffset = dname - bp;
+ ADD_SPACE_GOTO(sp, bp, *blenp,
+ *blenp * 2 + clen + dlen + 5);
+ p = bp + len;
+ blen = *blenp - len;
+ if (dname == path)
+ dname = bp + doffset;
+ }
+ if (dlen != 0) {
+ memcpy(p, dname, dlen);
+ p += dlen;
+ *p++ = '/';
+ len += dlen + 1;
+ blen -= dlen + 1;
+ }
+ memcpy(p, dp->d_name, clen);
+ p += clen;
+ *p++ = ' ';
+ len += clen + 1;
+ blen -= clen + 1;
+ }
+ }
+ (void)closedir(dirp);
+
+ /*
+ * If we didn't find a match, complain that the expansion failed. We
+ * can't know for certain that's the error, but it's a good guess, and
+ * it matches historic practice.
+ */
+ if (p == wp) {
+ msgq(sp, M_ERR, "304|Shell expansion failed");
+alloc_err: return (1);
+ }
+
+ /* Delete the final <space>, nul terminate the string. */
+ *--p = '\0';
+ *lenp = len - 1;
+ *bpp = bp; /* *blenp is already updated. */
+
+ return (0);
+}
+
+/*
* argv_sexp --
* Fork a shell, pipe a command through it, and read the output into
* a buffer.
@@ -502,6 +648,7 @@ argv_sexp(sp, bpp, blenp, lenp)
else
++sh;
+ /* Local copies of the buffer variables. */
bp = *bpp;
blen = *blenp;
@@ -581,10 +728,10 @@ err: if (ifp != NULL)
/* Delete the final newline, nul terminate the string. */
if (p > bp && (p[-1] == '\n' || p[-1] == '\r')) {
+ --p;
--len;
- *--p = '\0';
- } else
- *p = '\0';
+ }
+ *p = '\0';
*lenp = len;
*bpp = bp; /* *blenp is already updated. */
diff --git a/usr.bin/vi/ex/ex_cmd.c b/usr.bin/vi/ex/ex_cmd.c
index af8151117e6..88a1ea660c9 100644
--- a/usr.bin/vi/ex/ex_cmd.c
+++ b/usr.bin/vi/ex/ex_cmd.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_cmd.c 10.18 (Berkeley) 6/29/96";
+static const char sccsid[] = "@(#)ex_cmd.c 10.19 (Berkeley) 7/12/96";
#endif /* not lint */
#include <sys/types.h>
@@ -256,7 +256,7 @@ EXCMDLIST const cmds[] = {
"pe[rl] cmd",
"run the perl interpreter with the command"},
/* C_PERLDOCMD */
- {"perldo", ex_perldo, E_ADDR2_ALL|E_ADDR_ZERO|
+ {"perldo", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO|
E_ADDR_ZERODEF|E_SECURE,
"s",
"perld[o] cmd",
diff --git a/usr.bin/vi/ex/ex_cscope.c b/usr.bin/vi/ex/ex_cscope.c
index c5fca718cb8..2676e104ac6 100644
--- a/usr.bin/vi/ex/ex_cscope.c
+++ b/usr.bin/vi/ex/ex_cscope.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_cscope.c 10.8 (Berkeley) 6/30/96";
+static const char sccsid[] = "@(#)ex_cscope.c 10.12 (Berkeley) 8/11/96";
#endif /* not lint */
#include <sys/param.h>
@@ -34,6 +34,7 @@ static const char sccsid[] = "@(#)ex_cscope.c 10.8 (Berkeley) 6/30/96";
#include <unistd.h>
#include "../common/common.h"
+#include "pathnames.h"
#include "tag.h"
#define CSCOPE_DBFILE "cscope.out"
@@ -77,7 +78,7 @@ typedef struct _cc {
static CC const cscope_cmds[] = {
{ "add", cscope_add,
- "Add a new cscope database", "add db-name" },
+ "Add a new cscope database", "add file | directory" },
{ "find", cscope_find,
"Query the databases for a pattern", FINDHELP },
{ "help", cscope_help,
@@ -97,7 +98,7 @@ static int get_paths __P((SCR *, CSC *));
static CC const *lookup_ccmd __P((char *));
static int parse __P((SCR *, CSC *, TAGQ *, int *));
static int read_prompt __P((SCR *, CSC *));
-static int run_cscope __P((SCR *, CSC *));
+static int run_cscope __P((SCR *, CSC *, char *));
static int start_cscopes __P((SCR *, EXCMD *));
static int terminate __P((SCR *, CSC *, int));
@@ -158,7 +159,7 @@ start_cscopes(sp, cmdp)
EXCMD *cmdp;
{
size_t blen, len;
- char *bp, *cscopes, *p;
+ char *bp, *cscopes, *p, *t;
/*
* EXTENSION #1:
@@ -178,9 +179,11 @@ start_cscopes(sp, cmdp)
GET_SPACE_RET(sp, bp, blen, len);
memcpy(bp, cscopes, len + 1);
- for (cscopes = bp; (p = strsep(&bp, "\t ")) != NULL;)
+ for (cscopes = t = bp; (p = strsep(&t, "\t :")) != NULL;)
if (*p != '\0')
(void)cscope_add(sp, cmdp, p);
+
+ FREE_SPACE(sp, bp, blen);
return (0);
}
@@ -198,43 +201,51 @@ cscope_add(sp, cmdp, dname)
EX_PRIVATE *exp;
CSC *csc;
size_t len;
- char path[MAXPATHLEN];
+ int cur_argc;
+ char *dbname, path[MAXPATHLEN];
exp = EXP(sp);
- if (argv_exp2(sp, cmdp, dname, strlen(dname)))
- return (1);
/*
- * 0 args: impossible.
- * 1 args: usage.
- * 2 args: matched a directory.
- * >2 args: object, too many args.
- *
- * The 1 args case depends on the argv_sexp() function refusing
- * to return success without at least one non-blank character.
+ * 0 additional args: usage.
+ * 1 additional args: matched a file.
+ * >1 additional args: object, too many args.
*/
- switch (cmdp->argc) {
- case 0:
- abort();
- /* NOTREACHED */
- case 1:
+ cur_argc = cmdp->argc;
+ if (argv_exp2(sp, cmdp, dname, strlen(dname)))
+ return (1);
+ if (cmdp->argc == cur_argc) {
(void)csc_help(sp, "add");
return (1);
- case 2:
- dname = cmdp->argv[1]->bp;
- break;
- default:
+ }
+ if (cmdp->argc == cur_argc + 1)
+ dname = cmdp->argv[cur_argc]->bp;
+ else {
ex_emsg(sp, dname, EXM_FILECOUNT);
return (1);
}
- /* If the database file doesn't exist, we're done. */
- (void)snprintf(path, sizeof(path),
- "%s/%s", cmdp->argv[1]->bp, CSCOPE_DBFILE);
- if (stat(path, &sb)) {
- msgq(sp, M_SYSERR, path);
+ /*
+ * The user can specify a specific file (so they can have multiple
+ * Cscope databases in a single directory) or a directory. If the
+ * file doesn't exist, we're done. If it's a directory, append the
+ * standard database file name and try again. Store the directory
+ * name regardless so that we can use it as a base for searches.
+ */
+ if (stat(dname, &sb)) {
+ msgq(sp, M_SYSERR, dname);
return (1);
}
+ if (S_ISDIR(sb.st_mode)) {
+ (void)snprintf(path, sizeof(path),
+ "%s/%s", dname, CSCOPE_DBFILE);
+ if (stat(path, &sb)) {
+ msgq(sp, M_SYSERR, path);
+ return (1);
+ }
+ dbname = CSCOPE_DBFILE;
+ } else if ((dbname = strrchr(dname, '/')) != NULL)
+ *dbname++ = '\0';
/* Allocate a cscope connection structure and initialize its fields. */
len = strlen(dname);
@@ -249,7 +260,7 @@ cscope_add(sp, cmdp, dname)
goto err;
/* Start the cscope process. */
- if (run_cscope(sp, csc))
+ if (run_cscope(sp, csc, dbname))
goto err;
/*
@@ -352,9 +363,10 @@ alloc_err:
* Fork off the cscope process.
*/
static int
-run_cscope(sp, csc)
+run_cscope(sp, csc, dbname)
SCR *sp;
CSC *csc;
+ char *dbname;
{
int to_cs[2], from_cs[2];
char cmd[MAXPATHLEN * 2];
@@ -390,9 +402,10 @@ err: if (to_cs[0] != -1)
(void)close(from_cs[0]);
/* Run the cscope command. */
-#define CSCOPE_CMD_FMT "cd '%s' && exec cscope -dl"
- (void)snprintf(cmd, sizeof(cmd), CSCOPE_CMD_FMT, csc->dname);
- (void)execl("/bin/sh", "sh", "-c", cmd, NULL);
+#define CSCOPE_CMD_FMT "cd '%s' && exec cscope -dl -f %s"
+ (void)snprintf(cmd, sizeof(cmd),
+ CSCOPE_CMD_FMT, csc->dname, dbname);
+ (void)execl(_PATH_BSHELL, "sh", "-c", cmd, NULL);
msgq_str(sp, M_SYSERR, cmd, "execl: %s");
_exit (127);
/* NOTREACHED */
@@ -648,7 +661,7 @@ parse(sp, csc, tqp, matchesp)
TAG *tp;
recno_t slno;
size_t dlen, nlen, slen;
- int ch, i, isnewer, nlines;
+ int ch, i, isolder, nlines;
char *dname, *name, *search, *p, *t, dummy[2], buf[2048];
for (;;) {
@@ -709,14 +722,14 @@ parse(sp, csc, tqp, matchesp)
slen = strlen(p);
/* Resolve the file name. */
- csc_file(sp, csc, name, &dname, &dlen, &isnewer);
+ csc_file(sp, csc, name, &dname, &dlen, &isolder);
/*
- * If the file was modified more recently than the cscope
- * database, or there wasn't a search string, use the line
- * number.
+ * If the file is older than the cscope database, that is,
+ * the database was built since the file was last modified,
+ * or there wasn't a search string, use the line number.
*/
- if (isnewer || strcmp(search, "<unknown>") == 0) {
+ if (isolder || strcmp(search, "<unknown>") == 0) {
search = NULL;
slen = 0;
}
@@ -760,12 +773,12 @@ io_err: if (feof(csc->from_fp))
* Search for the right path to this file.
*/
static void
-csc_file(sp, csc, name, dirp, dlenp, isnewerp)
+csc_file(sp, csc, name, dirp, dlenp, isolderp)
SCR *sp;
CSC *csc;
char *name, **dirp;
size_t *dlenp;
- int *isnewerp;
+ int *isolderp;
{
struct stat sb;
char **pp, buf[MAXPATHLEN];
@@ -782,7 +795,7 @@ csc_file(sp, csc, name, dirp, dlenp, isnewerp)
if (stat(buf, &sb) == 0) {
*dirp = *pp;
*dlenp = strlen(*pp);
- *isnewerp = sb.st_mtime > csc->mtime;
+ *isolderp = sb.st_mtime < csc->mtime;
return;
}
}
diff --git a/usr.bin/vi/ex/ex_file.c b/usr.bin/vi/ex/ex_file.c
index 503f11bd1d4..3492f9c7bf0 100644
--- a/usr.bin/vi/ex/ex_file.c
+++ b/usr.bin/vi/ex/ex_file.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_file.c 10.11 (Berkeley) 5/2/96";
+static const char sccsid[] = "@(#)ex_file.c 10.12 (Berkeley) 7/12/96";
#endif /* not lint */
#include <sys/types.h>
@@ -70,7 +70,7 @@ ex_file(sp, cmdp)
F_SET(frp, FR_NAMECHANGE);
/* Notify the screen. */
- (void)sp->gp->scr_rename(sp);
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
break;
default:
abort();
diff --git a/usr.bin/vi/ex/ex_init.c b/usr.bin/vi/ex/ex_init.c
index 4aeffc26831..31bcb2a176f 100644
--- a/usr.bin/vi/ex/ex_init.c
+++ b/usr.bin/vi/ex/ex_init.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_init.c 10.24 (Berkeley) 6/30/96";
+static const char sccsid[] = "@(#)ex_init.c 10.25 (Berkeley) 7/10/96";
#endif /* not lint */
#include <sys/param.h>
@@ -186,6 +186,12 @@ ex_exrc(sp)
break;
}
+ /* Run the commands. */
+ if (EXCMD_RUNNING(sp->gp))
+ (void)ex_cmd(sp);
+ if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
+ return (0);
+
if ((p = getenv("NEXINIT")) != NULL) {
if (ex_run_str(sp, "NEXINIT", p, strlen(p), 1, 0))
return (1);
@@ -211,12 +217,13 @@ ex_exrc(sp)
}
}
- /* Run the commands, they may set the exrc edit option. */
+ /* Run the commands. */
if (EXCMD_RUNNING(sp->gp))
(void)ex_cmd(sp);
if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
return (0);
+ /* Previous commands may have set the exrc option. */
if (O_ISSET(sp, O_EXRC)) {
switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) {
case NOEXIST:
diff --git a/usr.bin/vi/ex/ex_perl.c b/usr.bin/vi/ex/ex_perl.c
index bdafcac4d59..501bb53f6fc 100644
--- a/usr.bin/vi/ex/ex_perl.c
+++ b/usr.bin/vi/ex/ex_perl.c
@@ -14,7 +14,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_perl.c 8.6 (Berkeley) 3/18/96";
+static const char sccsid[] = "@(#)ex_perl.c 8.9 (Berkeley) 7/19/96";
#endif /* not lint */
#include <sys/types.h>
@@ -32,106 +32,23 @@ static const char sccsid[] = "@(#)ex_perl.c 8.6 (Berkeley) 3/18/96";
#include "../common/common.h"
-#ifdef HAVE_PERL_INTERP
-#include <EXTERN.h>
-#include <perl.h>
-#include <XSUB.h>
-
-static int perl_eval(string)
- char *string;
-{
- char *argv[2];
-
- argv[0] = string;
- argv[1] = NULL;
- perl_call_argv("_eval_", G_EVAL | G_DISCARD | G_KEEPERR, argv);
-}
-#else
-
-static void
-noperl(scrp)
- SCR *scrp;
-{
- msgq(scrp, M_ERR, "306|Vi was not loaded with a Perl interpreter");
-}
-#endif
-
/*
* ex_perl -- :[line [,line]] perl [command]
* Run a command through the perl interpreter.
*
- * PUBLIC: int ex_perl __P((SCR*, EXCMD *));
- */
-int
-ex_perl(scrp, cmdp)
- SCR *scrp;
- EXCMD *cmdp;
-{
-#ifdef HAVE_PERL_INTERP
- CHAR_T *p;
- GS *gp;
- STRLEN length;
- size_t len;
- char *err, buf[64];
-
- /* Initialize the interpreter. */
- gp = scrp->gp;
- if (gp->perl_interp == NULL && perl_init(gp))
- return (1);
-
- /* Skip leading white space. */
- if (cmdp->argc != 0)
- for (p = cmdp->argv[0]->bp,
- len = cmdp->argv[0]->len; len > 0; --len, ++p)
- if (!isblank(*p))
- break;
- if (cmdp->argc == 0 || len == 0) {
- ex_emsg(scrp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
-
- (void)snprintf(buf, sizeof(buf),
- "$VI::ScreenId=%d;$VI::StartLine=%lu;$VI::StopLine=%lu",
- scrp->id, cmdp->addr1.lno, cmdp->addr2.lno);
- perl_eval(buf);
- perl_eval(cmdp->argv[0]->bp);
- err = SvPV(GvSV(errgv),length);
- if (!length)
- return (0);
-
- err[length - 1] = '\0';
- msgq(scrp, M_ERR, "perl: %s", err);
- return (1);
-#else
- noperl(scrp);
- return (1);
-#endif /* HAVE_PERL_INTERP */
-}
-
-/*
- * ex_perldo -- :[line [,line]] perl [command]
+ * ex_perldo -- :[line [,line]] perldo [command]
* Run a set of lines through the perl interpreter.
*
- * PUBLIC: int ex_perldo __P((SCR*, EXCMD *));
+ * PUBLIC: int ex_perl __P((SCR*, EXCMD *));
*/
int
-ex_perldo(scrp, cmdp)
- SCR *scrp;
+ex_perl(sp, cmdp)
+ SCR *sp;
EXCMD *cmdp;
{
#ifdef HAVE_PERL_INTERP
CHAR_T *p;
- GS *gp;
- STRLEN length;
size_t len;
- int i;
- char *str, *argv[2];
- dSP;
-
- /* Initialize the interpreter. */
- gp = scrp->gp;
- if (gp->perl_interp == NULL && perl_init(gp))
- return (1);
/* Skip leading white space. */
if (cmdp->argc != 0)
@@ -140,39 +57,14 @@ ex_perldo(scrp, cmdp)
if (!isblank(*p))
break;
if (cmdp->argc == 0 || len == 0) {
- ex_emsg(scrp, cmdp->cmd->usage, EXM_USAGE);
+ ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
return (1);
}
-
- argv[0] = cmdp->argv[0]->bp;
- argv[1] = NULL;
-
- ENTER;
- SAVETMPS;
- for (i = cmdp->addr1.lno; i <= cmdp->addr2.lno; i++) {
- /*api_gline(scrp, i, argv+1, &len);*/
- api_gline(scrp, i, &str, &len);
- sv_setpvn(perl_get_sv("_", FALSE),str,len);
- perl_call_argv("_eval_", G_SCALAR | G_EVAL | G_KEEPERR, argv);
- str = SvPV(GvSV(errgv),length);
- if (length) break;
- SPAGAIN;
- if(SvTRUEx(POPs)) {
- str = SvPV(perl_get_sv("_", FALSE),len);
- api_sline(scrp, i, str, len);
- }
- PUTBACK;
- }
- FREETMPS;
- LEAVE;
- if (!length)
- return (0);
-
- str[length - 1] = '\0';
- msgq(scrp, M_ERR, "perl: %s", str);
- return (1);
+ return (cmdp->cmd == &cmds[C_PERLCMD] ?
+ perl_ex_perl(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno) :
+ perl_ex_perldo(sp, p, len, cmdp->addr1.lno, cmdp->addr2.lno));
#else
- noperl(scrp);
+ msgq(sp, M_ERR, "306|Vi was not loaded with a Perl interpreter");
return (1);
-#endif /* HAVE_PERL_INTERP */
+#endif
}
diff --git a/usr.bin/vi/ex/ex_read.c b/usr.bin/vi/ex/ex_read.c
index 7d4e43f63c8..6e6afa8ebcf 100644
--- a/usr.bin/vi/ex/ex_read.c
+++ b/usr.bin/vi/ex/ex_read.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_read.c 10.36 (Berkeley) 6/28/96";
+static const char sccsid[] = "@(#)ex_read.c 10.37 (Berkeley) 7/12/96";
#endif /* not lint */
#include <sys/types.h>
@@ -229,7 +229,7 @@ ex_read(sp, cmdp)
F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
/* Notify the screen. */
- (void)gp->scr_rename(sp);
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
} else
set_alt_name(sp, name);
break;
diff --git a/usr.bin/vi/ex/ex_shell.c b/usr.bin/vi/ex/ex_shell.c
index 070d6d54706..5848baee0b3 100644
--- a/usr.bin/vi/ex/ex_shell.c
+++ b/usr.bin/vi/ex/ex_shell.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_shell.c 10.35 (Berkeley) 6/28/96";
+static const char sccsid[] = "@(#)ex_shell.c 10.37 (Berkeley) 8/11/96";
#endif /* not lint */
#include <sys/param.h>
@@ -55,9 +55,15 @@ ex_shell(sp, cmdp)
*/
(void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
- /* If we're stil in a vi screen, move out explicitly. */
+ /* Restore the window name. */
+ (void)cl_rename(sp, NULL, 0);
+
+ /* If we're still in a vi screen, move out explicitly. */
rval = ex_exec_proc(sp, cmdp, buf, NULL, !F_ISSET(sp, SC_SCR_EXWROTE));
+ /* Set the window name. */
+ (void)cl_rename(sp, sp->frp->name, 1);
+
/*
* !!!
* Historically, vi didn't require a continue message after the
diff --git a/usr.bin/vi/ex/ex_source.c b/usr.bin/vi/ex/ex_source.c
index 468fd79ee2c..b52c527716f 100644
--- a/usr.bin/vi/ex/ex_source.c
+++ b/usr.bin/vi/ex/ex_source.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_source.c 10.11 (Berkeley) 6/30/96";
+static const char sccsid[] = "@(#)ex_source.c 10.12 (Berkeley) 8/10/96";
#endif /* not lint */
#include <sys/types.h>
@@ -62,7 +62,7 @@ ex_source(sp, cmdp)
goto err;
}
- MALLOC(sp, bp, char *, (size_t)sb.st_size);
+ MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
if (bp == NULL) {
(void)close(fd);
return (1);
diff --git a/usr.bin/vi/ex/ex_subst.c b/usr.bin/vi/ex/ex_subst.c
index c935d92c248..52fef271698 100644
--- a/usr.bin/vi/ex/ex_subst.c
+++ b/usr.bin/vi/ex/ex_subst.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_subst.c 10.32 (Berkeley) 6/30/96";
+static const char sccsid[] = "@(#)ex_subst.c 10.35 (Berkeley) 8/11/96";
#endif /* not lint */
#include <sys/types.h>
@@ -91,7 +91,7 @@ subagain: return (ex_subagain(sp, cmdp));
sp->c_suffix = sp->g_suffix = 0;
/*
- * Get the pattern string, toss escaped characters.
+ * Get the pattern string, toss escaping characters.
*
* !!!
* Historic vi accepted any of the following forms:
@@ -103,10 +103,10 @@ subagain: return (ex_subagain(sp, cmdp));
*
* QUOTING NOTE:
*
- * Only toss an escape character if it escapes a delimiter.
+ * Only toss an escaping character if it escapes a delimiter.
* This means that "s/A/\\\\f" replaces "A" with "\\f". It
* would be nice to be more regular, i.e. for each layer of
- * escaping a single escape character is removed, but that's
+ * escaping a single escaping character is removed, but that's
* not how the historic vi worked.
*/
for (ptrn = t = p;;) {
@@ -179,7 +179,7 @@ subagain: return (ex_subagain(sp, cmdp));
*
* QUOTING NOTE:
*
- * Only toss an escape character if it escapes a delimiter or
+ * Only toss an escaping character if it escapes a delimiter or
* if O_MAGIC is set and it escapes a tilde.
*
* !!!
@@ -1208,8 +1208,10 @@ re_tag_conv(sp, ptrnp, plenp, replacedp)
}
/* If the first or second character is a '^', it's magic. */
- if (p[0] == '^')
+ if (p[0] == '^') {
*t++ = *p++;
+ --len;
+ }
/*
* Escape every other magic character we can find, meanwhile stripping
@@ -1278,7 +1280,7 @@ re_cscope_conv(sp, ptrnp, plenp, replacedp)
memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
t += sizeof(CSCOPE_RE_SPACE) - 1;
} else {
- if (strchr("\\^.[]$*", *p))
+ if (strchr("\\^.[]$*+?()|{}", *p))
*t++ = '\\';
*t++ = *p;
}
@@ -1358,7 +1360,7 @@ re_sub(sp, ip, lbp, lbclenp, lblenp, match)
* \U convert to upper-case, until \E, \e, or end of replacement
*
* Otherwise, since this is the lowest level of replacement, discard
- * all escape characters. This (hopefully) follows historic practice.
+ * all escaping characters. This (hopefully) matches historic practice.
*/
#define OUTCH(ch, nltrans) { \
CHAR_T __ch = (ch); \
diff --git a/usr.bin/vi/ex/ex_version.c b/usr.bin/vi/ex/ex_version.c
index bc92b680c64..5e279bdaca0 100644
--- a/usr.bin/vi/ex/ex_version.c
+++ b/usr.bin/vi/ex/ex_version.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_version.c 10.27 (Berkeley) 6/9/96";
+static const char sccsid[] = "@(#)ex_version.c 10.28 (Berkeley) 7/14/96";
#endif /* not lint */
#include <sys/types.h>
@@ -36,7 +36,7 @@ business and technical computing environments, the worldwide customer \
acceptance of BSD-based technology, the know-how of BSDI's leading \
computer scientists, and BSDI's focus on delivering and supporting \
industrial-strength software for computing platforms. BSDI may be \
-contacted at info@bsdi.com or 1-800-800-4273."
+contacted at http://www.bsdi.com/, info@bsdi.com or 1-800-800-4273."
/*
* ex_version -- :version
diff --git a/usr.bin/vi/ex/ex_write.c b/usr.bin/vi/ex/ex_write.c
index 5ab94480229..b3122e35356 100644
--- a/usr.bin/vi/ex/ex_write.c
+++ b/usr.bin/vi/ex/ex_write.c
@@ -10,7 +10,7 @@
#include "config.h"
#ifndef lint
-static const char sccsid[] = "@(#)ex_write.c 10.28 (Berkeley) 6/28/96";
+static const char sccsid[] = "@(#)ex_write.c 10.30 (Berkeley) 7/12/96";
#endif /* not lint */
#include <sys/types.h>
@@ -193,7 +193,7 @@ exwr(sp, cmdp, cmd)
}
/* Set the FS_ALL flag if we're writing the entire file. */
- if (cmdp->addr1.lno == 1 && !db_exist(sp, cmdp->addr2.lno + 1))
+ if (cmdp->addr1.lno <= 1 && !db_exist(sp, cmdp->addr2.lno + 1))
LF_SET(FS_ALL);
/* If "write >>" it's an append to a file. */
@@ -256,7 +256,7 @@ exwr(sp, cmdp, cmd)
F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
/* Notify the screen. */
- (void)sp->gp->scr_rename(sp);
+ (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
} else
set_alt_name(sp, name);
break;
diff --git a/usr.bin/vi/ex/version.h b/usr.bin/vi/ex/version.h
index 96884b40dbb..9586ba7942a 100644
--- a/usr.bin/vi/ex/version.h
+++ b/usr.bin/vi/ex/version.h
@@ -1,2 +1,2 @@
#define VI_VERSION \
- "Version 1.71 (7/1/96) The CSRG, University of California, Berkeley."
+ "Version 1.73 (8/12/96) The CSRG, University of California, Berkeley."