summaryrefslogtreecommitdiffstats
path: root/contrib/nvi/ex
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2013-08-11 08:38:10 +0000
committerpeter <peter@FreeBSD.org>2013-08-11 08:38:10 +0000
commit75700a8c067d4d910e2017f0aa29cbbca644f9cc (patch)
treefcfc8dee7b416cacdea763f18f34e0930234186a /contrib/nvi/ex
parent3102470d94db36e49a2262542f69cc4219ae1aee (diff)
downloadFreeBSD-src-75700a8c067d4d910e2017f0aa29cbbca644f9cc.zip
FreeBSD-src-75700a8c067d4d910e2017f0aa29cbbca644f9cc.tar.gz
Post-cvs2svn flatten pass.
Diffstat (limited to 'contrib/nvi/ex')
-rw-r--r--contrib/nvi/ex/ex.awk6
-rw-r--r--contrib/nvi/ex/ex.c2370
-rw-r--r--contrib/nvi/ex/ex.h228
-rw-r--r--contrib/nvi/ex/ex_abbrev.c117
-rw-r--r--contrib/nvi/ex/ex_append.c277
-rw-r--r--contrib/nvi/ex/ex_args.c327
-rw-r--r--contrib/nvi/ex/ex_argv.c756
-rw-r--r--contrib/nvi/ex/ex_at.c126
-rw-r--r--contrib/nvi/ex/ex_bang.c186
-rw-r--r--contrib/nvi/ex/ex_cd.c129
-rw-r--r--contrib/nvi/ex/ex_cmd.c457
-rw-r--r--contrib/nvi/ex/ex_cscope.c1057
-rw-r--r--contrib/nvi/ex/ex_delete.c65
-rw-r--r--contrib/nvi/ex/ex_display.c145
-rw-r--r--contrib/nvi/ex/ex_edit.c153
-rw-r--r--contrib/nvi/ex/ex_equal.c59
-rw-r--r--contrib/nvi/ex/ex_file.c80
-rw-r--r--contrib/nvi/ex/ex_filter.c316
-rw-r--r--contrib/nvi/ex/ex_global.c328
-rw-r--r--contrib/nvi/ex/ex_init.c417
-rw-r--r--contrib/nvi/ex/ex_join.c177
-rw-r--r--contrib/nvi/ex/ex_map.c121
-rw-r--r--contrib/nvi/ex/ex_mark.c45
-rw-r--r--contrib/nvi/ex/ex_mkexrc.c101
-rw-r--r--contrib/nvi/ex/ex_move.c198
-rw-r--r--contrib/nvi/ex/ex_open.c46
-rw-r--r--contrib/nvi/ex/ex_perl.c69
-rw-r--r--contrib/nvi/ex/ex_preserve.c103
-rw-r--r--contrib/nvi/ex/ex_print.c352
-rw-r--r--contrib/nvi/ex/ex_put.c51
-rw-r--r--contrib/nvi/ex/ex_quit.c46
-rw-r--r--contrib/nvi/ex/ex_read.c360
-rw-r--r--contrib/nvi/ex/ex_screen.c138
-rw-r--r--contrib/nvi/ex/ex_script.c798
-rw-r--r--contrib/nvi/ex/ex_set.c46
-rw-r--r--contrib/nvi/ex/ex_shell.c378
-rw-r--r--contrib/nvi/ex/ex_shift.c191
-rw-r--r--contrib/nvi/ex/ex_source.c85
-rw-r--r--contrib/nvi/ex/ex_stop.c51
-rw-r--r--contrib/nvi/ex/ex_subst.c1459
-rw-r--r--contrib/nvi/ex/ex_tag.c1324
-rw-r--r--contrib/nvi/ex/ex_tcl.c80
-rw-r--r--contrib/nvi/ex/ex_txt.c430
-rw-r--r--contrib/nvi/ex/ex_undo.c77
-rw-r--r--contrib/nvi/ex/ex_usage.c196
-rw-r--r--contrib/nvi/ex/ex_util.c234
-rw-r--r--contrib/nvi/ex/ex_version.c39
-rw-r--r--contrib/nvi/ex/ex_visual.c161
-rw-r--r--contrib/nvi/ex/ex_write.c375
-rw-r--r--contrib/nvi/ex/ex_yank.c46
-rw-r--r--contrib/nvi/ex/ex_z.c150
-rw-r--r--contrib/nvi/ex/script.h23
-rw-r--r--contrib/nvi/ex/tag.h107
-rw-r--r--contrib/nvi/ex/version.h2
54 files changed, 0 insertions, 15658 deletions
diff --git a/contrib/nvi/ex/ex.awk b/contrib/nvi/ex/ex.awk
deleted file mode 100644
index 3ee372e..0000000
--- a/contrib/nvi/ex/ex.awk
+++ /dev/null
@@ -1,6 +0,0 @@
-# @(#)ex.awk 10.1 (Berkeley) 6/8/95
-
-/^\/\* C_[0-9A-Z_]* \*\/$/ {
- printf("#define %s %d\n", $2, cnt++);
- next;
-}
diff --git a/contrib/nvi/ex/ex.c b/contrib/nvi/ex/ex.c
deleted file mode 100644
index f92d8f7..0000000
--- a/contrib/nvi/ex/ex.c
+++ /dev/null
@@ -1,2370 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex.c 10.57 (Berkeley) 10/10/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-#if defined(DEBUG) && defined(COMLOG)
-static void ex_comlog __P((SCR *, EXCMD *));
-#endif
-static EXCMDLIST const *
- ex_comm_search __P((char *, size_t));
-static int ex_discard __P((SCR *));
-static int ex_line __P((SCR *, EXCMD *, MARK *, int *, int *));
-static int ex_load __P((SCR *));
-static void ex_unknown __P((SCR *, char *, size_t));
-
-/*
- * ex --
- * Main ex loop.
- *
- * PUBLIC: int ex __P((SCR **));
- */
-int
-ex(spp)
- SCR **spp;
-{
- EX_PRIVATE *exp;
- GS *gp;
- MSGS *mp;
- SCR *sp;
- TEXT *tp;
- u_int32_t flags;
-
- sp = *spp;
- gp = sp->gp;
- exp = EXP(sp);
-
- /* Start the ex screen. */
- if (ex_init(sp))
- return (1);
-
- /* Flush any saved messages. */
- while ((mp = gp->msgq.lh_first) != NULL) {
- gp->scr_msg(sp, mp->mtype, mp->buf, mp->len);
- LIST_REMOVE(mp, q);
- free(mp->buf);
- free(mp);
- }
-
- /* If reading from a file, errors should have name and line info. */
- if (F_ISSET(gp, G_SCRIPTED)) {
- gp->excmd.if_lno = 1;
- gp->excmd.if_name = "script";
- }
-
- /*
- * !!!
- * Initialize the text flags. The beautify edit option historically
- * applied to ex command input read from a file. In addition, the
- * first time a ^H was discarded from the input, there was a message,
- * "^H discarded", that was displayed. We don't bother.
- */
- LF_INIT(TXT_BACKSLASH | TXT_CNTRLD | TXT_CR);
- for (;; ++gp->excmd.if_lno) {
- /* Display status line and flush. */
- if (F_ISSET(sp, SC_STATUS)) {
- if (!F_ISSET(sp, SC_EX_SILENT))
- msgq_status(sp, sp->lno, 0);
- F_CLR(sp, SC_STATUS);
- }
- (void)ex_fflush(sp);
-
- /* Set the flags the user can reset. */
- if (O_ISSET(sp, O_BEAUTIFY))
- LF_SET(TXT_BEAUTIFY);
- if (O_ISSET(sp, O_PROMPT))
- LF_SET(TXT_PROMPT);
-
- /* Clear any current interrupts, and get a command. */
- CLR_INTERRUPT(sp);
- if (ex_txt(sp, &sp->tiq, ':', flags))
- return (1);
- if (INTERRUPTED(sp)) {
- (void)ex_puts(sp, "\n");
- (void)ex_fflush(sp);
- continue;
- }
-
- /* Initialize the command structure. */
- CLEAR_EX_PARSER(&gp->excmd);
-
- /*
- * If the user entered a single carriage return, send
- * ex_cmd() a separator -- it discards single newlines.
- */
- tp = sp->tiq.cqh_first;
- if (tp->len == 0) {
- gp->excmd.cp = " "; /* __TK__ why not |? */
- gp->excmd.clen = 1;
- } else {
- gp->excmd.cp = tp->lb;
- gp->excmd.clen = tp->len;
- }
- F_INIT(&gp->excmd, E_NRSEP);
-
- if (ex_cmd(sp) && F_ISSET(gp, G_SCRIPTED))
- return (1);
-
- if (INTERRUPTED(sp)) {
- CLR_INTERRUPT(sp);
- msgq(sp, M_ERR, "170|Interrupted");
- }
-
- /*
- * If the last command caused a restart, or switched screens
- * or into vi, return.
- */
- if (F_ISSET(gp, G_SRESTART) || F_ISSET(sp, SC_SSWITCH | SC_VI)) {
- *spp = sp;
- break;
- }
-
- /* If the last command switched files, we don't care. */
- F_CLR(sp, SC_FSWITCH);
-
- /*
- * If we're exiting this screen, move to the next one. By
- * definition, this means returning into vi, so return to the
- * main editor loop. The ordering is careful, don't discard
- * the contents of sp until the end.
- */
- if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE)) {
- if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE)))
- return (1);
- *spp = screen_next(sp);
- return (screen_end(sp));
- }
- }
- return (0);
-}
-
-/*
- * ex_cmd --
- * The guts of the ex parser: parse and execute a string containing
- * ex commands.
- *
- * !!!
- * This code MODIFIES the string that gets passed in, to delete quoting
- * characters, etc. The string cannot be readonly/text space, nor should
- * you expect to use it again after ex_cmd() returns.
- *
- * !!!
- * For the fun of it, if you want to see if a vi clone got the ex argument
- * parsing right, try:
- *
- * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
- * vi
- * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
- *
- * or: vi
- * :set|file|append|set|file
- *
- * For extra credit, try them in a startup .exrc file.
- *
- * PUBLIC: int ex_cmd __P((SCR *));
- */
-int
-ex_cmd(sp)
- SCR *sp;
-{
- enum nresult nret;
- EX_PRIVATE *exp;
- EXCMD *ecp;
- GS *gp;
- MARK cur;
- recno_t lno;
- size_t arg1_len, discard, len;
- u_int32_t flags;
- long ltmp;
- int at_found, gv_found;
- int ch, cnt, delim, isaddr, namelen;
- int newscreen, notempty, tmp, vi_address;
- char *arg1, *p, *s, *t;
-
- gp = sp->gp;
- exp = EXP(sp);
-
- /*
- * We always start running the command on the top of the stack.
- * This means that *everything* must be resolved when we leave
- * this function for any reason.
- */
-loop: ecp = gp->ecq.lh_first;
-
- /* If we're reading a command from a file, set up error information. */
- if (ecp->if_name != NULL) {
- gp->if_lno = ecp->if_lno;
- gp->if_name = ecp->if_name;
- }
-
- /*
- * If a move to the end of the file is scheduled for this command,
- * do it now.
- */
- if (F_ISSET(ecp, E_MOVETOEND)) {
- if (db_last(sp, &sp->lno))
- goto rfail;
- sp->cno = 0;
- F_CLR(ecp, E_MOVETOEND);
- }
-
- /* If we found a newline, increment the count now. */
- if (F_ISSET(ecp, E_NEWLINE)) {
- ++gp->if_lno;
- ++ecp->if_lno;
- F_CLR(ecp, E_NEWLINE);
- }
-
- /* (Re)initialize the EXCMD structure, preserving some flags. */
- CLEAR_EX_CMD(ecp);
-
- /* Initialize the argument structures. */
- if (argv_init(sp, ecp))
- goto err;
-
- /* Initialize +cmd, saved command information. */
- arg1 = NULL;
- ecp->save_cmdlen = 0;
-
- /* Skip <blank>s, empty lines. */
- for (notempty = 0; ecp->clen > 0; ++ecp->cp, --ecp->clen)
- if ((ch = *ecp->cp) == '\n') {
- ++gp->if_lno;
- ++ecp->if_lno;
- } else if (isblank(ch))
- notempty = 1;
- else
- break;
-
- /*
- * !!!
- * Permit extra colons at the start of the line. Historically,
- * ex/vi allowed a single extra one. It's simpler not to count.
- * The stripping is done here because, historically, any command
- * could have preceding colons, e.g. ":g/pattern/:p" worked.
- */
- if (ecp->clen != 0 && ch == ':') {
- notempty = 1;
- while (--ecp->clen > 0 && (ch = *++ecp->cp) == ':');
- }
-
- /*
- * Command lines that start with a double-quote are comments.
- *
- * !!!
- * Historically, there was no escape or delimiter for a comment, e.g.
- * :"foo|set was a single comment and nothing was output. Since nvi
- * permits users to escape <newline> characters into command lines, we
- * have to check for that case.
- */
- if (ecp->clen != 0 && ch == '"') {
- while (--ecp->clen > 0 && *++ecp->cp != '\n');
- if (*ecp->cp == '\n') {
- F_SET(ecp, E_NEWLINE);
- ++ecp->cp;
- --ecp->clen;
- }
- goto loop;
- }
-
- /* Skip whitespace. */
- for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
- ch = *ecp->cp;
- if (!isblank(ch))
- break;
- }
-
- /*
- * The last point at which an empty line can mean do nothing.
- *
- * !!!
- * Historically, in ex mode, lines containing only <blank> characters
- * were the same as a single <carriage-return>, i.e. a default command.
- * In vi mode, they were ignored. In .exrc files this was a serious
- * annoyance, as vi kept trying to treat them as print commands. We
- * ignore backward compatibility in this case, discarding lines that
- * contain only <blank> characters from .exrc files.
- *
- * !!!
- * This is where you end up when you're done a command, i.e. clen has
- * gone to zero. Continue if there are more commands to run.
- */
- if (ecp->clen == 0 &&
- (!notempty || F_ISSET(sp, SC_VI) || F_ISSET(ecp, E_BLIGNORE))) {
- if (ex_load(sp))
- goto rfail;
- ecp = gp->ecq.lh_first;
- if (ecp->clen == 0)
- goto rsuccess;
- goto loop;
- }
-
- /*
- * Check to see if this is a command for which we may want to move
- * the cursor back up to the previous line. (The command :1<CR>
- * wants a <newline> separator, but the command :<CR> wants to erase
- * the command line.) If the line is empty except for <blank>s,
- * <carriage-return> or <eof>, we'll probably want to move up. I
- * don't think there's any way to get <blank> characters *after* the
- * command character, but this is the ex parser, and I've been wrong
- * before.
- */
- if (F_ISSET(ecp, E_NRSEP) &&
- ecp->clen != 0 && (ecp->clen != 1 || ecp->cp[0] != '\004'))
- F_CLR(ecp, E_NRSEP);
-
- /* Parse command addresses. */
- if (ex_range(sp, ecp, &tmp))
- goto rfail;
- if (tmp)
- goto err;
-
- /*
- * Skip <blank>s and any more colons (the command :3,5:print
- * worked, historically).
- */
- for (; ecp->clen > 0; ++ecp->cp, --ecp->clen) {
- ch = *ecp->cp;
- if (!isblank(ch) && ch != ':')
- break;
- }
-
- /*
- * If no command, ex does the last specified of p, l, or #, and vi
- * moves to the line. Otherwise, determine the length of the command
- * name by looking for the first non-alphabetic character. (There
- * are a few non-alphabetic characters in command names, but they're
- * all single character commands.) This isn't a great test, because
- * it means that, for the command ":e +cut.c file", we'll report that
- * the command "cut" wasn't known. However, it makes ":e+35 file" work
- * correctly.
- *
- * !!!
- * Historically, lines with multiple adjacent (or <blank> separated)
- * command separators were very strange. For example, the command
- * |||<carriage-return>, when the cursor was on line 1, displayed
- * lines 2, 3 and 5 of the file. In addition, the command " | "
- * would only display the line after the next line, instead of the
- * next two lines. No ideas why. It worked reasonably when executed
- * from vi mode, and displayed lines 2, 3, and 4, so we do a default
- * command for each separator.
- */
-#define SINGLE_CHAR_COMMANDS "\004!#&*<=>@~"
- newscreen = 0;
- if (ecp->clen != 0 && ecp->cp[0] != '|' && ecp->cp[0] != '\n') {
- if (strchr(SINGLE_CHAR_COMMANDS, *ecp->cp)) {
- p = ecp->cp;
- ++ecp->cp;
- --ecp->clen;
- namelen = 1;
- } else {
- for (p = ecp->cp;
- ecp->clen > 0; --ecp->clen, ++ecp->cp)
- if (!isalpha(*ecp->cp))
- break;
- if ((namelen = ecp->cp - p) == 0) {
- msgq(sp, M_ERR, "080|Unknown command name");
- goto err;
- }
- }
-
- /*
- * !!!
- * Historic vi permitted flags to immediately follow any
- * subset of the 'delete' command, but then did not permit
- * further arguments (flag, buffer, count). Make it work.
- * Permit further arguments for the few shreds of dignity
- * it offers.
- *
- * Adding commands that start with 'd', and match "delete"
- * up to a l, p, +, - or # character can break this code.
- *
- * !!!
- * Capital letters beginning the command names ex, edit,
- * next, previous, tag and visual (in vi mode) indicate the
- * command should happen in a new screen.
- */
- switch (p[0]) {
- case 'd':
- for (s = p,
- t = cmds[C_DELETE].name; *s == *t; ++s, ++t);
- if (s[0] == 'l' || s[0] == 'p' || s[0] == '+' ||
- s[0] == '-' || s[0] == '^' || s[0] == '#') {
- len = (ecp->cp - p) - (s - p);
- ecp->cp -= len;
- ecp->clen += len;
- ecp->rcmd = cmds[C_DELETE];
- ecp->rcmd.syntax = "1bca1";
- ecp->cmd = &ecp->rcmd;
- goto skip_srch;
- }
- break;
- case 'E': case 'F': case 'N': case 'P': case 'T': case 'V':
- newscreen = 1;
- p[0] = tolower(p[0]);
- break;
- }
-
- /*
- * Search the table for the command.
- *
- * !!!
- * Historic vi permitted the mark to immediately follow the
- * 'k' in the 'k' command. Make it work.
- *
- * !!!
- * Historic vi permitted any flag to follow the s command, e.g.
- * "s/e/E/|s|sgc3p" was legal. Make the command "sgc" work.
- * Since the following characters all have to be flags, i.e.
- * alphabetics, we can let the s command routine return errors
- * if it was some illegal command string. This code will break
- * if an "sg" or similar command is ever added. The substitute
- * code doesn't care if it's a "cgr" flag or a "#lp" flag that
- * follows the 's', but we limit the choices here to "cgr" so
- * that we get unknown command messages for wrong combinations.
- */
- if ((ecp->cmd = ex_comm_search(p, namelen)) == NULL)
- switch (p[0]) {
- case 'k':
- if (namelen == 2) {
- ecp->cp -= namelen - 1;
- ecp->clen += namelen - 1;
- ecp->cmd = &cmds[C_K];
- break;
- }
- goto unknown;
- case 's':
- for (s = p + 1, cnt = namelen; --cnt; ++s)
- if (s[0] != 'c' &&
- s[0] != 'g' && s[0] != 'r')
- break;
- if (cnt == 0) {
- ecp->cp -= namelen - 1;
- ecp->clen += namelen - 1;
- ecp->rcmd = cmds[C_SUBSTITUTE];
- ecp->rcmd.fn = ex_subagain;
- ecp->cmd = &ecp->rcmd;
- break;
- }
- /* FALLTHROUGH */
- default:
-unknown: if (newscreen)
- p[0] = toupper(p[0]);
- ex_unknown(sp, p, namelen);
- goto err;
- }
-
- /*
- * The visual command has a different syntax when called
- * from ex than when called from a vi colon command. FMH.
- * Make the change now, before we test for the newscreen
- * semantic, so that we're testing the right one.
- */
-skip_srch: if (ecp->cmd == &cmds[C_VISUAL_EX] && F_ISSET(sp, SC_VI))
- ecp->cmd = &cmds[C_VISUAL_VI];
-
- /*
- * !!!
- * Historic vi permitted a capital 'P' at the beginning of
- * any command that started with 'p'. Probably wanted the
- * P[rint] command for backward compatibility, and the code
- * just made Preserve and Put work by accident. Nvi uses
- * Previous to mean previous-in-a-new-screen, so be careful.
- */
- if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN) &&
- (ecp->cmd == &cmds[C_PRINT] ||
- ecp->cmd == &cmds[C_PRESERVE]))
- newscreen = 0;
-
- /* Test for a newscreen associated with this command. */
- if (newscreen && !F_ISSET(ecp->cmd, E_NEWSCREEN))
- goto unknown;
-
- /* Secure means no shell access. */
- if (F_ISSET(ecp->cmd, E_SECURE) && O_ISSET(sp, O_SECURE)) {
- ex_emsg(sp, ecp->cmd->name, EXM_SECURE);
- goto err;
- }
-
- /*
- * Multiple < and > characters; another "feature". Note,
- * The string passed to the underlying function may not be
- * nul terminated in this case.
- */
- if ((ecp->cmd == &cmds[C_SHIFTL] && *p == '<') ||
- (ecp->cmd == &cmds[C_SHIFTR] && *p == '>')) {
- for (ch = *p;
- ecp->clen > 0; --ecp->clen, ++ecp->cp)
- if (*ecp->cp != ch)
- break;
- if (argv_exp0(sp, ecp, p, ecp->cp - p))
- goto err;
- }
-
- /* Set the format style flags for the next command. */
- if (ecp->cmd == &cmds[C_HASH])
- exp->fdef = E_C_HASH;
- else if (ecp->cmd == &cmds[C_LIST])
- exp->fdef = E_C_LIST;
- else if (ecp->cmd == &cmds[C_PRINT])
- exp->fdef = E_C_PRINT;
- F_CLR(ecp, E_USELASTCMD);
- } else {
- /* Print is the default command. */
- ecp->cmd = &cmds[C_PRINT];
-
- /* Set the saved format flags. */
- F_SET(ecp, exp->fdef);
-
- /*
- * !!!
- * If no address was specified, and it's not a global command,
- * we up the address by one. (I have no idea why globals are
- * exempted, but it's (ahem) historic practice.)
- */
- if (ecp->addrcnt == 0 && !F_ISSET(sp, SC_EX_GLOBAL)) {
- ecp->addrcnt = 1;
- ecp->addr1.lno = sp->lno + 1;
- ecp->addr1.cno = sp->cno;
- }
-
- F_SET(ecp, E_USELASTCMD);
- }
-
- /*
- * !!!
- * Historically, the number option applied to both ex and vi. One
- * strangeness was that ex didn't switch display formats until a
- * command was entered, e.g. <CR>'s after the set didn't change to
- * the new format, but :1p would.
- */
- if (O_ISSET(sp, O_NUMBER)) {
- F_SET(ecp, E_OPTNUM);
- FL_SET(ecp->iflags, E_C_HASH);
- } else
- F_CLR(ecp, E_OPTNUM);
-
- /* Check for ex mode legality. */
- if (F_ISSET(sp, SC_EX) && (F_ISSET(ecp->cmd, E_VIONLY) || newscreen)) {
- msgq(sp, M_ERR,
- "082|%s: command not available in ex mode", ecp->cmd->name);
- goto err;
- }
-
- /* Add standard command flags. */
- F_SET(ecp, ecp->cmd->flags);
- if (!newscreen)
- F_CLR(ecp, E_NEWSCREEN);
-
- /*
- * There are three normal termination cases for an ex command. They
- * are the end of the string (ecp->clen), or unescaped (by <literal
- * next> characters) <newline> or '|' characters. As we're now past
- * possible addresses, we can determine how long the command is, so we
- * don't have to look for all the possible terminations. Naturally,
- * there are some exciting special cases:
- *
- * 1: The bang, global, v and the filter versions of the read and
- * write commands are delimited by <newline>s (they can contain
- * shell pipes).
- * 2: The ex, edit, next and visual in vi mode commands all take ex
- * commands as their first arguments.
- * 3: The s command takes an RE as its first argument, and wants it
- * to be specially delimited.
- *
- * Historically, '|' characters in the first argument of the ex, edit,
- * next, vi visual, and s commands didn't delimit the command. And,
- * in the filter cases for read and write, and the bang, global and v
- * commands, they did not delimit the command at all.
- *
- * For example, the following commands were legal:
- *
- * :edit +25|s/abc/ABC/ file.c
- * :s/|/PIPE/
- * :read !spell % | columnate
- * :global/pattern/p|l
- *
- * It's not quite as simple as it sounds, however. The command:
- *
- * :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 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
- * do normal command processing on whatever is left. Barf-O-Rama.
- */
- discard = 0; /* Characters discarded from the command. */
- arg1_len = 0;
- ecp->save_cmd = ecp->cp;
- if (ecp->cmd == &cmds[C_EDIT] || ecp->cmd == &cmds[C_EX] ||
- ecp->cmd == &cmds[C_NEXT] || ecp->cmd == &cmds[C_VISUAL_VI]) {
- /*
- * Move to the next non-whitespace character. A '!'
- * immediately following the command is eaten as a
- * force flag.
- */
- if (ecp->clen > 0 && *ecp->cp == '!') {
- ++ecp->cp;
- --ecp->clen;
- FL_SET(ecp->iflags, E_C_FORCE);
-
- /* Reset, don't reparse. */
- ecp->save_cmd = ecp->cp;
- }
- for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
- if (!isblank(*ecp->cp))
- break;
- /*
- * QUOTING NOTE:
- *
- * 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. The escaping
- * characters are stripped as no longer useful.
- */
- if (ecp->clen > 0 && *ecp->cp == '+') {
- ++ecp->cp;
- --ecp->clen;
- for (arg1 = p = ecp->cp;
- ecp->clen > 0; --ecp->clen, ++ecp->cp) {
- ch = *ecp->cp;
- if (IS_ESCAPE(sp, ecp, ch) &&
- ecp->clen > 1) {
- ++discard;
- --ecp->clen;
- ch = *++ecp->cp;
- } else if (isblank(ch))
- break;
- *p++ = ch;
- }
- arg1_len = ecp->cp - arg1;
-
- /* Reset, so the first argument isn't reparsed. */
- ecp->save_cmd = ecp->cp;
- }
- } else if (ecp->cmd == &cmds[C_BANG] ||
- ecp->cmd == &cmds[C_GLOBAL] || ecp->cmd == &cmds[C_V]) {
- /*
- * QUOTING NOTE:
- *
- * We use backslashes to escape <newline> characters, although
- * this wasn't historic practice for the bang command. It was
- * for the global and v commands, and it's common usage when
- * doing text insert during the command. Escaping characters
- * are stripped as no longer useful.
- */
- for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
- ch = *ecp->cp;
- if (ch == '\\' && ecp->clen > 1 && ecp->cp[1] == '\n') {
- ++discard;
- --ecp->clen;
- ch = *++ecp->cp;
-
- ++gp->if_lno;
- ++ecp->if_lno;
- } else if (ch == '\n')
- break;
- *p++ = ch;
- }
- } else if (ecp->cmd == &cmds[C_READ] || ecp->cmd == &cmds[C_WRITE]) {
- /*
- * 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 (tmp = 0; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
- ch = *ecp->cp;
- if (isblank(ch))
- tmp = 1;
- else
- break;
- }
- 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
- * the delimiter. If the character isn't an alphanumeric or
- * a '|', it's the delimiter, so parse it. Otherwise, we're
- * into something like ":s g", so use the special s command.
- */
- for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
- if (!isblank(ecp->cp[0]))
- break;
-
- if (isalnum(ecp->cp[0]) || ecp->cp[0] == '|') {
- ecp->rcmd = cmds[C_SUBSTITUTE];
- ecp->rcmd.fn = ex_subagain;
- ecp->cmd = &ecp->rcmd;
- } else if (ecp->clen > 0) {
- /*
- * QUOTING NOTE:
- *
- * Backslashes quote delimiter characters for RE's.
- * The backslashes are NOT removed since they'll be
- * used by the RE code. Move to the third delimiter
- * that's not escaped (or the end of the command).
- */
- delim = *ecp->cp;
- ++ecp->cp;
- --ecp->clen;
- for (cnt = 2; ecp->clen > 0 &&
- cnt != 0; --ecp->clen, ++ecp->cp)
- if (ecp->cp[0] == '\\' &&
- ecp->clen > 1) {
- ++ecp->cp;
- --ecp->clen;
- } else if (ecp->cp[0] == delim)
- --cnt;
- }
- }
-
- /*
- * Use normal quoting and termination rules to find the end of this
- * command.
- *
- * QUOTING NOTE:
- *
- * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
- * file. It was almost certainly a bug, but that's what bug-for-bug
- * compatibility means, Grasshopper. Also, ^V's escape the command
- * delimiters. Literal next quote characters in front of the newlines,
- * '|' characters or literal next characters are stripped as they're
- * no longer useful.
- */
- vi_address = ecp->clen != 0 && ecp->cp[0] != '\n';
- for (p = ecp->cp; ecp->clen > 0; --ecp->clen, ++ecp->cp) {
- ch = ecp->cp[0];
- if (IS_ESCAPE(sp, ecp, ch) && ecp->clen > 1) {
- tmp = ecp->cp[1];
- if (tmp == '\n' || tmp == '|') {
- if (tmp == '\n') {
- ++gp->if_lno;
- ++ecp->if_lno;
- }
- ++discard;
- --ecp->clen;
- ++ecp->cp;
- ch = tmp;
- }
- } else if (ch == '\n' || ch == '|') {
- if (ch == '\n')
- F_SET(ecp, E_NEWLINE);
- --ecp->clen;
- break;
- }
- *p++ = ch;
- }
-
- /*
- * Save off the next command information, go back to the
- * original start of the command.
- */
- p = ecp->cp + 1;
- ecp->cp = ecp->save_cmd;
- ecp->save_cmd = p;
- ecp->save_cmdlen = ecp->clen;
- ecp->clen = ((ecp->save_cmd - ecp->cp) - 1) - discard;
-
- /*
- * QUOTING NOTE:
- *
- * The "set tags" command historically used a backslash, not the
- * user's literal next character, to escape whitespace. Handle
- * it here instead of complicating the argv_exp3() code. Note,
- * this isn't a particularly complex trap, and if backslashes were
- * legal in set commands, this would have to be much more complicated.
- */
- if (ecp->cmd == &cmds[C_SET])
- for (p = ecp->cp, len = ecp->clen; len > 0; --len, ++p)
- if (*p == '\\')
- *p = CH_LITERAL;
-
- /*
- * Set the default addresses. It's an error to specify an address for
- * a command that doesn't take them. If two addresses are specified
- * for a command that only takes one, lose the first one. Two special
- * cases here, some commands take 0 or 2 addresses. For most of them
- * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
- * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
- *
- * Also, if the file is empty, some commands want to use an address of
- * 0, i.e. the entire file is 0 to 0, and the default first address is
- * 0. Otherwise, an entire file is 1 to N and the default line is 1.
- * Note, we also add the E_ADDR_ZERO flag to the command flags, for the
- * 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 or if we just used
- * the current cursor.
- */
- switch (F_ISSET(ecp, E_ADDR1 | E_ADDR2 | E_ADDR2_ALL | E_ADDR2_NONE)) {
- case E_ADDR1: /* One address: */
- switch (ecp->addrcnt) {
- case 0: /* Default cursor/empty file. */
- ecp->addrcnt = 1;
- F_SET(ecp, E_ADDR_DEF);
- if (F_ISSET(ecp, E_ADDR_ZERODEF)) {
- if (db_last(sp, &lno))
- goto err;
- if (lno == 0) {
- ecp->addr1.lno = 0;
- F_SET(ecp, E_ADDR_ZERO);
- } else
- ecp->addr1.lno = sp->lno;
- } else
- ecp->addr1.lno = sp->lno;
- ecp->addr1.cno = sp->cno;
- break;
- case 1:
- break;
- case 2: /* Lose the first address. */
- ecp->addrcnt = 1;
- ecp->addr1 = ecp->addr2;
- }
- break;
- case E_ADDR2_NONE: /* Zero/two addresses: */
- if (ecp->addrcnt == 0) /* Default to nothing. */
- break;
- goto two_addr;
- case E_ADDR2_ALL: /* Zero/two addresses: */
- if (ecp->addrcnt == 0) { /* Default entire/empty file. */
- F_SET(ecp, E_ADDR_DEF);
- ecp->addrcnt = 2;
- if (sp->ep == NULL)
- ecp->addr2.lno = 0;
- else if (db_last(sp, &ecp->addr2.lno))
- goto err;
- if (F_ISSET(ecp, E_ADDR_ZERODEF) &&
- ecp->addr2.lno == 0) {
- ecp->addr1.lno = 0;
- F_SET(ecp, E_ADDR_ZERO);
- } else
- ecp->addr1.lno = 1;
- ecp->addr1.cno = ecp->addr2.cno = 0;
- F_SET(ecp, E_ADDR2_ALL);
- break;
- }
- /* FALLTHROUGH */
- case E_ADDR2: /* Two addresses: */
-two_addr: switch (ecp->addrcnt) {
- case 0: /* Default cursor/empty file. */
- ecp->addrcnt = 2;
- F_SET(ecp, E_ADDR_DEF);
- if (sp->lno == 1 &&
- F_ISSET(ecp, E_ADDR_ZERODEF)) {
- if (db_last(sp, &lno))
- goto err;
- if (lno == 0) {
- ecp->addr1.lno = ecp->addr2.lno = 0;
- F_SET(ecp, E_ADDR_ZERO);
- } else
- ecp->addr1.lno =
- ecp->addr2.lno = sp->lno;
- } else
- ecp->addr1.lno = ecp->addr2.lno = sp->lno;
- ecp->addr1.cno = ecp->addr2.cno = sp->cno;
- break;
- case 1: /* Default to first address. */
- ecp->addrcnt = 2;
- ecp->addr2 = ecp->addr1;
- break;
- case 2:
- break;
- }
- break;
- default:
- if (ecp->addrcnt) /* Error. */
- goto usage;
- }
-
- /*
- * !!!
- * The ^D scroll command historically scrolled the value of the scroll
- * option or to EOF. It was an error if the cursor was already at EOF.
- * (Leading addresses were permitted, but were then ignored.)
- */
- if (ecp->cmd == &cmds[C_SCROLL]) {
- ecp->addrcnt = 2;
- ecp->addr1.lno = sp->lno + 1;
- ecp->addr2.lno = sp->lno + O_VAL(sp, O_SCROLL);
- ecp->addr1.cno = ecp->addr2.cno = sp->cno;
- if (db_last(sp, &lno))
- goto err;
- if (lno != 0 && lno > sp->lno && ecp->addr2.lno > lno)
- ecp->addr2.lno = lno;
- }
-
- ecp->flagoff = 0;
- for (p = ecp->cmd->syntax; *p != '\0'; ++p) {
- /*
- * The force flag is sensitive to leading whitespace, i.e.
- * "next !" is different from "next!". Handle it before
- * skipping leading <blank>s.
- */
- if (*p == '!') {
- if (ecp->clen > 0 && *ecp->cp == '!') {
- ++ecp->cp;
- --ecp->clen;
- FL_SET(ecp->iflags, E_C_FORCE);
- }
- continue;
- }
-
- /* Skip leading <blank>s. */
- for (; ecp->clen > 0; --ecp->clen, ++ecp->cp)
- if (!isblank(*ecp->cp))
- break;
- if (ecp->clen == 0)
- break;
-
- switch (*p) {
- case '1': /* +, -, #, l, p */
- /*
- * !!!
- * Historically, some flags were ignored depending
- * on where they occurred in the command line. For
- * example, in the command, ":3+++p--#", historic vi
- * acted on the '#' flag, but ignored the '-' flags.
- * It's unambiguous what the flags mean, so we just
- * handle them regardless of the stupidity of their
- * location.
- */
- for (; ecp->clen; --ecp->clen, ++ecp->cp)
- switch (*ecp->cp) {
- case '+':
- ++ecp->flagoff;
- break;
- case '-':
- case '^':
- --ecp->flagoff;
- break;
- case '#':
- F_CLR(ecp, E_OPTNUM);
- FL_SET(ecp->iflags, E_C_HASH);
- exp->fdef |= E_C_HASH;
- break;
- case 'l':
- FL_SET(ecp->iflags, E_C_LIST);
- exp->fdef |= E_C_LIST;
- break;
- case 'p':
- FL_SET(ecp->iflags, E_C_PRINT);
- exp->fdef |= E_C_PRINT;
- break;
- default:
- goto end_case1;
- }
-end_case1: break;
- case '2': /* -, ., +, ^ */
- case '3': /* -, ., +, ^, = */
- for (; ecp->clen; --ecp->clen, ++ecp->cp)
- switch (*ecp->cp) {
- case '-':
- FL_SET(ecp->iflags, E_C_DASH);
- break;
- case '.':
- FL_SET(ecp->iflags, E_C_DOT);
- break;
- case '+':
- FL_SET(ecp->iflags, E_C_PLUS);
- break;
- case '^':
- FL_SET(ecp->iflags, E_C_CARAT);
- break;
- case '=':
- if (*p == '3') {
- FL_SET(ecp->iflags, E_C_EQUAL);
- break;
- }
- /* FALLTHROUGH */
- default:
- goto end_case23;
- }
-end_case23: break;
- case 'b': /* buffer */
- /*
- * !!!
- * Historically, "d #" was a delete with a flag, not a
- * delete into the '#' buffer. If the current command
- * permits a flag, don't use one as a buffer. However,
- * the 'l' and 'p' flags were legal buffer names in the
- * historic ex, and were used as buffers, not flags.
- */
- if ((ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
- ecp->cp[0] == '^' || ecp->cp[0] == '#') &&
- strchr(p, '1') != NULL)
- break;
- /*
- * !!!
- * Digits can't be buffer names in ex commands, or the
- * command "d2" would be a delete into buffer '2', and
- * not a two-line deletion.
- */
- if (!isdigit(ecp->cp[0])) {
- ecp->buffer = *ecp->cp;
- ++ecp->cp;
- --ecp->clen;
- FL_SET(ecp->iflags, E_C_BUFFER);
- }
- break;
- case 'c': /* count [01+a] */
- ++p;
- /* Validate any signed value. */
- if (!isdigit(*ecp->cp) && (*p != '+' ||
- (*ecp->cp != '+' && *ecp->cp != '-')))
- break;
- /* If a signed value, set appropriate flags. */
- if (*ecp->cp == '-')
- FL_SET(ecp->iflags, E_C_COUNT_NEG);
- else if (*ecp->cp == '+')
- FL_SET(ecp->iflags, E_C_COUNT_POS);
- if ((nret =
- nget_slong(&ltmp, ecp->cp, &t, 10)) != NUM_OK) {
- ex_badaddr(sp, NULL, A_NOTSET, nret);
- goto err;
- }
- if (ltmp == 0 && *p != '0') {
- msgq(sp, M_ERR, "083|Count may not be zero");
- goto err;
- }
- ecp->clen -= (t - ecp->cp);
- ecp->cp = t;
-
- /*
- * Counts as address offsets occur in commands taking
- * two addresses. Historic vi practice was to use
- * the count as an offset from the *second* address.
- *
- * Set a count flag; some underlying commands (see
- * join) do different things with counts than with
- * line addresses.
- */
- if (*p == 'a') {
- ecp->addr1 = ecp->addr2;
- ecp->addr2.lno = ecp->addr1.lno + ltmp - 1;
- } else
- ecp->count = ltmp;
- FL_SET(ecp->iflags, E_C_COUNT);
- break;
- case 'f': /* file */
- if (argv_exp2(sp, ecp, ecp->cp, ecp->clen))
- goto err;
- goto arg_cnt_chk;
- case 'l': /* line */
- /*
- * Get a line specification.
- *
- * If the line was a search expression, we may have
- * changed state during the call, and we're now
- * searching the file. Push ourselves onto the state
- * stack.
- */
- if (ex_line(sp, ecp, &cur, &isaddr, &tmp))
- goto rfail;
- if (tmp)
- goto err;
-
- /* Line specifications are always required. */
- if (!isaddr) {
- msgq_str(sp, M_ERR, ecp->cp,
- "084|%s: bad line specification");
- goto err;
- }
- /*
- * The target line should exist for these commands,
- * but 0 is legal for them as well.
- */
- if (cur.lno != 0 && !db_exist(sp, cur.lno)) {
- ex_badaddr(sp, NULL, A_EOF, NUM_OK);
- goto err;
- }
- ecp->lineno = cur.lno;
- break;
- case 'S': /* string, file exp. */
- if (ecp->clen != 0) {
- if (argv_exp1(sp, ecp, ecp->cp,
- ecp->clen, ecp->cmd == &cmds[C_BANG]))
- goto err;
- goto addr_verify;
- }
- /* FALLTHROUGH */
- case 's': /* string */
- if (argv_exp0(sp, ecp, ecp->cp, ecp->clen))
- goto err;
- goto addr_verify;
- case 'W': /* word string */
- /*
- * QUOTING NOTE:
- *
- * Literal next characters escape the following
- * character. Quoting characters are stripped here
- * since they are no longer useful.
- *
- * First there was the word.
- */
- for (p = t = ecp->cp;
- ecp->clen > 0; --ecp->clen, ++ecp->cp) {
- ch = *ecp->cp;
- if (IS_ESCAPE(sp,
- ecp, ch) && ecp->clen > 1) {
- --ecp->clen;
- *p++ = *++ecp->cp;
- } else if (isblank(ch)) {
- ++ecp->cp;
- --ecp->clen;
- break;
- } else
- *p++ = ch;
- }
- if (argv_exp0(sp, ecp, t, p - t))
- goto err;
-
- /* Delete intervening whitespace. */
- for (; ecp->clen > 0;
- --ecp->clen, ++ecp->cp) {
- ch = *ecp->cp;
- if (!isblank(ch))
- break;
- }
- if (ecp->clen == 0)
- goto usage;
-
- /* Followed by the string. */
- for (p = t = ecp->cp; ecp->clen > 0;
- --ecp->clen, ++ecp->cp, ++p) {
- ch = *ecp->cp;
- if (IS_ESCAPE(sp,
- ecp, ch) && ecp->clen > 1) {
- --ecp->clen;
- *p = *++ecp->cp;
- } else
- *p = ch;
- }
- if (argv_exp0(sp, ecp, t, p - t))
- goto err;
- goto addr_verify;
- case 'w': /* word */
- if (argv_exp3(sp, ecp, ecp->cp, ecp->clen))
- goto err;
-arg_cnt_chk: if (*++p != 'N') { /* N */
- /*
- * If a number is specified, must either be
- * 0 or that number, if optional, and that
- * number, if required.
- */
- tmp = *p - '0';
- if ((*++p != 'o' || exp->argsoff != 0) &&
- exp->argsoff != tmp)
- goto usage;
- }
- goto addr_verify;
- default:
- msgq(sp, M_ERR,
- "085|Internal syntax table error (%s: %s)",
- ecp->cmd->name, KEY_NAME(sp, *p));
- }
- }
-
- /* Skip trailing whitespace. */
- for (; ecp->clen > 0; --ecp->clen) {
- ch = *ecp->cp++;
- if (!isblank(ch))
- break;
- }
-
- /*
- * There shouldn't be anything left, and no more required fields,
- * i.e neither 'l' or 'r' in the syntax string.
- */
- if (ecp->clen != 0 || strpbrk(p, "lr")) {
-usage: msgq(sp, M_ERR, "086|Usage: %s", ecp->cmd->usage);
- goto err;
- }
-
- /*
- * 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 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.
- *
- * If it's a "default vi command", an address of zero is okay.
- */
-addr_verify:
- switch (ecp->addrcnt) {
- case 2:
- /*
- * Historic ex/vi permitted commands with counts to go past
- * EOF. So, for example, if the file only had 5 lines, the
- * ex command "1,6>" would fail, but the command ">300"
- * would succeed. Since we don't want to have to make all
- * of the underlying commands handle random line numbers,
- * fix it here.
- */
- if (ecp->addr2.lno == 0) {
- if (!F_ISSET(ecp, E_ADDR_ZERO) &&
- (F_ISSET(sp, SC_EX) ||
- !F_ISSET(ecp, E_USELASTCMD))) {
- ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
- goto err;
- }
- } else if (!db_exist(sp, ecp->addr2.lno))
- if (FL_ISSET(ecp->iflags, E_C_COUNT)) {
- if (db_last(sp, &lno))
- goto err;
- ecp->addr2.lno = lno;
- } else {
- ex_badaddr(sp, NULL, A_EOF, NUM_OK);
- goto err;
- }
- /* FALLTHROUGH */
- case 1:
- if (ecp->addr1.lno == 0) {
- if (!F_ISSET(ecp, E_ADDR_ZERO) &&
- (F_ISSET(sp, SC_EX) ||
- !F_ISSET(ecp, E_USELASTCMD))) {
- ex_badaddr(sp, ecp->cmd, A_ZERO, NUM_OK);
- goto err;
- }
- } else if (!db_exist(sp, ecp->addr1.lno)) {
- ex_badaddr(sp, NULL, A_EOF, NUM_OK);
- goto err;
- }
- break;
- }
-
- /*
- * If doing a default command and there's nothing left on the line,
- * vi just moves to the line. For example, ":3" and ":'a,'b" just
- * move to line 3 and line 'b, respectively, but ":3|" prints line 3.
- *
- * !!!
- * In addition, IF THE LINE CHANGES, move to the first nonblank of
- * the line.
- *
- * !!!
- * This is done before the absolute mark gets set; historically,
- * "/a/,/b/" did NOT set vi's absolute mark, but "/a/,/b/d" did.
- */
- if ((F_ISSET(sp, SC_VI) || F_ISSET(ecp, E_NOPRDEF)) &&
- F_ISSET(ecp, E_USELASTCMD) && vi_address == 0) {
- switch (ecp->addrcnt) {
- case 2:
- if (sp->lno !=
- (ecp->addr2.lno ? ecp->addr2.lno : 1)) {
- sp->lno =
- ecp->addr2.lno ? ecp->addr2.lno : 1;
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- }
- break;
- case 1:
- if (sp->lno !=
- (ecp->addr1.lno ? ecp->addr1.lno : 1)) {
- sp->lno =
- ecp->addr1.lno ? ecp->addr1.lno : 1;
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- }
- break;
- }
- ecp->cp = ecp->save_cmd;
- ecp->clen = ecp->save_cmdlen;
- goto loop;
- }
-
- /*
- * Set the absolute mark -- we have to set it for vi here, in case
- * it's a compound command, e.g. ":5p|6" should set the absolute
- * mark for vi.
- */
- if (F_ISSET(ecp, E_ABSMARK)) {
- cur.lno = sp->lno;
- cur.cno = sp->cno;
- F_CLR(ecp, E_ABSMARK);
- if (mark_set(sp, ABSMARK1, &cur, 1))
- goto err;
- }
-
-#if defined(DEBUG) && defined(COMLOG)
- ex_comlog(sp, ecp);
-#endif
- /* Increment the command count if not called from vi. */
- if (F_ISSET(sp, SC_EX))
- ++sp->ccnt;
-
- /*
- * If file state available, and not doing a global command,
- * log the start of an action.
- */
- if (sp->ep != NULL && !F_ISSET(sp, SC_EX_GLOBAL))
- (void)log_cursor(sp);
-
- /*
- * !!!
- * There are two special commands for the purposes of this code: the
- * default command (<carriage-return>) or the scrolling commands (^D
- * and <EOF>) as the first non-<blank> characters in the line.
- *
- * If this is the first command in the command line, we received the
- * command from the ex command loop and we're talking to a tty, and
- * and there's nothing else on the command line, and it's one of the
- * special commands, we move back up to the previous line, and erase
- * the prompt character with the output. Since ex runs in canonical
- * mode, we don't have to do anything else, a <newline> has already
- * been echoed by the tty driver. It's OK if vi calls us -- we won't
- * be in ex mode so we'll do nothing.
- */
- if (F_ISSET(ecp, E_NRSEP)) {
- if (sp->ep != NULL &&
- F_ISSET(sp, SC_EX) && !F_ISSET(gp, G_SCRIPTED) &&
- (F_ISSET(ecp, E_USELASTCMD) || ecp->cmd == &cmds[C_SCROLL]))
- gp->scr_ex_adjust(sp, EX_TERM_SCROLL);
- F_CLR(ecp, E_NRSEP);
- }
-
- /*
- * Call the underlying function for the ex command.
- *
- * XXX
- * Interrupts behave like errors, for now.
- */
- if (ecp->cmd->fn(sp, ecp) || INTERRUPTED(sp)) {
- if (F_ISSET(gp, G_SCRIPTED))
- F_SET(sp, SC_EXIT_FORCE);
- goto err;
- }
-
-#ifdef DEBUG
- /* Make sure no function left global temporary space locked. */
- if (F_ISSET(gp, G_TMP_INUSE)) {
- F_CLR(gp, G_TMP_INUSE);
- msgq(sp, M_ERR, "087|%s: temporary buffer not released",
- ecp->cmd->name);
- }
-#endif
- /*
- * Ex displayed the number of lines modified immediately after each
- * command, so the command "1,10d|1,10d" would display:
- *
- * 10 lines deleted
- * 10 lines deleted
- * <autoprint line>
- *
- * Executing ex commands from vi only reported the final modified
- * lines message -- that's wrong enough that we don't match it.
- */
- if (F_ISSET(sp, SC_EX))
- mod_rpt(sp);
-
- /*
- * Integrate any offset parsed by the underlying command, and make
- * sure the referenced line exists.
- *
- * XXX
- * May not match historic practice (which I've never been able to
- * completely figure out.) For example, the '=' command from vi
- * mode often got the offset wrong, and complained it was too large,
- * but didn't seem to have a problem with the cursor. If anyone
- * complains, ask them how it's supposed to work, they might know.
- */
- if (sp->ep != NULL && ecp->flagoff) {
- if (ecp->flagoff < 0) {
- if (sp->lno <= -ecp->flagoff) {
- msgq(sp, M_ERR,
- "088|Flag offset to before line 1");
- goto err;
- }
- } else {
- if (!NPFITS(MAX_REC_NUMBER, sp->lno, ecp->flagoff)) {
- ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
- goto err;
- }
- if (!db_exist(sp, sp->lno + ecp->flagoff)) {
- msgq(sp, M_ERR,
- "089|Flag offset past end-of-file");
- goto err;
- }
- }
- sp->lno += ecp->flagoff;
- }
-
- /*
- * 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) {
- /*
- * The print commands have already handled the `print' flags.
- * If so, clear them.
- */
- if (FL_ISSET(ecp->iflags, E_CLRFLAG))
- FL_CLR(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT);
-
- /* If hash set only because of the number option, discard it. */
- if (F_ISSET(ecp, E_OPTNUM))
- FL_CLR(ecp->iflags, E_C_HASH);
-
- /*
- * If there was an explicit flag to display the new cursor line,
- * or autoprint is set and a change was made, display the line.
- * If any print flags were set use them, else default to print.
- */
- LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT));
- if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO) &&
- !F_ISSET(sp, SC_EX_GLOBAL) &&
- O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT))
- LF_INIT(E_C_PRINT);
-
- if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)) {
- cur.lno = sp->lno;
- cur.cno = 0;
- (void)ex_print(sp, ecp, &cur, &cur, flags);
- }
- }
-
- /*
- * If the command had an associated "+cmd", it has to be executed
- * before we finish executing any more of this ex command. For
- * example, consider a .exrc file that contains the following lines:
- *
- * :set all
- * :edit +25 file.c|s/abc/ABC/|1
- * :3,5 print
- *
- * This can happen more than once -- the historic vi simply hung or
- * dropped core, of course. Prepend the + command back into the
- * current command and continue. We may have to add an additional
- * <literal next> character. We know that it will fit because we
- * discarded at least one space and the + character.
- */
- if (arg1_len != 0) {
- /*
- * If the last character of the + command was a <literal next>
- * character, it would be treated differently because of the
- * append. Quote it, if necessary.
- */
- if (IS_ESCAPE(sp, ecp, arg1[arg1_len - 1])) {
- *--ecp->save_cmd = CH_LITERAL;
- ++ecp->save_cmdlen;
- }
-
- ecp->save_cmd -= arg1_len;
- ecp->save_cmdlen += arg1_len;
- memcpy(ecp->save_cmd, arg1, arg1_len);
-
- /*
- * Any commands executed from a +cmd are executed starting at
- * the first column of the last line of the file -- NOT the
- * first nonblank.) The main file startup code doesn't know
- * that a +cmd was set, however, so it may have put us at the
- * top of the file. (Note, this is safe because we must have
- * switched files to get here.)
- */
- F_SET(ecp, E_MOVETOEND);
- }
-
- /* Update the current command. */
- ecp->cp = ecp->save_cmd;
- ecp->clen = ecp->save_cmdlen;
-
- /*
- * !!!
- * If we've changed screens or underlying files, any pending global or
- * v command, or @ buffer that has associated addresses, has to be
- * discarded. This is historic practice for globals, and necessary for
- * @ buffers that had associated addresses.
- *
- * Otherwise, if we've changed underlying files, it's not a problem,
- * we continue with the rest of the ex command(s), operating on the
- * new file. However, if we switch screens (either by exiting or by
- * an explicit command), we have no way of knowing where to put output
- * messages, and, since we don't control screens here, we could screw
- * up the upper layers, (e.g. we could exit/reenter a screen multiple
- * times). So, return and continue after we've got a new screen.
- */
- if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_FSWITCH | SC_SSWITCH)) {
- at_found = gv_found = 0;
- for (ecp = sp->gp->ecq.lh_first;
- ecp != NULL; ecp = ecp->q.le_next)
- switch (ecp->agv_flags) {
- case 0:
- case AGV_AT_NORANGE:
- break;
- case AGV_AT:
- if (!at_found) {
- at_found = 1;
- msgq(sp, M_ERR,
- "090|@ with range running when the file/screen changed");
- }
- break;
- case AGV_GLOBAL:
- case AGV_V:
- if (!gv_found) {
- gv_found = 1;
- msgq(sp, M_ERR,
- "091|Global/v command running when the file/screen changed");
- }
- break;
- default:
- abort();
- }
- if (at_found || gv_found)
- goto discard;
- if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE | SC_SSWITCH))
- goto rsuccess;
- }
-
- goto loop;
- /* NOTREACHED */
-
-err: /*
- * On command failure, we discard keys and pending commands remaining,
- * as well as any keys that were mapped and waiting. The save_cmdlen
- * test is not necessarily correct. If we fail early enough we don't
- * know if the entire string was a single command or not. Guess, as
- * it's useful to know if commands other than the current one are being
- * discarded.
- */
- if (ecp->save_cmdlen == 0)
- for (; ecp->clen; --ecp->clen) {
- ch = *ecp->cp++;
- if (IS_ESCAPE(sp, ecp, ch) && ecp->clen > 1) {
- --ecp->clen;
- ++ecp->cp;
- } else if (ch == '\n' || ch == '|') {
- if (ecp->clen > 1)
- ecp->save_cmdlen = 1;
- break;
- }
- }
- if (ecp->save_cmdlen != 0 || gp->ecq.lh_first != &gp->excmd) {
-discard: msgq(sp, M_BERR,
- "092|Ex command failed: pending commands discarded");
- ex_discard(sp);
- }
- if (v_event_flush(sp, CH_MAPPED))
- msgq(sp, M_BERR,
- "093|Ex command failed: mapped keys discarded");
-
-rfail: tmp = 1;
- if (0)
-rsuccess: tmp = 0;
-
- /* Turn off any file name error information. */
- gp->if_name = NULL;
-
- /* Turn off the global bit. */
- F_CLR(sp, SC_EX_GLOBAL);
-
- return (tmp);
-}
-
-/*
- * ex_range --
- * Get a line range for ex commands, or perform a vi ex address search.
- *
- * PUBLIC: int ex_range __P((SCR *, EXCMD *, int *));
- */
-int
-ex_range(sp, ecp, errp)
- SCR *sp;
- EXCMD *ecp;
- int *errp;
-{
- enum { ADDR_FOUND, ADDR_NEED, ADDR_NONE } addr;
- GS *gp;
- EX_PRIVATE *exp;
- MARK m;
- int isaddr;
-
- *errp = 0;
-
- /*
- * Parse comma or semi-colon delimited line specs.
- *
- * Semi-colon delimiters update the current address to be the last
- * address. For example, the command
- *
- * :3;/pattern/ecp->cp
- *
- * will search for pattern from line 3. In addition, if ecp->cp
- * is not a valid command, the current line will be left at 3, not
- * at the original address.
- *
- * Extra addresses are discarded, starting with the first.
- *
- * !!!
- * If any addresses are missing, they default to the current line.
- * This was historically true for both leading and trailing comma
- * delimited addresses as well as for trailing semicolon delimited
- * addresses. For consistency, we make it true for leading semicolon
- * addresses as well.
- */
- gp = sp->gp;
- exp = EXP(sp);
- for (addr = ADDR_NONE, ecp->addrcnt = 0; ecp->clen > 0;)
- switch (*ecp->cp) {
- case '%': /* Entire file. */
- /* Vi ex address searches didn't permit % signs. */
- if (F_ISSET(ecp, E_VISEARCH))
- goto ret;
-
- /* It's an error if the file is empty. */
- if (sp->ep == NULL) {
- ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
- *errp = 1;
- return (0);
- }
- /*
- * !!!
- * A percent character addresses all of the lines in
- * the file. Historically, it couldn't be followed by
- * any other address. We do it as a text substitution
- * for simplicity. POSIX 1003.2 is expected to follow
- * this practice.
- *
- * If it's an empty file, the first line is 0, not 1.
- */
- if (addr == ADDR_FOUND) {
- ex_badaddr(sp, NULL, A_COMBO, NUM_OK);
- *errp = 1;
- return (0);
- }
- if (db_last(sp, &ecp->addr2.lno))
- return (1);
- ecp->addr1.lno = ecp->addr2.lno == 0 ? 0 : 1;
- ecp->addr1.cno = ecp->addr2.cno = 0;
- ecp->addrcnt = 2;
- addr = ADDR_FOUND;
- ++ecp->cp;
- --ecp->clen;
- break;
- case ',': /* Comma delimiter. */
- /* Vi ex address searches didn't permit commas. */
- if (F_ISSET(ecp, E_VISEARCH))
- goto ret;
- /* FALLTHROUGH */
- case ';': /* Semi-colon delimiter. */
- if (sp->ep == NULL) {
- ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
- *errp = 1;
- return (0);
- }
- if (addr != ADDR_FOUND)
- switch (ecp->addrcnt) {
- case 0:
- ecp->addr1.lno = sp->lno;
- ecp->addr1.cno = sp->cno;
- ecp->addrcnt = 1;
- break;
- case 2:
- ecp->addr1 = ecp->addr2;
- /* FALLTHROUGH */
- case 1:
- ecp->addr2.lno = sp->lno;
- ecp->addr2.cno = sp->cno;
- ecp->addrcnt = 2;
- break;
- }
- if (*ecp->cp == ';')
- switch (ecp->addrcnt) {
- case 0:
- abort();
- /* NOTREACHED */
- case 1:
- sp->lno = ecp->addr1.lno;
- sp->cno = ecp->addr1.cno;
- break;
- case 2:
- sp->lno = ecp->addr2.lno;
- sp->cno = ecp->addr2.cno;
- break;
- }
- addr = ADDR_NEED;
- /* FALLTHROUGH */
- case ' ': /* Whitespace. */
- case '\t': /* Whitespace. */
- ++ecp->cp;
- --ecp->clen;
- break;
- default:
- /* Get a line specification. */
- if (ex_line(sp, ecp, &m, &isaddr, errp))
- return (1);
- if (*errp)
- return (0);
- if (!isaddr)
- goto ret;
- if (addr == ADDR_FOUND) {
- ex_badaddr(sp, NULL, A_COMBO, NUM_OK);
- *errp = 1;
- return (0);
- }
- switch (ecp->addrcnt) {
- case 0:
- ecp->addr1 = m;
- ecp->addrcnt = 1;
- break;
- case 1:
- ecp->addr2 = m;
- ecp->addrcnt = 2;
- break;
- case 2:
- ecp->addr1 = ecp->addr2;
- ecp->addr2 = m;
- break;
- }
- addr = ADDR_FOUND;
- break;
- }
-
- /*
- * !!!
- * Vi ex address searches are indifferent to order or trailing
- * semi-colons.
- */
-ret: if (F_ISSET(ecp, E_VISEARCH))
- return (0);
-
- if (addr == ADDR_NEED)
- switch (ecp->addrcnt) {
- case 0:
- ecp->addr1.lno = sp->lno;
- ecp->addr1.cno = sp->cno;
- ecp->addrcnt = 1;
- break;
- case 2:
- ecp->addr1 = ecp->addr2;
- /* FALLTHROUGH */
- case 1:
- ecp->addr2.lno = sp->lno;
- ecp->addr2.cno = sp->cno;
- ecp->addrcnt = 2;
- break;
- }
-
- if (ecp->addrcnt == 2 && ecp->addr2.lno < ecp->addr1.lno) {
- msgq(sp, M_ERR,
- "094|The second address is smaller than the first");
- *errp = 1;
- }
- return (0);
-}
-
-/*
- * ex_line --
- * Get a single line address specifier.
- *
- * The way the "previous context" mark worked was that any "non-relative"
- * motion set it. While ex/vi wasn't totally consistent about this, ANY
- * numeric address, search pattern, '$', or mark reference in an address
- * was considered non-relative, and set the value. Which should explain
- * why we're hacking marks down here. The problem was that the mark was
- * only set if the command was called, i.e. we have to set a flag and test
- * it later.
- *
- * XXX
- * This is probably still not exactly historic practice, although I think
- * it's fairly close.
- */
-static int
-ex_line(sp, ecp, mp, isaddrp, errp)
- SCR *sp;
- EXCMD *ecp;
- MARK *mp;
- int *isaddrp, *errp;
-{
- enum nresult nret;
- EX_PRIVATE *exp;
- GS *gp;
- long total, val;
- int isneg;
- int (*sf) __P((SCR *, MARK *, MARK *, char *, size_t, char **, u_int));
- char *endp;
-
- gp = sp->gp;
- exp = EXP(sp);
-
- *isaddrp = *errp = 0;
- F_CLR(ecp, E_DELTA);
-
- /* No addresses permitted until a file has been read in. */
- if (sp->ep == NULL && strchr("$0123456789'\\/?.+-^", *ecp->cp)) {
- ex_badaddr(sp, NULL, A_EMPTY, NUM_OK);
- *errp = 1;
- return (0);
- }
-
- switch (*ecp->cp) {
- case '$': /* Last line in the file. */
- *isaddrp = 1;
- F_SET(ecp, E_ABSMARK);
-
- mp->cno = 0;
- if (db_last(sp, &mp->lno))
- return (1);
- ++ecp->cp;
- --ecp->clen;
- break; /* Absolute line number. */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- *isaddrp = 1;
- F_SET(ecp, E_ABSMARK);
-
- if ((nret = nget_slong(&val, ecp->cp, &endp, 10)) != NUM_OK) {
- ex_badaddr(sp, NULL, A_NOTSET, nret);
- *errp = 1;
- return (0);
- }
- if (!NPFITS(MAX_REC_NUMBER, 0, val)) {
- ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
- *errp = 1;
- return (0);
- }
- mp->lno = val;
- mp->cno = 0;
- ecp->clen -= (endp - ecp->cp);
- ecp->cp = endp;
- break;
- case '\'': /* Use a mark. */
- *isaddrp = 1;
- F_SET(ecp, E_ABSMARK);
-
- if (ecp->clen == 1) {
- msgq(sp, M_ERR, "095|No mark name supplied");
- *errp = 1;
- return (0);
- }
- if (mark_get(sp, ecp->cp[1], mp, M_ERR)) {
- *errp = 1;
- return (0);
- }
- ecp->cp += 2;
- ecp->clen -= 2;
- break;
- case '\\': /* Search: forward/backward. */
- /*
- * !!!
- * I can't find any difference between // and \/ or between
- * ?? and \?. Mark Horton doesn't remember there being any
- * difference. C'est la vie.
- */
- if (ecp->clen < 2 ||
- ecp->cp[1] != '/' && ecp->cp[1] != '?') {
- msgq(sp, M_ERR, "096|\\ not followed by / or ?");
- *errp = 1;
- return (0);
- }
- ++ecp->cp;
- --ecp->clen;
- sf = ecp->cp[0] == '/' ? f_search : b_search;
- goto search;
- case '/': /* Search forward. */
- sf = f_search;
- goto search;
- case '?': /* Search backward. */
- sf = b_search;
-
-search: mp->lno = sp->lno;
- mp->cno = sp->cno;
- if (sf(sp, mp, mp, ecp->cp, ecp->clen, &endp,
- SEARCH_MSG | SEARCH_PARSE | SEARCH_SET |
- (F_ISSET(ecp, E_SEARCH_WMSG) ? SEARCH_WMSG : 0))) {
- *errp = 1;
- return (0);
- }
-
- /* Fix up the command pointers. */
- ecp->clen -= (endp - ecp->cp);
- ecp->cp = endp;
-
- *isaddrp = 1;
- F_SET(ecp, E_ABSMARK);
- break;
- case '.': /* Current position. */
- *isaddrp = 1;
- mp->cno = sp->cno;
-
- /* If an empty file, then '.' is 0, not 1. */
- if (sp->lno == 1) {
- if (db_last(sp, &mp->lno))
- return (1);
- if (mp->lno != 0)
- mp->lno = 1;
- } else
- mp->lno = sp->lno;
-
- /*
- * !!!
- * Historically, .<number> was the same as .+<number>, i.e.
- * the '+' could be omitted. (This feature is found in ed
- * as well.)
- */
- if (ecp->clen > 1 && isdigit(ecp->cp[1]))
- *ecp->cp = '+';
- else {
- ++ecp->cp;
- --ecp->clen;
- }
- break;
- }
-
- /* Skip trailing <blank>s. */
- for (; ecp->clen > 0 &&
- isblank(ecp->cp[0]); ++ecp->cp, --ecp->clen);
-
- /*
- * Evaluate any offset. If no address yet found, the offset
- * is relative to ".".
- */
- total = 0;
- if (ecp->clen != 0 && (isdigit(ecp->cp[0]) ||
- ecp->cp[0] == '+' || ecp->cp[0] == '-' ||
- ecp->cp[0] == '^')) {
- if (!*isaddrp) {
- *isaddrp = 1;
- mp->lno = sp->lno;
- mp->cno = sp->cno;
- }
- /*
- * Evaluate an offset, defined as:
- *
- * [+-^<blank>]*[<blank>]*[0-9]*
- *
- * The rough translation is any number of signs, optionally
- * followed by numbers, or a number by itself, all <blank>
- * separated.
- *
- * !!!
- * All address offsets were additive, e.g. "2 2 3p" was the
- * same as "7p", or, "/ZZZ/ 2" was the same as "/ZZZ/+2".
- * Note, however, "2 /ZZZ/" was an error. It was also legal
- * to insert signs without numbers, so "3 - 2" was legal, and
- * equal to 4.
- *
- * !!!
- * Offsets were historically permitted for any line address,
- * e.g. the command "1,2 copy 2 2 2 2" copied lines 1,2 after
- * line 8.
- *
- * !!!
- * Offsets were historically permitted for search commands,
- * and handled as addresses: "/pattern/2 2 2" was legal, and
- * referenced the 6th line after pattern.
- */
- F_SET(ecp, E_DELTA);
- for (;;) {
- for (; ecp->clen > 0 && isblank(ecp->cp[0]);
- ++ecp->cp, --ecp->clen);
- if (ecp->clen == 0 || !isdigit(ecp->cp[0]) &&
- ecp->cp[0] != '+' && ecp->cp[0] != '-' &&
- ecp->cp[0] != '^')
- break;
- if (!isdigit(ecp->cp[0]) &&
- !isdigit(ecp->cp[1])) {
- total += ecp->cp[0] == '+' ? 1 : -1;
- --ecp->clen;
- ++ecp->cp;
- } else {
- if (ecp->cp[0] == '-' ||
- ecp->cp[0] == '^') {
- ++ecp->cp;
- --ecp->clen;
- isneg = 1;
- } else
- isneg = 0;
-
- /* Get a signed long, add it to the total. */
- if ((nret = nget_slong(&val,
- ecp->cp, &endp, 10)) != NUM_OK ||
- (nret = NADD_SLONG(sp,
- total, val)) != NUM_OK) {
- ex_badaddr(sp, NULL, A_NOTSET, nret);
- *errp = 1;
- return (0);
- }
- total += isneg ? -val : val;
- ecp->clen -= (endp - ecp->cp);
- ecp->cp = endp;
- }
- }
- }
-
- /*
- * Any value less than 0 is an error. Make sure that the new value
- * will fit into a recno_t.
- */
- if (*isaddrp && total != 0) {
- if (total < 0) {
- if (-total > mp->lno) {
- msgq(sp, M_ERR,
- "097|Reference to a line number less than 0");
- *errp = 1;
- return (0);
- }
- } else
- if (!NPFITS(MAX_REC_NUMBER, mp->lno, total)) {
- ex_badaddr(sp, NULL, A_NOTSET, NUM_OVER);
- *errp = 1;
- return (0);
- }
- mp->lno += total;
- }
- return (0);
-}
-
-
-/*
- * ex_load --
- * Load up the next command, which may be an @ buffer or global command.
- */
-static int
-ex_load(sp)
- SCR *sp;
-{
- GS *gp;
- EXCMD *ecp;
- RANGE *rp;
-
- F_CLR(sp, SC_EX_GLOBAL);
-
- /*
- * Lose any exhausted commands. We know that the first command
- * can't be an AGV command, which makes things a bit easier.
- */
- for (gp = sp->gp;;) {
- /*
- * If we're back to the original structure, leave it around,
- * but discard any allocated source name, we've returned to
- * the beginning of the command stack.
- */
- if ((ecp = gp->ecq.lh_first) == &gp->excmd) {
- if (F_ISSET(ecp, E_NAMEDISCARD)) {
- free(ecp->if_name);
- ecp->if_name = NULL;
- }
- return (0);
- }
-
- /*
- * ecp->clen will be 0 for the first discarded command, but
- * may not be 0 for subsequent ones, e.g. if the original
- * command was ":g/xx/@a|s/b/c/", then when we discard the
- * command pushed on the stack by the @a, we have to resume
- * the global command which included the substitute command.
- */
- if (ecp->clen != 0)
- return (0);
-
- /*
- * If it's an @, global or v command, we may need to continue
- * the command on a different line.
- */
- if (FL_ISSET(ecp->agv_flags, AGV_ALL)) {
- /* Discard any exhausted ranges. */
- while ((rp = ecp->rq.cqh_first) != (void *)&ecp->rq)
- if (rp->start > rp->stop) {
- CIRCLEQ_REMOVE(&ecp->rq, rp, q);
- free(rp);
- } else
- break;
-
- /* If there's another range, continue with it. */
- if (rp != (void *)&ecp->rq)
- break;
-
- /* If it's a global/v command, fix up the last line. */
- if (FL_ISSET(ecp->agv_flags,
- AGV_GLOBAL | AGV_V) && ecp->range_lno != OOBLNO)
- if (db_exist(sp, ecp->range_lno))
- sp->lno = ecp->range_lno;
- else {
- if (db_last(sp, &sp->lno))
- return (1);
- if (sp->lno == 0)
- sp->lno = 1;
- }
- free(ecp->o_cp);
- }
-
- /* Discard the EXCMD. */
- LIST_REMOVE(ecp, q);
- free(ecp);
- }
-
- /*
- * We only get here if it's an active @, global or v command. Set
- * the current line number, and get a new copy of the command for
- * the parser. Note, the original pointer almost certainly moved,
- * so we have play games.
- */
- ecp->cp = ecp->o_cp;
- memcpy(ecp->cp, ecp->cp + ecp->o_clen, ecp->o_clen);
- ecp->clen = ecp->o_clen;
- ecp->range_lno = sp->lno = rp->start++;
-
- if (FL_ISSET(ecp->agv_flags, AGV_GLOBAL | AGV_V))
- F_SET(sp, SC_EX_GLOBAL);
- return (0);
-}
-
-/*
- * ex_discard --
- * Discard any pending ex commands.
- */
-static int
-ex_discard(sp)
- SCR *sp;
-{
- GS *gp;
- EXCMD *ecp;
- RANGE *rp;
-
- /*
- * We know the first command can't be an AGV command, so we don't
- * process it specially. We do, however, nail the command itself.
- */
- for (gp = sp->gp; (ecp = gp->ecq.lh_first) != &gp->excmd;) {
- if (FL_ISSET(ecp->agv_flags, AGV_ALL)) {
- while ((rp = ecp->rq.cqh_first) != (void *)&ecp->rq) {
- CIRCLEQ_REMOVE(&ecp->rq, rp, q);
- free(rp);
- }
- free(ecp->o_cp);
- }
- LIST_REMOVE(ecp, q);
- free(ecp);
- }
- gp->ecq.lh_first->clen = 0;
- return (0);
-}
-
-/*
- * ex_unknown --
- * Display an unknown command name.
- */
-static void
-ex_unknown(sp, cmd, len)
- SCR *sp;
- char *cmd;
- size_t len;
-{
- size_t blen;
- char *bp;
-
- GET_SPACE_GOTO(sp, bp, blen, len + 1);
- bp[len] = '\0';
- memcpy(bp, cmd, len);
- msgq_str(sp, M_ERR, bp, "098|The %s command is unknown");
- FREE_SPACE(sp, bp, blen);
-
-alloc_err:
- return;
-}
-
-/*
- * ex_is_abbrev -
- * The vi text input routine needs to know if ex thinks this is an
- * [un]abbreviate command, so it can turn off abbreviations. See
- * the usual ranting in the vi/v_txt_ev.c:txt_abbrev() routine.
- *
- * PUBLIC: int ex_is_abbrev __P((char *, size_t));
- */
-int
-ex_is_abbrev(name, len)
- char *name;
- size_t len;
-{
- EXCMDLIST const *cp;
-
- return ((cp = ex_comm_search(name, len)) != NULL &&
- (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
-}
-
-/*
- * ex_is_unmap -
- * The vi text input routine needs to know if ex thinks this is an
- * unmap command, so it can turn off input mapping. See the usual
- * ranting in the vi/v_txt_ev.c:txt_unmap() routine.
- *
- * PUBLIC: int ex_is_unmap __P((char *, size_t));
- */
-int
-ex_is_unmap(name, len)
- char *name;
- size_t len;
-{
- EXCMDLIST const *cp;
-
- /*
- * The command the vi input routines are really interested in
- * is "unmap!", not just unmap.
- */
- if (name[len - 1] != '!')
- return (0);
- --len;
- return ((cp = ex_comm_search(name, len)) != NULL &&
- cp == &cmds[C_UNMAP]);
-}
-
-/*
- * ex_comm_search --
- * Search for a command name.
- */
-static EXCMDLIST const *
-ex_comm_search(name, len)
- char *name;
- size_t len;
-{
- EXCMDLIST const *cp;
-
- for (cp = cmds; cp->name != NULL; ++cp) {
- if (cp->name[0] > name[0])
- return (NULL);
- if (cp->name[0] != name[0])
- continue;
- if (!memcmp(name, cp->name, len))
- return (cp);
- }
- return (NULL);
-}
-
-/*
- * ex_badaddr --
- * Display a bad address message.
- *
- * PUBLIC: void ex_badaddr
- * PUBLIC: __P((SCR *, EXCMDLIST const *, enum badaddr, enum nresult));
- */
-void
-ex_badaddr(sp, cp, ba, nret)
- SCR *sp;
- EXCMDLIST const *cp;
- enum badaddr ba;
- enum nresult nret;
-{
- recno_t lno;
-
- switch (nret) {
- case NUM_OK:
- break;
- case NUM_ERR:
- msgq(sp, M_SYSERR, NULL);
- return;
- case NUM_OVER:
- msgq(sp, M_ERR, "099|Address value overflow");
- return;
- case NUM_UNDER:
- msgq(sp, M_ERR, "100|Address value underflow");
- return;
- }
-
- /*
- * When encountering an address error, tell the user if there's no
- * underlying file, that's the real problem.
- */
- if (sp->ep == NULL) {
- ex_emsg(sp, cp->name, EXM_NOFILEYET);
- return;
- }
-
- switch (ba) {
- case A_COMBO:
- msgq(sp, M_ERR, "101|Illegal address combination");
- break;
- case A_EOF:
- if (db_last(sp, &lno))
- return;
- if (lno != 0) {
- msgq(sp, M_ERR,
- "102|Illegal address: only %lu lines in the file",
- lno);
- break;
- }
- /* FALLTHROUGH */
- case A_EMPTY:
- msgq(sp, M_ERR, "103|Illegal address: the file is empty");
- break;
- case A_NOTSET:
- abort();
- /* NOTREACHED */
- case A_ZERO:
- msgq(sp, M_ERR,
- "104|The %s command doesn't permit an address of 0",
- cp->name);
- break;
- }
- return;
-}
-
-#if defined(DEBUG) && defined(COMLOG)
-/*
- * ex_comlog --
- * Log ex commands.
- */
-static void
-ex_comlog(sp, ecp)
- SCR *sp;
- EXCMD *ecp;
-{
- TRACE(sp, "ecmd: %s", ecp->cmd->name);
- if (ecp->addrcnt > 0) {
- TRACE(sp, " a1 %d", ecp->addr1.lno);
- if (ecp->addrcnt > 1)
- TRACE(sp, " a2: %d", ecp->addr2.lno);
- }
- if (ecp->lineno)
- TRACE(sp, " line %d", ecp->lineno);
- if (ecp->flags)
- TRACE(sp, " flags 0x%x", ecp->flags);
- if (F_ISSET(&exc, E_BUFFER))
- TRACE(sp, " buffer %c", ecp->buffer);
- if (ecp->argc)
- for (cnt = 0; cnt < ecp->argc; ++cnt)
- TRACE(sp, " arg %d: {%s}", cnt, ecp->argv[cnt]->bp);
- TRACE(sp, "\n");
-}
-#endif
diff --git a/contrib/nvi/ex/ex.h b/contrib/nvi/ex/ex.h
deleted file mode 100644
index 5870990..0000000
--- a/contrib/nvi/ex/ex.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- *
- * @(#)ex.h 10.24 (Berkeley) 8/12/96
- */
-
-#define PROMPTCHAR ':' /* Prompt using a colon. */
-
-typedef struct _excmdlist { /* Ex command table structure. */
- char *name; /* Command name, underlying function. */
- int (*fn) __P((SCR *, EXCMD *));
-
-#define E_ADDR1 0x00000001 /* One address. */
-#define E_ADDR2 0x00000002 /* Two addresses. */
-#define E_ADDR2_ALL 0x00000004 /* Zero/two addresses; zero == all. */
-#define E_ADDR2_NONE 0x00000008 /* Zero/two addresses; zero == none. */
-#define E_ADDR_ZERO 0x00000010 /* 0 is a legal addr1. */
-#define E_ADDR_ZERODEF 0x00000020 /* 0 is default addr1 of empty files. */
-#define E_AUTOPRINT 0x00000040 /* Command always sets autoprint. */
-#define E_CLRFLAG 0x00000080 /* Clear the print (#, l, p) flags. */
-#define E_NEWSCREEN 0x00000100 /* Create a new screen. */
-#define E_SECURE 0x00000200 /* Permission denied if O_SECURE set. */
-#define E_VIONLY 0x00000400 /* Meaningful only in vi. */
-#define __INUSE1 0xfffff800 /* Same name space as EX_PRIVATE. */
- u_int16_t flags;
-
- char *syntax; /* Syntax script. */
- char *usage; /* Usage line. */
- char *help; /* Help line. */
-} EXCMDLIST;
-
-#define MAXCMDNAMELEN 12 /* Longest command name. */
-extern EXCMDLIST const cmds[]; /* Table of ex commands. */
-
-/*
- * !!!
- * QUOTING NOTE:
- *
- * Historically, .exrc files and EXINIT variables could only use ^V as an
- * escape character, neither ^Q or a user specified character worked. We
- * enforce that here, just in case someone depends on it.
- */
-#define IS_ESCAPE(sp, cmdp, ch) \
- (F_ISSET(cmdp, E_VLITONLY) ? \
- (ch) == CH_LITERAL : KEY_VAL(sp, ch) == K_VLNEXT)
-
-/*
- * File state must be checked for each command -- any ex command may be entered
- * at any time, and most of them won't work well if a file hasn't yet been read
- * in. Historic vi generally took the easy way out and dropped core.
- */
-#define NEEDFILE(sp, cmdp) { \
- if ((sp)->ep == NULL) { \
- ex_emsg(sp, (cmdp)->cmd->name, EXM_NOFILEYET); \
- return (1); \
- } \
-}
-
-/* Range structures for global and @ commands. */
-typedef struct _range RANGE;
-struct _range { /* Global command range. */
- CIRCLEQ_ENTRY(_range) q; /* Linked list of ranges. */
- recno_t start, stop; /* Start/stop of the range. */
-};
-
-/* Ex command structure. */
-struct _excmd {
- LIST_ENTRY(_excmd) q; /* Linked list of commands. */
-
- char *if_name; /* Associated file. */
- recno_t if_lno; /* Associated line number. */
-
- /* Clear the structure for the ex parser. */
-#define CLEAR_EX_PARSER(cmdp) \
- memset(&((cmdp)->cp), 0, ((char *)&(cmdp)->flags - \
- (char *)&((cmdp)->cp)) + sizeof((cmdp)->flags))
-
- char *cp; /* Current command text. */
- size_t clen; /* Current command length. */
-
- char *save_cmd; /* Remaining command. */
- size_t save_cmdlen; /* Remaining command length. */
-
- EXCMDLIST const *cmd; /* Command: entry in command table. */
- EXCMDLIST rcmd; /* Command: table entry/replacement. */
-
- CIRCLEQ_HEAD(_rh, _range) rq; /* @/global range: linked list. */
- recno_t range_lno; /* @/global range: set line number. */
- char *o_cp; /* Original @/global command. */
- size_t o_clen; /* Original @/global command length. */
-#define AGV_AT 0x01 /* @ buffer execution. */
-#define AGV_AT_NORANGE 0x02 /* @ buffer execution without range. */
-#define AGV_GLOBAL 0x04 /* global command. */
-#define AGV_V 0x08 /* v command. */
-#define AGV_ALL (AGV_AT | AGV_AT_NORANGE | AGV_GLOBAL | AGV_V)
- u_int8_t agv_flags;
-
- /* Clear the structure before each ex command. */
-#define CLEAR_EX_CMD(cmdp) { \
- u_int32_t L__f = F_ISSET(cmdp, E_PRESERVE); \
- memset(&((cmdp)->buffer), 0, ((char *)&(cmdp)->flags - \
- (char *)&((cmdp)->buffer)) + sizeof((cmdp)->flags)); \
- F_SET(cmdp, L__f); \
-}
-
- CHAR_T buffer; /* Command: named buffer. */
- recno_t lineno; /* Command: line number. */
- long count; /* Command: signed count. */
- long flagoff; /* Command: signed flag offset. */
- int addrcnt; /* Command: addresses (0, 1 or 2). */
- MARK addr1; /* Command: 1st address. */
- MARK addr2; /* Command: 2nd address. */
- ARGS **argv; /* Command: array of arguments. */
- int argc; /* Command: count of arguments. */
-
-#define E_C_BUFFER 0x00001 /* Buffer name specified. */
-#define E_C_CARAT 0x00002 /* ^ flag. */
-#define E_C_COUNT 0x00004 /* Count specified. */
-#define E_C_COUNT_NEG 0x00008 /* Count was signed negative. */
-#define E_C_COUNT_POS 0x00010 /* Count was signed positive. */
-#define E_C_DASH 0x00020 /* - flag. */
-#define E_C_DOT 0x00040 /* . flag. */
-#define E_C_EQUAL 0x00080 /* = flag. */
-#define E_C_FORCE 0x00100 /* ! flag. */
-#define E_C_HASH 0x00200 /* # flag. */
-#define E_C_LIST 0x00400 /* l flag. */
-#define E_C_PLUS 0x00800 /* + flag. */
-#define E_C_PRINT 0x01000 /* p flag. */
- u_int16_t iflags; /* User input information. */
-
-#define __INUSE2 0x000004ff /* Same name space as EXCMDLIST. */
-#define E_BLIGNORE 0x00000800 /* Ignore blank lines. */
-#define E_NAMEDISCARD 0x00001000 /* Free/discard the name. */
-#define E_NOAUTO 0x00002000 /* Don't do autoprint output. */
-#define E_NOPRDEF 0x00004000 /* Don't print as default. */
-#define E_NRSEP 0x00008000 /* Need to line adjust ex output. */
-#define E_OPTNUM 0x00010000 /* Number edit option affected. */
-#define E_VLITONLY 0x00020000 /* Use ^V quoting only. */
-#define E_PRESERVE 0x0003f800 /* Bits to preserve across commands. */
-
-#define E_ABSMARK 0x00040000 /* Set the absolute mark. */
-#define E_ADDR_DEF 0x00080000 /* Default addresses used. */
-#define E_DELTA 0x00100000 /* Search address with delta. */
-#define E_MODIFY 0x00200000 /* File name expansion modified arg. */
-#define E_MOVETOEND 0x00400000 /* Move to the end of the file first. */
-#define E_NEWLINE 0x00800000 /* Found ending <newline>. */
-#define E_SEARCH_WMSG 0x01000000 /* Display search-wrapped message. */
-#define E_USELASTCMD 0x02000000 /* Use the last command. */
-#define E_VISEARCH 0x04000000 /* It's really a vi search command. */
- u_int32_t flags; /* Current flags. */
-};
-
-/* Ex private, per-screen memory. */
-typedef struct _ex_private {
- CIRCLEQ_HEAD(_tqh, _tagq) tq; /* Tag queue. */
- TAILQ_HEAD(_tagfh, _tagf) tagfq;/* Tag file list. */
- LIST_HEAD(_csch, _csc) cscq; /* Cscope connection list. */
- char *tag_last; /* Saved last tag string. */
-
- CHAR_T *lastbcomm; /* Last bang command. */
-
- ARGS **args; /* Command: argument list. */
- int argscnt; /* Command: argument list count. */
- int argsoff; /* Command: offset into arguments. */
-
- u_int32_t fdef; /* Saved E_C_* default command flags. */
-
- char *ibp; /* File line input buffer. */
- size_t ibp_len; /* File line input buffer length. */
-
- /*
- * Buffers for the ex output. The screen/vi support doesn't do any
- * character buffering of any kind. We do it here so that we're not
- * calling the screen output routines on every character.
- *
- * XXX
- * Change to grow dynamically.
- */
- char obp[1024]; /* Ex output buffer. */
- size_t obp_len; /* Ex output buffer length. */
-
-#define EXP_CSCINIT 0x01 /* Cscope initialized. */
- u_int8_t flags;
-} EX_PRIVATE;
-#define EXP(sp) ((EX_PRIVATE *)((sp)->ex_private))
-
-/*
- * Filter actions:
- *
- * FILTER_BANG !: filter text through the utility.
- * FILTER_RBANG !: read from the utility (without stdin).
- * FILTER_READ read: read from the utility (with stdin).
- * FILTER_WRITE write: write to the utility, display its output.
- */
-enum filtertype { FILTER_BANG, FILTER_RBANG, FILTER_READ, FILTER_WRITE };
-
-/* Ex common error messages. */
-typedef enum {
- EXM_EMPTYBUF, /* Empty buffer. */
- EXM_FILECOUNT, /* Too many file names. */
- EXM_NOCANON, /* No terminal interface. */
- EXM_NOCANON_F, /* EXM_NOCANO: filter version. */
- EXM_NOFILEYET, /* Illegal until a file read in. */
- EXM_NOPREVBUF, /* No previous buffer specified. */
- EXM_NOPREVRE, /* No previous RE specified. */
- EXM_NOSUSPEND, /* No suspension. */
- EXM_SECURE, /* Illegal if secure edit option set. */
- EXM_SECURE_F, /* EXM_SECURE: filter version */
- EXM_USAGE /* Standard usage message. */
-} exm_t;
-
-/* Ex address error types. */
-enum badaddr { A_COMBO, A_EMPTY, A_EOF, A_NOTSET, A_ZERO };
-
-/* Ex common tag error messages. */
-typedef enum {
- TAG_BADLNO, /* Tag line doesn't exist. */
- TAG_EMPTY, /* Tags stack is empty. */
- TAG_SEARCH /* Tags search pattern wasn't found. */
-} tagmsg_t;
-
-#include "ex_def.h"
-#include "ex_extern.h"
diff --git a/contrib/nvi/ex/ex_abbrev.c b/contrib/nvi/ex/ex_abbrev.c
deleted file mode 100644
index 231098c..0000000
--- a/contrib/nvi/ex/ex_abbrev.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_abbrev.c 10.7 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-/*
- * ex_abbr -- :abbreviate [key replacement]
- * Create an abbreviation or display abbreviations.
- *
- * PUBLIC: int ex_abbr __P((SCR *, EXCMD *));
- */
-int
-ex_abbr(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- CHAR_T *p;
- size_t len;
-
- switch (cmdp->argc) {
- case 0:
- if (seq_dump(sp, SEQ_ABBREV, 0) == 0)
- msgq(sp, M_INFO, "105|No abbreviations to display");
- return (0);
- case 2:
- break;
- default:
- abort();
- }
-
- /*
- * Check for illegal characters.
- *
- * !!!
- * Another fun one, historically. See vi/v_ntext.c:txt_abbrev() for
- * details. The bottom line is that all abbreviations have to end
- * with a "word" character, because it's the transition from word to
- * non-word characters that triggers the test for an abbreviation. In
- * addition, because of the way the test is done, there can't be any
- * transitions from word to non-word character (or vice-versa) other
- * than between the next-to-last and last characters of the string,
- * and there can't be any <blank> characters. Warn the user.
- */
- if (!inword(cmdp->argv[0]->bp[cmdp->argv[0]->len - 1])) {
- msgq(sp, M_ERR,
- "106|Abbreviations must end with a \"word\" character");
- return (1);
- }
- for (p = cmdp->argv[0]->bp; *p != '\0'; ++p)
- if (isblank(p[0])) {
- msgq(sp, M_ERR,
- "107|Abbreviations may not contain tabs or spaces");
- return (1);
- }
- if (cmdp->argv[0]->len > 2)
- for (p = cmdp->argv[0]->bp,
- len = cmdp->argv[0]->len - 2; len; --len, ++p)
- if (inword(p[0]) != inword(p[1])) {
- msgq(sp, M_ERR,
-"108|Abbreviations may not mix word/non-word characters, except at the end");
- return (1);
- }
-
- if (seq_set(sp, NULL, 0, cmdp->argv[0]->bp, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len, SEQ_ABBREV, SEQ_USERDEF))
- return (1);
-
- F_SET(sp->gp, G_ABBREV);
- return (0);
-}
-
-/*
- * ex_unabbr -- :unabbreviate key
- * Delete an abbreviation.
- *
- * PUBLIC: int ex_unabbr __P((SCR *, EXCMD *));
- */
-int
-ex_unabbr(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- ARGS *ap;
-
- ap = cmdp->argv[0];
- if (!F_ISSET(sp->gp, G_ABBREV) ||
- seq_delete(sp, ap->bp, ap->len, SEQ_ABBREV)) {
- msgq_str(sp, M_ERR, ap->bp,
- "109|\"%s\" is not an abbreviation");
- return (1);
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_append.c b/contrib/nvi/ex/ex_append.c
deleted file mode 100644
index 8d89e12..0000000
--- a/contrib/nvi/ex/ex_append.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_append.c 10.30 (Berkeley) 10/23/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-enum which {APPEND, CHANGE, INSERT};
-
-static int ex_aci __P((SCR *, EXCMD *, enum which));
-
-/*
- * ex_append -- :[line] a[ppend][!]
- * Append one or more lines of new text after the specified line,
- * or the current line if no address is specified.
- *
- * PUBLIC: int ex_append __P((SCR *, EXCMD *));
- */
-int
-ex_append(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (ex_aci(sp, cmdp, APPEND));
-}
-
-/*
- * ex_change -- :[line[,line]] c[hange][!] [count]
- * Change one or more lines to the input text.
- *
- * PUBLIC: int ex_change __P((SCR *, EXCMD *));
- */
-int
-ex_change(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (ex_aci(sp, cmdp, CHANGE));
-}
-
-/*
- * ex_insert -- :[line] i[nsert][!]
- * Insert one or more lines of new text before the specified line,
- * or the current line if no address is specified.
- *
- * PUBLIC: int ex_insert __P((SCR *, EXCMD *));
- */
-int
-ex_insert(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (ex_aci(sp, cmdp, INSERT));
-}
-
-/*
- * ex_aci --
- * Append, change, insert in ex.
- */
-static int
-ex_aci(sp, cmdp, cmd)
- SCR *sp;
- EXCMD *cmdp;
- enum which cmd;
-{
- CHAR_T *p, *t;
- GS *gp;
- TEXT *tp;
- TEXTH tiq;
- recno_t cnt, lno;
- size_t len;
- u_int32_t flags;
- int need_newline;
-
- gp = sp->gp;
- NEEDFILE(sp, cmdp);
-
- /*
- * If doing a change, replace lines for as long as possible. Then,
- * append more lines or delete remaining lines. Changes to an empty
- * file are appends, inserts are the same as appends to the previous
- * line.
- *
- * !!!
- * Set the address to which we'll append. We set sp->lno to this
- * address as well so that autoindent works correctly when get text
- * from the user.
- */
- lno = cmdp->addr1.lno;
- sp->lno = lno;
- if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
- --lno;
-
- /*
- * !!!
- * If the file isn't empty, cut changes into the unnamed buffer.
- */
- if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
- (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
- del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
- return (1);
-
- /*
- * !!!
- * Anything that was left after the command separator becomes part
- * of the inserted text. Apparently, it was common usage to enter:
- *
- * :g/pattern/append|stuff1
- *
- * and append the line of text "stuff1" to the lines containing the
- * pattern. It was also historically legal to enter:
- *
- * :append|stuff1
- * stuff2
- * .
- *
- * and the text on the ex command line would be appended as well as
- * the text inserted after it. There was an historic bug however,
- * that the user had to enter *two* terminating lines (the '.' lines)
- * to terminate text input mode, in this case. This whole thing
- * could be taken too far, however. Entering:
- *
- * :append|stuff1\
- * stuff2
- * stuff3
- * .
- *
- * i.e. mixing and matching the forms confused the historic vi, and,
- * not only did it take two terminating lines to terminate text input
- * mode, but the trailing backslashes were retained on the input. We
- * match historic practice except that we discard the backslashes.
- *
- * Input lines specified on the ex command line lines are separated by
- * <newline>s. If there is a trailing delimiter an empty line was
- * inserted. There may also be a leading delimiter, which is ignored
- * unless it's also a trailing delimiter. It is possible to encounter
- * a termination line, i.e. a single '.', in a global command, but not
- * necessary if the text insert command was the last of the global
- * commands.
- */
- if (cmdp->save_cmdlen != 0) {
- for (p = cmdp->save_cmd,
- len = cmdp->save_cmdlen; len > 0; p = t) {
- for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
- if (t != p || len == 0) {
- if (F_ISSET(sp, SC_EX_GLOBAL) &&
- t - p == 1 && p[0] == '.') {
- ++t;
- if (len > 0)
- --len;
- break;
- }
- if (db_append(sp, 1, lno++, p, t - p))
- return (1);
- }
- if (len != 0) {
- ++t;
- if (--len == 0 &&
- db_append(sp, 1, lno++, "", 0))
- return (1);
- }
- }
- /*
- * If there's any remaining text, we're in a global, and
- * there's more command to parse.
- *
- * !!!
- * We depend on the fact that non-global commands will eat the
- * rest of the command line as text input, and before getting
- * any text input from the user. Otherwise, we'd have to save
- * off the command text before or during the call to the text
- * input function below.
- */
- if (len != 0)
- cmdp->save_cmd = t;
- cmdp->save_cmdlen = len;
- }
-
- if (F_ISSET(sp, SC_EX_GLOBAL)) {
- if ((sp->lno = lno) == 0 && db_exist(sp, 1))
- sp->lno = 1;
- return (0);
- }
-
- /*
- * If not in a global command, read from the terminal.
- *
- * If this code is called by vi, we want to reset the terminal and use
- * ex's line get routine. It actually works fine if we use vi's get
- * routine, but it doesn't look as nice. Maybe if we had a separate
- * window or something, but getting a line at a time looks awkward.
- * However, depending on the screen that we're using, that may not
- * be possible.
- */
- if (F_ISSET(sp, SC_VI)) {
- if (gp->scr_screen(sp, SC_EX)) {
- ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
- return (1);
- }
-
- /* If we're still in the vi screen, move out explicitly. */
- need_newline = !F_ISSET(sp, SC_SCR_EXWROTE);
- F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
- if (need_newline)
- (void)ex_puts(sp, "\n");
-
- /*
- * !!!
- * Users of historical versions of vi sometimes get confused
- * when they enter append mode, and can't seem to get out of
- * it. Give them an informational message.
- */
- (void)ex_puts(sp,
- msg_cat(sp, "273|Entering ex input mode.", NULL));
- (void)ex_puts(sp, "\n");
- (void)ex_fflush(sp);
- }
-
- /*
- * Set input flags; the ! flag turns off autoindent for append,
- * change and insert.
- */
- LF_INIT(TXT_DOTTERM | TXT_NUMBER);
- if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && O_ISSET(sp, O_AUTOINDENT))
- LF_SET(TXT_AUTOINDENT);
- if (O_ISSET(sp, O_BEAUTIFY))
- LF_SET(TXT_BEAUTIFY);
-
- /*
- * This code can't use the common screen TEXTH structure (sp->tiq),
- * as it may already be in use, e.g. ":append|s/abc/ABC/" would fail
- * as we are only halfway through the text when the append code fires.
- * Use a local structure instead. (The ex code would have to use a
- * local structure except that we're guaranteed to finish remaining
- * characters in the common TEXTH structure when they were inserted
- * into the file, above.)
- */
- memset(&tiq, 0, sizeof(TEXTH));
- CIRCLEQ_INIT(&tiq);
-
- if (ex_txt(sp, &tiq, 0, flags))
- return (1);
-
- for (cnt = 0, tp = tiq.cqh_first;
- tp != (TEXT *)&tiq; ++cnt, tp = tp->q.cqe_next)
- if (db_append(sp, 1, lno++, tp->lb, tp->len))
- return (1);
-
- /*
- * Set sp->lno to the final line number value (correcting for a
- * possible 0 value) as that's historically correct for the final
- * line value, whether or not the user entered any text.
- */
- if ((sp->lno = lno) == 0 && db_exist(sp, 1))
- sp->lno = 1;
-
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_args.c b/contrib/nvi/ex/ex_args.c
deleted file mode 100644
index bc37109..0000000
--- a/contrib/nvi/ex/ex_args.c
+++ /dev/null
@@ -1,327 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1991, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_args.c 10.16 (Berkeley) 7/13/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-static int ex_N_next __P((SCR *, EXCMD *));
-
-/*
- * ex_next -- :next [+cmd] [files]
- * Edit the next file, optionally setting the list of files.
- *
- * !!!
- * The :next command behaved differently from the :rewind command in
- * historic vi. See nvi/docs/autowrite for details, but the basic
- * idea was that it ignored the force flag if the autowrite flag was
- * set. This implementation handles them all identically.
- *
- * PUBLIC: int ex_next __P((SCR *, EXCMD *));
- */
-int
-ex_next(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- ARGS **argv;
- FREF *frp;
- int noargs;
- char **ap;
-
- /* Check for file to move to. */
- if (cmdp->argc == 0 && (sp->cargv == NULL || sp->cargv[1] == NULL)) {
- msgq(sp, M_ERR, "111|No more files to edit");
- return (1);
- }
-
- if (F_ISSET(cmdp, E_NEWSCREEN)) {
- /* By default, edit the next file in the old argument list. */
- if (cmdp->argc == 0) {
- if (argv_exp0(sp,
- cmdp, sp->cargv[1], strlen(sp->cargv[1])))
- return (1);
- return (ex_edit(sp, cmdp));
- }
- return (ex_N_next(sp, cmdp));
- }
-
- /* Check modification. */
- if (file_m1(sp,
- FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
-
- /* Any arguments are a replacement file list. */
- if (cmdp->argc) {
- /* Free the current list. */
- if (!F_ISSET(sp, SC_ARGNOFREE) && sp->argv != NULL) {
- for (ap = sp->argv; *ap != NULL; ++ap)
- free(*ap);
- free(sp->argv);
- }
- F_CLR(sp, SC_ARGNOFREE | SC_ARGRECOVER);
- sp->cargv = NULL;
-
- /* Create a new list. */
- CALLOC_RET(sp,
- sp->argv, char **, cmdp->argc + 1, sizeof(char *));
- for (ap = sp->argv,
- argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
- if ((*ap =
- v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
- return (1);
- *ap = NULL;
-
- /* Switch to the first file. */
- sp->cargv = sp->argv;
- 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);
- if (F_ISSET(sp, SC_ARGRECOVER))
- F_SET(frp, FR_RECOVER);
- noargs = 1;
- }
-
- if (file_init(sp, frp, NULL, FS_SETALT |
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
- return (1);
- if (noargs)
- ++sp->cargv;
-
- F_SET(sp, SC_FSWITCH);
- return (0);
-}
-
-/*
- * ex_N_next --
- * New screen version of ex_next.
- */
-static int
-ex_N_next(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- SCR *new;
- FREF *frp;
-
- /* Get a new screen. */
- if (screen_init(sp->gp, sp, &new))
- return (1);
- if (vs_split(sp, new, 0)) {
- (void)screen_end(new);
- return (1);
- }
-
- /* Get a backing file. */
- if ((frp = file_add(new, cmdp->argv[0]->bp)) == NULL ||
- file_init(new, frp, NULL,
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
- (void)vs_discard(new, NULL);
- (void)screen_end(new);
- return (1);
- }
-
- /* 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);
-
- return (0);
-}
-
-/*
- * ex_prev -- :prev
- * Edit the previous file.
- *
- * PUBLIC: int ex_prev __P((SCR *, EXCMD *));
- */
-int
-ex_prev(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- FREF *frp;
-
- if (sp->cargv == sp->argv) {
- msgq(sp, M_ERR, "112|No previous files to edit");
- return (1);
- }
-
- if (F_ISSET(cmdp, E_NEWSCREEN)) {
- if (argv_exp0(sp, cmdp, sp->cargv[-1], strlen(sp->cargv[-1])))
- return (1);
- return (ex_edit(sp, cmdp));
- }
-
- if (file_m1(sp,
- FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
-
- if ((frp = file_add(sp, sp->cargv[-1])) == NULL)
- return (1);
-
- if (file_init(sp, frp, NULL, FS_SETALT |
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
- return (1);
- --sp->cargv;
-
- F_SET(sp, SC_FSWITCH);
- return (0);
-}
-
-/*
- * ex_rew -- :rew
- * Re-edit the list of files.
- *
- * !!!
- * Historic practice was that all files would start editing at the beginning
- * of the file. We don't get this right because we may have multiple screens
- * and we can't clear the FR_CURSORSET bit for a single screen. I don't see
- * anyone noticing, but if they do, we'll have to put information into the SCR
- * structure so we can keep track of it.
- *
- * PUBLIC: int ex_rew __P((SCR *, EXCMD *));
- */
-int
-ex_rew(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- FREF *frp;
-
- /*
- * !!!
- * Historic practice -- you can rewind to the current file.
- */
- if (sp->argv == NULL) {
- msgq(sp, M_ERR, "113|No previous files to rewind");
- return (1);
- }
-
- if (file_m1(sp,
- FL_ISSET(cmdp->iflags, E_C_FORCE), FS_ALL | FS_POSSIBLE))
- return (1);
-
- /* Switch to the first one. */
- sp->cargv = sp->argv;
- if ((frp = file_add(sp, *sp->cargv)) == NULL)
- return (1);
- if (file_init(sp, frp, NULL, FS_SETALT |
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
- return (1);
-
- /* Switch and display a file count with the welcome message. */
- F_SET(sp, SC_FSWITCH | SC_STATUS_CNT);
-
- return (0);
-}
-
-/*
- * ex_args -- :args
- * Display the list of files.
- *
- * PUBLIC: int ex_args __P((SCR *, EXCMD *));
- */
-int
-ex_args(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- GS *gp;
- int cnt, col, len, sep;
- char **ap;
-
- if (sp->argv == NULL) {
- (void)msgq(sp, M_ERR, "114|No file list to display");
- return (0);
- }
-
- gp = sp->gp;
- col = len = sep = 0;
- for (cnt = 1, ap = sp->argv; *ap != NULL; ++ap) {
- col += len = strlen(*ap) + sep + (ap == sp->cargv ? 2 : 0);
- if (col >= sp->cols - 1) {
- col = len;
- sep = 0;
- (void)ex_puts(sp, "\n");
- } else if (cnt != 1) {
- sep = 1;
- (void)ex_puts(sp, " ");
- }
- ++cnt;
-
- (void)ex_printf(sp, "%s%s%s", ap == sp->cargv ? "[" : "",
- *ap, ap == sp->cargv ? "]" : "");
- if (INTERRUPTED(sp))
- break;
- }
- (void)ex_puts(sp, "\n");
- return (0);
-}
-
-/*
- * ex_buildargv --
- * Build a new file argument list.
- *
- * PUBLIC: char **ex_buildargv __P((SCR *, EXCMD *, char *));
- */
-char **
-ex_buildargv(sp, cmdp, name)
- SCR *sp;
- EXCMD *cmdp;
- char *name;
-{
- ARGS **argv;
- int argc;
- char **ap, **s_argv;
-
- argc = cmdp == NULL ? 1 : cmdp->argc;
- CALLOC(sp, s_argv, char **, argc + 1, sizeof(char *));
- if ((ap = s_argv) == NULL)
- return (NULL);
-
- if (cmdp == NULL) {
- if ((*ap = v_strdup(sp, name, strlen(name))) == NULL)
- return (NULL);
- ++ap;
- } else
- for (argv = cmdp->argv; argv[0]->len != 0; ++ap, ++argv)
- if ((*ap =
- v_strdup(sp, argv[0]->bp, argv[0]->len)) == NULL)
- return (NULL);
- *ap = NULL;
- return (s_argv);
-}
diff --git a/contrib/nvi/ex/ex_argv.c b/contrib/nvi/ex/ex_argv.c
deleted file mode 100644
index cc5a201..0000000
--- a/contrib/nvi/ex/ex_argv.c
+++ /dev/null
@@ -1,756 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_argv.c 10.26 (Berkeley) 9/20/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-static int argv_alloc __P((SCR *, size_t));
-static int argv_comp __P((const void *, const void *));
-static int argv_fexp __P((SCR *, EXCMD *,
- char *, size_t, char *, size_t *, char **, size_t *, int));
-static int argv_lexp __P((SCR *, EXCMD *, char *));
-static int argv_sexp __P((SCR *, char **, size_t *, size_t *));
-
-/*
- * argv_init --
- * Build a prototype arguments list.
- *
- * PUBLIC: int argv_init __P((SCR *, EXCMD *));
- */
-int
-argv_init(sp, excp)
- SCR *sp;
- EXCMD *excp;
-{
- EX_PRIVATE *exp;
-
- exp = EXP(sp);
- exp->argsoff = 0;
- argv_alloc(sp, 1);
-
- excp->argv = exp->args;
- excp->argc = exp->argsoff;
- return (0);
-}
-
-/*
- * argv_exp0 --
- * Append a string to the argument list.
- *
- * PUBLIC: int argv_exp0 __P((SCR *, EXCMD *, char *, size_t));
- */
-int
-argv_exp0(sp, excp, cmd, cmdlen)
- SCR *sp;
- EXCMD *excp;
- char *cmd;
- size_t cmdlen;
-{
- EX_PRIVATE *exp;
-
- exp = EXP(sp);
- argv_alloc(sp, cmdlen);
- memcpy(exp->args[exp->argsoff]->bp, cmd, cmdlen);
- exp->args[exp->argsoff]->bp[cmdlen] = '\0';
- exp->args[exp->argsoff]->len = cmdlen;
- ++exp->argsoff;
- excp->argv = exp->args;
- excp->argc = exp->argsoff;
- return (0);
-}
-
-/*
- * argv_exp1 --
- * Do file name expansion on a string, and append it to the
- * argument list.
- *
- * PUBLIC: int argv_exp1 __P((SCR *, EXCMD *, char *, size_t, int));
- */
-int
-argv_exp1(sp, excp, cmd, cmdlen, is_bang)
- SCR *sp;
- EXCMD *excp;
- char *cmd;
- size_t cmdlen;
- int is_bang;
-{
- EX_PRIVATE *exp;
- size_t blen, len;
- char *bp, *p, *t;
-
- GET_SPACE_RET(sp, bp, blen, 512);
-
- len = 0;
- exp = EXP(sp);
- if (argv_fexp(sp, excp, cmd, cmdlen, bp, &len, &bp, &blen, is_bang)) {
- FREE_SPACE(sp, bp, blen);
- return (1);
- }
-
- /* If it's empty, we're done. */
- if (len != 0) {
- for (p = bp, t = bp + len; p < t; ++p)
- if (!isblank(*p))
- break;
- if (p == t)
- goto ret;
- } else
- goto ret;
-
- (void)argv_exp0(sp, excp, bp, len);
-
-ret: FREE_SPACE(sp, bp, blen);
- return (0);
-}
-
-/*
- * argv_exp2 --
- * Do file name and shell expansion on a string, and append it to
- * the argument list.
- *
- * PUBLIC: int argv_exp2 __P((SCR *, EXCMD *, char *, size_t));
- */
-int
-argv_exp2(sp, excp, cmd, cmdlen)
- SCR *sp;
- EXCMD *excp;
- char *cmd;
- size_t cmdlen;
-{
- size_t blen, len, n;
- int rval;
- char *bp, *mp, *p;
-
- GET_SPACE_RET(sp, bp, blen, 512);
-
-#define SHELLECHO "echo "
-#define SHELLOFFSET (sizeof(SHELLECHO) - 1)
- memcpy(bp, SHELLECHO, SHELLOFFSET);
- p = bp + SHELLOFFSET;
- len = SHELLOFFSET;
-
-#if defined(DEBUG) && 0
- TRACE(sp, "file_argv: {%.*s}\n", (int)cmdlen, cmd);
-#endif
-
- if (argv_fexp(sp, excp, cmd, cmdlen, p, &len, &bp, &blen, 0)) {
- rval = 1;
- goto err;
- }
-
-#if defined(DEBUG) && 0
- TRACE(sp, "before shell: %d: {%s}\n", len, bp);
-#endif
-
- /*
- * Do shell word expansion -- it's very, very hard to figure out what
- * magic characters the user's shell expects. Historically, it was a
- * union of v7 shell and csh meta characters. We match that practice
- * by default, so ":read \%" tries to read a file named '%'. It would
- * make more sense to pass any special characters through the shell,
- * but then, if your shell was csh, the above example will behave
- * differently in nvi than in vi. If you want to get other characters
- * passed through to your shell, change the "meta" option.
- *
- * To avoid a function call per character, we do a first pass through
- * the meta characters looking for characters that aren't expected
- * to be there, and then we can ignore them in the user's argument.
- */
- if (opts_empty(sp, O_SHELL, 1) || opts_empty(sp, O_SHELLMETA, 1))
- n = 0;
- else {
- 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 (; n > 0; --n, ++p)
- if (strchr(mp, *p) != NULL)
- break;
- } else
- for (; n > 0; --n, ++p)
- if (!isblank(*p) &&
- !isalnum(*p) && strchr(mp, *p) != NULL)
- break;
- }
-
- /*
- * 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;
- rval = argv_exp3(sp, excp, p, len);
- break;
- case 1:
- if (*p == '*') {
- *p = '\0';
- rval = argv_lexp(sp, excp, bp + SHELLOFFSET);
- break;
- }
- /* FALLTHROUGH */
- default:
- if (argv_sexp(sp, &bp, &blen, &len)) {
- rval = 1;
- goto err;
- }
- p = bp;
- rval = argv_exp3(sp, excp, p, len);
- break;
- }
-
-err: FREE_SPACE(sp, bp, blen);
- return (rval);
-}
-
-/*
- * argv_exp3 --
- * Take a string and break it up into an argv, which is appended
- * to the argument list.
- *
- * PUBLIC: int argv_exp3 __P((SCR *, EXCMD *, char *, size_t));
- */
-int
-argv_exp3(sp, excp, cmd, cmdlen)
- SCR *sp;
- EXCMD *excp;
- char *cmd;
- size_t cmdlen;
-{
- EX_PRIVATE *exp;
- size_t len;
- int ch, off;
- char *ap, *p;
-
- for (exp = EXP(sp); cmdlen > 0; ++exp->argsoff) {
- /* Skip any leading whitespace. */
- for (; cmdlen > 0; --cmdlen, ++cmd) {
- ch = *cmd;
- if (!isblank(ch))
- break;
- }
- if (cmdlen == 0)
- break;
-
- /*
- * Determine the length of this whitespace delimited
- * argument.
- *
- * QUOTING NOTE:
- *
- * Skip any character preceded by the user's quoting
- * character.
- */
- for (ap = cmd, len = 0; cmdlen > 0; ++cmd, --cmdlen, ++len) {
- ch = *cmd;
- if (IS_ESCAPE(sp, excp, ch) && cmdlen > 1) {
- ++cmd;
- --cmdlen;
- } else if (isblank(ch))
- break;
- }
-
- /*
- * Copy the argument into place.
- *
- * QUOTING NOTE:
- *
- * Lose quote chars.
- */
- argv_alloc(sp, len);
- off = exp->argsoff;
- exp->args[off]->len = len;
- for (p = exp->args[off]->bp; len > 0; --len, *p++ = *ap++)
- if (IS_ESCAPE(sp, excp, *ap))
- ++ap;
- *p = '\0';
- }
- excp->argv = exp->args;
- excp->argc = exp->argsoff;
-
-#if defined(DEBUG) && 0
- for (cnt = 0; cnt < exp->argsoff; ++cnt)
- TRACE(sp, "arg %d: {%s}\n", cnt, exp->argv[cnt]);
-#endif
- return (0);
-}
-
-/*
- * argv_fexp --
- * Do file name and bang command expansion.
- */
-static int
-argv_fexp(sp, excp, cmd, cmdlen, p, lenp, bpp, blenp, is_bang)
- SCR *sp;
- EXCMD *excp;
- char *cmd, *p, **bpp;
- size_t cmdlen, *lenp, *blenp;
- int is_bang;
-{
- EX_PRIVATE *exp;
- char *bp, *t;
- size_t blen, len, off, tlen;
-
- /* Replace file name characters. */
- for (bp = *bpp, blen = *blenp, len = *lenp; cmdlen > 0; --cmdlen, ++cmd)
- switch (*cmd) {
- case '!':
- if (!is_bang)
- goto ins_ch;
- exp = EXP(sp);
- if (exp->lastbcomm == NULL) {
- msgq(sp, M_ERR,
- "115|No previous command to replace \"!\"");
- return (1);
- }
- len += tlen = strlen(exp->lastbcomm);
- off = p - bp;
- ADD_SPACE_RET(sp, bp, blen, len);
- p = bp + off;
- memcpy(p, exp->lastbcomm, tlen);
- p += tlen;
- F_SET(excp, E_MODIFY);
- break;
- case '%':
- if ((t = sp->frp->name) == NULL) {
- msgq(sp, M_ERR,
- "116|No filename to substitute for %%");
- return (1);
- }
- tlen = strlen(t);
- len += tlen;
- off = p - bp;
- ADD_SPACE_RET(sp, bp, blen, len);
- p = bp + off;
- memcpy(p, t, tlen);
- p += tlen;
- F_SET(excp, E_MODIFY);
- break;
- case '#':
- if ((t = sp->alt_name) == NULL) {
- msgq(sp, M_ERR,
- "117|No filename to substitute for #");
- return (1);
- }
- len += tlen = strlen(t);
- off = p - bp;
- ADD_SPACE_RET(sp, bp, blen, len);
- p = bp + off;
- memcpy(p, t, tlen);
- p += tlen;
- F_SET(excp, E_MODIFY);
- break;
- case '\\':
- /*
- * QUOTING NOTE:
- *
- * Strip any backslashes that protected the file
- * expansion characters.
- */
- if (cmdlen > 1 &&
- (cmd[1] == '%' || cmd[1] == '#' || cmd[1] == '!')) {
- ++cmd;
- --cmdlen;
- }
- /* FALLTHROUGH */
- default:
-ins_ch: ++len;
- off = p - bp;
- ADD_SPACE_RET(sp, bp, blen, len);
- p = bp + off;
- *p++ = *cmd;
- }
-
- /* Nul termination. */
- ++len;
- off = p - bp;
- ADD_SPACE_RET(sp, bp, blen, len);
- p = bp + off;
- *p = '\0';
-
- /* Return the new string length, buffer, buffer length. */
- *lenp = len - 1;
- *bpp = bp;
- *blenp = blen;
- return (0);
-}
-
-/*
- * argv_alloc --
- * Make more space for arguments.
- */
-static int
-argv_alloc(sp, len)
- SCR *sp;
- size_t len;
-{
- ARGS *ap;
- EX_PRIVATE *exp;
- int cnt, off;
-
- /*
- * Allocate room for another argument, always leaving
- * enough room for an ARGS structure with a length of 0.
- */
-#define INCREMENT 20
- exp = EXP(sp);
- off = exp->argsoff;
- if (exp->argscnt == 0 || off + 2 >= exp->argscnt - 1) {
- cnt = exp->argscnt + INCREMENT;
- REALLOC(sp, exp->args, ARGS **, cnt * sizeof(ARGS *));
- if (exp->args == NULL) {
- (void)argv_free(sp);
- goto mem;
- }
- memset(&exp->args[exp->argscnt], 0, INCREMENT * sizeof(ARGS *));
- exp->argscnt = cnt;
- }
-
- /* First argument. */
- if (exp->args[off] == NULL) {
- CALLOC(sp, exp->args[off], ARGS *, 1, sizeof(ARGS));
- if (exp->args[off] == NULL)
- goto mem;
- }
-
- /* First argument buffer. */
- ap = exp->args[off];
- ap->len = 0;
- if (ap->blen < len + 1) {
- ap->blen = len + 1;
- REALLOC(sp, ap->bp, CHAR_T *, ap->blen * sizeof(CHAR_T));
- if (ap->bp == NULL) {
- ap->bp = NULL;
- ap->blen = 0;
- F_CLR(ap, A_ALLOCATED);
-mem: msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- F_SET(ap, A_ALLOCATED);
- }
-
- /* Second argument. */
- if (exp->args[++off] == NULL) {
- CALLOC(sp, exp->args[off], ARGS *, 1, sizeof(ARGS));
- if (exp->args[off] == NULL)
- goto mem;
- }
- /* 0 length serves as end-of-argument marker. */
- exp->args[off]->len = 0;
- return (0);
-}
-
-/*
- * argv_free --
- * Free up argument structures.
- *
- * PUBLIC: int argv_free __P((SCR *));
- */
-int
-argv_free(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- int off;
-
- exp = EXP(sp);
- if (exp->args != NULL) {
- for (off = 0; off < exp->argscnt; ++off) {
- if (exp->args[off] == NULL)
- continue;
- if (F_ISSET(exp->args[off], A_ALLOCATED))
- free(exp->args[off]->bp);
- free(exp->args[off]);
- }
- free(exp->args);
- }
- exp->args = NULL;
- exp->argscnt = 0;
- exp->argsoff = 0;
- return (0);
-}
-
-/*
- * argv_lexp --
- * Find all file names matching the prefix and append them to the
- * buffer.
- */
-static int
-argv_lexp(sp, excp, path)
- SCR *sp;
- EXCMD *excp;
- char *path;
-{
- struct dirent *dp;
- DIR *dirp;
- EX_PRIVATE *exp;
- int off;
- size_t dlen, len, nlen;
- char *dname, *name, *p;
-
- exp = EXP(sp);
-
- /* Set up the name and length for comparison. */
- if ((p = strrchr(path, '/')) == NULL) {
- dname = ".";
- dlen = 0;
- name = path;
- } else {
- if (p == path) {
- dname = "/";
- dlen = 1;
- } else {
- *p = '\0';
- dname = path;
- dlen = strlen(path);
- }
- name = p + 1;
- }
- nlen = strlen(name);
-
- /*
- * XXX
- * We don't use the d_namlen field, it's not portable enough; we
- * assume that d_name is nul terminated, instead.
- */
- if ((dirp = opendir(dname)) == NULL) {
- msgq_str(sp, M_SYSERR, dname, "%s");
- return (1);
- }
- for (off = exp->argsoff; (dp = readdir(dirp)) != NULL;) {
- if (nlen == 0) {
- if (dp->d_name[0] == '.')
- continue;
- len = strlen(dp->d_name);
- } else {
- len = strlen(dp->d_name);
- if (len < nlen || memcmp(dp->d_name, name, nlen))
- continue;
- }
-
- /* Directory + name + slash + null. */
- argv_alloc(sp, dlen + len + 2);
- p = exp->args[exp->argsoff]->bp;
- if (dlen != 0) {
- memcpy(p, dname, dlen);
- p += dlen;
- if (dlen > 1 || dname[0] != '/')
- *p++ = '/';
- }
- memcpy(p, dp->d_name, len + 1);
- exp->args[exp->argsoff]->len = dlen + len + 1;
- ++exp->argsoff;
- excp->argv = exp->args;
- excp->argc = exp->argsoff;
- }
- closedir(dirp);
-
- if (off == exp->argsoff) {
- /*
- * 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.
- */
- msgq(sp, M_ERR, "304|Shell expansion failed");
- return (1);
- }
- qsort(exp->args + off, exp->argsoff - off, sizeof(ARGS *), argv_comp);
- return (0);
-}
-
-/*
- * argv_comp --
- * Alphabetic comparison.
- */
-static int
-argv_comp(a, b)
- const void *a, *b;
-{
- return (strcmp((char *)(*(ARGS **)a)->bp, (char *)(*(ARGS **)b)->bp));
-}
-
-/*
- * argv_sexp --
- * Fork a shell, pipe a command through it, and read the output into
- * a buffer.
- */
-static int
-argv_sexp(sp, bpp, blenp, lenp)
- SCR *sp;
- char **bpp;
- size_t *blenp, *lenp;
-{
- enum { SEXP_ERR, SEXP_EXPANSION_ERR, SEXP_OK } rval;
- FILE *ifp;
- pid_t pid;
- size_t blen, len;
- int ch, std_output[2];
- char *bp, *p, *sh, *sh_path;
-
- /* Secure means no shell access. */
- if (O_ISSET(sp, O_SECURE)) {
- msgq(sp, M_ERR,
-"289|Shell expansions not supported when the secure edit option is set");
- return (1);
- }
-
- sh_path = O_STR(sp, O_SHELL);
- if ((sh = strrchr(sh_path, '/')) == NULL)
- sh = sh_path;
- else
- ++sh;
-
- /* Local copies of the buffer variables. */
- bp = *bpp;
- blen = *blenp;
-
- /*
- * There are two different processes running through this code, named
- * the utility (the shell) and the parent. The utility reads standard
- * input and writes standard output and standard error output. The
- * parent writes to the utility, reads its standard output and ignores
- * its standard error output. Historically, the standard error output
- * was discarded by vi, as it produces a lot of noise when file patterns
- * don't match.
- *
- * The parent reads std_output[0], and the utility writes std_output[1].
- */
- ifp = NULL;
- std_output[0] = std_output[1] = -1;
- if (pipe(std_output) < 0) {
- msgq(sp, M_SYSERR, "pipe");
- return (1);
- }
- if ((ifp = fdopen(std_output[0], "r")) == NULL) {
- msgq(sp, M_SYSERR, "fdopen");
- goto err;
- }
-
- /*
- * Do the minimal amount of work possible, the shell is going to run
- * briefly and then exit. We sincerely hope.
- */
- switch (pid = vfork()) {
- case -1: /* Error. */
- msgq(sp, M_SYSERR, "vfork");
-err: if (ifp != NULL)
- (void)fclose(ifp);
- else if (std_output[0] != -1)
- close(std_output[0]);
- if (std_output[1] != -1)
- close(std_output[0]);
- return (1);
- case 0: /* Utility. */
- /* Redirect stdout to the write end of the pipe. */
- (void)dup2(std_output[1], STDOUT_FILENO);
-
- /* Close the utility's file descriptors. */
- (void)close(std_output[0]);
- (void)close(std_output[1]);
- (void)close(STDERR_FILENO);
-
- /*
- * XXX
- * Assume that all shells have -c.
- */
- execl(sh_path, sh, "-c", bp, NULL);
- msgq_str(sp, M_SYSERR, sh_path, "118|Error: execl: %s");
- _exit(127);
- default: /* Parent. */
- /* Close the pipe ends the parent won't use. */
- (void)close(std_output[1]);
- break;
- }
-
- /*
- * Copy process standard output into a buffer.
- *
- * !!!
- * Historic vi apparently discarded leading \n and \r's from
- * the shell output stream. We don't on the grounds that any
- * shell that does that is broken.
- */
- for (p = bp, len = 0, ch = EOF;
- (ch = getc(ifp)) != EOF; *p++ = ch, --blen, ++len)
- if (blen < 5) {
- ADD_SPACE_GOTO(sp, bp, *blenp, *blenp * 2);
- p = bp + len;
- blen = *blenp - len;
- }
-
- /* Delete the final newline, nul terminate the string. */
- if (p > bp && (p[-1] == '\n' || p[-1] == '\r')) {
- --p;
- --len;
- }
- *p = '\0';
- *lenp = len;
- *bpp = bp; /* *blenp is already updated. */
-
- if (ferror(ifp))
- goto ioerr;
- if (fclose(ifp)) {
-ioerr: msgq_str(sp, M_ERR, sh, "119|I/O error: %s");
-alloc_err: rval = SEXP_ERR;
- } else
- rval = SEXP_OK;
-
- /*
- * Wait for the process. If the shell process fails (e.g., "echo $q"
- * where q wasn't a defined variable) or if the returned string has
- * no characters or only blank characters, (e.g., "echo $5"), complain
- * that the shell expansion failed. We can't know for certain that's
- * the error, but it's a good guess, and it matches historic practice.
- * This won't catch "echo foo_$5", but that's not a common error and
- * historic vi didn't catch it either.
- */
- if (proc_wait(sp, (long)pid, sh, 1, 0))
- rval = SEXP_EXPANSION_ERR;
-
- for (p = bp; len; ++p, --len)
- if (!isblank(*p))
- break;
- if (len == 0)
- rval = SEXP_EXPANSION_ERR;
-
- if (rval == SEXP_EXPANSION_ERR)
- msgq(sp, M_ERR, "304|Shell expansion failed");
-
- return (rval == SEXP_OK ? 0 : 1);
-}
diff --git a/contrib/nvi/ex/ex_at.c b/contrib/nvi/ex/ex_at.c
deleted file mode 100644
index e9c6c59..0000000
--- a/contrib/nvi/ex/ex_at.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_at.c 10.12 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_at -- :@[@ | buffer]
- * :*[* | buffer]
- *
- * Execute the contents of the buffer.
- *
- * PUBLIC: int ex_at __P((SCR *, EXCMD *));
- */
-int
-ex_at(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- CB *cbp;
- CHAR_T name;
- EXCMD *ecp;
- RANGE *rp;
- TEXT *tp;
- size_t len;
- char *p;
-
- /*
- * !!!
- * Historically, [@*]<carriage-return> and [@*][@*] executed the most
- * recently executed buffer in ex mode.
- */
- name = FL_ISSET(cmdp->iflags, E_C_BUFFER) ? cmdp->buffer : '@';
- if (name == '@' || name == '*') {
- if (!F_ISSET(sp, SC_AT_SET)) {
- ex_emsg(sp, NULL, EXM_NOPREVBUF);
- return (1);
- }
- name = sp->at_lbuf;
- }
- sp->at_lbuf = name;
- F_SET(sp, SC_AT_SET);
-
- CBNAME(sp, cbp, name);
- if (cbp == NULL) {
- ex_emsg(sp, KEY_NAME(sp, name), EXM_EMPTYBUF);
- return (1);
- }
-
- /*
- * !!!
- * Historically the @ command took a range of lines, and the @ buffer
- * was executed once per line. The historic vi could be trashed by
- * this because it didn't notice if the underlying file changed, or,
- * for that matter, if there were no more lines on which to operate.
- * For example, take a 10 line file, load "%delete" into a buffer,
- * and enter :8,10@<buffer>.
- *
- * The solution is a bit tricky. If the user specifies a range, take
- * the same approach as for global commands, and discard the command
- * if exit or switch to a new file/screen. If the user doesn't specify
- * the range, continue to execute after a file/screen switch, which
- * means @ buffers are still useful in a multi-screen environment.
- */
- CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
- CIRCLEQ_INIT(&ecp->rq);
- CALLOC_RET(sp, rp, RANGE *, 1, sizeof(RANGE));
- rp->start = cmdp->addr1.lno;
- if (F_ISSET(cmdp, E_ADDR_DEF)) {
- rp->stop = rp->start;
- FL_SET(ecp->agv_flags, AGV_AT_NORANGE);
- } else {
- rp->stop = cmdp->addr2.lno;
- FL_SET(ecp->agv_flags, AGV_AT);
- }
- CIRCLEQ_INSERT_HEAD(&ecp->rq, rp, q);
-
- /*
- * Buffers executed in ex mode or from the colon command line in vi
- * were ex commands. We can't push it on the terminal queue, since
- * it has to be executed immediately, and we may be in the middle of
- * an ex command already. Push the command on the ex command stack.
- * Build two copies of the command. We need two copies because the
- * ex parser may step on the command string when it's parsing it.
- */
- for (len = 0, tp = cbp->textq.cqh_last;
- tp != (void *)&cbp->textq; tp = tp->q.cqe_prev)
- len += tp->len + 1;
-
- MALLOC_RET(sp, ecp->cp, char *, len * 2);
- ecp->o_cp = ecp->cp;
- ecp->o_clen = len;
- ecp->cp[len] = '\0';
-
- /* Copy the buffer into the command space. */
- for (p = ecp->cp + len, tp = cbp->textq.cqh_last;
- tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) {
- memcpy(p, tp->lb, tp->len);
- p += tp->len;
- *p++ = '\n';
- }
-
- LIST_INSERT_HEAD(&sp->gp->ecq, ecp, q);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_bang.c b/contrib/nvi/ex/ex_bang.c
deleted file mode 100644
index 25f3f77..0000000
--- a/contrib/nvi/ex/ex_bang.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_bang.c 10.33 (Berkeley) 9/23/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-/*
- * ex_bang -- :[line [,line]] ! command
- *
- * Pass the rest of the line after the ! character to the program named by
- * the O_SHELL option.
- *
- * Historical vi did NOT do shell expansion on the arguments before passing
- * them, only file name expansion. This means that the O_SHELL program got
- * "$t" as an argument if that is what the user entered. Also, there's a
- * special expansion done for the bang command. Any exclamation points in
- * the user's argument are replaced by the last, expanded ! command.
- *
- * There's some fairly amazing slop in this routine to make the different
- * ways of getting here display the right things. It took a long time to
- * get it right (wrong?), so be careful.
- *
- * PUBLIC: int ex_bang __P((SCR *, EXCMD *));
- */
-int
-ex_bang(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- enum filtertype ftype;
- ARGS *ap;
- EX_PRIVATE *exp;
- MARK rm;
- recno_t lno;
- int rval;
- const char *msg;
-
- ap = cmdp->argv[0];
- if (ap->len == 0) {
- ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
-
- /* Set the "last bang command" remembered value. */
- exp = EXP(sp);
- if (exp->lastbcomm != NULL)
- free(exp->lastbcomm);
- if ((exp->lastbcomm = strdup(ap->bp)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- /*
- * If the command was modified by the expansion, it was historically
- * redisplayed.
- */
- if (F_ISSET(cmdp, E_MODIFY) && !F_ISSET(sp, SC_EX_SILENT)) {
- /*
- * Display the command if modified. Historic ex/vi displayed
- * the command if it was modified due to file name and/or bang
- * expansion. If piping lines in vi, it would be immediately
- * overwritten by any error or line change reporting.
- */
- if (F_ISSET(sp, SC_VI))
- vs_update(sp, "!", ap->bp);
- else {
- (void)ex_printf(sp, "!%s\n", ap->bp);
- (void)ex_fflush(sp);
- }
- }
-
- /*
- * If no addresses were specified, run the command. If there's an
- * underlying file, it's been modified and autowrite is set, write
- * the file back. If the file has been modified, autowrite is not
- * set and the warn option is set, tell the user about the file.
- */
- if (cmdp->addrcnt == 0) {
- msg = NULL;
- if (sp->ep != NULL && F_ISSET(sp->ep, F_MODIFIED))
- if (O_ISSET(sp, O_AUTOWRITE)) {
- if (file_aw(sp, FS_ALL))
- return (0);
- } else if (O_ISSET(sp, O_WARN) &&
- !F_ISSET(sp, SC_EX_SILENT))
- msg = msg_cat(sp,
- "303|File modified since last write.",
- NULL);
-
- /* If we're still in a vi screen, move out explicitly. */
- (void)ex_exec_proc(sp,
- cmdp, ap->bp, msg, !F_ISSET(sp, SC_EX | SC_SCR_EXWROTE));
- }
-
- /*
- * If addresses were specified, pipe lines from the file through the
- * command.
- *
- * Historically, vi lines were replaced by both the stdout and stderr
- * lines of the command, but ex lines by only the stdout lines. This
- * makes no sense to me, so nvi makes it consistent for both, and
- * matches vi's historic behavior.
- */
- else {
- NEEDFILE(sp, cmdp);
-
- /* Autoprint is set historically, even if the command fails. */
- F_SET(cmdp, E_AUTOPRINT);
-
- /*
- * !!!
- * Historical vi permitted "!!" in an empty file. When this
- * happens, we arrive here with two addresses of 1,1 and a
- * bad attitude. The simple solution is to turn it into a
- * FILTER_READ operation, with the exception that stdin isn't
- * opened for the utility, and the cursor position isn't the
- * same. The only historic glitch (I think) is that we don't
- * put an empty line into the default cut buffer, as historic
- * vi did. Imagine, if you can, my disappointment.
- */
- ftype = FILTER_BANG;
- if (cmdp->addr1.lno == 1 && cmdp->addr2.lno == 1) {
- if (db_last(sp, &lno))
- return (1);
- if (lno == 0) {
- cmdp->addr1.lno = cmdp->addr2.lno = 0;
- ftype = FILTER_RBANG;
- }
- }
- rval = ex_filter(sp, cmdp,
- &cmdp->addr1, &cmdp->addr2, &rm, ap->bp, ftype);
-
- /*
- * If in vi mode, move to the first nonblank.
- *
- * !!!
- * Historic vi wasn't consistent in this area -- if you used
- * a forward motion it moved to the first nonblank, but if you
- * did a backward motion it didn't. And, if you followed a
- * backward motion with a forward motion, it wouldn't move to
- * the nonblank for either. Going to the nonblank generally
- * seems more useful and consistent, so we do it.
- */
- sp->lno = rm.lno;
- if (F_ISSET(sp, SC_VI)) {
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- } else
- sp->cno = rm.cno;
- }
-
- /* Ex terminates with a bang, even if the command fails. */
- if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
- (void)ex_puts(sp, "!\n");
-
- /*
- * XXX
- * The ! commands never return an error, so that autoprint always
- * happens in the ex parser.
- */
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_cd.c b/contrib/nvi/ex/ex_cd.c
deleted file mode 100644
index 3307c7b..0000000
--- a/contrib/nvi/ex/ex_cd.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_cd.c 10.10 (Berkeley) 8/12/96";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-/*
- * ex_cd -- :cd[!] [directory]
- * Change directories.
- *
- * PUBLIC: int ex_cd __P((SCR *, EXCMD *));
- */
-int
-ex_cd(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- struct passwd *pw;
- ARGS *ap;
- CHAR_T savech;
- char *dir, *p, *t; /* XXX: END OF THE STACK, DON'T TRUST GETCWD. */
- char buf[MAXPATHLEN * 2];
-
- /*
- * !!!
- * Historic practice is that the cd isn't attempted if the file has
- * been modified, unless its name begins with a leading '/' or the
- * force flag is set.
- */
- if (F_ISSET(sp->ep, F_MODIFIED) &&
- !FL_ISSET(cmdp->iflags, E_C_FORCE) && sp->frp->name[0] != '/') {
- msgq(sp, M_ERR,
- "120|File modified since last complete write; write or use ! to override");
- return (1);
- }
-
- switch (cmdp->argc) {
- case 0:
- /* If no argument, change to the user's home directory. */
- if ((dir = getenv("HOME")) == NULL) {
- if ((pw = getpwuid(getuid())) == NULL ||
- pw->pw_dir == NULL || pw->pw_dir[0] == '\0') {
- msgq(sp, M_ERR,
- "121|Unable to find home directory location");
- return (1);
- }
- dir = pw->pw_dir;
- }
- break;
- case 1:
- dir = cmdp->argv[0]->bp;
- break;
- default:
- abort();
- }
-
- /*
- * Try the current directory first. If this succeeds, don't display
- * a message, vi didn't historically, and it should be obvious to the
- * user where they are.
- */
- if (!chdir(dir))
- return (0);
-
- /*
- * If moving to the user's home directory, or, the path begins with
- * "/", "./" or "../", it's the only place we try.
- */
- if (cmdp->argc == 0 ||
- (ap = cmdp->argv[0])->bp[0] == '/' ||
- ap->len == 1 && ap->bp[0] == '.' ||
- ap->len >= 2 && ap->bp[0] == '.' && ap->bp[1] == '.' &&
- (ap->bp[2] == '/' || ap->bp[2] == '\0'))
- goto err;
-
- /* Try the O_CDPATH option values. */
- for (p = t = O_STR(sp, O_CDPATH);; ++p)
- if (*p == '\0' || *p == ':') {
- /*
- * Empty strings specify ".". The only way to get an
- * empty string is a leading colon, colons in a row,
- * or a trailing colon. Or, to put it the other way,
- * if the length is 1 or less, then we're dealing with
- * ":XXX", "XXX::XXXX" , "XXX:", or "". Since we've
- * already tried dot, we ignore tham all.
- */
- if (t < p - 1) {
- savech = *p;
- *p = '\0';
- (void)snprintf(buf,
- sizeof(buf), "%s/%s", t, dir);
- *p = savech;
- if (!chdir(buf)) {
- if (getcwd(buf, sizeof(buf)) != NULL)
- msgq_str(sp, M_INFO, buf, "122|New current directory: %s");
- return (0);
- }
- }
- t = p + 1;
- if (*p == '\0')
- break;
- }
-
-err: msgq_str(sp, M_SYSERR, dir, "%s");
- return (1);
-}
diff --git a/contrib/nvi/ex/ex_cmd.c b/contrib/nvi/ex/ex_cmd.c
deleted file mode 100644
index 8f7fc8d..0000000
--- a/contrib/nvi/ex/ex_cmd.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_cmd.c 10.20 (Berkeley) 10/10/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * This array maps ex command names to command functions.
- *
- * The order in which command names are listed below is important --
- * ambiguous abbreviations are resolved to be the first possible match,
- * e.g. "r" means "read", not "rewind", because "read" is listed before
- * "rewind".
- *
- * The syntax of the ex commands is unbelievably irregular, and a special
- * case from beginning to end. Each command has an associated "syntax
- * script" which describes the "arguments" that are possible. The script
- * syntax is as follows:
- *
- * ! -- ! flag
- * 1 -- flags: [+-]*[pl#][+-]*
- * 2 -- flags: [-.+^]
- * 3 -- flags: [-.+^=]
- * b -- buffer
- * c[01+a] -- count (0-N, 1-N, signed 1-N, address offset)
- * f[N#][or] -- file (a number or N, optional or required)
- * l -- line
- * S -- string with file name expansion
- * s -- string
- * W -- word string
- * w[N#][or] -- word (a number or N, optional or required)
- */
-EXCMDLIST const cmds[] = {
-/* C_SCROLL */
- {"\004", ex_pr, E_ADDR2,
- "",
- "^D",
- "scroll lines"},
-/* C_BANG */
- {"!", ex_bang, E_ADDR2_NONE | E_SECURE,
- "S",
- "[line [,line]] ! command",
- "filter lines through commands or run commands"},
-/* C_HASH */
- {"#", ex_number, E_ADDR2|E_CLRFLAG,
- "ca1",
- "[line [,line]] # [count] [l]",
- "display numbered lines"},
-/* C_SUBAGAIN */
- {"&", ex_subagain, E_ADDR2,
- "s",
- "[line [,line]] & [cgr] [count] [#lp]",
- "repeat the last subsitution"},
-/* C_STAR */
- {"*", ex_at, 0,
- "b",
- "* [buffer]",
- "execute a buffer"},
-/* C_SHIFTL */
- {"<", ex_shiftl, E_ADDR2|E_AUTOPRINT,
- "ca1",
- "[line [,line]] <[<...] [count] [flags]",
- "shift lines left"},
-/* C_EQUAL */
- {"=", ex_equal, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
- "1",
- "[line] = [flags]",
- "display line number"},
-/* C_SHIFTR */
- {">", ex_shiftr, E_ADDR2|E_AUTOPRINT,
- "ca1",
- "[line [,line]] >[>...] [count] [flags]",
- "shift lines right"},
-/* C_AT */
- {"@", ex_at, E_ADDR2,
- "b",
- "@ [buffer]",
- "execute a buffer"},
-/* C_APPEND */
- {"append", ex_append, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
- "!",
- "[line] a[ppend][!]",
- "append input to a line"},
-/* C_ABBR */
- {"abbreviate", ex_abbr, 0,
- "W",
- "ab[brev] [word replace]",
- "specify an input abbreviation"},
-/* C_ARGS */
- {"args", ex_args, 0,
- "",
- "ar[gs]",
- "display file argument list"},
-/* C_BG */
- {"bg", ex_bg, E_VIONLY,
- "",
- "bg",
- "put a foreground screen into the background"},
-/* C_CHANGE */
- {"change", ex_change, E_ADDR2|E_ADDR_ZERODEF,
- "!ca",
- "[line [,line]] c[hange][!] [count]",
- "change lines to input"},
-/* C_CD */
- {"cd", ex_cd, 0,
- "!f1o",
- "cd[!] [directory]",
- "change the current directory"},
-/* C_CHDIR */
- {"chdir", ex_cd, 0,
- "!f1o",
- "chd[ir][!] [directory]",
- "change the current directory"},
-/* C_COPY */
- {"copy", ex_copy, E_ADDR2|E_AUTOPRINT,
- "l1",
- "[line [,line]] co[py] line [flags]",
- "copy lines elsewhere in the file"},
-/* C_CSCOPE */
- {"cscope", ex_cscope, 0,
- "!s",
- "cs[cope] command [args]",
- "create a set of tags using a cscope command"},
-/*
- * !!!
- * Adding new commands starting with 'd' may break the delete command code
- * in ex_cmd() (the ex parser). Read through the comments there, first.
- */
-/* C_DELETE */
- {"delete", ex_delete, E_ADDR2|E_AUTOPRINT,
- "bca1",
- "[line [,line]] d[elete][flags] [buffer] [count] [flags]",
- "delete lines from the file"},
-/* C_DISPLAY */
- {"display", ex_display, 0,
- "w1r",
- "display b[uffers] | c[onnections] | s[creens] | t[ags]",
- "display buffers, connections, screens or tags"},
-/* C_EDIT */
- {"edit", ex_edit, E_NEWSCREEN,
- "f1o",
- "[Ee][dit][!] [+cmd] [file]",
- "begin editing another file"},
-/* C_EX */
- {"ex", ex_edit, E_NEWSCREEN,
- "f1o",
- "[Ee]x[!] [+cmd] [file]",
- "begin editing another file"},
-/* C_EXUSAGE */
- {"exusage", ex_usage, 0,
- "w1o",
- "[exu]sage [command]",
- "display ex command usage statement"},
-/* C_FILE */
- {"file", ex_file, 0,
- "f1o",
- "f[ile] [name]",
- "display (and optionally set) file name"},
-/* C_FG */
- {"fg", ex_fg, E_NEWSCREEN|E_VIONLY,
- "f1o",
- "[Ff]g [file]",
- "bring a backgrounded screen into the foreground"},
-/* C_GLOBAL */
- {"global", ex_global, E_ADDR2_ALL,
- "!s",
- "[line [,line]] g[lobal][!] [;/]RE[;/] [commands]",
- "execute a global command on lines matching an RE"},
-/* C_HELP */
- {"help", ex_help, 0,
- "",
- "he[lp]",
- "display help statement"},
-/* C_INSERT */
- {"insert", ex_insert, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
- "!",
- "[line] i[nsert][!]",
- "insert input before a line"},
-/* C_JOIN */
- {"join", ex_join, E_ADDR2|E_AUTOPRINT,
- "!ca1",
- "[line [,line]] j[oin][!] [count] [flags]",
- "join lines into a single line"},
-/* C_K */
- {"k", ex_mark, E_ADDR1,
- "w1r",
- "[line] k key",
- "mark a line position"},
-/* C_LIST */
- {"list", ex_list, E_ADDR2|E_CLRFLAG,
- "ca1",
- "[line [,line]] l[ist] [count] [#]",
- "display lines in an unambiguous form"},
-/* C_MOVE */
- {"move", ex_move, E_ADDR2|E_AUTOPRINT,
- "l",
- "[line [,line]] m[ove] line",
- "move lines elsewhere in the file"},
-/* C_MARK */
- {"mark", ex_mark, E_ADDR1,
- "w1r",
- "[line] ma[rk] key",
- "mark a line position"},
-/* C_MAP */
- {"map", ex_map, 0,
- "!W",
- "map[!] [keys replace]",
- "map input or commands to one or more keys"},
-/* C_MKEXRC */
- {"mkexrc", ex_mkexrc, 0,
- "!f1r",
- "mkexrc[!] file",
- "write a .exrc file"},
-/* C_NEXT */
- {"next", ex_next, E_NEWSCREEN,
- "!fN",
- "[Nn][ext][!] [+cmd] [file ...]",
- "edit (and optionally specify) the next file"},
-/* C_NUMBER */
- {"number", ex_number, E_ADDR2|E_CLRFLAG,
- "ca1",
- "[line [,line]] nu[mber] [count] [l]",
- "change display to number lines"},
-/* C_OPEN */
- {"open", ex_open, E_ADDR1,
- "s",
- "[line] o[pen] [/RE/] [flags]",
- "enter \"open\" mode (not implemented)"},
-/* C_PRINT */
- {"print", ex_pr, E_ADDR2|E_CLRFLAG,
- "ca1",
- "[line [,line]] p[rint] [count] [#l]",
- "display lines"},
-/* C_PERLCMD */
- {"perl", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO|
- E_ADDR_ZERODEF|E_SECURE,
- "s",
- "pe[rl] cmd",
- "run the perl interpreter with the command"},
-/* C_PERLDOCMD */
- {"perldo", ex_perl, E_ADDR2_ALL|E_ADDR_ZERO|
- E_ADDR_ZERODEF|E_SECURE,
- "s",
- "perld[o] cmd",
- "run the perl interpreter with the command, on each line"},
-/* C_PRESERVE */
- {"preserve", ex_preserve, 0,
- "",
- "pre[serve]",
- "preserve an edit session for recovery"},
-/* C_PREVIOUS */
- {"previous", ex_prev, E_NEWSCREEN,
- "!",
- "[Pp]rev[ious][!]",
- "edit the previous file in the file argument list"},
-/* C_PUT */
- {"put", ex_put,
- E_ADDR1|E_AUTOPRINT|E_ADDR_ZERO|E_ADDR_ZERODEF,
- "b",
- "[line] pu[t] [buffer]",
- "append a cut buffer to the line"},
-/* C_QUIT */
- {"quit", ex_quit, 0,
- "!",
- "q[uit][!]",
- "exit ex/vi"},
-/* C_READ */
- {"read", ex_read, E_ADDR1|E_ADDR_ZERO|E_ADDR_ZERODEF,
- "s",
- "[line] r[ead] [!cmd | [file]]",
- "append input from a command or file to the line"},
-/* C_RECOVER */
- {"recover", ex_recover, 0,
- "!f1r",
- "recover[!] file",
- "recover a saved file"},
-/* C_RESIZE */
- {"resize", ex_resize, E_VIONLY,
- "c+",
- "resize [+-]rows",
- "grow or shrink the current screen"},
-/* C_REWIND */
- {"rewind", ex_rew, 0,
- "!",
- "rew[ind][!]",
- "re-edit all the files in the file argument list"},
-/*
- * !!!
- * Adding new commands starting with 's' may break the substitute command code
- * in ex_cmd() (the ex parser). Read through the comments there, first.
- */
-/* C_SUBSTITUTE */
- {"s", ex_s, E_ADDR2,
- "s",
- "[line [,line]] s [[/;]RE[/;]repl[/;] [cgr] [count] [#lp]]",
- "substitute on lines matching an RE"},
-/* C_SCRIPT */
- {"script", ex_script, E_SECURE,
- "!f1o",
- "sc[ript][!] [file]",
- "run a shell in a screen"},
-/* C_SET */
- {"set", ex_set, 0,
- "wN",
- "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]",
- "set options (use \":set all\" to see all options)"},
-/* C_SHELL */
- {"shell", ex_shell, E_SECURE,
- "",
- "sh[ell]",
- "suspend editing and run a shell"},
-/* C_SOURCE */
- {"source", ex_source, 0,
- "f1r",
- "so[urce] file",
- "read a file of ex commands"},
-/* C_STOP */
- {"stop", ex_stop, E_SECURE,
- "!",
- "st[op][!]",
- "suspend the edit session"},
-/* C_SUSPEND */
- {"suspend", ex_stop, E_SECURE,
- "!",
- "su[spend][!]",
- "suspend the edit session"},
-/* C_T */
- {"t", ex_copy, E_ADDR2|E_AUTOPRINT,
- "l1",
- "[line [,line]] t line [flags]",
- "copy lines elsewhere in the file"},
-/* C_TAG */
- {"tag", ex_tag_push, E_NEWSCREEN,
- "!w1o",
- "[Tt]a[g][!] [string]",
- "edit the file containing the tag"},
-/* C_TAGNEXT */
- {"tagnext", ex_tag_next, 0,
- "!",
- "tagn[ext][!]",
- "move to the next tag"},
-/* C_TAGPOP */
- {"tagpop", ex_tag_pop, 0,
- "!w1o",
- "tagp[op][!] [number | file]",
- "return to the previous group of tags"},
-/* C_TAGPREV */
- {"tagprev", ex_tag_prev, 0,
- "!",
- "tagpr[ev][!]",
- "move to the previous tag"},
-/* C_TAGTOP */
- {"tagtop", ex_tag_top, 0,
- "!",
- "tagt[op][!]",
- "discard all tags"},
-/* C_TCLCMD */
- {"tcl", ex_tcl, E_ADDR2_ALL|E_ADDR_ZERO|
- E_ADDR_ZERODEF|E_SECURE,
- "s",
- "tc[l] cmd",
- "run the tcl interpreter with the command"},
-/* C_UNDO */
- {"undo", ex_undo, E_AUTOPRINT,
- "",
- "u[ndo]",
- "undo the most recent change"},
-/* C_UNABBREVIATE */
- {"unabbreviate",ex_unabbr, 0,
- "w1r",
- "una[bbrev] word",
- "delete an abbreviation"},
-/* C_UNMAP */
- {"unmap", ex_unmap, 0,
- "!w1r",
- "unm[ap][!] word",
- "delete an input or command map"},
-/* C_V */
- {"v", ex_v, E_ADDR2_ALL,
- "s",
- "[line [,line]] v [;/]RE[;/] [commands]",
- "execute a global command on lines NOT matching an RE"},
-/* C_VERSION */
- {"version", ex_version, 0,
- "",
- "version",
- "display the program version information"},
-/* C_VISUAL_EX */
- {"visual", ex_visual, E_ADDR1|E_ADDR_ZERODEF,
- "2c11",
- "[line] vi[sual] [-|.|+|^] [window_size] [flags]",
- "enter visual (vi) mode from ex mode"},
-/* C_VISUAL_VI */
- {"visual", ex_edit, E_NEWSCREEN,
- "f1o",
- "[Vv]i[sual][!] [+cmd] [file]",
- "edit another file (from vi mode only)"},
-/* C_VIUSAGE */
- {"viusage", ex_viusage, 0,
- "w1o",
- "[viu]sage [key]",
- "display vi key usage statement"},
-/* C_WRITE */
- {"write", ex_write, E_ADDR2_ALL|E_ADDR_ZERODEF,
- "!s",
- "[line [,line]] w[rite][!] [ !cmd | [>>] [file]]",
- "write the file"},
-/* C_WN */
- {"wn", ex_wn, E_ADDR2_ALL|E_ADDR_ZERODEF,
- "!s",
- "[line [,line]] wn[!] [>>] [file]",
- "write the file and switch to the next file"},
-/* C_WQ */
- {"wq", ex_wq, E_ADDR2_ALL|E_ADDR_ZERODEF,
- "!s",
- "[line [,line]] wq[!] [>>] [file]",
- "write the file and exit"},
-/* C_XIT */
- {"xit", ex_xit, E_ADDR2_ALL|E_ADDR_ZERODEF,
- "!f1o",
- "[line [,line]] x[it][!] [file]",
- "exit"},
-/* C_YANK */
- {"yank", ex_yank, E_ADDR2,
- "bca",
- "[line [,line]] ya[nk] [buffer] [count]",
- "copy lines to a cut buffer"},
-/* C_Z */
- {"z", ex_z, E_ADDR1,
- "3c01",
- "[line] z [-|.|+|^|=] [count] [flags]",
- "display different screens of the file"},
-/* C_SUBTILDE */
- {"~", ex_subtilde, E_ADDR2,
- "s",
- "[line [,line]] ~ [cgr] [count] [#lp]",
- "replace previous RE with previous replacement string,"},
- {NULL},
-};
diff --git a/contrib/nvi/ex/ex_cscope.c b/contrib/nvi/ex/ex_cscope.c
deleted file mode 100644
index c2fa0a5..0000000
--- a/contrib/nvi/ex/ex_cscope.c
+++ /dev/null
@@ -1,1057 +0,0 @@
-/*-
- * Copyright (c) 1994, 1996
- * Rob Mayoff. All rights reserved.
- * Copyright (c) 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_cscope.c 10.13 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/types.h> /* XXX: param.h may not have included types.h */
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "pathnames.h"
-#include "tag.h"
-
-#define CSCOPE_DBFILE "cscope.out"
-#define CSCOPE_PATHS "cscope.tpath"
-
-/*
- * 0name find all uses of name
- * 1name find definition of name
- * 2name find all function calls made from name
- * 3name find callers of name
- * 4string find text string (cscope 12.9)
- * 4name find assignments to name (cscope 13.3)
- * 5pattern change pattern -- NOT USED
- * 6pattern find pattern
- * 7name find files with name as substring
- * 8name find files #including name
- */
-#define FINDHELP "\
-find c|d|e|f|g|i|s|t buffer|pattern\n\
- c: find callers of name\n\
- d: find all function calls made from name\n\
- e: find pattern\n\
- f: find files with name as substring\n\
- g: find definition of name\n\
- i: find files #including name\n\
- s: find all uses of name\n\
- t: find assignments to name"
-
-static int cscope_add __P((SCR *, EXCMD *, char *));
-static int cscope_find __P((SCR *, EXCMD*, char *));
-static int cscope_help __P((SCR *, EXCMD *, char *));
-static int cscope_kill __P((SCR *, EXCMD *, char *));
-static int cscope_reset __P((SCR *, EXCMD *, char *));
-
-typedef struct _cc {
- char *name;
- int (*function) __P((SCR *, EXCMD *, char *));
- char *help_msg;
- char *usage_msg;
-} CC;
-
-static CC const cscope_cmds[] = {
- { "add", cscope_add,
- "Add a new cscope database", "add file | directory" },
- { "find", cscope_find,
- "Query the databases for a pattern", FINDHELP },
- { "help", cscope_help,
- "Show help for cscope commands", "help [command]" },
- { "kill", cscope_kill,
- "Kill a cscope connection", "kill number" },
- { "reset", cscope_reset,
- "Discard all current cscope connections", "reset" },
- { NULL }
-};
-
-static TAGQ *create_cs_cmd __P((SCR *, char *, size_t *));
-static int csc_help __P((SCR *, char *));
-static void csc_file __P((SCR *,
- CSC *, char *, char **, size_t *, int *));
-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 *, char *));
-static int start_cscopes __P((SCR *, EXCMD *));
-static int terminate __P((SCR *, CSC *, int));
-
-/*
- * ex_cscope --
- * Perform an ex cscope.
- *
- * PUBLIC: int ex_cscope __P((SCR *, EXCMD *));
- */
-int
-ex_cscope(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- CC const *ccp;
- EX_PRIVATE *exp;
- int i;
- char *cmd, *p;
-
- /* Initialize the default cscope directories. */
- exp = EXP(sp);
- if (!F_ISSET(exp, EXP_CSCINIT) && start_cscopes(sp, cmdp))
- return (1);
- F_SET(exp, EXP_CSCINIT);
-
- /* Skip leading whitespace. */
- for (p = cmdp->argv[0]->bp, i = cmdp->argv[0]->len; i > 0; --i, ++p)
- if (!isspace(*p))
- break;
- if (i == 0)
- goto usage;
-
- /* Skip the command to any arguments. */
- for (cmd = p; i > 0; --i, ++p)
- if (isspace(*p))
- break;
- if (*p != '\0') {
- *p++ = '\0';
- for (; *p && isspace(*p); ++p);
- }
-
- if ((ccp = lookup_ccmd(cmd)) == NULL) {
-usage: msgq(sp, M_ERR, "309|Use \"cscope help\" for help");
- return (1);
- }
-
- /* Call the underlying function. */
- return (ccp->function(sp, cmdp, p));
-}
-
-/*
- * start_cscopes --
- * Initialize the cscope package.
- */
-static int
-start_cscopes(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- size_t blen, len;
- char *bp, *cscopes, *p, *t;
-
- /*
- * EXTENSION #1:
- *
- * If the CSCOPE_DIRS environment variable is set, we treat it as a
- * list of cscope directories that we're using, similar to the tags
- * edit option.
- *
- * XXX
- * This should probably be an edit option, although that implies that
- * we start/stop cscope processes periodically, instead of once when
- * the editor starts.
- */
- if ((cscopes = getenv("CSCOPE_DIRS")) == NULL)
- return (0);
- len = strlen(cscopes);
- GET_SPACE_RET(sp, bp, blen, len);
- memcpy(bp, cscopes, len + 1);
-
- 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);
-}
-
-/*
- * cscope_add --
- * The cscope add command.
- */
-static int
-cscope_add(sp, cmdp, dname)
- SCR *sp;
- EXCMD *cmdp;
- char *dname;
-{
- struct stat sb;
- EX_PRIVATE *exp;
- CSC *csc;
- size_t len;
- int cur_argc;
- char *dbname, path[MAXPATHLEN];
-
- exp = EXP(sp);
-
- /*
- * 0 additional args: usage.
- * 1 additional args: matched a file.
- * >1 additional args: object, too many args.
- */
- 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);
- }
- if (cmdp->argc == cur_argc + 1)
- dname = cmdp->argv[cur_argc]->bp;
- else {
- ex_emsg(sp, dname, EXM_FILECOUNT);
- return (1);
- }
-
- /*
- * 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);
- CALLOC_RET(sp, csc, CSC *, 1, sizeof(CSC) + len);
- csc->dname = csc->buf;
- csc->dlen = len;
- memcpy(csc->dname, dname, len);
- csc->mtime = sb.st_mtime;
-
- /* Get the search paths for the cscope. */
- if (get_paths(sp, csc))
- goto err;
-
- /* Start the cscope process. */
- if (run_cscope(sp, csc, dbname))
- goto err;
-
- /*
- * Add the cscope connection to the screen's list. From now on,
- * on error, we have to call terminate, which expects the csc to
- * be on the chain.
- */
- LIST_INSERT_HEAD(&exp->cscq, csc, q);
-
- /* Read the initial prompt from the cscope to make sure it's okay. */
- if (read_prompt(sp, csc)) {
- terminate(sp, csc, 0);
- return (1);
- }
-
- return (0);
-
-err: free(csc);
- return (1);
-}
-
-/*
- * get_paths --
- * Get the directories to search for the files associated with this
- * cscope database.
- */
-static int
-get_paths(sp, csc)
- SCR *sp;
- CSC *csc;
-{
- struct stat sb;
- int fd, nentries;
- size_t len;
- char *p, **pathp, buf[MAXPATHLEN * 2];
-
- /*
- * EXTENSION #2:
- *
- * If there's a cscope directory with a file named CSCOPE_PATHS, it
- * contains a colon-separated list of paths in which to search for
- * files returned by cscope.
- *
- * XXX
- * These paths are absolute paths, and not relative to the cscope
- * directory. To fix this, rewrite the each path using the cscope
- * directory as a prefix.
- */
- (void)snprintf(buf, sizeof(buf), "%s/%s", csc->dname, CSCOPE_PATHS);
- if (stat(buf, &sb) == 0) {
- /* Read in the CSCOPE_PATHS file. */
- len = sb.st_size;
- MALLOC_RET(sp, csc->pbuf, char *, len + 1);
- if ((fd = open(buf, O_RDONLY, 0)) < 0 ||
- read(fd, csc->pbuf, len) != len) {
- msgq_str(sp, M_SYSERR, buf, "%s");
- if (fd >= 0)
- (void)close(fd);
- return (1);
- }
- (void)close(fd);
- csc->pbuf[len] = '\0';
-
- /* Count up the entries. */
- for (nentries = 0, p = csc->pbuf; *p != '\0'; ++p)
- if (p[0] == ':' && p[1] != '\0')
- ++nentries;
-
- /* Build an array of pointers to the paths. */
- CALLOC_GOTO(sp,
- csc->paths, char **, nentries + 1, sizeof(char **));
- for (pathp = csc->paths, p = strtok(csc->pbuf, ":");
- p != NULL; p = strtok(NULL, ":"))
- *pathp++ = p;
- return (0);
- }
-
- /*
- * If the CSCOPE_PATHS file doesn't exist, we look for files
- * relative to the cscope directory.
- */
- if ((csc->pbuf = strdup(csc->dname)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- CALLOC_GOTO(sp, csc->paths, char **, 2, sizeof(char *));
- csc->paths[0] = csc->pbuf;
- return (0);
-
-alloc_err:
- if (csc->pbuf != NULL) {
- free(csc->pbuf);
- csc->pbuf = NULL;
- }
- return (1);
-}
-
-/*
- * run_cscope --
- * Fork off the cscope process.
- */
-static int
-run_cscope(sp, csc, dbname)
- SCR *sp;
- CSC *csc;
- char *dbname;
-{
- int to_cs[2], from_cs[2];
- char cmd[MAXPATHLEN * 2];
-
- /*
- * Cscope reads from to_cs[0] and writes to from_cs[1]; vi reads from
- * from_cs[0] and writes to to_cs[1].
- */
- to_cs[0] = to_cs[1] = from_cs[0] = from_cs[0] = -1;
- if (pipe(to_cs) < 0 || pipe(from_cs) < 0) {
- msgq(sp, M_SYSERR, "pipe");
- goto err;
- }
- switch (csc->pid = vfork()) {
- case -1:
- msgq(sp, M_SYSERR, "vfork");
-err: if (to_cs[0] != -1)
- (void)close(to_cs[0]);
- if (to_cs[1] != -1)
- (void)close(to_cs[1]);
- if (from_cs[0] != -1)
- (void)close(from_cs[0]);
- if (from_cs[1] != -1)
- (void)close(from_cs[1]);
- return (1);
- case 0: /* child: run cscope. */
- (void)dup2(to_cs[0], STDIN_FILENO);
- (void)dup2(from_cs[1], STDOUT_FILENO);
- (void)dup2(from_cs[1], STDERR_FILENO);
-
- /* Close unused file descriptors. */
- (void)close(to_cs[1]);
- (void)close(from_cs[0]);
-
- /* Run the cscope command. */
-#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 */
- default: /* parent. */
- /* Close unused file descriptors. */
- (void)close(to_cs[0]);
- (void)close(from_cs[1]);
-
- /*
- * Save the file descriptors for later duplication, and
- * reopen as streams.
- */
- csc->to_fd = to_cs[1];
- csc->to_fp = fdopen(to_cs[1], "w");
- csc->from_fd = from_cs[0];
- csc->from_fp = fdopen(from_cs[0], "r");
- break;
- }
- return (0);
-}
-
-/*
- * cscope_find --
- * The cscope find command.
- */
-static int
-cscope_find(sp, cmdp, pattern)
- SCR *sp;
- EXCMD *cmdp;
- char *pattern;
-{
- CSC *csc, *csc_next;
- EX_PRIVATE *exp;
- FREF *frp;
- TAGQ *rtqp, *tqp;
- TAG *rtp;
- recno_t lno;
- size_t cno, search;
- int force, istmp, matches;
-
- exp = EXP(sp);
-
- /* Check for connections. */
- if (exp->cscq.lh_first == NULL) {
- msgq(sp, M_ERR, "310|No cscope connections running");
- return (1);
- }
-
- /*
- * Allocate all necessary memory before doing anything hard. If the
- * tags stack is empty, we'll need the `local context' TAGQ structure
- * later.
- */
- rtp = NULL;
- rtqp = NULL;
- if (exp->tq.cqh_first == (void *)&exp->tq) {
- /* Initialize the `local context' tag queue structure. */
- CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
- CIRCLEQ_INIT(&rtqp->tagq);
-
- /* Initialize and link in its tag structure. */
- CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
- CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
- rtqp->current = rtp;
- }
-
- /* Create the cscope command. */
- if ((tqp = create_cs_cmd(sp, pattern, &search)) == NULL)
- goto err;
-
- /*
- * Stick the current context in a convenient place, we'll lose it
- * when we switch files.
- */
- frp = sp->frp;
- lno = sp->lno;
- cno = sp->cno;
- istmp = F_ISSET(sp->frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN);
-
- /* Search all open connections for a match. */
- matches = 0;
- for (csc = exp->cscq.lh_first; csc != NULL; csc = csc_next) {
- /* Copy csc->q.lh_next here in case csc is killed. */
- csc_next = csc->q.le_next;
-
- /*
- * Send the command to the cscope program. (We skip the
- * first two bytes of the command, because we stored the
- * search cscope command character and a leading space
- * there.)
- */
- (void)fprintf(csc->to_fp, "%d%s\n", search, tqp->tag + 2);
- (void)fflush(csc->to_fp);
-
- /* Read the output. */
- if (parse(sp, csc, tqp, &matches)) {
- if (rtqp != NULL)
- free(rtqp);
- tagq_free(sp, tqp);
- return (1);
- }
- }
-
- if (matches == 0) {
- msgq(sp, M_INFO, "278|No matches for query");
- return (0);
- }
-
- tqp->current = tqp->tagq.cqh_first;
-
- /* Try to switch to the first tag. */
- force = FL_ISSET(cmdp->iflags, E_C_FORCE);
- if (F_ISSET(cmdp, E_NEWSCREEN)) {
- if (ex_tag_Nswitch(sp, tqp->current, force))
- goto err;
-
- /* Everything else gets done in the new screen. */
- sp = sp->nextdisp;
- exp = EXP(sp);
- } else
- if (ex_tag_nswitch(sp, tqp->current, force))
- goto err;
-
- /*
- * If this is the first tag, put a `current location' queue entry
- * in place, so we can pop all the way back to the current mark.
- * Note, it doesn't point to much of anything, it's a placeholder.
- */
- if (exp->tq.cqh_first == (void *)&exp->tq) {
- CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
- } else
- rtqp = exp->tq.cqh_first;
-
- /* Link the current TAGQ structure into place. */
- CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
-
- (void)cscope_search(sp, tqp, tqp->current);
-
- /*
- * Move the current context from the temporary save area into the
- * right structure.
- *
- * If we were in a temporary file, we don't have a context to which
- * we can return, so just make it be the same as what we're moving
- * to. It will be a little odd that ^T doesn't change anything, but
- * I don't think it's a big deal.
- */
- if (istmp) {
- rtqp->current->frp = sp->frp;
- rtqp->current->lno = sp->lno;
- rtqp->current->cno = sp->cno;
- } else {
- rtqp->current->frp = frp;
- rtqp->current->lno = lno;
- rtqp->current->cno = cno;
- }
-
- return (0);
-
-err:
-alloc_err:
- if (rtqp != NULL)
- free(rtqp);
- if (rtp != NULL)
- free(rtp);
- return (1);
-}
-
-/*
- * create_cs_cmd --
- * Build a cscope command, creating and initializing the base TAGQ.
- */
-static TAGQ *
-create_cs_cmd(sp, pattern, searchp)
- SCR *sp;
- char *pattern;
- size_t *searchp;
-{
- CB *cbp;
- TAGQ *tqp;
- size_t tlen;
- char *p;
-
- /*
- * Cscope supports a "change pattern" command which we never use,
- * cscope command 5. Set CSCOPE_QUERIES[5] to " " since the user
- * can't pass " " as the first character of pattern. That way the
- * user can't ask for pattern 5 so we don't need any special-case
- * code.
- */
-#define CSCOPE_QUERIES "sgdct efi"
-
- if (pattern == NULL)
- goto usage;
-
- /* Skip leading blanks, check for command character. */
- for (; isblank(pattern[0]); ++pattern);
- if (pattern[0] == '\0' || !isblank(pattern[1]))
- goto usage;
- for (*searchp = 0, p = CSCOPE_QUERIES;
- *p != '\0' && *p != pattern[0]; ++*searchp, ++p);
- if (*p == '\0') {
- msgq(sp, M_ERR,
- "311|%s: unknown search type: use one of %s",
- KEY_NAME(sp, pattern[0]), CSCOPE_QUERIES);
- return (NULL);
- }
-
- /* Skip <blank> characters to the pattern. */
- for (p = pattern + 1; *p != '\0' && isblank(*p); ++p);
- if (*p == '\0') {
-usage: (void)csc_help(sp, "find");
- return (NULL);
- }
-
- /* The user can specify the contents of a buffer as the pattern. */
- cbp = NULL;
- if (p[0] == '"' && p[1] != '\0' && p[2] == '\0')
- CBNAME(sp, cbp, p[1]);
- if (cbp != NULL) {
- p = cbp->textq.cqh_first->lb;
- tlen = cbp->textq.cqh_first->len;
- } else
- tlen = strlen(p);
-
- /* Allocate and initialize the TAGQ structure. */
- CALLOC(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + tlen + 3);
- if (tqp == NULL)
- return (NULL);
- CIRCLEQ_INIT(&tqp->tagq);
- tqp->tag = tqp->buf;
- tqp->tag[0] = pattern[0];
- tqp->tag[1] = ' ';
- tqp->tlen = tlen + 2;
- memcpy(tqp->tag + 2, p, tlen);
- tqp->tag[tlen + 2] = '\0';
- F_SET(tqp, TAG_CSCOPE);
-
- return (tqp);
-}
-
-/*
- * parse --
- * Parse the cscope output.
- */
-static int
-parse(sp, csc, tqp, matchesp)
- SCR *sp;
- CSC *csc;
- TAGQ *tqp;
- int *matchesp;
-{
- TAG *tp;
- recno_t slno;
- size_t dlen, nlen, slen;
- int ch, i, isolder, nlines;
- char *dname, *name, *search, *p, *t, dummy[2], buf[2048];
-
- for (;;) {
- if (!fgets(buf, sizeof(buf), csc->from_fp))
- goto io_err;
-
- /*
- * If the database is out of date, or there's some other
- * problem, cscope will output error messages before the
- * number-of-lines output. Display/discard any output
- * that doesn't match what we want.
- */
-#define CSCOPE_NLINES_FMT "cscope: %d lines%1[\n]"
- if (sscanf(buf, CSCOPE_NLINES_FMT, &nlines, dummy) == 2)
- break;
- if ((p = strchr(buf, '\n')) != NULL)
- *p = '\0';
- msgq(sp, M_ERR, "%s: \"%s\"", csc->dname, buf);
- }
-
- while (nlines--) {
- if (fgets(buf, sizeof(buf), csc->from_fp) == NULL)
- goto io_err;
-
- /* If the line's too long for the buffer, discard it. */
- if ((p = strchr(buf, '\n')) == NULL) {
- while ((ch = getc(csc->from_fp)) != EOF && ch != '\n');
- continue;
- }
- *p = '\0';
-
- /*
- * The cscope output is in the following format:
- *
- * <filename> <context> <line number> <pattern>
- *
- * Figure out how long everything is so we can allocate in one
- * swell foop, but discard anything that looks wrong.
- */
- for (p = buf, i = 0;
- i < 3 && (t = strsep(&p, "\t ")) != NULL; ++i)
- switch (i) {
- case 0: /* Filename. */
- name = t;
- nlen = strlen(name);
- break;
- case 1: /* Context. */
- break;
- case 2: /* Line number. */
- slno = (recno_t)atol(t);
- break;
- }
- if (i != 3 || p == NULL || t == NULL)
- continue;
-
- /* The rest of the string is the search pattern. */
- search = p;
- slen = strlen(p);
-
- /* Resolve the file name. */
- csc_file(sp, csc, name, &dname, &dlen, &isolder);
-
- /*
- * 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 (isolder || strcmp(search, "<unknown>") == 0) {
- search = NULL;
- slen = 0;
- }
-
- /*
- * Allocate and initialize a tag structure plus the variable
- * length cscope information that follows it.
- */
- CALLOC_RET(sp, tp,
- TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + slen + 1);
- tp->fname = tp->buf;
- if (dlen != 0) {
- memcpy(tp->fname, dname, dlen);
- tp->fname[dlen] = '/';
- ++dlen;
- }
- memcpy(tp->fname + dlen, name, nlen + 1);
- tp->fnlen = dlen + nlen;
- tp->slno = slno;
- if (slen != 0) {
- tp->search = tp->fname + tp->fnlen + 1;
- memcpy(tp->search, search, (tp->slen = slen) + 1);
- }
- CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
-
- ++*matchesp;
- }
-
- (void)read_prompt(sp, csc);
- return (0);
-
-io_err: if (feof(csc->from_fp))
- errno = EIO;
- msgq_str(sp, M_SYSERR, "%s", csc->dname);
- terminate(sp, csc, 0);
- return (1);
-}
-
-/*
- * csc_file --
- * Search for the right path to this file.
- */
-static void
-csc_file(sp, csc, name, dirp, dlenp, isolderp)
- SCR *sp;
- CSC *csc;
- char *name, **dirp;
- size_t *dlenp;
- int *isolderp;
-{
- struct stat sb;
- char **pp, buf[MAXPATHLEN];
-
- /*
- * Check for the file in all of the listed paths. If we don't
- * find it, we simply return it unchanged. We have to do this
- * now, even though it's expensive, because if the user changes
- * directories, we can't change our minds as to where the file
- * lives.
- */
- for (pp = csc->paths; *pp != NULL; ++pp) {
- (void)snprintf(buf, sizeof(buf), "%s/%s", *pp, name);
- if (stat(buf, &sb) == 0) {
- *dirp = *pp;
- *dlenp = strlen(*pp);
- *isolderp = sb.st_mtime < csc->mtime;
- return;
- }
- }
- *dlenp = 0;
-}
-
-/*
- * cscope_help --
- * The cscope help command.
- */
-static int
-cscope_help(sp, cmdp, subcmd)
- SCR *sp;
- EXCMD *cmdp;
- char *subcmd;
-{
- return (csc_help(sp, subcmd));
-}
-
-/*
- * csc_help --
- * Display help/usage messages.
- */
-static int
-csc_help(sp, cmd)
- SCR *sp;
- char *cmd;
-{
- CC const *ccp;
-
- if (cmd != NULL && *cmd != '\0')
- if ((ccp = lookup_ccmd(cmd)) == NULL) {
- ex_printf(sp,
- "%s doesn't match any cscope command\n", cmd);
- return (1);
- } else {
- ex_printf(sp,
- "Command: %s (%s)\n", ccp->name, ccp->help_msg);
- ex_printf(sp, " Usage: %s\n", ccp->usage_msg);
- return (0);
- }
-
- ex_printf(sp, "cscope commands:\n");
- for (ccp = cscope_cmds; ccp->name != NULL; ++ccp)
- ex_printf(sp, " %*s: %s\n", 5, ccp->name, ccp->help_msg);
- return (0);
-}
-
-/*
- * cscope_kill --
- * The cscope kill command.
- */
-static int
-cscope_kill(sp, cmdp, cn)
- SCR *sp;
- EXCMD *cmdp;
- char *cn;
-{
- return (terminate(sp, NULL, atoi(cn)));
-}
-
-/*
- * terminate --
- * Detach from a cscope process.
- */
-static int
-terminate(sp, csc, n)
- SCR *sp;
- CSC *csc;
- int n;
-{
- EX_PRIVATE *exp;
- int i, pstat;
-
- exp = EXP(sp);
-
- /*
- * We either get a csc structure or a number. If not provided a
- * csc structure, find the right one.
- */
- if (csc == NULL) {
- if (n < 1)
- goto badno;
- for (i = 1, csc = exp->cscq.lh_first;
- csc != NULL; csc = csc->q.le_next, i++)
- if (i == n)
- break;
- if (csc == NULL) {
-badno: msgq(sp, M_ERR, "312|%d: no such cscope session", n);
- return (1);
- }
- }
-
- /*
- * XXX
- * Theoretically, we have the only file descriptors to the process,
- * so closing them should let it exit gracefully, deleting temporary
- * files, etc. The original vi cscope integration sent the cscope
- * connection a SIGTERM signal, so I'm not sure if closing the file
- * descriptors is sufficient.
- */
- if (csc->from_fp != NULL)
- (void)fclose(csc->from_fp);
- if (csc->to_fp != NULL)
- (void)fclose(csc->to_fp);
- (void)waitpid(csc->pid, &pstat, 0);
-
- /* Discard cscope connection information. */
- LIST_REMOVE(csc, q);
- if (csc->pbuf != NULL)
- free(csc->pbuf);
- if (csc->paths != NULL)
- free(csc->paths);
- free(csc);
- return (0);
-}
-
-/*
- * cscope_reset --
- * The cscope reset command.
- */
-static int
-cscope_reset(sp, cmdp, notusedp)
- SCR *sp;
- EXCMD *cmdp;
- char *notusedp;
-{
- EX_PRIVATE *exp;
-
- for (exp = EXP(sp); exp->cscq.lh_first != NULL;)
- if (cscope_kill(sp, cmdp, "1"))
- return (1);
- return (0);
-}
-
-/*
- * cscope_display --
- * Display current connections.
- *
- * PUBLIC: int cscope_display __P((SCR *));
- */
-int
-cscope_display(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- CSC *csc;
- int i;
-
- exp = EXP(sp);
- if (exp->cscq.lh_first == NULL) {
- ex_printf(sp, "No cscope connections.\n");
- return (0);
- }
- for (i = 1,
- csc = exp->cscq.lh_first; csc != NULL; ++i, csc = csc->q.le_next)
- ex_printf(sp,
- "%2d %s (process %lu)\n", i, csc->dname, (u_long)csc->pid);
- return (0);
-}
-
-/*
- * cscope_search --
- * Search a file for a cscope entry.
- *
- * PUBLIC: int cscope_search __P((SCR *, TAGQ *, TAG *));
- */
-int
-cscope_search(sp, tqp, tp)
- SCR *sp;
- TAGQ *tqp;
- TAG *tp;
-{
- MARK m;
-
- /* If we don't have a search pattern, use the line number. */
- if (tp->search == NULL) {
- if (!db_exist(sp, tp->slno)) {
- tag_msg(sp, TAG_BADLNO, tqp->tag);
- return (1);
- }
- m.lno = tp->slno;
- } else {
- /*
- * Search for the tag; cheap fallback for C functions
- * if the name is the same but the arguments have changed.
- */
- m.lno = 1;
- m.cno = 0;
- if (f_search(sp, &m, &m,
- tp->search, tp->slen, NULL, SEARCH_CSCOPE | SEARCH_FILE)) {
- tag_msg(sp, TAG_SEARCH, tqp->tag);
- return (1);
- }
-
- /*
- * !!!
- * Historically, tags set the search direction if it wasn't
- * already set.
- */
- if (sp->searchdir == NOTSET)
- sp->searchdir = FORWARD;
- }
-
- /*
- * !!!
- * Tags move to the first non-blank, NOT the search pattern start.
- */
- sp->lno = m.lno;
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- return (0);
-}
-
-
-/*
- * lookup_ccmd --
- * Return a pointer to the command structure.
- */
-static CC const *
-lookup_ccmd(name)
- char *name;
-{
- CC const *ccp;
- size_t len;
-
- len = strlen(name);
- for (ccp = cscope_cmds; ccp->name != NULL; ++ccp)
- if (strncmp(name, ccp->name, len) == 0)
- return (ccp);
- return (NULL);
-}
-
-/*
- * read_prompt --
- * Read a prompt from cscope.
- */
-static int
-read_prompt(sp, csc)
- SCR *sp;
- CSC *csc;
-{
- int ch;
-
-#define CSCOPE_PROMPT ">> "
- for (;;) {
- while ((ch =
- getc(csc->from_fp)) != EOF && ch != CSCOPE_PROMPT[0]);
- if (ch == EOF) {
- terminate(sp, csc, 0);
- return (1);
- }
- if (getc(csc->from_fp) != CSCOPE_PROMPT[1])
- continue;
- if (getc(csc->from_fp) != CSCOPE_PROMPT[2])
- continue;
- break;
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_delete.c b/contrib/nvi/ex/ex_delete.c
deleted file mode 100644
index 58734bb..0000000
--- a/contrib/nvi/ex/ex_delete.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_delete.c 10.9 (Berkeley) 10/23/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_delete: [line [,line]] d[elete] [buffer] [count] [flags]
- *
- * Delete lines from the file.
- *
- * PUBLIC: int ex_delete __P((SCR *, EXCMD *));
- */
-int
-ex_delete(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- recno_t lno;
-
- NEEDFILE(sp, cmdp);
-
- /*
- * !!!
- * Historically, lines deleted in ex were not placed in the numeric
- * buffers. We follow historic practice so that we don't overwrite
- * vi buffers accidentally.
- */
- if (cut(sp,
- FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
- &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
- return (1);
-
- /* Delete the lines. */
- if (del(sp, &cmdp->addr1, &cmdp->addr2, 1))
- return (1);
-
- /* Set the cursor to the line after the last line deleted. */
- sp->lno = cmdp->addr1.lno;
-
- /* Or the last line in the file if deleted to the end of the file. */
- if (db_last(sp, &lno))
- return (1);
- if (sp->lno > lno)
- sp->lno = lno;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_display.c b/contrib/nvi/ex/ex_display.c
deleted file mode 100644
index 7531517..0000000
--- a/contrib/nvi/ex/ex_display.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_display.c 10.12 (Berkeley) 4/10/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "tag.h"
-
-static int bdisplay __P((SCR *));
-static void db __P((SCR *, CB *, CHAR_T *));
-
-/*
- * ex_display -- :display b[uffers] | c[onnections] | s[creens] | t[ags]
- *
- * Display cscope connections, buffers, tags or screens.
- *
- * PUBLIC: int ex_display __P((SCR *, EXCMD *));
- */
-int
-ex_display(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- switch (cmdp->argv[0]->bp[0]) {
- case 'b':
-#undef ARG
-#define ARG "buffers"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (bdisplay(sp));
- case 'c':
-#undef ARG
-#define ARG "connections"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (cscope_display(sp));
- case 's':
-#undef ARG
-#define ARG "screens"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (ex_sdisplay(sp));
- case 't':
-#undef ARG
-#define ARG "tags"
- if (cmdp->argv[0]->len >= sizeof(ARG) ||
- memcmp(cmdp->argv[0]->bp, ARG, cmdp->argv[0]->len))
- break;
- return (ex_tag_display(sp));
- }
- ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
-}
-
-/*
- * bdisplay --
- *
- * Display buffers.
- */
-static int
-bdisplay(sp)
- SCR *sp;
-{
- CB *cbp;
-
- if (sp->gp->cutq.lh_first == NULL && sp->gp->dcbp == NULL) {
- msgq(sp, M_INFO, "123|No cut buffers to display");
- return (0);
- }
-
- /* Display regular cut buffers. */
- for (cbp = sp->gp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
- if (isdigit(cbp->name))
- continue;
- if (cbp->textq.cqh_first != (void *)&cbp->textq)
- db(sp, cbp, NULL);
- if (INTERRUPTED(sp))
- return (0);
- }
- /* Display numbered buffers. */
- for (cbp = sp->gp->cutq.lh_first; cbp != NULL; cbp = cbp->q.le_next) {
- if (!isdigit(cbp->name))
- continue;
- if (cbp->textq.cqh_first != (void *)&cbp->textq)
- db(sp, cbp, NULL);
- if (INTERRUPTED(sp))
- return (0);
- }
- /* Display default buffer. */
- if ((cbp = sp->gp->dcbp) != NULL)
- db(sp, cbp, "default buffer");
- return (0);
-}
-
-/*
- * db --
- * Display a buffer.
- */
-static void
-db(sp, cbp, name)
- SCR *sp;
- CB *cbp;
- CHAR_T *name;
-{
- CHAR_T *p;
- GS *gp;
- TEXT *tp;
- size_t len;
-
- gp = sp->gp;
- (void)ex_printf(sp, "********** %s%s\n",
- name == NULL ? KEY_NAME(sp, cbp->name) : name,
- F_ISSET(cbp, CB_LMODE) ? " (line mode)" : " (character mode)");
- for (tp = cbp->textq.cqh_first;
- tp != (void *)&cbp->textq; tp = tp->q.cqe_next) {
- for (len = tp->len, p = tp->lb; len--; ++p) {
- (void)ex_puts(sp, KEY_NAME(sp, *p));
- if (INTERRUPTED(sp))
- return;
- }
- (void)ex_puts(sp, "\n");
- }
-}
diff --git a/contrib/nvi/ex/ex_edit.c b/contrib/nvi/ex/ex_edit.c
deleted file mode 100644
index 8b18e0f..0000000
--- a/contrib/nvi/ex/ex_edit.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_edit.c 10.10 (Berkeley) 4/27/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-static int ex_N_edit __P((SCR *, EXCMD *, FREF *, int));
-
-/*
- * ex_edit -- :e[dit][!] [+cmd] [file]
- * :ex[!] [+cmd] [file]
- * :vi[sual][!] [+cmd] [file]
- *
- * Edit a file; if none specified, re-edit the current file. The third
- * form of the command can only be executed while in vi mode. See the
- * hack in ex.c:ex_cmd().
- *
- * !!!
- * Historic vi didn't permit the '+' command form without specifying
- * a file name as well. This seems unreasonable, so we support it
- * regardless.
- *
- * PUBLIC: int ex_edit __P((SCR *, EXCMD *));
- */
-int
-ex_edit(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- FREF *frp;
- int attach, setalt;
-
- switch (cmdp->argc) {
- case 0:
- /*
- * If the name has been changed, we edit that file, not the
- * original name. If the user was editing a temporary file
- * (or wasn't editing any file), create another one. The
- * reason for not reusing temporary files is that there is
- * special exit processing of them, and reuse is tricky.
- */
- frp = sp->frp;
- if (sp->ep == NULL || F_ISSET(frp, FR_TMPFILE)) {
- if ((frp = file_add(sp, NULL)) == NULL)
- return (1);
- attach = 0;
- } else
- attach = 1;
- setalt = 0;
- break;
- case 1:
- if ((frp = file_add(sp, cmdp->argv[0]->bp)) == NULL)
- return (1);
- attach = 0;
- setalt = 1;
- set_alt_name(sp, cmdp->argv[0]->bp);
- break;
- default:
- abort();
- }
-
- if (F_ISSET(cmdp, E_NEWSCREEN))
- return (ex_N_edit(sp, cmdp, frp, attach));
-
- /*
- * Check for modifications.
- *
- * !!!
- * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit.
- */
- if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
- return (1);
-
- /* Switch files. */
- if (file_init(sp, frp, NULL, (setalt ? FS_SETALT : 0) |
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
- return (1);
-
- F_SET(sp, SC_FSWITCH);
- return (0);
-}
-
-/*
- * ex_N_edit --
- * New screen version of ex_edit.
- */
-static int
-ex_N_edit(sp, cmdp, frp, attach)
- SCR *sp;
- EXCMD *cmdp;
- FREF *frp;
- int attach;
-{
- SCR *new;
-
- /* Get a new screen. */
- if (screen_init(sp->gp, sp, &new))
- return (1);
- if (vs_split(sp, new, 0)) {
- (void)screen_end(new);
- return (1);
- }
-
- /* Get a backing file. */
- if (attach) {
- /* Copy file state, keep the screen and cursor the same. */
- new->ep = sp->ep;
- ++new->ep->refcnt;
-
- new->frp = frp;
- new->frp->flags = sp->frp->flags;
-
- new->lno = sp->lno;
- new->cno = sp->cno;
- } else if (file_init(new, frp, NULL,
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0))) {
- (void)vs_discard(new, NULL);
- (void)screen_end(new);
- return (1);
- }
-
- /* Create the argument list. */
- new->cargv = new->argv = ex_buildargv(sp, NULL, frp->name);
-
- /* Set up the switch. */
- sp->nextdisp = new;
- F_SET(sp, SC_SSWITCH);
-
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_equal.c b/contrib/nvi/ex/ex_equal.c
deleted file mode 100644
index 565df66..0000000
--- a/contrib/nvi/ex/ex_equal.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_equal.c 10.10 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_equal -- :address =
- *
- * PUBLIC: int ex_equal __P((SCR *, EXCMD *));
- */
-int
-ex_equal(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- recno_t lno;
-
- NEEDFILE(sp, cmdp);
-
- /*
- * Print out the line number matching the specified address,
- * or the number of the last line in the file if no address
- * specified.
- *
- * !!!
- * Historically, ":0=" displayed 0, and ":=" or ":1=" in an
- * empty file displayed 1. Until somebody complains loudly,
- * we're going to do it right. The tables in excmd.c permit
- * lno to get away with any address from 0 to the end of the
- * file, which, in an empty file, is 0.
- */
- if (F_ISSET(cmdp, E_ADDR_DEF)) {
- if (db_last(sp, &lno))
- return (1);
- } else
- lno = cmdp->addr1.lno;
-
- (void)ex_printf(sp, "%ld\n", lno);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_file.c b/contrib/nvi/ex/ex_file.c
deleted file mode 100644
index 3492f9c..0000000
--- a/contrib/nvi/ex/ex_file.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_file.c 10.12 (Berkeley) 7/12/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_file -- :f[ile] [name]
- * Change the file's name and display the status line.
- *
- * PUBLIC: int ex_file __P((SCR *, EXCMD *));
- */
-int
-ex_file(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- CHAR_T *p;
- FREF *frp;
-
- NEEDFILE(sp, cmdp);
-
- switch (cmdp->argc) {
- case 0:
- break;
- case 1:
- frp = sp->frp;
-
- /* Make sure can allocate enough space. */
- if ((p = v_strdup(sp,
- cmdp->argv[0]->bp, cmdp->argv[0]->len)) == NULL)
- return (1);
-
- /* If already have a file name, it becomes the alternate. */
- if (!F_ISSET(frp, FR_TMPFILE))
- set_alt_name(sp, frp->name);
-
- /* Free the previous name. */
- free(frp->name);
- frp->name = p;
-
- /*
- * The file has a real name, it's no longer a temporary,
- * clear the temporary file flags.
- */
- F_CLR(frp, FR_TMPEXIT | FR_TMPFILE);
-
- /* Have to force a write if the file exists, next time. */
- F_SET(frp, FR_NAMECHANGE);
-
- /* Notify the screen. */
- (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
- break;
- default:
- abort();
- }
- msgq_status(sp, sp->lno, MSTAT_SHOWLAST);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_filter.c b/contrib/nvi/ex/ex_filter.c
deleted file mode 100644
index 2e86e58..0000000
--- a/contrib/nvi/ex/ex_filter.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1991, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_filter.c 10.34 (Berkeley) 10/23/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-static int filter_ldisplay __P((SCR *, FILE *));
-
-/*
- * ex_filter --
- * Run a range of lines through a filter utility and optionally
- * replace the original text with the stdout/stderr output of
- * the utility.
- *
- * PUBLIC: int ex_filter __P((SCR *,
- * PUBLIC: EXCMD *, MARK *, MARK *, MARK *, char *, enum filtertype));
- */
-int
-ex_filter(sp, cmdp, fm, tm, rp, cmd, ftype)
- SCR *sp;
- EXCMD *cmdp;
- MARK *fm, *tm, *rp;
- char *cmd;
- enum filtertype ftype;
-{
- FILE *ifp, *ofp;
- pid_t parent_writer_pid, utility_pid;
- recno_t nread;
- int input[2], output[2], rval;
- char *name;
-
- rval = 0;
-
- /* Set return cursor position, which is never less than line 1. */
- *rp = *fm;
- if (rp->lno == 0)
- rp->lno = 1;
-
- /* We're going to need a shell. */
- if (opts_empty(sp, O_SHELL, 0))
- return (1);
-
- /*
- * There are three different processes running through this code.
- * They are the utility, the parent-writer and the parent-reader.
- * The parent-writer is the process that writes from the file to
- * the utility, the parent reader is the process that reads from
- * the utility.
- *
- * Input and output are named from the utility's point of view.
- * The utility reads from input[0] and the parent(s) write to
- * input[1]. The parent(s) read from output[0] and the utility
- * writes to output[1].
- *
- * !!!
- * Historically, in the FILTER_READ case, the utility reads from
- * the terminal (e.g. :r! cat works). Otherwise open up utility
- * input pipe.
- */
- ofp = NULL;
- input[0] = input[1] = output[0] = output[1] = -1;
- if (ftype != FILTER_READ && pipe(input) < 0) {
- msgq(sp, M_SYSERR, "pipe");
- goto err;
- }
-
- /* Open up utility output pipe. */
- if (pipe(output) < 0) {
- msgq(sp, M_SYSERR, "pipe");
- goto err;
- }
- if ((ofp = fdopen(output[0], "r")) == NULL) {
- msgq(sp, M_SYSERR, "fdopen");
- goto err;
- }
-
- /* Fork off the utility process. */
- switch (utility_pid = vfork()) {
- case -1: /* Error. */
- msgq(sp, M_SYSERR, "vfork");
-err: if (input[0] != -1)
- (void)close(input[0]);
- if (input[1] != -1)
- (void)close(input[1]);
- if (ofp != NULL)
- (void)fclose(ofp);
- else if (output[0] != -1)
- (void)close(output[0]);
- if (output[1] != -1)
- (void)close(output[1]);
- return (1);
- case 0: /* Utility. */
- /*
- * Redirect stdin from the read end of the input pipe, and
- * redirect stdout/stderr to the write end of the output pipe.
- *
- * !!!
- * Historically, ex only directed stdout into the input pipe,
- * letting stderr come out on the terminal as usual. Vi did
- * not, directing both stdout and stderr into the input pipe.
- * We match that practice in both ex and vi for consistency.
- */
- if (input[0] != -1)
- (void)dup2(input[0], STDIN_FILENO);
- (void)dup2(output[1], STDOUT_FILENO);
- (void)dup2(output[1], STDERR_FILENO);
-
- /* Close the utility's file descriptors. */
- if (input[0] != -1)
- (void)close(input[0]);
- if (input[1] != -1)
- (void)close(input[1]);
- (void)close(output[0]);
- (void)close(output[1]);
-
- if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
- name = O_STR(sp, O_SHELL);
- else
- ++name;
-
- execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
- msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
- _exit (127);
- /* NOTREACHED */
- default: /* Parent-reader, parent-writer. */
- /* Close the pipe ends neither parent will use. */
- if (input[0] != -1)
- (void)close(input[0]);
- (void)close(output[1]);
- break;
- }
-
- /*
- * FILTER_RBANG, FILTER_READ:
- *
- * Reading is the simple case -- we don't need a parent writer,
- * so the parent reads the output from the read end of the output
- * pipe until it finishes, then waits for the child. Ex_readfp
- * appends to the MARK, and closes ofp.
- *
- * For FILTER_RBANG, there is nothing to write to the utility.
- * Make sure it doesn't wait forever by closing its standard
- * input.
- *
- * !!!
- * Set the return cursor to the last line read in for FILTER_READ.
- * Historically, this behaves differently from ":r file" command,
- * which leaves the cursor at the first line read in. Check to
- * make sure that it's not past EOF because we were reading into an
- * empty file.
- */
- if (ftype == FILTER_RBANG || ftype == FILTER_READ) {
- if (ftype == FILTER_RBANG)
- (void)close(input[1]);
-
- if (ex_readfp(sp, "filter", ofp, fm, &nread, 1))
- rval = 1;
- sp->rptlines[L_ADDED] += nread;
- if (ftype == FILTER_READ)
- if (fm->lno == 0)
- rp->lno = nread;
- else
- rp->lno += nread;
- goto uwait;
- }
-
- /*
- * FILTER_BANG, FILTER_WRITE
- *
- * Here we need both a reader and a writer. Temporary files are
- * expensive and we'd like to avoid disk I/O. Using pipes has the
- * obvious starvation conditions. It's done as follows:
- *
- * fork
- * child
- * write lines out
- * exit
- * parent
- * FILTER_BANG:
- * read lines into the file
- * delete old lines
- * FILTER_WRITE
- * read and display lines
- * wait for child
- *
- * XXX
- * We get away without locking the underlying database because we know
- * that none of the records that we're reading will be modified until
- * after we've read them. This depends on the fact that the current
- * B+tree implementation doesn't balance pages or similar things when
- * it inserts new records. When the DB code has locking, we should
- * treat vi as if it were multiple applications sharing a database, and
- * do the required locking. If necessary a work-around would be to do
- * explicit locking in the line.c:db_get() code, based on the flag set
- * here.
- */
- F_SET(sp->ep, F_MULTILOCK);
- switch (parent_writer_pid = fork()) {
- case -1: /* Error. */
- msgq(sp, M_SYSERR, "fork");
- (void)close(input[1]);
- (void)close(output[0]);
- rval = 1;
- break;
- case 0: /* Parent-writer. */
- /*
- * Write the selected lines to the write end of the input
- * pipe. This instance of ifp is closed by ex_writefp.
- */
- (void)close(output[0]);
- if ((ifp = fdopen(input[1], "w")) == NULL)
- _exit (1);
- _exit(ex_writefp(sp, "filter", ifp, fm, tm, NULL, NULL, 1));
-
- /* NOTREACHED */
- default: /* Parent-reader. */
- (void)close(input[1]);
- if (ftype == FILTER_WRITE) {
- /*
- * Read the output from the read end of the output
- * pipe and display it. Filter_ldisplay closes ofp.
- */
- if (filter_ldisplay(sp, ofp))
- rval = 1;
- } else {
- /*
- * Read the output from the read end of the output
- * pipe. Ex_readfp appends to the MARK and closes
- * ofp.
- */
- if (ex_readfp(sp, "filter", ofp, tm, &nread, 1))
- rval = 1;
- sp->rptlines[L_ADDED] += nread;
- }
-
- /* Wait for the parent-writer. */
- if (proc_wait(sp,
- (long)parent_writer_pid, "parent-writer", 0, 1))
- rval = 1;
-
- /* Delete any lines written to the utility. */
- if (rval == 0 && ftype == FILTER_BANG &&
- (cut(sp, NULL, fm, tm, CUT_LINEMODE) ||
- del(sp, fm, tm, 1))) {
- rval = 1;
- break;
- }
-
- /*
- * If the filter had no output, we may have just deleted
- * the cursor. Don't do any real error correction, we'll
- * try and recover later.
- */
- if (rp->lno > 1 && !db_exist(sp, rp->lno))
- --rp->lno;
- break;
- }
- F_CLR(sp->ep, F_MULTILOCK);
-
- /*
- * !!!
- * Ignore errors on vi file reads, to make reads prettier. It's
- * completely inconsistent, and historic practice.
- */
-uwait: return (proc_wait(sp, (long)utility_pid, cmd,
- ftype == FILTER_READ && F_ISSET(sp, SC_VI) ? 1 : 0, 0) || rval);
-}
-
-/*
- * filter_ldisplay --
- * Display output from a utility.
- *
- * !!!
- * Historically, the characters were passed unmodified to the terminal.
- * We use the ex print routines to make sure they're printable.
- */
-static int
-filter_ldisplay(sp, fp)
- SCR *sp;
- FILE *fp;
-{
- size_t len;
-
- EX_PRIVATE *exp;
-
- for (exp = EXP(sp); !ex_getline(sp, fp, &len) && !INTERRUPTED(sp);)
- if (ex_ldisplay(sp, exp->ibp, len, 0, 0))
- break;
- if (ferror(fp))
- msgq(sp, M_SYSERR, "filter read");
- (void)fclose(fp);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_global.c b/contrib/nvi/ex/ex_global.c
deleted file mode 100644
index aba9dc5..0000000
--- a/contrib/nvi/ex/ex_global.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_global.c 10.22 (Berkeley) 10/10/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-enum which {GLOBAL, V};
-
-static int ex_g_setup __P((SCR *, EXCMD *, enum which));
-
-/*
- * ex_global -- [line [,line]] g[lobal][!] /pattern/ [commands]
- * Exec on lines matching a pattern.
- *
- * PUBLIC: int ex_global __P((SCR *, EXCMD *));
- */
-int
-ex_global(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (ex_g_setup(sp,
- cmdp, FL_ISSET(cmdp->iflags, E_C_FORCE) ? V : GLOBAL));
-}
-
-/*
- * ex_v -- [line [,line]] v /pattern/ [commands]
- * Exec on lines not matching a pattern.
- *
- * PUBLIC: int ex_v __P((SCR *, EXCMD *));
- */
-int
-ex_v(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (ex_g_setup(sp, cmdp, V));
-}
-
-/*
- * ex_g_setup --
- * Ex global and v commands.
- */
-static int
-ex_g_setup(sp, cmdp, cmd)
- SCR *sp;
- EXCMD *cmdp;
- enum which cmd;
-{
- CHAR_T *ptrn, *p, *t;
- EXCMD *ecp;
- MARK abs;
- RANGE *rp;
- busy_t btype;
- recno_t start, end;
- regex_t *re;
- regmatch_t match[1];
- size_t len;
- int cnt, delim, eval;
- char *dbp;
-
- NEEDFILE(sp, cmdp);
-
- if (F_ISSET(sp, SC_EX_GLOBAL)) {
- msgq(sp, M_ERR,
- "124|The %s command can't be used as part of a global or v command",
- cmdp->cmd->name);
- return (1);
- }
-
- /*
- * Skip leading white space. Historic vi allowed any non-alphanumeric
- * to serve as the global command delimiter.
- */
- if (cmdp->argc == 0)
- goto usage;
- for (p = cmdp->argv[0]->bp; isblank(*p); ++p);
- if (*p == '\0' || isalnum(*p) ||
- *p == '\\' || *p == '|' || *p == '\n') {
-usage: ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
- delim = *p++;
-
- /*
- * Get the pattern string, toss escaped characters.
- *
- * QUOTING NOTE:
- * Only toss an escaped character if it escapes a delimiter.
- */
- for (ptrn = t = p;;) {
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
- ++p;
- /*
- * !!!
- * Nul terminate the pattern string -- it's passed
- * to regcomp which doesn't understand anything else.
- */
- *t = '\0';
- break;
- }
- if (p[0] == '\\')
- if (p[1] == delim)
- ++p;
- else if (p[1] == '\\')
- *t++ = *p++;
- *t++ = *p++;
- }
-
- /* If the pattern string is empty, use the last one. */
- if (*ptrn == '\0') {
- if (sp->re == NULL) {
- ex_emsg(sp, NULL, EXM_NOPREVRE);
- return (1);
- }
-
- /* Re-compile the RE if necessary. */
- if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
- sp->re, sp->re_len, NULL, NULL, &sp->re_c, RE_C_SEARCH))
- return (1);
- } else {
- /* Compile the RE. */
- if (re_compile(sp, ptrn, t - ptrn,
- &sp->re, &sp->re_len, &sp->re_c, RE_C_SEARCH))
- return (1);
-
- /*
- * Set saved RE. Historic practice is that globals set
- * direction as well as the RE.
- */
- sp->searchdir = FORWARD;
- }
- re = &sp->re_c;
-
- /* The global commands always set the previous context mark. */
- abs.lno = sp->lno;
- abs.cno = sp->cno;
- if (mark_set(sp, ABSMARK1, &abs, 1))
- return (1);
-
- /* Get an EXCMD structure. */
- CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
- CIRCLEQ_INIT(&ecp->rq);
-
- /*
- * Get a copy of the command string; the default command is print.
- * Don't worry about a set of <blank>s with no command, that will
- * default to print in the ex parser. We need to have two copies
- * because the ex parser may step on the command string when it's
- * parsing it.
- */
- if ((len = cmdp->argv[0]->len - (p - cmdp->argv[0]->bp)) == 0) {
- p = "pp";
- len = 1;
- }
-
- MALLOC_RET(sp, ecp->cp, char *, len * 2);
- ecp->o_cp = ecp->cp;
- ecp->o_clen = len;
- memcpy(ecp->cp + len, p, len);
- ecp->range_lno = OOBLNO;
- FL_SET(ecp->agv_flags, cmd == GLOBAL ? AGV_GLOBAL : AGV_V);
- LIST_INSERT_HEAD(&sp->gp->ecq, ecp, q);
-
- /*
- * For each line... The semantics of global matching are that we first
- * have to decide which lines are going to get passed to the command,
- * and then pass them to the command, ignoring other changes. There's
- * really no way to do this in a single pass, since arbitrary line
- * creation, deletion and movement can be done in the ex command. For
- * example, a good vi clone test is ":g/X/mo.-3", or "g/X/.,.+1d".
- * What we do is create linked list of lines that are tracked through
- * each ex command. There's a callback routine which the DB interface
- * routines call when a line is created or deleted. This doesn't help
- * the layering much.
- */
- btype = BUSY_ON;
- cnt = INTERRUPT_CHECK;
- for (start = cmdp->addr1.lno,
- end = cmdp->addr2.lno; start <= end; ++start) {
- if (cnt-- == 0) {
- if (INTERRUPTED(sp)) {
- LIST_REMOVE(ecp, q);
- free(ecp->cp);
- free(ecp);
- break;
- }
- search_busy(sp, btype);
- btype = BUSY_UPDATE;
- cnt = INTERRUPT_CHECK;
- }
- if (db_get(sp, start, DBG_FATAL, &dbp, &len))
- return (1);
- match[0].rm_so = 0;
- match[0].rm_eo = len;
- switch (eval =
- regexec(&sp->re_c, dbp, 0, match, REG_STARTEND)) {
- case 0:
- if (cmd == V)
- continue;
- break;
- case REG_NOMATCH:
- if (cmd == GLOBAL)
- continue;
- break;
- default:
- re_error(sp, eval, &sp->re_c);
- break;
- }
-
- /* If follows the last entry, extend the last entry's range. */
- if ((rp = ecp->rq.cqh_last) != (void *)&ecp->rq &&
- rp->stop == start - 1) {
- ++rp->stop;
- continue;
- }
-
- /* Allocate a new range, and append it to the list. */
- CALLOC(sp, rp, RANGE *, 1, sizeof(RANGE));
- if (rp == NULL)
- return (1);
- rp->start = rp->stop = start;
- CIRCLEQ_INSERT_TAIL(&ecp->rq, rp, q);
- }
- search_busy(sp, BUSY_OFF);
- return (0);
-}
-
-/*
- * ex_g_insdel --
- * Update the ranges based on an insertion or deletion.
- *
- * PUBLIC: int ex_g_insdel __P((SCR *, lnop_t, recno_t));
- */
-int
-ex_g_insdel(sp, op, lno)
- SCR *sp;
- lnop_t op;
- recno_t lno;
-{
- EXCMD *ecp;
- RANGE *nrp, *rp;
-
- /* All insert/append operations are done as inserts. */
- if (op == LINE_APPEND)
- abort();
-
- if (op == LINE_RESET)
- return (0);
-
- for (ecp = sp->gp->ecq.lh_first; ecp != NULL; ecp = ecp->q.le_next) {
- if (!FL_ISSET(ecp->agv_flags, AGV_AT | AGV_GLOBAL | AGV_V))
- continue;
- for (rp = ecp->rq.cqh_first; rp != (void *)&ecp->rq; rp = nrp) {
- nrp = rp->q.cqe_next;
-
- /* If range less than the line, ignore it. */
- if (rp->stop < lno)
- continue;
-
- /*
- * If range greater than the line, decrement or
- * increment the range.
- */
- if (rp->start > lno) {
- if (op == LINE_DELETE) {
- --rp->start;
- --rp->stop;
- } else {
- ++rp->start;
- ++rp->stop;
- }
- continue;
- }
-
- /*
- * Lno is inside the range, decrement the end point
- * for deletion, and split the range for insertion.
- * In the latter case, since we're inserting a new
- * element, neither range can be exhausted.
- */
- if (op == LINE_DELETE) {
- if (rp->start > --rp->stop) {
- CIRCLEQ_REMOVE(&ecp->rq, rp, q);
- free(rp);
- }
- } else {
- CALLOC_RET(sp, nrp, RANGE *, 1, sizeof(RANGE));
- nrp->start = lno + 1;
- nrp->stop = rp->stop + 1;
- rp->stop = lno - 1;
- CIRCLEQ_INSERT_AFTER(&ecp->rq, rp, nrp, q);
- rp = nrp;
- }
- }
-
- /*
- * If the command deleted/inserted lines, the cursor moves to
- * the line after the deleted/inserted line.
- */
- ecp->range_lno = lno;
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_init.c b/contrib/nvi/ex/ex_init.c
deleted file mode 100644
index 6a78416..0000000
--- a/contrib/nvi/ex/ex_init.c
+++ /dev/null
@@ -1,417 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_init.c 10.26 (Berkeley) 8/12/96";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/types.h> /* XXX: param.h may not have included types.h */
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <bitstring.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "tag.h"
-#include "pathnames.h"
-
-enum rc { NOEXIST, NOPERM, RCOK };
-static enum rc exrc_isok __P((SCR *, struct stat *, char *, int, int));
-
-static int ex_run_file __P((SCR *, char *));
-
-/*
- * ex_screen_copy --
- * Copy ex screen.
- *
- * PUBLIC: int ex_screen_copy __P((SCR *, SCR *));
- */
-int
-ex_screen_copy(orig, sp)
- SCR *orig, *sp;
-{
- EX_PRIVATE *oexp, *nexp;
-
- /* Create the private ex structure. */
- CALLOC_RET(orig, nexp, EX_PRIVATE *, 1, sizeof(EX_PRIVATE));
- sp->ex_private = nexp;
-
- /* Initialize queues. */
- CIRCLEQ_INIT(&nexp->tq);
- TAILQ_INIT(&nexp->tagfq);
- LIST_INIT(&nexp->cscq);
-
- if (orig == NULL) {
- } else {
- oexp = EXP(orig);
-
- if (oexp->lastbcomm != NULL &&
- (nexp->lastbcomm = strdup(oexp->lastbcomm)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return(1);
- }
- if (ex_tag_copy(orig, sp))
- return (1);
- }
- return (0);
-}
-
-/*
- * ex_screen_end --
- * End a vi screen.
- *
- * PUBLIC: int ex_screen_end __P((SCR *));
- */
-int
-ex_screen_end(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- int rval;
-
- if ((exp = EXP(sp)) == NULL)
- return (0);
-
- rval = 0;
-
- /* Close down script connections. */
- if (F_ISSET(sp, SC_SCRIPT) && sscr_end(sp))
- rval = 1;
-
- if (argv_free(sp))
- rval = 1;
-
- if (exp->ibp != NULL)
- free(exp->ibp);
-
- if (exp->lastbcomm != NULL)
- free(exp->lastbcomm);
-
- if (ex_tag_free(sp))
- rval = 1;
-
- /* Free private memory. */
- free(exp);
- sp->ex_private = NULL;
-
- return (rval);
-}
-
-/*
- * ex_optchange --
- * Handle change of options for ex.
- *
- * PUBLIC: int ex_optchange __P((SCR *, int, char *, u_long *));
- */
-int
-ex_optchange(sp, offset, str, valp)
- SCR *sp;
- int offset;
- char *str;
- u_long *valp;
-{
- switch (offset) {
- case O_TAGS:
- return (ex_tagf_alloc(sp, str));
- }
- return (0);
-}
-
-/*
- * ex_exrc --
- * Read the EXINIT environment variable and the startup exrc files,
- * and execute their commands.
- *
- * PUBLIC: int ex_exrc __P((SCR *));
- */
-int
-ex_exrc(sp)
- SCR *sp;
-{
- struct stat hsb, lsb;
- char *p, path[MAXPATHLEN];
-
- /*
- * Source the system, environment, $HOME and local .exrc values.
- * Vi historically didn't check $HOME/.exrc if the environment
- * variable EXINIT was set. This is all done before the file is
- * read in, because things in the .exrc information can set, for
- * example, the recovery directory.
- *
- * !!!
- * While nvi can handle any of the options settings of historic vi,
- * the converse is not true. Since users are going to have to have
- * files and environmental variables that work with both, we use nvi
- * versions of both the $HOME and local startup files if they exist,
- * otherwise the historic ones.
- *
- * !!!
- * For a discussion of permissions and when what .exrc files are
- * read, see the comment above the exrc_isok() function below.
- *
- * !!!
- * If the user started the historic of vi in $HOME, vi read the user's
- * .exrc file twice, as $HOME/.exrc and as ./.exrc. We avoid this, as
- * it's going to make some commands behave oddly, and I can't imagine
- * anyone depending on it.
- */
- switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1, 0)) {
- case NOEXIST:
- case NOPERM:
- break;
- case RCOK:
- if (ex_run_file(sp, _PATH_SYSEXRC))
- return (1);
- 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);
- } else if ((p = getenv("EXINIT")) != NULL) {
- if (ex_run_str(sp, "EXINIT", p, strlen(p), 1, 0))
- return (1);
- } else if ((p = getenv("HOME")) != NULL && *p) {
- (void)snprintf(path, sizeof(path), "%s/%s", p, _PATH_NEXRC);
- switch (exrc_isok(sp, &hsb, path, 0, 1)) {
- case NOEXIST:
- (void)snprintf(path,
- sizeof(path), "%s/%s", p, _PATH_EXRC);
- if (exrc_isok(sp,
- &hsb, path, 0, 1) == RCOK && ex_run_file(sp, path))
- return (1);
- break;
- case NOPERM:
- break;
- case RCOK:
- if (ex_run_file(sp, path))
- return (1);
- break;
- }
- }
-
- /* 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:
- if (exrc_isok(sp, &lsb, _PATH_EXRC, 0, 0) == RCOK &&
- (lsb.st_dev != hsb.st_dev ||
- lsb.st_ino != hsb.st_ino) &&
- ex_run_file(sp, _PATH_EXRC))
- return (1);
- break;
- case NOPERM:
- break;
- case RCOK:
- if ((lsb.st_dev != hsb.st_dev ||
- lsb.st_ino != hsb.st_ino) &&
- ex_run_file(sp, _PATH_NEXRC))
- return (1);
- break;
- }
- /* Run the commands. */
- if (EXCMD_RUNNING(sp->gp))
- (void)ex_cmd(sp);
- if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
- return (0);
- }
-
- return (0);
-}
-
-/*
- * ex_run_file --
- * Set up a file of ex commands to run.
- */
-static int
-ex_run_file(sp, name)
- SCR *sp;
- char *name;
-{
- ARGS *ap[2], a;
- EXCMD cmd;
-
- ex_cinit(&cmd, C_SOURCE, 0, OOBLNO, OOBLNO, 0, ap);
- ex_cadd(&cmd, &a, name, strlen(name));
- return (ex_source(sp, &cmd));
-}
-
-/*
- * ex_run_str --
- * Set up a string of ex commands to run.
- *
- * PUBLIC: int ex_run_str __P((SCR *, char *, char *, size_t, int, int));
- */
-int
-ex_run_str(sp, name, str, len, ex_flags, nocopy)
- SCR *sp;
- char *name, *str;
- size_t len;
- int ex_flags, nocopy;
-{
- GS *gp;
- EXCMD *ecp;
-
- gp = sp->gp;
- if (EXCMD_RUNNING(gp)) {
- CALLOC_RET(sp, ecp, EXCMD *, 1, sizeof(EXCMD));
- LIST_INSERT_HEAD(&gp->ecq, ecp, q);
- } else
- ecp = &gp->excmd;
-
- F_INIT(ecp,
- ex_flags ? E_BLIGNORE | E_NOAUTO | E_NOPRDEF | E_VLITONLY : 0);
-
- if (nocopy)
- ecp->cp = str;
- else
- if ((ecp->cp = v_strdup(sp, str, len)) == NULL)
- return (1);
- ecp->clen = len;
-
- if (name == NULL)
- ecp->if_name = NULL;
- else {
- if ((ecp->if_name = v_strdup(sp, name, strlen(name))) == NULL)
- return (1);
- ecp->if_lno = 1;
- F_SET(ecp, E_NAMEDISCARD);
- }
-
- return (0);
-}
-
-/*
- * exrc_isok --
- * Check a .exrc file for source-ability.
- *
- * !!!
- * Historically, vi read the $HOME and local .exrc files if they were owned
- * by the user's real ID, or the "sourceany" option was set, regardless of
- * any other considerations. We no longer support the sourceany option as
- * it's a security problem of mammoth proportions. We require the system
- * .exrc file to be owned by root, the $HOME .exrc file to be owned by the
- * user's effective ID (or that the user's effective ID be root) and the
- * local .exrc files to be owned by the user's effective ID. In all cases,
- * the file cannot be writeable by anyone other than its owner.
- *
- * In O'Reilly ("Learning the VI Editor", Fifth Ed., May 1992, page 106),
- * it notes that System V release 3.2 and later has an option "[no]exrc".
- * The behavior is that local .exrc files are read only if the exrc option
- * is set. The default for the exrc option was off, so, by default, local
- * .exrc files were not read. The problem this was intended to solve was
- * that System V permitted users to give away files, so there's no possible
- * ownership or writeability test to ensure that the file is safe.
- *
- * POSIX 1003.2-1992 standardized exrc as an option. It required the exrc
- * option to be off by default, thus local .exrc files are not to be read
- * by default. The Rationale noted (incorrectly) that this was a change
- * to historic practice, but correctly noted that a default of off improves
- * system security. POSIX also required that vi check the effective user
- * ID instead of the real user ID, which is why we've switched from historic
- * practice.
- *
- * We initialize the exrc variable to off. If it's turned on by the system
- * or $HOME .exrc files, and the local .exrc file passes the ownership and
- * writeability tests, then we read it. This breaks historic 4BSD practice,
- * but it gives us a measure of security on systems where users can give away
- * files.
- */
-static enum rc
-exrc_isok(sp, sbp, path, rootown, rootid)
- SCR *sp;
- struct stat *sbp;
- char *path;
- int rootown, rootid;
-{
- enum { ROOTOWN, OWN, WRITER } etype;
- uid_t euid;
- int nf1, nf2;
- char *a, *b, buf[MAXPATHLEN];
-
- /* Check for the file's existence. */
- if (stat(path, sbp))
- return (NOEXIST);
-
- /* Check ownership permissions. */
- euid = geteuid();
- if (!(rootown && sbp->st_uid == 0) &&
- !(rootid && euid == 0) && sbp->st_uid != euid) {
- etype = rootown ? ROOTOWN : OWN;
- goto denied;
- }
-
- /* Check writeability. */
- if (sbp->st_mode & (S_IWGRP | S_IWOTH)) {
- etype = WRITER;
- goto denied;
- }
- return (RCOK);
-
-denied: a = msg_print(sp, path, &nf1);
- if (strchr(path, '/') == NULL && getcwd(buf, sizeof(buf)) != NULL) {
- b = msg_print(sp, buf, &nf2);
- switch (etype) {
- case ROOTOWN:
- msgq(sp, M_ERR,
- "125|%s/%s: not sourced: not owned by you or root",
- b, a);
- break;
- case OWN:
- msgq(sp, M_ERR,
- "126|%s/%s: not sourced: not owned by you", b, a);
- break;
- case WRITER:
- msgq(sp, M_ERR,
- "127|%s/%s: not sourced: writeable by a user other than the owner", b, a);
- break;
- }
- if (nf2)
- FREE_SPACE(sp, b, 0);
- } else
- switch (etype) {
- case ROOTOWN:
- msgq(sp, M_ERR,
- "128|%s: not sourced: not owned by you or root", a);
- break;
- case OWN:
- msgq(sp, M_ERR,
- "129|%s: not sourced: not owned by you", a);
- break;
- case WRITER:
- msgq(sp, M_ERR,
- "130|%s: not sourced: writeable by a user other than the owner", a);
- break;
- }
-
- if (nf1)
- FREE_SPACE(sp, a, 0);
- return (NOPERM);
-}
diff --git a/contrib/nvi/ex/ex_join.c b/contrib/nvi/ex/ex_join.c
deleted file mode 100644
index c26c424..0000000
--- a/contrib/nvi/ex/ex_join.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_join.c 10.10 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_join -- :[line [,line]] j[oin][!] [count] [flags]
- * Join lines.
- *
- * PUBLIC: int ex_join __P((SCR *, EXCMD *));
- */
-int
-ex_join(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- recno_t from, to;
- size_t blen, clen, len, tlen;
- int echar, extra, first;
- char *bp, *p, *tbp;
-
- NEEDFILE(sp, cmdp);
-
- from = cmdp->addr1.lno;
- to = cmdp->addr2.lno;
-
- /* Check for no lines to join. */
- if (!db_exist(sp, from + 1)) {
- msgq(sp, M_ERR, "131|No following lines to join");
- return (1);
- }
-
- GET_SPACE_RET(sp, bp, blen, 256);
-
- /*
- * The count for the join command was off-by-one,
- * historically, to other counts for other commands.
- */
- if (FL_ISSET(cmdp->iflags, E_C_COUNT))
- ++cmdp->addr2.lno;
-
- /*
- * If only a single address specified, or, the same address
- * specified twice, the from/two addresses will be the same.
- */
- if (cmdp->addr1.lno == cmdp->addr2.lno)
- ++cmdp->addr2.lno;
-
- clen = tlen = 0;
- for (first = 1,
- from = cmdp->addr1.lno, to = cmdp->addr2.lno; from <= to; ++from) {
- /*
- * Get next line. Historic versions of vi allowed "10J" while
- * less than 10 lines from the end-of-file, so we do too.
- */
- if (db_get(sp, from, 0, &p, &len)) {
- cmdp->addr2.lno = from - 1;
- break;
- }
-
- /* Empty lines just go away. */
- if (len == 0)
- continue;
-
- /*
- * Get more space if necessary. Note, tlen isn't the length
- * of the new line, it's roughly the amount of space needed.
- * tbp - bp is the length of the new line.
- */
- tlen += len + 2;
- ADD_SPACE_RET(sp, bp, blen, tlen);
- tbp = bp + clen;
-
- /*
- * Historic practice:
- *
- * If force specified, join without modification.
- * If the current line ends with whitespace, strip leading
- * whitespace from the joined line.
- * If the next line starts with a ), do nothing.
- * If the current line ends with ., insert two spaces.
- * Else, insert one space.
- *
- * One change -- add ? and ! to the list of characters for
- * which we insert two spaces. I expect that POSIX 1003.2
- * will require this as well.
- *
- * Echar is the last character in the last line joined.
- */
- extra = 0;
- if (!first && !FL_ISSET(cmdp->iflags, E_C_FORCE)) {
- if (isblank(echar))
- for (; len && isblank(*p); --len, ++p);
- else if (p[0] != ')') {
- if (strchr(".?!", echar)) {
- *tbp++ = ' ';
- ++clen;
- extra = 1;
- }
- *tbp++ = ' ';
- ++clen;
- for (; len && isblank(*p); --len, ++p);
- }
- }
-
- if (len != 0) {
- memcpy(tbp, p, len);
- tbp += len;
- clen += len;
- echar = p[len - 1];
- } else
- echar = ' ';
-
- /*
- * Historic practice for vi was to put the cursor at the first
- * inserted whitespace character, if there was one, or the
- * first character of the joined line, if there wasn't, or the
- * last character of the line if joined to an empty line. If
- * a count was specified, the cursor was moved as described
- * for the first line joined, ignoring subsequent lines. If
- * the join was a ':' command, the cursor was placed at the
- * first non-blank character of the line unless the cursor was
- * "attracted" to the end of line when the command was executed
- * in which case it moved to the new end of line. There are
- * probably several more special cases, but frankly, my dear,
- * I don't give a damn. This implementation puts the cursor
- * on the first inserted whitespace character, the first
- * character of the joined line, or the last character of the
- * line regardless. Note, if the cursor isn't on the joined
- * line (possible with : commands), it is reset to the starting
- * line.
- */
- if (first) {
- sp->cno = (tbp - bp) - (1 + extra);
- first = 0;
- } else
- sp->cno = (tbp - bp) - len - (1 + extra);
- }
- sp->lno = cmdp->addr1.lno;
-
- /* Delete the joined lines. */
- for (from = cmdp->addr1.lno, to = cmdp->addr2.lno; to > from; --to)
- if (db_delete(sp, to))
- goto err;
-
- /* If the original line changed, reset it. */
- if (!first && db_set(sp, from, bp, tbp - bp)) {
-err: FREE_SPACE(sp, bp, blen);
- return (1);
- }
- FREE_SPACE(sp, bp, blen);
-
- sp->rptlines[L_JOINED] += (cmdp->addr2.lno - cmdp->addr1.lno) + 1;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_map.c b/contrib/nvi/ex/ex_map.c
deleted file mode 100644
index bc2cf08..0000000
--- a/contrib/nvi/ex/ex_map.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_map.c 10.9 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_map -- :map[!] [input] [replacement]
- * Map a key/string or display mapped keys.
- *
- * Historical note:
- * Historic vi maps were fairly bizarre, and likely to differ in
- * very subtle and strange ways from this implementation. Two
- * things worth noting are that vi would often hang or drop core
- * if the map was strange enough (ex: map X "xy$@x^V), or, simply
- * not work. One trick worth remembering is that if you put a
- * mark at the start of the map, e.g. map X mx"xy ...), or if you
- * put the map in a .exrc file, things would often work much better.
- * No clue why.
- *
- * PUBLIC: int ex_map __P((SCR *, EXCMD *));
- */
-int
-ex_map(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- seq_t stype;
- CHAR_T *input, *p;
-
- stype = FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND;
-
- switch (cmdp->argc) {
- case 0:
- if (seq_dump(sp, stype, 1) == 0)
- msgq(sp, M_INFO, stype == SEQ_INPUT ?
- "132|No input map entries" :
- "133|No command map entries");
- return (0);
- case 2:
- input = cmdp->argv[0]->bp;
- break;
- default:
- abort();
- }
-
- /*
- * If the mapped string is #[0-9]* (and wasn't quoted) then store the
- * function key mapping. If the screen specific routine has been set,
- * call it as well. Note, the SEQ_FUNCMAP type is persistent across
- * screen types, maybe the next screen type will get it right.
- */
- if (input[0] == '#' && isdigit(input[1])) {
- for (p = input + 2; isdigit(*p); ++p);
- if (p[0] != '\0')
- goto nofunc;
-
- if (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len, stype,
- SEQ_FUNCMAP | SEQ_USERDEF))
- return (1);
- return (sp->gp->scr_fmap == NULL ? 0 :
- sp->gp->scr_fmap(sp, stype, input, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len));
- }
-
- /* Some single keys may not be remapped in command mode. */
-nofunc: if (stype == SEQ_COMMAND && input[1] == '\0')
- switch (KEY_VAL(sp, input[0])) {
- case K_COLON:
- case K_ESCAPE:
- case K_NL:
- msgq(sp, M_ERR,
- "134|The %s character may not be remapped",
- KEY_NAME(sp, input[0]));
- return (1);
- }
- return (seq_set(sp, NULL, 0, input, cmdp->argv[0]->len,
- cmdp->argv[1]->bp, cmdp->argv[1]->len, stype, SEQ_USERDEF));
-}
-
-/*
- * ex_unmap -- (:unmap[!] key)
- * Unmap a key.
- *
- * PUBLIC: int ex_unmap __P((SCR *, EXCMD *));
- */
-int
-ex_unmap(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (seq_delete(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len,
- FL_ISSET(cmdp->iflags, E_C_FORCE) ? SEQ_INPUT : SEQ_COMMAND)) {
- msgq_str(sp, M_INFO,
- cmdp->argv[0]->bp, "135|\"%s\" isn't currently mapped");
- return (1);
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_mark.c b/contrib/nvi/ex/ex_mark.c
deleted file mode 100644
index 08ad8c2..0000000
--- a/contrib/nvi/ex/ex_mark.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_mark.c 10.8 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_mark -- :mark char
- * :k char
- * Mark lines.
- *
- *
- * PUBLIC: int ex_mark __P((SCR *, EXCMD *));
- */
-int
-ex_mark(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- NEEDFILE(sp, cmdp);
-
- if (cmdp->argv[0]->len != 1) {
- msgq(sp, M_ERR, "136|Mark names must be a single character");
- return (1);
- }
- return (mark_set(sp, cmdp->argv[0]->bp[0], &cmdp->addr1, 1));
-}
diff --git a/contrib/nvi/ex/ex_mkexrc.c b/contrib/nvi/ex/ex_mkexrc.c
deleted file mode 100644
index 0eb15d4..0000000
--- a/contrib/nvi/ex/ex_mkexrc.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_mkexrc.c 10.11 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "pathnames.h"
-
-/*
- * ex_mkexrc -- :mkexrc[!] [file]
- *
- * Create (or overwrite) a .exrc file with the current info.
- *
- * PUBLIC: int ex_mkexrc __P((SCR *, EXCMD *));
- */
-int
-ex_mkexrc(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- struct stat sb;
- FILE *fp;
- int fd, sverrno;
- char *fname;
-
- switch (cmdp->argc) {
- case 0:
- fname = _PATH_EXRC;
- break;
- case 1:
- fname = cmdp->argv[0]->bp;
- set_alt_name(sp, fname);
- break;
- default:
- abort();
- }
-
- if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && !stat(fname, &sb)) {
- msgq_str(sp, M_ERR, fname,
- "137|%s exists, not written; use ! to override");
- return (1);
- }
-
- /* Create with max permissions of rw-r--r--. */
- if ((fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
- msgq_str(sp, M_SYSERR, fname, "%s");
- return (1);
- }
-
- if ((fp = fdopen(fd, "w")) == NULL) {
- sverrno = errno;
- (void)close(fd);
- goto e2;
- }
-
- if (seq_save(sp, fp, "abbreviate ", SEQ_ABBREV) || ferror(fp))
- goto e1;
- if (seq_save(sp, fp, "map ", SEQ_COMMAND) || ferror(fp))
- goto e1;
- if (seq_save(sp, fp, "map! ", SEQ_INPUT) || ferror(fp))
- goto e1;
- if (opts_save(sp, fp) || ferror(fp))
- goto e1;
- if (fclose(fp)) {
- sverrno = errno;
- goto e2;
- }
-
- msgq_str(sp, M_INFO, fname, "138|New exrc file: %s");
- return (0);
-
-e1: sverrno = errno;
- (void)fclose(fp);
-e2: errno = sverrno;
- msgq_str(sp, M_SYSERR, fname, "%s");
- return (1);
-}
diff --git a/contrib/nvi/ex/ex_move.c b/contrib/nvi/ex/ex_move.c
deleted file mode 100644
index d6e45c3..0000000
--- a/contrib/nvi/ex/ex_move.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_move.c 10.10 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_copy -- :[line [,line]] co[py] line [flags]
- * Copy selected lines.
- *
- * PUBLIC: int ex_copy __P((SCR *, EXCMD *));
- */
-int
-ex_copy(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- CB cb;
- MARK fm1, fm2, m, tm;
- recno_t cnt;
- int rval;
-
- rval = 0;
-
- NEEDFILE(sp, cmdp);
-
- /*
- * It's possible to copy things into the area that's being
- * copied, e.g. "2,5copy3" is legitimate. Save the text to
- * a cut buffer.
- */
- fm1 = cmdp->addr1;
- fm2 = cmdp->addr2;
- memset(&cb, 0, sizeof(cb));
- CIRCLEQ_INIT(&cb.textq);
- for (cnt = fm1.lno; cnt <= fm2.lno; ++cnt)
- if (cut_line(sp, cnt, 0, 0, &cb)) {
- rval = 1;
- goto err;
- }
- cb.flags |= CB_LMODE;
-
- /* Put the text into place. */
- tm.lno = cmdp->lineno;
- tm.cno = 0;
- if (put(sp, &cb, NULL, &tm, &m, 1))
- rval = 1;
- else {
- /*
- * Copy puts the cursor on the last line copied. The cursor
- * returned by the put routine is the first line put, not the
- * last, because that's the historic semantic of vi.
- */
- cnt = (fm2.lno - fm1.lno) + 1;
- sp->lno = m.lno + (cnt - 1);
- sp->cno = 0;
- }
-err: text_lfree(&cb.textq);
- return (rval);
-}
-
-/*
- * ex_move -- :[line [,line]] mo[ve] line
- * Move selected lines.
- *
- * PUBLIC: int ex_move __P((SCR *, EXCMD *));
- */
-int
-ex_move(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- LMARK *lmp;
- MARK fm1, fm2;
- recno_t cnt, diff, fl, tl, mfl, mtl;
- size_t blen, len;
- int mark_reset;
- char *bp, *p;
-
- NEEDFILE(sp, cmdp);
-
- /*
- * It's not possible to move things into the area that's being
- * moved.
- */
- fm1 = cmdp->addr1;
- fm2 = cmdp->addr2;
- if (cmdp->lineno >= fm1.lno && cmdp->lineno <= fm2.lno) {
- msgq(sp, M_ERR, "139|Destination line is inside move range");
- return (1);
- }
-
- /*
- * Log the positions of any marks in the to-be-deleted lines. This
- * has to work with the logging code. What happens is that we log
- * the old mark positions, make the changes, then log the new mark
- * positions. Then the marks end up in the right positions no matter
- * which way the log is traversed.
- *
- * XXX
- * Reset the MARK_USERSET flag so that the log can undo the mark.
- * This isn't very clean, and should probably be fixed.
- */
- fl = fm1.lno;
- tl = cmdp->lineno;
-
- /* Log the old positions of the marks. */
- mark_reset = 0;
- for (lmp = sp->ep->marks.lh_first; lmp != NULL; lmp = lmp->q.le_next)
- if (lmp->name != ABSMARK1 &&
- lmp->lno >= fl && lmp->lno <= tl) {
- mark_reset = 1;
- F_CLR(lmp, MARK_USERSET);
- (void)log_mark(sp, lmp);
- }
-
- /* Get memory for the copy. */
- GET_SPACE_RET(sp, bp, blen, 256);
-
- /* Move the lines. */
- diff = (fm2.lno - fm1.lno) + 1;
- if (tl > fl) { /* Destination > source. */
- mfl = tl - diff;
- mtl = tl;
- for (cnt = diff; cnt--;) {
- if (db_get(sp, fl, DBG_FATAL, &p, &len))
- return (1);
- BINC_RET(sp, bp, blen, len);
- memcpy(bp, p, len);
- if (db_append(sp, 1, tl, bp, len))
- return (1);
- if (mark_reset)
- for (lmp = sp->ep->marks.lh_first;
- lmp != NULL; lmp = lmp->q.le_next)
- if (lmp->name != ABSMARK1 &&
- lmp->lno == fl)
- lmp->lno = tl + 1;
- if (db_delete(sp, fl))
- return (1);
- }
- } else { /* Destination < source. */
- mfl = tl;
- mtl = tl + diff;
- for (cnt = diff; cnt--;) {
- if (db_get(sp, fl, DBG_FATAL, &p, &len))
- return (1);
- BINC_RET(sp, bp, blen, len);
- memcpy(bp, p, len);
- if (db_append(sp, 1, tl++, bp, len))
- return (1);
- if (mark_reset)
- for (lmp = sp->ep->marks.lh_first;
- lmp != NULL; lmp = lmp->q.le_next)
- if (lmp->name != ABSMARK1 &&
- lmp->lno == fl)
- lmp->lno = tl;
- ++fl;
- if (db_delete(sp, fl))
- return (1);
- }
- }
- FREE_SPACE(sp, bp, blen);
-
- sp->lno = tl; /* Last line moved. */
- sp->cno = 0;
-
- /* Log the new positions of the marks. */
- if (mark_reset)
- for (lmp = sp->ep->marks.lh_first;
- lmp != NULL; lmp = lmp->q.le_next)
- if (lmp->name != ABSMARK1 &&
- lmp->lno >= mfl && lmp->lno <= mtl)
- (void)log_mark(sp, lmp);
-
-
- sp->rptlines[L_MOVED] += diff;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_open.c b/contrib/nvi/ex/ex_open.c
deleted file mode 100644
index afffaeb..0000000
--- a/contrib/nvi/ex/ex_open.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_open.c 10.7 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_open -- :[line] o[pen] [/pattern/] [flags]
- *
- * Switch to single line "open" mode.
- *
- * PUBLIC: int ex_open __P((SCR *, EXCMD *));
- */
-int
-ex_open(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- /* If open option off, disallow open command. */
- if (!O_ISSET(sp, O_OPEN)) {
- msgq(sp, M_ERR,
- "140|The open command requires that the open option be set");
- return (1);
- }
-
- msgq(sp, M_ERR, "141|The open command is not yet implemented");
- return (1);
-}
diff --git a/contrib/nvi/ex/ex_perl.c b/contrib/nvi/ex/ex_perl.c
deleted file mode 100644
index e620352..0000000
--- a/contrib/nvi/ex/ex_perl.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- * Copyright (c) 1995
- * George V. Neville-Neil. All rights reserved.
- * Copyright (c) 1996
- * Sven Verdoolaege. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_perl.c 8.10 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-/*
- * ex_perl -- :[line [,line]] perl [command]
- * Run a command through the perl interpreter.
- *
- * ex_perldo -- :[line [,line]] perldo [command]
- * Run a set of lines through the perl interpreter.
- *
- * PUBLIC: int ex_perl __P((SCR*, EXCMD *));
- */
-int
-ex_perl(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
-#ifdef HAVE_PERL_INTERP
- CHAR_T *p;
- size_t len;
-
- /* 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(sp, cmdp->cmd->usage, EXM_USAGE);
- 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
- msgq(sp, M_ERR, "306|Vi was not loaded with a Perl interpreter");
- return (1);
-#endif
-}
diff --git a/contrib/nvi/ex/ex_preserve.c b/contrib/nvi/ex/ex_preserve.c
deleted file mode 100644
index 5614c88..0000000
--- a/contrib/nvi/ex/ex_preserve.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_preserve.c 10.12 (Berkeley) 4/27/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_preserve -- :pre[serve]
- * Push the file to recovery.
- *
- * PUBLIC: int ex_preserve __P((SCR *, EXCMD *));
- */
-int
-ex_preserve(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- recno_t lno;
-
- NEEDFILE(sp, cmdp);
-
- if (!F_ISSET(sp->ep, F_RCV_ON)) {
- msgq(sp, M_ERR, "142|Preservation of this file not possible");
- return (1);
- }
-
- /* If recovery not initialized, do so. */
- if (F_ISSET(sp->ep, F_FIRSTMODIFY) && rcv_init(sp))
- return (1);
-
- /* Force the file to be read in, in case it hasn't yet. */
- if (db_last(sp, &lno))
- return (1);
-
- /* Sync to disk. */
- if (rcv_sync(sp, RCV_SNAPSHOT))
- return (1);
-
- msgq(sp, M_INFO, "143|File preserved");
- return (0);
-}
-
-/*
- * ex_recover -- :rec[over][!] file
- * Recover the file.
- *
- * PUBLIC: int ex_recover __P((SCR *, EXCMD *));
- */
-int
-ex_recover(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- ARGS *ap;
- FREF *frp;
-
- ap = cmdp->argv[0];
-
- /* Set the alternate file name. */
- set_alt_name(sp, ap->bp);
-
- /*
- * Check for modifications. Autowrite did not historically
- * affect :recover.
- */
- if (file_m2(sp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
- return (1);
-
- /* Get a file structure for the file. */
- if ((frp = file_add(sp, ap->bp)) == NULL)
- return (1);
-
- /* Set the recover bit. */
- F_SET(frp, FR_RECOVER);
-
- /* Switch files. */
- if (file_init(sp, frp, NULL, FS_SETALT |
- (FL_ISSET(cmdp->iflags, E_C_FORCE) ? FS_FORCE : 0)))
- return (1);
-
- F_SET(sp, SC_FSWITCH);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_print.c b/contrib/nvi/ex/ex_print.c
deleted file mode 100644
index 4218e08..0000000
--- a/contrib/nvi/ex/ex_print.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_print.c 10.18 (Berkeley) 5/12/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-#include "../common/common.h"
-
-static int ex_prchars __P((SCR *, const char *, size_t *, size_t, u_int, int));
-
-/*
- * ex_list -- :[line [,line]] l[ist] [count] [flags]
- *
- * Display the addressed lines such that the output is unambiguous.
- *
- * PUBLIC: int ex_list __P((SCR *, EXCMD *));
- */
-int
-ex_list(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (ex_print(sp, cmdp,
- &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_LIST))
- return (1);
- sp->lno = cmdp->addr2.lno;
- sp->cno = cmdp->addr2.cno;
- return (0);
-}
-
-/*
- * ex_number -- :[line [,line]] nu[mber] [count] [flags]
- *
- * Display the addressed lines with a leading line number.
- *
- * PUBLIC: int ex_number __P((SCR *, EXCMD *));
- */
-int
-ex_number(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (ex_print(sp, cmdp,
- &cmdp->addr1, &cmdp->addr2, cmdp->iflags | E_C_HASH))
- return (1);
- sp->lno = cmdp->addr2.lno;
- sp->cno = cmdp->addr2.cno;
- return (0);
-}
-
-/*
- * ex_pr -- :[line [,line]] p[rint] [count] [flags]
- *
- * Display the addressed lines.
- *
- * PUBLIC: int ex_pr __P((SCR *, EXCMD *));
- */
-int
-ex_pr(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (ex_print(sp, cmdp, &cmdp->addr1, &cmdp->addr2, cmdp->iflags))
- return (1);
- sp->lno = cmdp->addr2.lno;
- sp->cno = cmdp->addr2.cno;
- return (0);
-}
-
-/*
- * ex_print --
- * Print the selected lines.
- *
- * PUBLIC: int ex_print __P((SCR *, EXCMD *, MARK *, MARK *, u_int32_t));
- */
-int
-ex_print(sp, cmdp, fp, tp, flags)
- SCR *sp;
- EXCMD *cmdp;
- MARK *fp, *tp;
- u_int32_t flags;
-{
- GS *gp;
- recno_t from, to;
- size_t col, len;
- char *p, buf[10];
-
- NEEDFILE(sp, cmdp);
-
- gp = sp->gp;
- for (from = fp->lno, to = tp->lno; from <= to; ++from) {
- col = 0;
-
- /*
- * Display the line number. The %6 format is specified
- * by POSIX 1003.2, and is almost certainly large enough.
- * Check, though, just in case.
- */
- if (LF_ISSET(E_C_HASH)) {
- if (from <= 999999) {
- snprintf(buf, sizeof(buf), "%6ld ", from);
- p = buf;
- } else
- p = "TOOBIG ";
- if (ex_prchars(sp, p, &col, 8, 0, 0))
- return (1);
- }
-
- /*
- * Display the line. The format for E_C_PRINT isn't very good,
- * especially in handling end-of-line tabs, but they're almost
- * backward compatible.
- */
- if (db_get(sp, from, DBG_FATAL, &p, &len))
- return (1);
-
- if (len == 0 && !LF_ISSET(E_C_LIST))
- (void)ex_puts(sp, "\n");
- else if (ex_ldisplay(sp, p, len, col, flags))
- return (1);
-
- if (INTERRUPTED(sp))
- break;
- }
- return (0);
-}
-
-/*
- * ex_ldisplay --
- * Display a line without any preceding number.
- *
- * PUBLIC: int ex_ldisplay __P((SCR *, const char *, size_t, size_t, u_int));
- */
-int
-ex_ldisplay(sp, p, len, col, flags)
- SCR *sp;
- const char *p;
- size_t len, col;
- u_int flags;
-{
- if (len > 0 && ex_prchars(sp, p, &col, len, LF_ISSET(E_C_LIST), 0))
- return (1);
- if (!INTERRUPTED(sp) && LF_ISSET(E_C_LIST)) {
- p = "$";
- if (ex_prchars(sp, p, &col, 1, LF_ISSET(E_C_LIST), 0))
- return (1);
- }
- if (!INTERRUPTED(sp))
- (void)ex_puts(sp, "\n");
- return (0);
-}
-
-/*
- * ex_scprint --
- * Display a line for the substitute with confirmation routine.
- *
- * PUBLIC: int ex_scprint __P((SCR *, MARK *, MARK *));
- */
-int
-ex_scprint(sp, fp, tp)
- SCR *sp;
- MARK *fp, *tp;
-{
- const char *p;
- size_t col, len;
-
- col = 0;
- if (O_ISSET(sp, O_NUMBER)) {
- p = " ";
- if (ex_prchars(sp, p, &col, 8, 0, 0))
- return (1);
- }
-
- if (db_get(sp, fp->lno, DBG_FATAL, (char **)&p, &len))
- return (1);
-
- if (ex_prchars(sp, p, &col, fp->cno, 0, ' '))
- return (1);
- p += fp->cno;
- if (ex_prchars(sp,
- p, &col, tp->cno == fp->cno ? 1 : tp->cno - fp->cno, 0, '^'))
- return (1);
- if (INTERRUPTED(sp))
- return (1);
- p = "[ynq]"; /* XXX: should be msg_cat. */
- if (ex_prchars(sp, p, &col, 5, 0, 0))
- return (1);
- (void)ex_fflush(sp);
- return (0);
-}
-
-/*
- * ex_prchars --
- * Local routine to dump characters to the screen.
- */
-static int
-ex_prchars(sp, p, colp, len, flags, repeatc)
- SCR *sp;
- const char *p;
- size_t *colp, len;
- u_int flags;
- int repeatc;
-{
- CHAR_T ch, *kp;
- GS *gp;
- size_t col, tlen, ts;
-
- if (O_ISSET(sp, O_LIST))
- LF_SET(E_C_LIST);
- gp = sp->gp;
- ts = O_VAL(sp, O_TABSTOP);
- for (col = *colp; len--;)
- if ((ch = *p++) == '\t' && !LF_ISSET(E_C_LIST))
- for (tlen = ts - col % ts;
- col < sp->cols && tlen--; ++col) {
- (void)ex_printf(sp,
- "%c", repeatc ? repeatc : ' ');
- if (INTERRUPTED(sp))
- goto intr;
- }
- else {
- kp = KEY_NAME(sp, ch);
- tlen = KEY_LEN(sp, ch);
- if (!repeatc && col + tlen < sp->cols) {
- (void)ex_puts(sp, kp);
- col += tlen;
- } else
- for (; tlen--; ++kp, ++col) {
- if (col == sp->cols) {
- col = 0;
- (void)ex_puts(sp, "\n");
- }
- (void)ex_printf(sp,
- "%c", repeatc ? repeatc : *kp);
- if (INTERRUPTED(sp))
- goto intr;
- }
- }
-intr: *colp = col;
- return (0);
-}
-
-/*
- * ex_printf --
- * Ex's version of printf.
- *
- * PUBLIC: int ex_printf __P((SCR *, const char *, ...));
- */
-int
-#ifdef __STDC__
-ex_printf(SCR *sp, const char *fmt, ...)
-#else
-ex_printf(sp, fmt, va_alist)
- SCR *sp;
- const char *fmt;
- va_dcl
-#endif
-{
- EX_PRIVATE *exp;
- va_list ap;
- size_t n;
-
- exp = EXP(sp);
-
-#ifdef __STDC__
- va_start(ap, fmt);
-#else
- va_start(ap);
-#endif
- exp->obp_len += n = vsnprintf(exp->obp + exp->obp_len,
- sizeof(exp->obp) - exp->obp_len, fmt, ap);
- va_end(ap);
-
- /* Flush when reach a <newline> or half the buffer. */
- if (exp->obp[exp->obp_len - 1] == '\n' ||
- exp->obp_len > sizeof(exp->obp) / 2)
- (void)ex_fflush(sp);
- return (n);
-}
-
-/*
- * ex_puts --
- * Ex's version of puts.
- *
- * PUBLIC: int ex_puts __P((SCR *, const char *));
- */
-int
-ex_puts(sp, str)
- SCR *sp;
- const char *str;
-{
- EX_PRIVATE *exp;
- int doflush, n;
-
- exp = EXP(sp);
-
- /* Flush when reach a <newline> or the end of the buffer. */
- for (doflush = n = 0; *str != '\0'; ++n) {
- if (exp->obp_len > sizeof(exp->obp))
- (void)ex_fflush(sp);
- if ((exp->obp[exp->obp_len++] = *str++) == '\n')
- doflush = 1;
- }
- if (doflush)
- (void)ex_fflush(sp);
- return (n);
-}
-
-/*
- * ex_fflush --
- * Ex's version of fflush.
- *
- * PUBLIC: int ex_fflush __P((SCR *sp));
- */
-int
-ex_fflush(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
-
- exp = EXP(sp);
-
- if (exp->obp_len != 0) {
- sp->gp->scr_msg(sp, M_NONE, exp->obp, exp->obp_len);
- exp->obp_len = 0;
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_put.c b/contrib/nvi/ex/ex_put.c
deleted file mode 100644
index 2facb03..0000000
--- a/contrib/nvi/ex/ex_put.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_put.c 10.7 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_put -- [line] pu[t] [buffer]
- * Append a cut buffer into the file.
- *
- * PUBLIC: int ex_put __P((SCR *, EXCMD *));
- */
-int
-ex_put(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- MARK m;
-
- NEEDFILE(sp, cmdp);
-
- m.lno = sp->lno;
- m.cno = sp->cno;
- if (put(sp, NULL,
- FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
- &cmdp->addr1, &m, 1))
- return (1);
- sp->lno = m.lno;
- sp->cno = m.cno;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_quit.c b/contrib/nvi/ex/ex_quit.c
deleted file mode 100644
index 705fa1a..0000000
--- a/contrib/nvi/ex/ex_quit.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_quit.c 10.7 (Berkeley) 4/27/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_quit -- :quit[!]
- * Quit.
- *
- * PUBLIC: int ex_quit __P((SCR *, EXCMD *));
- */
-int
-ex_quit(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- int force;
-
- force = FL_ISSET(cmdp->iflags, E_C_FORCE);
-
- /* Check for file modifications, or more files to edit. */
- if (file_m2(sp, force) || ex_ncheck(sp, force))
- return (1);
-
- F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_read.c b/contrib/nvi/ex/ex_read.c
deleted file mode 100644
index 78296ff..0000000
--- a/contrib/nvi/ex/ex_read.c
+++ /dev/null
@@ -1,360 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_read.c 10.38 (Berkeley) 8/12/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-/*
- * ex_read -- :read [file]
- * :read [!cmd]
- * Read from a file or utility.
- *
- * !!!
- * Historical vi wouldn't undo a filter read, for no apparent reason.
- *
- * PUBLIC: int ex_read __P((SCR *, EXCMD *));
- */
-int
-ex_read(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- enum { R_ARG, R_EXPANDARG, R_FILTER } which;
- struct stat sb;
- CHAR_T *arg, *name;
- EX_PRIVATE *exp;
- FILE *fp;
- FREF *frp;
- GS *gp;
- MARK rm;
- recno_t nlines;
- size_t arglen;
- int argc, rval;
- char *p;
-
- gp = sp->gp;
-
- /*
- * 0 args: read the current pathname.
- * 1 args: check for "read !arg".
- */
- switch (cmdp->argc) {
- case 0:
- which = R_ARG;
- break;
- case 1:
- arg = cmdp->argv[0]->bp;
- arglen = cmdp->argv[0]->len;
- if (*arg == '!') {
- ++arg;
- --arglen;
- which = R_FILTER;
-
- /* Secure means no shell access. */
- if (O_ISSET(sp, O_SECURE)) {
- ex_emsg(sp, cmdp->cmd->name, EXM_SECURE_F);
- return (1);
- }
- } else
- which = R_EXPANDARG;
- break;
- default:
- abort();
- /* NOTREACHED */
- }
-
- /* Load a temporary file if no file being edited. */
- if (sp->ep == NULL) {
- if ((frp = file_add(sp, NULL)) == NULL)
- return (1);
- if (file_init(sp, frp, NULL, 0))
- return (1);
- }
-
- switch (which) {
- case R_FILTER:
- /*
- * File name and bang expand the user's argument. If
- * we don't get an additional argument, it's illegal.
- */
- argc = cmdp->argc;
- if (argv_exp1(sp, cmdp, arg, arglen, 1))
- return (1);
- if (argc == cmdp->argc) {
- ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
- argc = cmdp->argc - 1;
-
- /* Set the last bang command. */
- exp = EXP(sp);
- if (exp->lastbcomm != NULL)
- free(exp->lastbcomm);
- if ((exp->lastbcomm =
- strdup(cmdp->argv[argc]->bp)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- /*
- * Vi redisplayed the user's argument if it changed, ex
- * always displayed a !, plus the user's argument if it
- * changed.
- */
- if (F_ISSET(sp, SC_VI)) {
- if (F_ISSET(cmdp, E_MODIFY))
- (void)vs_update(sp, "!", cmdp->argv[argc]->bp);
- } else {
- if (F_ISSET(cmdp, E_MODIFY))
- (void)ex_printf(sp,
- "!%s\n", cmdp->argv[argc]->bp);
- else
- (void)ex_puts(sp, "!\n");
- (void)ex_fflush(sp);
- }
-
- /*
- * Historically, filter reads as the first ex command didn't
- * wait for the user. If SC_SCR_EXWROTE not already set, set
- * the don't-wait flag.
- */
- if (!F_ISSET(sp, SC_SCR_EXWROTE))
- F_SET(sp, SC_EX_WAIT_NO);
-
- /*
- * Switch into ex canonical mode. The reason to restore the
- * original terminal modes for read filters is so that users
- * can do things like ":r! cat /dev/tty".
- *
- * !!!
- * We do not output an extra <newline>, so that we don't touch
- * the screen on a normal read.
- */
- if (F_ISSET(sp, SC_VI)) {
- if (gp->scr_screen(sp, SC_EX)) {
- ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON_F);
- return (1);
- }
- /*
- * !!!
- * Historically, the read command doesn't switch to
- * the alternate X11 xterm screen, if doing a filter
- * read -- don't set SA_ALTERNATE.
- */
- F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
- }
-
- if (ex_filter(sp, cmdp, &cmdp->addr1,
- NULL, &rm, cmdp->argv[argc]->bp, FILTER_READ))
- return (1);
-
- /* The filter version of read set the autoprint flag. */
- F_SET(cmdp, E_AUTOPRINT);
-
- /*
- * If in vi mode, move to the first nonblank. Might have
- * switched into ex mode, so saved the original SC_VI value.
- */
- sp->lno = rm.lno;
- if (F_ISSET(sp, SC_VI)) {
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- }
- return (0);
- case R_ARG:
- name = sp->frp->name;
- break;
- case R_EXPANDARG:
- if (argv_exp2(sp, cmdp, arg, arglen))
- return (1);
- /*
- * 0 args: impossible.
- * 1 args: impossible (I hope).
- * 2 args: read it.
- * >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.
- */
- switch (cmdp->argc) {
- case 0:
- case 1:
- abort();
- /* NOTREACHED */
- case 2:
- name = cmdp->argv[1]->bp;
- /*
- * !!!
- * Historically, the read and write commands renamed
- * "unnamed" files, or, if the file had a name, set
- * the alternate file name.
- */
- if (F_ISSET(sp->frp, FR_TMPFILE) &&
- !F_ISSET(sp->frp, FR_EXNAMED)) {
- if ((p = v_strdup(sp, cmdp->argv[1]->bp,
- cmdp->argv[1]->len)) != NULL) {
- free(sp->frp->name);
- sp->frp->name = p;
- }
- /*
- * The file has a real name, it's no longer a
- * temporary, clear the temporary file flags.
- */
- F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
- F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
-
- /* Notify the screen. */
- (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
- } else
- set_alt_name(sp, name);
- break;
- default:
- ex_emsg(sp, cmdp->argv[0]->bp, EXM_FILECOUNT);
- return (1);
-
- }
- break;
- }
-
- /*
- * !!!
- * Historically, vi did not permit reads from non-regular files, nor
- * did it distinguish between "read !" and "read!", so there was no
- * way to "force" it. We permit reading from named pipes too, since
- * they didn't exist when the original implementation of vi was done
- * and they seem a reasonable addition.
- */
- if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) {
- msgq_str(sp, M_SYSERR, name, "%s");
- return (1);
- }
- if (!S_ISFIFO(sb.st_mode) && !S_ISREG(sb.st_mode)) {
- (void)fclose(fp);
- msgq(sp, M_ERR,
- "145|Only regular files and named pipes may be read");
- return (1);
- }
-
- /* Try and get a lock. */
- if (file_lock(sp, NULL, NULL, fileno(fp), 0) == LOCK_UNAVAIL)
- msgq(sp, M_ERR, "146|%s: read lock was unavailable", name);
-
- rval = ex_readfp(sp, name, fp, &cmdp->addr1, &nlines, 0);
-
- /*
- * In vi, set the cursor to the first line read in, if anything read
- * in, otherwise, the address. (Historic vi set it to the line after
- * the address regardless, but since that line may not exist we don't
- * bother.)
- *
- * In ex, set the cursor to the last line read in, if anything read in,
- * otherwise, the address.
- */
- if (F_ISSET(sp, SC_VI)) {
- sp->lno = cmdp->addr1.lno;
- if (nlines)
- ++sp->lno;
- } else
- sp->lno = cmdp->addr1.lno + nlines;
- return (rval);
-}
-
-/*
- * ex_readfp --
- * Read lines into the file.
- *
- * PUBLIC: int ex_readfp __P((SCR *, char *, FILE *, MARK *, recno_t *, int));
- */
-int
-ex_readfp(sp, name, fp, fm, nlinesp, silent)
- SCR *sp;
- char *name;
- FILE *fp;
- MARK *fm;
- recno_t *nlinesp;
- int silent;
-{
- EX_PRIVATE *exp;
- GS *gp;
- recno_t lcnt, lno;
- size_t len;
- u_long ccnt; /* XXX: can't print off_t portably. */
- int nf, rval;
- char *p;
-
- gp = sp->gp;
- exp = EXP(sp);
-
- /*
- * Add in the lines from the output. Insertion starts at the line
- * following the address.
- */
- ccnt = 0;
- lcnt = 0;
- p = "147|Reading...";
- for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) {
- if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
- if (INTERRUPTED(sp))
- break;
- if (!silent) {
- gp->scr_busy(sp, p,
- p == NULL ? BUSY_UPDATE : BUSY_ON);
- p = NULL;
- }
- }
- if (db_append(sp, 1, lno, exp->ibp, len))
- goto err;
- ccnt += len;
- }
-
- if (ferror(fp) || fclose(fp))
- goto err;
-
- /* Return the number of lines read in. */
- if (nlinesp != NULL)
- *nlinesp = lcnt;
-
- if (!silent) {
- p = msg_print(sp, name, &nf);
- msgq(sp, M_INFO,
- "148|%s: %lu lines, %lu characters", p, lcnt, ccnt);
- if (nf)
- FREE_SPACE(sp, p, 0);
- }
-
- rval = 0;
- if (0) {
-err: msgq_str(sp, M_SYSERR, name, "%s");
- (void)fclose(fp);
- rval = 1;
- }
-
- if (!silent)
- gp->scr_busy(sp, NULL, BUSY_OFF);
- return (rval);
-}
diff --git a/contrib/nvi/ex/ex_screen.c b/contrib/nvi/ex/ex_screen.c
deleted file mode 100644
index 9bc5bf0..0000000
--- a/contrib/nvi/ex/ex_screen.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_screen.c 10.11 (Berkeley) 6/29/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-/*
- * ex_bg -- :bg
- * Hide the screen.
- *
- * PUBLIC: int ex_bg __P((SCR *, EXCMD *));
- */
-int
-ex_bg(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (vs_bg(sp));
-}
-
-/*
- * ex_fg -- :fg [file]
- * Show the screen.
- *
- * PUBLIC: int ex_fg __P((SCR *, EXCMD *));
- */
-int
-ex_fg(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- SCR *nsp;
- int newscreen;
-
- newscreen = F_ISSET(cmdp, E_NEWSCREEN);
- if (vs_fg(sp, &nsp, cmdp->argc ? cmdp->argv[0]->bp : NULL, newscreen))
- return (1);
-
- /* Set up the switch. */
- if (newscreen) {
- sp->nextdisp = nsp;
- F_SET(sp, SC_SSWITCH);
- }
- return (0);
-}
-
-/*
- * ex_resize -- :resize [+-]rows
- * Change the screen size.
- *
- * PUBLIC: int ex_resize __P((SCR *, EXCMD *));
- */
-int
-ex_resize(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- adj_t adj;
-
- switch (FL_ISSET(cmdp->iflags,
- E_C_COUNT | E_C_COUNT_NEG | E_C_COUNT_POS)) {
- case E_C_COUNT:
- adj = A_SET;
- break;
- case E_C_COUNT | E_C_COUNT_NEG:
- adj = A_DECREASE;
- break;
- case E_C_COUNT | E_C_COUNT_POS:
- adj = A_INCREASE;
- break;
- default:
- ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
- return (vs_resize(sp, cmdp->count, adj));
-}
-
-/*
- * ex_sdisplay --
- * Display the list of screens.
- *
- * PUBLIC: int ex_sdisplay __P((SCR *));
- */
-int
-ex_sdisplay(sp)
- SCR *sp;
-{
- GS *gp;
- SCR *tsp;
- int cnt, col, len, sep;
-
- gp = sp->gp;
- if ((tsp = gp->hq.cqh_first) == (void *)&gp->hq) {
- msgq(sp, M_INFO, "149|No background screens to display");
- return (0);
- }
-
- col = len = sep = 0;
- for (cnt = 1; tsp != (void *)&gp->hq && !INTERRUPTED(sp);
- tsp = tsp->q.cqe_next) {
- col += len = strlen(tsp->frp->name) + sep;
- if (col >= sp->cols - 1) {
- col = len;
- sep = 0;
- (void)ex_puts(sp, "\n");
- } else if (cnt != 1) {
- sep = 1;
- (void)ex_puts(sp, " ");
- }
- (void)ex_puts(sp, tsp->frp->name);
- ++cnt;
- }
- if (!INTERRUPTED(sp))
- (void)ex_puts(sp, "\n");
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_script.c b/contrib/nvi/ex/ex_script.c
deleted file mode 100644
index 9ca6d60..0000000
--- a/contrib/nvi/ex/ex_script.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Brian Hirt.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_script.c 10.30 (Berkeley) 9/24/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/queue.h>
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#include <sys/stat.h>
-#ifdef HAVE_SYS5_PTY
-#include <sys/stropts.h>
-#endif
-#include <sys/time.h>
-#include <sys/wait.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h> /* XXX: OSF/1 bug: include before <grp.h> */
-#include <grp.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-#include "script.h"
-#include "pathnames.h"
-
-static void sscr_check __P((SCR *));
-static int sscr_getprompt __P((SCR *));
-static int sscr_init __P((SCR *));
-static int sscr_insert __P((SCR *));
-static int sscr_matchprompt __P((SCR *, char *, size_t, size_t *));
-static int sscr_pty __P((int *, int *, char *, struct termios *, void *));
-static int sscr_setprompt __P((SCR *, char *, size_t));
-
-/*
- * ex_script -- : sc[ript][!] [file]
- * Switch to script mode.
- *
- * PUBLIC: int ex_script __P((SCR *, EXCMD *));
- */
-int
-ex_script(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- /* Vi only command. */
- if (!F_ISSET(sp, SC_VI)) {
- msgq(sp, M_ERR,
- "150|The script command is only available in vi mode");
- return (1);
- }
-
- /* Switch to the new file. */
- if (cmdp->argc != 0 && ex_edit(sp, cmdp))
- return (1);
-
- /* Create the shell, figure out the prompt. */
- if (sscr_init(sp))
- return (1);
-
- return (0);
-}
-
-/*
- * sscr_init --
- * Create a pty setup for a shell.
- */
-static int
-sscr_init(sp)
- SCR *sp;
-{
- SCRIPT *sc;
- char *sh, *sh_path;
-
- /* We're going to need a shell. */
- if (opts_empty(sp, O_SHELL, 0))
- return (1);
-
- MALLOC_RET(sp, sc, SCRIPT *, sizeof(SCRIPT));
- sp->script = sc;
- sc->sh_prompt = NULL;
- sc->sh_prompt_len = 0;
-
- /*
- * There are two different processes running through this code.
- * They are the shell and the parent.
- */
- sc->sh_master = sc->sh_slave = -1;
-
- if (tcgetattr(STDIN_FILENO, &sc->sh_term) == -1) {
- msgq(sp, M_SYSERR, "tcgetattr");
- goto err;
- }
-
- /*
- * Turn off output postprocessing and echo.
- */
- sc->sh_term.c_oflag &= ~OPOST;
- sc->sh_term.c_cflag &= ~(ECHO|ECHOE|ECHONL|ECHOK);
-
-#ifdef TIOCGWINSZ
- if (ioctl(STDIN_FILENO, TIOCGWINSZ, &sc->sh_win) == -1) {
- msgq(sp, M_SYSERR, "tcgetattr");
- goto err;
- }
-
- if (sscr_pty(&sc->sh_master,
- &sc->sh_slave, sc->sh_name, &sc->sh_term, &sc->sh_win) == -1) {
- msgq(sp, M_SYSERR, "pty");
- goto err;
- }
-#else
- if (sscr_pty(&sc->sh_master,
- &sc->sh_slave, sc->sh_name, &sc->sh_term, NULL) == -1) {
- msgq(sp, M_SYSERR, "pty");
- goto err;
- }
-#endif
-
- /*
- * __TK__ huh?
- * Don't use vfork() here, because the signal semantics differ from
- * implementation to implementation.
- */
- switch (sc->sh_pid = fork()) {
- case -1: /* Error. */
- msgq(sp, M_SYSERR, "fork");
-err: if (sc->sh_master != -1)
- (void)close(sc->sh_master);
- if (sc->sh_slave != -1)
- (void)close(sc->sh_slave);
- return (1);
- case 0: /* Utility. */
- /*
- * XXX
- * So that shells that do command line editing turn it off.
- */
- (void)setenv("TERM", "emacs", 1);
- (void)setenv("TERMCAP", "emacs:", 1);
- (void)setenv("EMACS", "t", 1);
-
- (void)setsid();
-#ifdef TIOCSCTTY
- /*
- * 4.4BSD allocates a controlling terminal using the TIOCSCTTY
- * ioctl, not by opening a terminal device file. POSIX 1003.1
- * doesn't define a portable way to do this. If TIOCSCTTY is
- * not available, hope that the open does it.
- */
- (void)ioctl(sc->sh_slave, TIOCSCTTY, 0);
-#endif
- (void)close(sc->sh_master);
- (void)dup2(sc->sh_slave, STDIN_FILENO);
- (void)dup2(sc->sh_slave, STDOUT_FILENO);
- (void)dup2(sc->sh_slave, STDERR_FILENO);
- (void)close(sc->sh_slave);
-
- /* Assumes that all shells have -i. */
- sh_path = O_STR(sp, O_SHELL);
- if ((sh = strrchr(sh_path, '/')) == NULL)
- sh = sh_path;
- else
- ++sh;
- execl(sh_path, sh, "-i", NULL);
- msgq_str(sp, M_SYSERR, sh_path, "execl: %s");
- _exit(127);
- default: /* Parent. */
- break;
- }
-
- if (sscr_getprompt(sp))
- return (1);
-
- F_SET(sp, SC_SCRIPT);
- F_SET(sp->gp, G_SCRWIN);
- return (0);
-}
-
-/*
- * sscr_getprompt --
- * Eat lines printed by the shell until a line with no trailing
- * carriage return comes; set the prompt from that line.
- */
-static int
-sscr_getprompt(sp)
- SCR *sp;
-{
- struct timeval tv;
- CHAR_T *endp, *p, *t, buf[1024];
- SCRIPT *sc;
- fd_set fdset;
- recno_t lline;
- size_t llen, len;
- u_int value;
- int nr;
-
- FD_ZERO(&fdset);
- endp = buf;
- len = sizeof(buf);
-
- /* Wait up to a second for characters to read. */
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- sc = sp->script;
- FD_SET(sc->sh_master, &fdset);
- switch (select(sc->sh_master + 1, &fdset, NULL, NULL, &tv)) {
- case -1: /* Error or interrupt. */
- msgq(sp, M_SYSERR, "select");
- goto prompterr;
- case 0: /* Timeout */
- msgq(sp, M_ERR, "Error: timed out");
- goto prompterr;
- case 1: /* Characters to read. */
- break;
- }
-
- /* Read the characters. */
-more: len = sizeof(buf) - (endp - buf);
- switch (nr = read(sc->sh_master, endp, len)) {
- case 0: /* EOF. */
- msgq(sp, M_ERR, "Error: shell: EOF");
- goto prompterr;
- case -1: /* Error or interrupt. */
- msgq(sp, M_SYSERR, "shell");
- goto prompterr;
- default:
- endp += nr;
- break;
- }
-
- /* If any complete lines, push them into the file. */
- for (p = t = buf; p < endp; ++p) {
- value = KEY_VAL(sp, *p);
- if (value == K_CR || value == K_NL) {
- if (db_last(sp, &lline) ||
- db_append(sp, 0, lline, t, p - t))
- goto prompterr;
- t = p + 1;
- }
- }
- if (p > buf) {
- memmove(buf, t, endp - t);
- endp = buf + (endp - t);
- }
- if (endp == buf)
- goto more;
-
- /* Wait up 1/10 of a second to make sure that we got it all. */
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
- switch (select(sc->sh_master + 1, &fdset, NULL, NULL, &tv)) {
- case -1: /* Error or interrupt. */
- msgq(sp, M_SYSERR, "select");
- goto prompterr;
- case 0: /* Timeout */
- break;
- case 1: /* Characters to read. */
- goto more;
- }
-
- /* Timed out, so theoretically we have a prompt. */
- llen = endp - buf;
- endp = buf;
-
- /* Append the line into the file. */
- if (db_last(sp, &lline) || db_append(sp, 0, lline, buf, llen)) {
-prompterr: sscr_end(sp);
- return (1);
- }
-
- return (sscr_setprompt(sp, buf, llen));
-}
-
-/*
- * sscr_exec --
- * Take a line and hand it off to the shell.
- *
- * PUBLIC: int sscr_exec __P((SCR *, recno_t));
- */
-int
-sscr_exec(sp, lno)
- SCR *sp;
- recno_t lno;
-{
- SCRIPT *sc;
- recno_t last_lno;
- size_t blen, len, last_len, tlen;
- int isempty, matchprompt, nw, rval;
- char *bp, *p;
-
- /* If there's a prompt on the last line, append the command. */
- if (db_last(sp, &last_lno))
- return (1);
- if (db_get(sp, last_lno, DBG_FATAL, &p, &last_len))
- return (1);
- if (sscr_matchprompt(sp, p, last_len, &tlen) && tlen == 0) {
- matchprompt = 1;
- GET_SPACE_RET(sp, bp, blen, last_len + 128);
- memmove(bp, p, last_len);
- } else
- matchprompt = 0;
-
- /* Get something to execute. */
- if (db_eget(sp, lno, &p, &len, &isempty)) {
- if (isempty)
- goto empty;
- goto err1;
- }
-
- /* Empty lines aren't interesting. */
- if (len == 0)
- goto empty;
-
- /* Delete any prompt. */
- if (sscr_matchprompt(sp, p, len, &tlen)) {
- if (tlen == len) {
-empty: msgq(sp, M_BERR, "151|No command to execute");
- goto err1;
- }
- p += (len - tlen);
- len = tlen;
- }
-
- /* Push the line to the shell. */
- sc = sp->script;
- if ((nw = write(sc->sh_master, p, len)) != len)
- goto err2;
- rval = 0;
- if (write(sc->sh_master, "\n", 1) != 1) {
-err2: if (nw == 0)
- errno = EIO;
- msgq(sp, M_SYSERR, "shell");
- goto err1;
- }
-
- if (matchprompt) {
- ADD_SPACE_RET(sp, bp, blen, last_len + len);
- memmove(bp + last_len, p, len);
- if (db_set(sp, last_lno, bp, last_len + len))
-err1: rval = 1;
- }
- if (matchprompt)
- FREE_SPACE(sp, bp, blen);
- return (rval);
-}
-
-/*
- * sscr_input --
- * Read any waiting shell input.
- *
- * PUBLIC: int sscr_input __P((SCR *));
- */
-int
-sscr_input(sp)
- SCR *sp;
-{
- GS *gp;
- struct timeval poll;
- fd_set rdfd;
- int maxfd;
-
- gp = sp->gp;
-
-loop: maxfd = 0;
- FD_ZERO(&rdfd);
- poll.tv_sec = 0;
- poll.tv_usec = 0;
-
- /* Set up the input mask. */
- for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
- if (F_ISSET(sp, SC_SCRIPT)) {
- FD_SET(sp->script->sh_master, &rdfd);
- if (sp->script->sh_master > maxfd)
- maxfd = sp->script->sh_master;
- }
-
- /* Check for input. */
- switch (select(maxfd + 1, &rdfd, NULL, NULL, &poll)) {
- case -1:
- msgq(sp, M_SYSERR, "select");
- return (1);
- case 0:
- return (0);
- default:
- break;
- }
-
- /* Read the input. */
- for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
- if (F_ISSET(sp, SC_SCRIPT) &&
- FD_ISSET(sp->script->sh_master, &rdfd) && sscr_insert(sp))
- return (1);
- goto loop;
-}
-
-/*
- * sscr_insert --
- * Take a line from the shell and insert it into the file.
- */
-static int
-sscr_insert(sp)
- SCR *sp;
-{
- struct timeval tv;
- CHAR_T *endp, *p, *t;
- SCRIPT *sc;
- fd_set rdfd;
- recno_t lno;
- size_t blen, len, tlen;
- u_int value;
- int nr, rval;
- char *bp;
-
- /* Find out where the end of the file is. */
- if (db_last(sp, &lno))
- return (1);
-
-#define MINREAD 1024
- GET_SPACE_RET(sp, bp, blen, MINREAD);
- endp = bp;
-
- /* Read the characters. */
- rval = 1;
- sc = sp->script;
-more: switch (nr = read(sc->sh_master, endp, MINREAD)) {
- case 0: /* EOF; shell just exited. */
- sscr_end(sp);
- rval = 0;
- goto ret;
- case -1: /* Error or interrupt. */
- msgq(sp, M_SYSERR, "shell");
- goto ret;
- default:
- endp += nr;
- break;
- }
-
- /* Append the lines into the file. */
- for (p = t = bp; p < endp; ++p) {
- value = KEY_VAL(sp, *p);
- if (value == K_CR || value == K_NL) {
- len = p - t;
- if (db_append(sp, 1, lno++, t, len))
- goto ret;
- t = p + 1;
- }
- }
- if (p > t) {
- len = p - t;
- /*
- * If the last thing from the shell isn't another prompt, wait
- * up to 1/10 of a second for more stuff to show up, so that
- * we don't break the output into two separate lines. Don't
- * want to hang indefinitely because some program is hanging,
- * confused the shell, or whatever.
- */
- if (!sscr_matchprompt(sp, t, len, &tlen) || tlen != 0) {
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
- FD_ZERO(&rdfd);
- FD_SET(sc->sh_master, &rdfd);
- if (select(sc->sh_master + 1,
- &rdfd, NULL, NULL, &tv) == 1) {
- memmove(bp, t, len);
- endp = bp + len;
- goto more;
- }
- }
- if (sscr_setprompt(sp, t, len))
- return (1);
- if (db_append(sp, 1, lno++, t, len))
- goto ret;
- }
-
- /* The cursor moves to EOF. */
- sp->lno = lno;
- sp->cno = len ? len - 1 : 0;
- rval = vs_refresh(sp, 1);
-
-ret: FREE_SPACE(sp, bp, blen);
- return (rval);
-}
-
-/*
- * sscr_setprompt --
- *
- * Set the prompt to the last line we got from the shell.
- *
- */
-static int
-sscr_setprompt(sp, buf, len)
- SCR *sp;
- char *buf;
- size_t len;
-{
- SCRIPT *sc;
-
- sc = sp->script;
- if (sc->sh_prompt)
- free(sc->sh_prompt);
- MALLOC(sp, sc->sh_prompt, char *, len + 1);
- if (sc->sh_prompt == NULL) {
- sscr_end(sp);
- return (1);
- }
- memmove(sc->sh_prompt, buf, len);
- sc->sh_prompt_len = len;
- sc->sh_prompt[len] = '\0';
- return (0);
-}
-
-/*
- * sscr_matchprompt --
- * Check to see if a line matches the prompt. Nul's indicate
- * parts that can change, in both content and size.
- */
-static int
-sscr_matchprompt(sp, lp, line_len, lenp)
- SCR *sp;
- char *lp;
- size_t line_len, *lenp;
-{
- SCRIPT *sc;
- size_t prompt_len;
- char *pp;
-
- sc = sp->script;
- if (line_len < (prompt_len = sc->sh_prompt_len))
- return (0);
-
- for (pp = sc->sh_prompt;
- prompt_len && line_len; --prompt_len, --line_len) {
- if (*pp == '\0') {
- for (; prompt_len && *pp == '\0'; --prompt_len, ++pp);
- if (!prompt_len)
- return (0);
- for (; line_len && *lp != *pp; --line_len, ++lp);
- if (!line_len)
- return (0);
- }
- if (*pp++ != *lp++)
- break;
- }
-
- if (prompt_len)
- return (0);
- if (lenp != NULL)
- *lenp = line_len;
- return (1);
-}
-
-/*
- * sscr_end --
- * End the pipe to a shell.
- *
- * PUBLIC: int sscr_end __P((SCR *));
- */
-int
-sscr_end(sp)
- SCR *sp;
-{
- SCRIPT *sc;
-
- if ((sc = sp->script) == NULL)
- return (0);
-
- /* Turn off the script flags. */
- F_CLR(sp, SC_SCRIPT);
- sscr_check(sp);
-
- /* Close down the parent's file descriptors. */
- if (sc->sh_master != -1)
- (void)close(sc->sh_master);
- if (sc->sh_slave != -1)
- (void)close(sc->sh_slave);
-
- /* This should have killed the child. */
- (void)proc_wait(sp, (long)sc->sh_pid, "script-shell", 0, 0);
-
- /* Free memory. */
- free(sc->sh_prompt);
- free(sc);
- sp->script = NULL;
-
- return (0);
-}
-
-/*
- * sscr_check --
- * Set/clear the global scripting bit.
- */
-static void
-sscr_check(sp)
- SCR *sp;
-{
- GS *gp;
-
- gp = sp->gp;
- for (sp = gp->dq.cqh_first; sp != (void *)&gp->dq; sp = sp->q.cqe_next)
- if (F_ISSET(sp, SC_SCRIPT)) {
- F_SET(gp, G_SCRWIN);
- return;
- }
- F_CLR(gp, G_SCRWIN);
-}
-
-#ifdef HAVE_SYS5_PTY
-static int ptys_open __P((int, char *));
-static int ptym_open __P((char *));
-
-static int
-sscr_pty(amaster, aslave, name, termp, winp)
- int *amaster, *aslave;
- char *name;
- struct termios *termp;
- void *winp;
-{
- int master, slave, ttygid;
-
- /* open master terminal */
- if ((master = ptym_open(name)) < 0) {
- errno = ENOENT; /* out of ptys */
- return (-1);
- }
-
- /* open slave terminal */
- if ((slave = ptys_open(master, name)) >= 0) {
- *amaster = master;
- *aslave = slave;
- } else {
- errno = ENOENT; /* out of ptys */
- return (-1);
- }
-
- if (termp)
- (void) tcsetattr(slave, TCSAFLUSH, termp);
-#ifdef TIOCSWINSZ
- if (winp != NULL)
- (void) ioctl(slave, TIOCSWINSZ, (struct winsize *)winp);
-#endif
- return (0);
-}
-
-/*
- * ptym_open --
- * This function opens a master pty and returns the file descriptor
- * to it. pts_name is also returned which is the name of the slave.
- */
-static int
-ptym_open(pts_name)
- char *pts_name;
-{
- int fdm;
- char *ptr, *ptsname();
-
- strcpy(pts_name, _PATH_SYSV_PTY);
- if ((fdm = open(pts_name, O_RDWR)) < 0 )
- return (-1);
-
- if (grantpt(fdm) < 0) {
- close(fdm);
- return (-2);
- }
-
- if (unlockpt(fdm) < 0) {
- close(fdm);
- return (-3);
- }
-
- if (unlockpt(fdm) < 0) {
- close(fdm);
- return (-3);
- }
-
- /* get slave's name */
- if ((ptr = ptsname(fdm)) == NULL) {
- close(fdm);
- return (-3);
- }
- strcpy(pts_name, ptr);
- return (fdm);
-}
-
-/*
- * ptys_open --
- * This function opens the slave pty.
- */
-static int
-ptys_open(fdm, pts_name)
- int fdm;
- char *pts_name;
-{
- int fds;
-
- if ((fds = open(pts_name, O_RDWR)) < 0) {
- close(fdm);
- return (-5);
- }
-
- if (ioctl(fds, I_PUSH, "ptem") < 0) {
- close(fds);
- close(fdm);
- return (-6);
- }
-
- if (ioctl(fds, I_PUSH, "ldterm") < 0) {
- close(fds);
- close(fdm);
- return (-7);
- }
-
- if (ioctl(fds, I_PUSH, "ttcompat") < 0) {
- close(fds);
- close(fdm);
- return (-8);
- }
-
- return (fds);
-}
-
-#else /* !HAVE_SYS5_PTY */
-
-static int
-sscr_pty(amaster, aslave, name, termp, winp)
- int *amaster, *aslave;
- char *name;
- struct termios *termp;
- void *winp;
-{
- static char line[] = "/dev/ptyXX";
- register char *cp1, *cp2;
- register int master, slave, ttygid;
- struct group *gr;
-
- if ((gr = getgrnam("tty")) != NULL)
- ttygid = gr->gr_gid;
- else
- ttygid = -1;
-
- for (cp1 = "pqrs"; *cp1; cp1++) {
- line[8] = *cp1;
- for (cp2 = "0123456789abcdef"; *cp2; cp2++) {
- line[5] = 'p';
- line[9] = *cp2;
- if ((master = open(line, O_RDWR, 0)) == -1) {
- if (errno == ENOENT)
- return (-1); /* out of ptys */
- } else {
- line[5] = 't';
- (void) chown(line, getuid(), ttygid);
- (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
-#ifdef HAVE_REVOKE
- (void) revoke(line);
-#endif
- if ((slave = open(line, O_RDWR, 0)) != -1) {
- *amaster = master;
- *aslave = slave;
- if (name)
- strcpy(name, line);
- if (termp)
- (void) tcsetattr(slave,
- TCSAFLUSH, termp);
-#ifdef TIOCSWINSZ
- if (winp)
- (void) ioctl(slave, TIOCSWINSZ,
- (char *)winp);
-#endif
- return (0);
- }
- (void) close(master);
- }
- }
- }
- errno = ENOENT; /* out of ptys */
- return (-1);
-}
-#endif /* HAVE_SYS5_PTY */
diff --git a/contrib/nvi/ex/ex_set.c b/contrib/nvi/ex/ex_set.c
deleted file mode 100644
index 11e9297..0000000
--- a/contrib/nvi/ex/ex_set.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_set.c 10.7 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_set -- :set
- * Ex set option.
- *
- * PUBLIC: int ex_set __P((SCR *, EXCMD *));
- */
-int
-ex_set(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- switch(cmdp->argc) {
- case 0:
- opts_dump(sp, CHANGED_DISPLAY);
- break;
- default:
- if (opts_set(sp, cmdp->argv, cmdp->cmd->usage))
- return (1);
- break;
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_shell.c b/contrib/nvi/ex/ex_shell.c
deleted file mode 100644
index 9516803..0000000
--- a/contrib/nvi/ex/ex_shell.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_shell.c 10.38 (Berkeley) 8/19/96";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/wait.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-static const char *sigmsg __P((int));
-
-/*
- * ex_shell -- :sh[ell]
- * Invoke the program named in the SHELL environment variable
- * with the argument -i.
- *
- * PUBLIC: int ex_shell __P((SCR *, EXCMD *));
- */
-int
-ex_shell(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- int rval;
- char buf[MAXPATHLEN];
-
- /* We'll need a shell. */
- if (opts_empty(sp, O_SHELL, 0))
- return (1);
-
- /*
- * XXX
- * Assumes all shells use -i.
- */
- (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL));
-
- /* Restore the window name. */
- (void)sp->gp->scr_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)sp->gp->scr_rename(sp, sp->frp->name, 1);
-
- /*
- * !!!
- * Historically, vi didn't require a continue message after the
- * return of the shell. Match it.
- */
- F_SET(sp, SC_EX_WAIT_NO);
-
- return (rval);
-}
-
-/*
- * ex_exec_proc --
- * Run a separate process.
- *
- * PUBLIC: int ex_exec_proc __P((SCR *, EXCMD *, char *, const char *, int));
- */
-int
-ex_exec_proc(sp, cmdp, cmd, msg, need_newline)
- SCR *sp;
- EXCMD *cmdp;
- char *cmd;
- const char *msg;
- int need_newline;
-{
- GS *gp;
- const char *name;
- pid_t pid;
-
- gp = sp->gp;
-
- /* We'll need a shell. */
- if (opts_empty(sp, O_SHELL, 0))
- return (1);
-
- /* Enter ex mode. */
- if (F_ISSET(sp, SC_VI)) {
- if (gp->scr_screen(sp, SC_EX)) {
- ex_emsg(sp, cmdp->cmd->name, EXM_NOCANON);
- return (1);
- }
- (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
- F_SET(sp, SC_SCR_EX | SC_SCR_EXWROTE);
- }
-
- /* Put out additional newline, message. */
- if (need_newline)
- (void)ex_puts(sp, "\n");
- if (msg != NULL) {
- (void)ex_puts(sp, msg);
- (void)ex_puts(sp, "\n");
- }
- (void)ex_fflush(sp);
-
- switch (pid = vfork()) {
- case -1: /* Error. */
- msgq(sp, M_SYSERR, "vfork");
- return (1);
- case 0: /* Utility. */
- if ((name = strrchr(O_STR(sp, O_SHELL), '/')) == NULL)
- name = O_STR(sp, O_SHELL);
- else
- ++name;
- execl(O_STR(sp, O_SHELL), name, "-c", cmd, NULL);
- msgq_str(sp, M_SYSERR, O_STR(sp, O_SHELL), "execl: %s");
- _exit(127);
- /* NOTREACHED */
- default: /* Parent. */
- return (proc_wait(sp, (long)pid, cmd, 0, 0));
- }
- /* NOTREACHED */
-}
-
-/*
- * proc_wait --
- * Wait for one of the processes.
- *
- * !!!
- * The pid_t type varies in size from a short to a long depending on the
- * system. It has to be cast into something or the standard promotion
- * rules get you. I'm using a long based on the belief that nobody is
- * going to make it unsigned and it's unlikely to be a quad.
- *
- * PUBLIC: int proc_wait __P((SCR *, long, const char *, int, int));
- */
-int
-proc_wait(sp, pid, cmd, silent, okpipe)
- SCR *sp;
- long pid;
- const char *cmd;
- int silent, okpipe;
-{
- size_t len;
- int nf, pstat;
- char *p;
-
- /* Wait for the utility, ignoring interruptions. */
- for (;;) {
- errno = 0;
- if (waitpid((pid_t)pid, &pstat, 0) != -1)
- break;
- if (errno != EINTR) {
- msgq(sp, M_SYSERR, "waitpid");
- return (1);
- }
- }
-
- /*
- * Display the utility's exit status. Ignore SIGPIPE from the
- * parent-writer, as that only means that the utility chose to
- * exit before reading all of its input.
- */
- if (WIFSIGNALED(pstat) && (!okpipe || WTERMSIG(pstat) != SIGPIPE)) {
- for (; isblank(*cmd); ++cmd);
- p = msg_print(sp, cmd, &nf);
- len = strlen(p);
- msgq(sp, M_ERR, "%.*s%s: received signal: %s%s",
- MIN(len, 20), p, len > 20 ? " ..." : "",
- sigmsg(WTERMSIG(pstat)),
- WCOREDUMP(pstat) ? "; core dumped" : "");
- if (nf)
- FREE_SPACE(sp, p, 0);
- return (1);
- }
-
- if (WIFEXITED(pstat) && WEXITSTATUS(pstat)) {
- /*
- * Remain silent for "normal" errors when doing shell file
- * name expansions, they almost certainly indicate nothing
- * more than a failure to match.
- *
- * Remain silent for vi read filter errors. It's historic
- * practice.
- */
- if (!silent) {
- for (; isblank(*cmd); ++cmd);
- p = msg_print(sp, cmd, &nf);
- len = strlen(p);
- msgq(sp, M_ERR, "%.*s%s: exited with status %d",
- MIN(len, 20), p, len > 20 ? " ..." : "",
- WEXITSTATUS(pstat));
- if (nf)
- FREE_SPACE(sp, p, 0);
- }
- return (1);
- }
- return (0);
-}
-
-/*
- * XXX
- * The sys_siglist[] table in the C library has this information, but there's
- * no portable way to get to it. (Believe me, I tried.)
- */
-typedef struct _sigs {
- int number; /* signal number */
- char *message; /* related message */
-} SIGS;
-
-SIGS const sigs[] = {
-#ifdef SIGABRT
- SIGABRT, "Abort trap",
-#endif
-#ifdef SIGALRM
- SIGALRM, "Alarm clock",
-#endif
-#ifdef SIGBUS
- SIGBUS, "Bus error",
-#endif
-#ifdef SIGCLD
- SIGCLD, "Child exited or stopped",
-#endif
-#ifdef SIGCHLD
- SIGCHLD, "Child exited",
-#endif
-#ifdef SIGCONT
- SIGCONT, "Continued",
-#endif
-#ifdef SIGDANGER
- SIGDANGER, "System crash imminent",
-#endif
-#ifdef SIGEMT
- SIGEMT, "EMT trap",
-#endif
-#ifdef SIGFPE
- SIGFPE, "Floating point exception",
-#endif
-#ifdef SIGGRANT
- SIGGRANT, "HFT monitor mode granted",
-#endif
-#ifdef SIGHUP
- SIGHUP, "Hangup",
-#endif
-#ifdef SIGILL
- SIGILL, "Illegal instruction",
-#endif
-#ifdef SIGINFO
- SIGINFO, "Information request",
-#endif
-#ifdef SIGINT
- SIGINT, "Interrupt",
-#endif
-#ifdef SIGIO
- SIGIO, "I/O possible",
-#endif
-#ifdef SIGIOT
- SIGIOT, "IOT trap",
-#endif
-#ifdef SIGKILL
- SIGKILL, "Killed",
-#endif
-#ifdef SIGLOST
- SIGLOST, "Record lock",
-#endif
-#ifdef SIGMIGRATE
- SIGMIGRATE, "Migrate process to another CPU",
-#endif
-#ifdef SIGMSG
- SIGMSG, "HFT input data pending",
-#endif
-#ifdef SIGPIPE
- SIGPIPE, "Broken pipe",
-#endif
-#ifdef SIGPOLL
- SIGPOLL, "I/O possible",
-#endif
-#ifdef SIGPRE
- SIGPRE, "Programming error",
-#endif
-#ifdef SIGPROF
- SIGPROF, "Profiling timer expired",
-#endif
-#ifdef SIGPWR
- SIGPWR, "Power failure imminent",
-#endif
-#ifdef SIGRETRACT
- SIGRETRACT, "HFT monitor mode retracted",
-#endif
-#ifdef SIGQUIT
- SIGQUIT, "Quit",
-#endif
-#ifdef SIGSAK
- SIGSAK, "Secure Attention Key",
-#endif
-#ifdef SIGSEGV
- SIGSEGV, "Segmentation fault",
-#endif
-#ifdef SIGSOUND
- SIGSOUND, "HFT sound sequence completed",
-#endif
-#ifdef SIGSTOP
- SIGSTOP, "Suspended (signal)",
-#endif
-#ifdef SIGSYS
- SIGSYS, "Bad system call",
-#endif
-#ifdef SIGTERM
- SIGTERM, "Terminated",
-#endif
-#ifdef SIGTRAP
- SIGTRAP, "Trace/BPT trap",
-#endif
-#ifdef SIGTSTP
- SIGTSTP, "Suspended",
-#endif
-#ifdef SIGTTIN
- SIGTTIN, "Stopped (tty input)",
-#endif
-#ifdef SIGTTOU
- SIGTTOU, "Stopped (tty output)",
-#endif
-#ifdef SIGURG
- SIGURG, "Urgent I/O condition",
-#endif
-#ifdef SIGUSR1
- SIGUSR1, "User defined signal 1",
-#endif
-#ifdef SIGUSR2
- SIGUSR2, "User defined signal 2",
-#endif
-#ifdef SIGVTALRM
- SIGVTALRM, "Virtual timer expired",
-#endif
-#ifdef SIGWINCH
- SIGWINCH, "Window size changes",
-#endif
-#ifdef SIGXCPU
- SIGXCPU, "Cputime limit exceeded",
-#endif
-#ifdef SIGXFSZ
- SIGXFSZ, "Filesize limit exceeded",
-#endif
-};
-
-/*
- * sigmsg --
- * Return a pointer to a message describing a signal.
- */
-static const char *
-sigmsg(signo)
- int signo;
-{
- static char buf[40];
- const SIGS *sigp;
- int n;
-
- for (n = 0,
- sigp = &sigs[0]; n < sizeof(sigs) / sizeof(sigs[0]); ++n, ++sigp)
- if (sigp->number == signo)
- return (sigp->message);
- (void)snprintf(buf, sizeof(buf), "Unknown signal: %d", signo);
- return (buf);
-}
diff --git a/contrib/nvi/ex/ex_shift.c b/contrib/nvi/ex/ex_shift.c
deleted file mode 100644
index 83bd36d..0000000
--- a/contrib/nvi/ex/ex_shift.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_shift.c 10.11 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-enum which {LEFT, RIGHT};
-static int shift __P((SCR *, EXCMD *, enum which));
-
-/*
- * ex_shiftl -- :<[<...]
- *
- *
- * PUBLIC: int ex_shiftl __P((SCR *, EXCMD *));
- */
-int
-ex_shiftl(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (shift(sp, cmdp, LEFT));
-}
-
-/*
- * ex_shiftr -- :>[>...]
- *
- * PUBLIC: int ex_shiftr __P((SCR *, EXCMD *));
- */
-int
-ex_shiftr(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (shift(sp, cmdp, RIGHT));
-}
-
-/*
- * shift --
- * Ex shift support.
- */
-static int
-shift(sp, cmdp, rl)
- SCR *sp;
- EXCMD *cmdp;
- enum which rl;
-{
- recno_t from, to;
- size_t blen, len, newcol, newidx, oldcol, oldidx, sw;
- int curset;
- char *p, *bp, *tbp;
-
- NEEDFILE(sp, cmdp);
-
- if (O_VAL(sp, O_SHIFTWIDTH) == 0) {
- msgq(sp, M_INFO, "152|shiftwidth option set to 0");
- return (0);
- }
-
- /* Copy the lines being shifted into the unnamed buffer. */
- if (cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE))
- return (1);
-
- /*
- * The historic version of vi permitted the user to string any number
- * of '>' or '<' characters together, resulting in an indent of the
- * appropriate levels. There's a special hack in ex_cmd() so that
- * cmdp->argv[0] points to the string of '>' or '<' characters.
- *
- * Q: What's the difference between the people adding features
- * to vi and the Girl Scouts?
- * A: The Girl Scouts have mint cookies and adult supervision.
- */
- for (p = cmdp->argv[0]->bp, sw = 0; *p == '>' || *p == '<'; ++p)
- sw += O_VAL(sp, O_SHIFTWIDTH);
-
- GET_SPACE_RET(sp, bp, blen, 256);
-
- curset = 0;
- for (from = cmdp->addr1.lno, to = cmdp->addr2.lno; from <= to; ++from) {
- if (db_get(sp, from, DBG_FATAL, &p, &len))
- goto err;
- if (!len) {
- if (sp->lno == from)
- curset = 1;
- continue;
- }
-
- /*
- * Calculate the old indent amount and the number of
- * characters it used.
- */
- for (oldidx = 0, oldcol = 0; oldidx < len; ++oldidx)
- if (p[oldidx] == ' ')
- ++oldcol;
- else if (p[oldidx] == '\t')
- oldcol += O_VAL(sp, O_TABSTOP) -
- oldcol % O_VAL(sp, O_TABSTOP);
- else
- break;
-
- /* Calculate the new indent amount. */
- if (rl == RIGHT)
- newcol = oldcol + sw;
- else {
- newcol = oldcol < sw ? 0 : oldcol - sw;
- if (newcol == oldcol) {
- if (sp->lno == from)
- curset = 1;
- continue;
- }
- }
-
- /* Get a buffer that will hold the new line. */
- ADD_SPACE_RET(sp, bp, blen, newcol + len);
-
- /*
- * Build a new indent string and count the number of
- * characters it uses.
- */
- for (tbp = bp, newidx = 0;
- newcol >= O_VAL(sp, O_TABSTOP); ++newidx) {
- *tbp++ = '\t';
- newcol -= O_VAL(sp, O_TABSTOP);
- }
- for (; newcol > 0; --newcol, ++newidx)
- *tbp++ = ' ';
-
- /* Add the original line. */
- memcpy(tbp, p + oldidx, len - oldidx);
-
- /* Set the replacement line. */
- if (db_set(sp, from, bp, (tbp + (len - oldidx)) - bp)) {
-err: FREE_SPACE(sp, bp, blen);
- return (1);
- }
-
- /*
- * !!!
- * The shift command in historic vi had the usual bizarre
- * collection of cursor semantics. If called from vi, the
- * cursor was repositioned to the first non-blank character
- * of the lowest numbered line shifted. If called from ex,
- * the cursor was repositioned to the first non-blank of the
- * highest numbered line shifted. Here, if the cursor isn't
- * part of the set of lines that are moved, move it to the
- * first non-blank of the last line shifted. (This makes
- * ":3>>" in vi work reasonably.) If the cursor is part of
- * the shifted lines, it doesn't get moved at all. This
- * permits shifting of marked areas, i.e. ">'a." shifts the
- * marked area twice, something that couldn't be done with
- * historic vi.
- */
- if (sp->lno == from) {
- curset = 1;
- if (newidx > oldidx)
- sp->cno += newidx - oldidx;
- else if (sp->cno >= oldidx - newidx)
- sp->cno -= oldidx - newidx;
- }
- }
- if (!curset) {
- sp->lno = to;
- sp->cno = 0;
- (void)nonblank(sp, to, &sp->cno);
- }
-
- FREE_SPACE(sp, bp, blen);
-
- sp->rptlines[L_SHIFT] += cmdp->addr2.lno - cmdp->addr1.lno + 1;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_source.c b/contrib/nvi/ex/ex_source.c
deleted file mode 100644
index b52c527..0000000
--- a/contrib/nvi/ex/ex_source.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_source.c 10.12 (Berkeley) 8/10/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-/*
- * ex_source -- :source file
- * Execute ex commands from a file.
- *
- * PUBLIC: int ex_source __P((SCR *, EXCMD *));
- */
-int
-ex_source(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- struct stat sb;
- int fd, len;
- char *bp, *name;
-
- name = cmdp->argv[0]->bp;
- if ((fd = open(name, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
- goto err;
-
- /*
- * XXX
- * I'd like to test to see if the file is too large to malloc. Since
- * we don't know what size or type off_t's or size_t's are, what the
- * largest unsigned integral type is, or what random insanity the local
- * C compiler will perpetrate, doing the comparison in a portable way
- * is flatly impossible. So, put an fairly unreasonable limit on it,
- * I don't want to be dropping core here.
- */
-#define MEGABYTE 1048576
- if (sb.st_size > MEGABYTE) {
- errno = ENOMEM;
- goto err;
- }
-
- MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
- if (bp == NULL) {
- (void)close(fd);
- return (1);
- }
- bp[sb.st_size] = '\0';
-
- /* Read the file into memory. */
- len = read(fd, bp, (int)sb.st_size);
- (void)close(fd);
- if (len == -1 || len != sb.st_size) {
- if (len != sb.st_size)
- errno = EIO;
- free(bp);
-err: msgq_str(sp, M_SYSERR, name, "%s");
- return (1);
- }
-
- /* Put it on the ex queue. */
- return (ex_run_str(sp, name, bp, (size_t)sb.st_size, 1, 1));
-}
diff --git a/contrib/nvi/ex/ex_stop.c b/contrib/nvi/ex/ex_stop.c
deleted file mode 100644
index bc55fd2..0000000
--- a/contrib/nvi/ex/ex_stop.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_stop.c 10.10 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-/*
- * ex_stop -- :stop[!]
- * :suspend[!]
- * Suspend execution.
- *
- * PUBLIC: int ex_stop __P((SCR *, EXCMD *));
- */
-int
-ex_stop(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- int allowed;
-
- /* For some strange reason, the force flag turns off autowrite. */
- if (!FL_ISSET(cmdp->iflags, E_C_FORCE) && file_aw(sp, FS_ALL))
- return (1);
-
- if (sp->gp->scr_suspend(sp, &allowed))
- return (1);
- if (!allowed)
- ex_emsg(sp, NULL, EXM_NOSUSPEND);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_subst.c b/contrib/nvi/ex/ex_subst.c
deleted file mode 100644
index 0ebb81d..0000000
--- a/contrib/nvi/ex/ex_subst.c
+++ /dev/null
@@ -1,1459 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_subst.c 10.37 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-#define SUB_FIRST 0x01 /* The 'r' flag isn't reasonable. */
-#define SUB_MUSTSETR 0x02 /* The 'r' flag is required. */
-
-static int re_conv __P((SCR *, char **, size_t *, int *));
-static int re_cscope_conv __P((SCR *, char **, size_t *, int *));
-static int re_sub __P((SCR *,
- char *, char **, size_t *, size_t *, regmatch_t [10]));
-static int re_tag_conv __P((SCR *, char **, size_t *, int *));
-static int s __P((SCR *, EXCMD *, char *, regex_t *, u_int));
-
-/*
- * ex_s --
- * [line [,line]] s[ubstitute] [[/;]pat[/;]/repl[/;] [cgr] [count] [#lp]]
- *
- * Substitute on lines matching a pattern.
- *
- * PUBLIC: int ex_s __P((SCR *, EXCMD *));
- */
-int
-ex_s(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- regex_t *re;
- size_t blen, len;
- u_int flags;
- int delim;
- char *bp, *ptrn, *rep, *p, *t;
-
- /*
- * Skip leading white space.
- *
- * !!!
- * Historic vi allowed any non-alphanumeric to serve as the
- * substitution command delimiter.
- *
- * !!!
- * If the arguments are empty, it's the same as &, i.e. we
- * repeat the last substitution.
- */
- if (cmdp->argc == 0)
- goto subagain;
- for (p = cmdp->argv[0]->bp,
- len = cmdp->argv[0]->len; len > 0; --len, ++p) {
- if (!isblank(*p))
- break;
- }
- if (len == 0)
-subagain: return (ex_subagain(sp, cmdp));
-
- delim = *p++;
- if (isalnum(delim) || delim == '\\')
- return (s(sp, cmdp, p, &sp->subre_c, SUB_MUSTSETR));
-
- /*
- * !!!
- * The full-blown substitute command reset the remembered
- * state of the 'c' and 'g' suffices.
- */
- sp->c_suffix = sp->g_suffix = 0;
-
- /*
- * Get the pattern string, toss escaping characters.
- *
- * !!!
- * Historic vi accepted any of the following forms:
- *
- * :s/abc/def/ change "abc" to "def"
- * :s/abc/def change "abc" to "def"
- * :s/abc/ delete "abc"
- * :s/abc delete "abc"
- *
- * QUOTING NOTE:
- *
- * 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 escaping character is removed, but that's
- * not how the historic vi worked.
- */
- for (ptrn = t = p;;) {
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
- ++p;
- /*
- * !!!
- * Nul terminate the pattern string -- it's passed
- * to regcomp which doesn't understand anything else.
- */
- *t = '\0';
- break;
- }
- if (p[0] == '\\')
- if (p[1] == delim)
- ++p;
- else if (p[1] == '\\')
- *t++ = *p++;
- *t++ = *p++;
- }
-
- /*
- * If the pattern string is empty, use the last RE (not just the
- * last substitution RE).
- */
- if (*ptrn == '\0') {
- if (sp->re == NULL) {
- ex_emsg(sp, NULL, EXM_NOPREVRE);
- return (1);
- }
-
- /* Re-compile the RE if necessary. */
- if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
- sp->re, sp->re_len, NULL, NULL, &sp->re_c, RE_C_SEARCH))
- return (1);
- flags = 0;
- } else {
- /*
- * !!!
- * Compile the RE. Historic practice is that substitutes set
- * the search direction as well as both substitute and search
- * RE's. We compile the RE twice, as we don't want to bother
- * ref counting the pattern string and (opaque) structure.
- */
- if (re_compile(sp, ptrn, t - ptrn,
- &sp->re, &sp->re_len, &sp->re_c, RE_C_SEARCH))
- return (1);
- if (re_compile(sp, ptrn, t - ptrn,
- &sp->subre, &sp->subre_len, &sp->subre_c, RE_C_SUBST))
- return (1);
-
- flags = SUB_FIRST;
- sp->searchdir = FORWARD;
- }
- re = &sp->re_c;
-
- /*
- * Get the replacement string.
- *
- * The special character & (\& if O_MAGIC not set) matches the
- * entire RE. No handling of & is required here, it's done by
- * re_sub().
- *
- * The special character ~ (\~ if O_MAGIC not set) inserts the
- * previous replacement string into this replacement string.
- * Count ~'s to figure out how much space we need. We could
- * special case nonexistent last patterns or whether or not
- * O_MAGIC is set, but it's probably not worth the effort.
- *
- * QUOTING NOTE:
- *
- * Only toss an escaping character if it escapes a delimiter or
- * if O_MAGIC is set and it escapes a tilde.
- *
- * !!!
- * If the entire replacement pattern is "%", then use the last
- * replacement pattern. This semantic was added to vi in System
- * V and then percolated elsewhere, presumably around the time
- * that it was added to their version of ed(1).
- */
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
- ++p;
- if (sp->repl != NULL)
- free(sp->repl);
- sp->repl = NULL;
- sp->repl_len = 0;
- } else if (p[0] == '%' && (p[1] == '\0' || p[1] == delim))
- p += p[1] == delim ? 2 : 1;
- else {
- for (rep = p, len = 0;
- p[0] != '\0' && p[0] != delim; ++p, ++len)
- if (p[0] == '~')
- len += sp->repl_len;
- GET_SPACE_RET(sp, bp, blen, len);
- for (t = bp, len = 0, p = rep;;) {
- if (p[0] == '\0' || p[0] == delim) {
- if (p[0] == delim)
- ++p;
- break;
- }
- if (p[0] == '\\') {
- if (p[1] == delim)
- ++p;
- else if (p[1] == '\\') {
- *t++ = *p++;
- ++len;
- } else if (p[1] == '~') {
- ++p;
- if (!O_ISSET(sp, O_MAGIC))
- goto tilde;
- }
- } else if (p[0] == '~' && O_ISSET(sp, O_MAGIC)) {
-tilde: ++p;
- memcpy(t, sp->repl, sp->repl_len);
- t += sp->repl_len;
- len += sp->repl_len;
- continue;
- }
- *t++ = *p++;
- ++len;
- }
- if ((sp->repl_len = len) != 0) {
- if (sp->repl != NULL)
- free(sp->repl);
- if ((sp->repl = malloc(len)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- FREE_SPACE(sp, bp, blen);
- return (1);
- }
- memcpy(sp->repl, bp, len);
- }
- FREE_SPACE(sp, bp, blen);
- }
- return (s(sp, cmdp, p, re, flags));
-}
-
-/*
- * ex_subagain --
- * [line [,line]] & [cgr] [count] [#lp]]
- *
- * Substitute using the last substitute RE and replacement pattern.
- *
- * PUBLIC: int ex_subagain __P((SCR *, EXCMD *));
- */
-int
-ex_subagain(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (sp->subre == NULL) {
- ex_emsg(sp, NULL, EXM_NOPREVRE);
- return (1);
- }
- if (!F_ISSET(sp, SC_RE_SUBST) && re_compile(sp,
- sp->subre, sp->subre_len, NULL, NULL, &sp->subre_c, RE_C_SUBST))
- return (1);
- return (s(sp,
- cmdp, cmdp->argc ? cmdp->argv[0]->bp : NULL, &sp->subre_c, 0));
-}
-
-/*
- * ex_subtilde --
- * [line [,line]] ~ [cgr] [count] [#lp]]
- *
- * Substitute using the last RE and last substitute replacement pattern.
- *
- * PUBLIC: int ex_subtilde __P((SCR *, EXCMD *));
- */
-int
-ex_subtilde(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (sp->re == NULL) {
- ex_emsg(sp, NULL, EXM_NOPREVRE);
- return (1);
- }
- if (!F_ISSET(sp, SC_RE_SEARCH) && re_compile(sp,
- sp->re, sp->re_len, NULL, NULL, &sp->re_c, RE_C_SEARCH))
- return (1);
- return (s(sp,
- cmdp, cmdp->argc ? cmdp->argv[0]->bp : NULL, &sp->re_c, 0));
-}
-
-/*
- * s --
- * Do the substitution. This stuff is *really* tricky. There are lots of
- * special cases, and general nastiness. Don't mess with it unless you're
- * pretty confident.
- *
- * The nasty part of the substitution is what happens when the replacement
- * string contains newlines. It's a bit tricky -- consider the information
- * that has to be retained for "s/f\(o\)o/^M\1^M\1/". The solution here is
- * to build a set of newline offsets which we use to break the line up later,
- * when the replacement is done. Don't change it unless you're *damned*
- * confident.
- */
-#define NEEDNEWLINE(sp) { \
- if (sp->newl_len == sp->newl_cnt) { \
- sp->newl_len += 25; \
- REALLOC(sp, sp->newl, size_t *, \
- sp->newl_len * sizeof(size_t)); \
- if (sp->newl == NULL) { \
- sp->newl_len = 0; \
- return (1); \
- } \
- } \
-}
-
-#define BUILD(sp, l, len) { \
- if (lbclen + (len) > lblen) { \
- lblen += MAX(lbclen + (len), 256); \
- REALLOC(sp, lb, char *, lblen); \
- if (lb == NULL) { \
- lbclen = 0; \
- return (1); \
- } \
- } \
- memcpy(lb + lbclen, l, len); \
- lbclen += len; \
-}
-
-#define NEEDSP(sp, len, pnt) { \
- if (lbclen + (len) > lblen) { \
- lblen += MAX(lbclen + (len), 256); \
- REALLOC(sp, lb, char *, lblen); \
- if (lb == NULL) { \
- lbclen = 0; \
- return (1); \
- } \
- pnt = lb + lbclen; \
- } \
-}
-
-static int
-s(sp, cmdp, s, re, flags)
- SCR *sp;
- EXCMD *cmdp;
- char *s;
- regex_t *re;
- u_int flags;
-{
- EVENT ev;
- MARK from, to;
- TEXTH tiq;
- recno_t elno, lno, slno;
- regmatch_t match[10];
- size_t blen, cnt, last, lbclen, lblen, len, llen;
- size_t offset, saved_offset, scno;
- int cflag, lflag, nflag, pflag, rflag;
- int didsub, do_eol_match, eflags, empty_ok, eval;
- int linechanged, matched, quit, rval;
- char *bp, *lb;
-
- NEEDFILE(sp, cmdp);
-
- slno = sp->lno;
- scno = sp->cno;
-
- /*
- * !!!
- * Historically, the 'g' and 'c' suffices were always toggled as flags,
- * so ":s/A/B/" was the same as ":s/A/B/ccgg". If O_EDCOMPATIBLE was
- * not set, they were initialized to 0 for all substitute commands. If
- * O_EDCOMPATIBLE was set, they were initialized to 0 only if the user
- * specified substitute/replacement patterns (see ex_s()).
- */
- if (!O_ISSET(sp, O_EDCOMPATIBLE))
- sp->c_suffix = sp->g_suffix = 0;
-
- /*
- * Historic vi permitted the '#', 'l' and 'p' options in vi mode, but
- * it only displayed the last change. I'd disallow them, but they are
- * useful in combination with the [v]global commands. In the current
- * model the problem is combining them with the 'c' flag -- the screen
- * would have to flip back and forth between the confirm screen and the
- * ex print screen, which would be pretty awful. We do display all
- * changes, though, for what that's worth.
- *
- * !!!
- * Historic vi was fairly strict about the order of "options", the
- * count, and "flags". I'm somewhat fuzzy on the difference between
- * options and flags, anyway, so this is a simpler approach, and we
- * just take it them in whatever order the user gives them. (The ex
- * usage statement doesn't reflect this.)
- */
- cflag = lflag = nflag = pflag = rflag = 0;
- if (s == NULL)
- goto noargs;
- for (lno = OOBLNO; *s != '\0'; ++s)
- switch (*s) {
- case ' ':
- case '\t':
- continue;
- case '+':
- ++cmdp->flagoff;
- break;
- case '-':
- --cmdp->flagoff;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (lno != OOBLNO)
- goto usage;
- errno = 0;
- lno = strtoul(s, &s, 10);
- if (*s == '\0') /* Loop increment correction. */
- --s;
- if (errno == ERANGE) {
- if (lno == LONG_MAX)
- msgq(sp, M_ERR, "153|Count overflow");
- else if (lno == LONG_MIN)
- msgq(sp, M_ERR, "154|Count underflow");
- else
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- /*
- * In historic vi, the count was inclusive from the
- * second address.
- */
- cmdp->addr1.lno = cmdp->addr2.lno;
- cmdp->addr2.lno += lno - 1;
- if (!db_exist(sp, cmdp->addr2.lno) &&
- db_last(sp, &cmdp->addr2.lno))
- return (1);
- break;
- case '#':
- nflag = 1;
- break;
- case 'c':
- sp->c_suffix = !sp->c_suffix;
-
- /* Ex text structure initialization. */
- if (F_ISSET(sp, SC_EX)) {
- memset(&tiq, 0, sizeof(TEXTH));
- CIRCLEQ_INIT(&tiq);
- }
- break;
- case 'g':
- sp->g_suffix = !sp->g_suffix;
- break;
- case 'l':
- lflag = 1;
- break;
- case 'p':
- pflag = 1;
- break;
- case 'r':
- if (LF_ISSET(SUB_FIRST)) {
- msgq(sp, M_ERR,
- "155|Regular expression specified; r flag meaningless");
- return (1);
- }
- if (!F_ISSET(sp, SC_RE_SEARCH)) {
- ex_emsg(sp, NULL, EXM_NOPREVRE);
- return (1);
- }
- rflag = 1;
- re = &sp->re_c;
- break;
- default:
- goto usage;
- }
-
- if (*s != '\0' || !rflag && LF_ISSET(SUB_MUSTSETR)) {
-usage: ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
-
-noargs: if (F_ISSET(sp, SC_VI) && sp->c_suffix && (lflag || nflag || pflag)) {
- msgq(sp, M_ERR,
-"156|The #, l and p flags may not be combined with the c flag in vi mode");
- return (1);
- }
-
- /*
- * bp: if interactive, line cache
- * blen: if interactive, line cache length
- * lb: build buffer pointer.
- * lbclen: current length of built buffer.
- * lblen; length of build buffer.
- */
- bp = lb = NULL;
- blen = lbclen = lblen = 0;
-
- /* For each line... */
- for (matched = quit = 0, lno = cmdp->addr1.lno,
- elno = cmdp->addr2.lno; !quit && lno <= elno; ++lno) {
-
- /* Someone's unhappy, time to stop. */
- if (INTERRUPTED(sp))
- break;
-
- /* Get the line. */
- if (db_get(sp, lno, DBG_FATAL, &s, &llen))
- goto err;
-
- /*
- * Make a local copy if doing confirmation -- when calling
- * the confirm routine we're likely to lose the cached copy.
- */
- if (sp->c_suffix) {
- if (bp == NULL) {
- GET_SPACE_RET(sp, bp, blen, llen);
- } else
- ADD_SPACE_RET(sp, bp, blen, llen);
- memcpy(bp, s, llen);
- s = bp;
- }
-
- /* Start searching from the beginning. */
- offset = 0;
- len = llen;
-
- /* Reset the build buffer offset. */
- lbclen = 0;
-
- /* Reset empty match flag. */
- empty_ok = 1;
-
- /*
- * We don't want to have to do a setline if the line didn't
- * change -- keep track of whether or not this line changed.
- * If doing confirmations, don't want to keep setting the
- * line if change is refused -- keep track of substitutions.
- */
- didsub = linechanged = 0;
-
- /* New line, do an EOL match. */
- do_eol_match = 1;
-
- /* It's not nul terminated, but we pretend it is. */
- eflags = REG_STARTEND;
-
- /*
- * The search area is from s + offset to the EOL.
- *
- * Generally, match[0].rm_so is the offset of the start
- * of the match from the start of the search, and offset
- * is the offset of the start of the last search.
- */
-nextmatch: match[0].rm_so = 0;
- match[0].rm_eo = len;
-
- /* Get the next match. */
- eval = regexec(re, (char *)s + offset, 10, match, eflags);
-
- /*
- * There wasn't a match or if there was an error, deal with
- * it. If there was a previous match in this line, resolve
- * the changes into the database. Otherwise, just move on.
- */
- if (eval == REG_NOMATCH)
- goto endmatch;
- if (eval != 0) {
- re_error(sp, eval, re);
- goto err;
- }
- matched = 1;
-
- /* Only the first search can match an anchored expression. */
- eflags |= REG_NOTBOL;
-
- /*
- * !!!
- * It's possible to match 0-length strings -- for example, the
- * command s;a*;X;, when matched against the string "aabb" will
- * result in "XbXbX", i.e. the matches are "aa", the space
- * between the b's and the space between the b's and the end of
- * the string. There is a similar space between the beginning
- * of the string and the a's. The rule that we use (because vi
- * historically used it) is that any 0-length match, occurring
- * immediately after a match, is ignored. Otherwise, the above
- * example would have resulted in "XXbXbX". Another example is
- * incorrectly using " *" to replace groups of spaces with one
- * space.
- *
- * The way we do this is that if we just had a successful match,
- * the starting offset does not skip characters, and the match
- * is empty, ignore the match and move forward. If there's no
- * more characters in the string, we were attempting to match
- * after the last character, so quit.
- */
- if (!empty_ok && match[0].rm_so == 0 && match[0].rm_eo == 0) {
- empty_ok = 1;
- if (len == 0)
- goto endmatch;
- BUILD(sp, s + offset, 1)
- ++offset;
- --len;
- goto nextmatch;
- }
-
- /* Confirm change. */
- if (sp->c_suffix) {
- /*
- * Set the cursor position for confirmation. Note,
- * if we matched on a '$', the cursor may be past
- * the end of line.
- */
- from.lno = to.lno = lno;
- from.cno = match[0].rm_so + offset;
- to.cno = match[0].rm_eo + offset;
- /*
- * Both ex and vi have to correct for a change before
- * the first character in the line.
- */
- if (llen == 0)
- from.cno = to.cno = 0;
- if (F_ISSET(sp, SC_VI)) {
- /*
- * Only vi has to correct for a change after
- * the last character in the line.
- *
- * XXX
- * It would be nice to change the vi code so
- * that we could display a cursor past EOL.
- */
- if (to.cno >= llen)
- to.cno = llen - 1;
- if (from.cno >= llen)
- from.cno = llen - 1;
-
- sp->lno = from.lno;
- sp->cno = from.cno;
- if (vs_refresh(sp, 1))
- goto err;
-
- vs_update(sp, msg_cat(sp,
- "169|Confirm change? [n]", NULL), NULL);
-
- if (v_event_get(sp, &ev, 0, 0))
- goto err;
- switch (ev.e_event) {
- case E_CHARACTER:
- break;
- case E_EOF:
- case E_ERR:
- case E_INTERRUPT:
- goto lquit;
- default:
- v_event_err(sp, &ev);
- goto lquit;
- }
- } else {
- if (ex_print(sp, cmdp, &from, &to, 0) ||
- ex_scprint(sp, &from, &to))
- goto lquit;
- if (ex_txt(sp, &tiq, 0, TXT_CR))
- goto err;
- ev.e_c = tiq.cqh_first->lb[0];
- }
-
- switch (ev.e_c) {
- case CH_YES:
- break;
- default:
- case CH_NO:
- didsub = 0;
- BUILD(sp, s +offset, match[0].rm_eo);
- goto skip;
- case CH_QUIT:
- /* Set the quit/interrupted flags. */
-lquit: quit = 1;
- F_SET(sp->gp, G_INTERRUPTED);
-
- /*
- * Resolve any changes, then return to (and
- * exit from) the main loop.
- */
- goto endmatch;
- }
- }
-
- /*
- * Set the cursor to the last position changed, converting
- * from 1-based to 0-based.
- */
- sp->lno = lno;
- sp->cno = match[0].rm_so;
-
- /* Copy the bytes before the match into the build buffer. */
- BUILD(sp, s + offset, match[0].rm_so);
-
- /* Substitute the matching bytes. */
- didsub = 1;
- if (re_sub(sp, s + offset, &lb, &lbclen, &lblen, match))
- goto err;
-
- /* Set the change flag so we know this line was modified. */
- linechanged = 1;
-
- /* Move past the matched bytes. */
-skip: offset += match[0].rm_eo;
- len -= match[0].rm_eo;
-
- /* A match cannot be followed by an empty pattern. */
- empty_ok = 0;
-
- /*
- * If doing a global change with confirmation, we have to
- * update the screen. The basic idea is to store the line
- * so the screen update routines can find it, and restart.
- */
- if (didsub && sp->c_suffix && sp->g_suffix) {
- /*
- * The new search offset will be the end of the
- * modified line.
- */
- saved_offset = lbclen;
-
- /* Copy the rest of the line. */
- if (len)
- BUILD(sp, s + offset, len)
-
- /* Set the new offset. */
- offset = saved_offset;
-
- /* Store inserted lines, adjusting the build buffer. */
- last = 0;
- if (sp->newl_cnt) {
- for (cnt = 0;
- cnt < sp->newl_cnt; ++cnt, ++lno, ++elno) {
- if (db_insert(sp, lno,
- lb + last, sp->newl[cnt] - last))
- goto err;
- last = sp->newl[cnt] + 1;
- ++sp->rptlines[L_ADDED];
- }
- lbclen -= last;
- offset -= last;
- sp->newl_cnt = 0;
- }
-
- /* Store and retrieve the line. */
- if (db_set(sp, lno, lb + last, lbclen))
- goto err;
- if (db_get(sp, lno, DBG_FATAL, &s, &llen))
- goto err;
- ADD_SPACE_RET(sp, bp, blen, llen)
- memcpy(bp, s, llen);
- s = bp;
- len = llen - offset;
-
- /* Restart the build. */
- lbclen = 0;
- BUILD(sp, s, offset);
-
- /*
- * If we haven't already done the after-the-string
- * match, do one. Set REG_NOTEOL so the '$' pattern
- * only matches once.
- */
- if (!do_eol_match)
- goto endmatch;
- if (offset == len) {
- do_eol_match = 0;
- eflags |= REG_NOTEOL;
- }
- goto nextmatch;
- }
-
- /*
- * If it's a global:
- *
- * If at the end of the string, do a test for the after
- * the string match. Set REG_NOTEOL so the '$' pattern
- * only matches once.
- */
- if (sp->g_suffix && do_eol_match) {
- if (len == 0) {
- do_eol_match = 0;
- eflags |= REG_NOTEOL;
- }
- goto nextmatch;
- }
-
-endmatch: if (!linechanged)
- continue;
-
- /* Copy any remaining bytes into the build buffer. */
- if (len)
- BUILD(sp, s + offset, len)
-
- /* Store inserted lines, adjusting the build buffer. */
- last = 0;
- if (sp->newl_cnt) {
- for (cnt = 0;
- cnt < sp->newl_cnt; ++cnt, ++lno, ++elno) {
- if (db_insert(sp,
- lno, lb + last, sp->newl[cnt] - last))
- goto err;
- last = sp->newl[cnt] + 1;
- ++sp->rptlines[L_ADDED];
- }
- lbclen -= last;
- sp->newl_cnt = 0;
- }
-
- /* Store the changed line. */
- if (db_set(sp, lno, lb + last, lbclen))
- goto err;
-
- /* Update changed line counter. */
- if (sp->rptlchange != lno) {
- sp->rptlchange = lno;
- ++sp->rptlines[L_CHANGED];
- }
-
- /*
- * !!!
- * Display as necessary. Historic practice is to only
- * display the last line of a line split into multiple
- * lines.
- */
- if (lflag || nflag || pflag) {
- from.lno = to.lno = lno;
- from.cno = to.cno = 0;
- if (lflag)
- (void)ex_print(sp, cmdp, &from, &to, E_C_LIST);
- if (nflag)
- (void)ex_print(sp, cmdp, &from, &to, E_C_HASH);
- if (pflag)
- (void)ex_print(sp, cmdp, &from, &to, E_C_PRINT);
- }
- }
-
- /*
- * !!!
- * Historically, vi attempted to leave the cursor at the same place if
- * the substitution was done at the current cursor position. Otherwise
- * it moved it to the first non-blank of the last line changed. There
- * were some problems: for example, :s/$/foo/ with the cursor on the
- * last character of the line left the cursor on the last character, or
- * the & command with multiple occurrences of the matching string in the
- * line usually left the cursor in a fairly random position.
- *
- * We try to do the same thing, with the exception that if the user is
- * doing substitution with confirmation, we move to the last line about
- * which the user was consulted, as opposed to the last line that they
- * actually changed. This prevents a screen flash if the user doesn't
- * change many of the possible lines.
- */
- if (!sp->c_suffix && (sp->lno != slno || sp->cno != scno)) {
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- }
-
- /*
- * If not in a global command, and nothing matched, say so.
- * Else, if none of the lines displayed, put something up.
- */
- rval = 0;
- if (!matched) {
- if (!F_ISSET(sp, SC_EX_GLOBAL)) {
- msgq(sp, M_ERR, "157|No match found");
- goto err;
- }
- } else if (!lflag && !nflag && !pflag)
- F_SET(cmdp, E_AUTOPRINT);
-
- if (0) {
-err: rval = 1;
- }
-
- if (bp != NULL)
- FREE_SPACE(sp, bp, blen);
- if (lb != NULL)
- free(lb);
- return (rval);
-}
-
-/*
- * re_compile --
- * Compile the RE.
- *
- * PUBLIC: int re_compile __P((SCR *,
- * PUBLIC: char *, size_t, char **, size_t *, regex_t *, u_int));
- */
-int
-re_compile(sp, ptrn, plen, ptrnp, lenp, rep, flags)
- SCR *sp;
- char *ptrn, **ptrnp;
- size_t plen, *lenp;
- regex_t *rep;
- u_int flags;
-{
- size_t len;
- int reflags, replaced, rval;
- char *p;
-
- /* Set RE flags. */
- reflags = 0;
- if (!LF_ISSET(RE_C_CSCOPE | RE_C_TAG)) {
- if (O_ISSET(sp, O_EXTENDED))
- reflags |= REG_EXTENDED;
- if (O_ISSET(sp, O_IGNORECASE))
- reflags |= REG_ICASE;
- if (O_ISSET(sp, O_ICLOWER)) {
- for (p = ptrn, len = plen; len > 0; ++p, --len)
- if (isupper(*p))
- break;
- if (len == 0)
- reflags |= REG_ICASE;
- }
- }
-
- /* If we're replacing a saved value, clear the old one. */
- if (LF_ISSET(RE_C_SEARCH) && F_ISSET(sp, SC_RE_SEARCH)) {
- regfree(&sp->re_c);
- F_CLR(sp, SC_RE_SEARCH);
- }
- if (LF_ISSET(RE_C_SUBST) && F_ISSET(sp, SC_RE_SUBST)) {
- regfree(&sp->subre_c);
- F_CLR(sp, SC_RE_SUBST);
- }
-
- /*
- * If we're saving the string, it's a pattern we haven't seen before,
- * so convert the vi-style RE's to POSIX 1003.2 RE's. Save a copy for
- * later recompilation. Free any previously saved value.
- */
- if (ptrnp != NULL) {
- if (LF_ISSET(RE_C_CSCOPE)) {
- if (re_cscope_conv(sp, &ptrn, &plen, &replaced))
- return (1);
- /*
- * XXX
- * Currently, the match-any-<blank> expression used in
- * re_cscope_conv() requires extended RE's. This may
- * not be right or safe.
- */
- reflags |= REG_EXTENDED;
- } else if (LF_ISSET(RE_C_TAG)) {
- if (re_tag_conv(sp, &ptrn, &plen, &replaced))
- return (1);
- } else
- if (re_conv(sp, &ptrn, &plen, &replaced))
- return (1);
-
- /* Discard previous pattern. */
- if (*ptrnp != NULL) {
- free(*ptrnp);
- *ptrnp = NULL;
- }
- if (lenp != NULL)
- *lenp = plen;
-
- /*
- * Copy the string into allocated memory.
- *
- * XXX
- * Regcomp isn't 8-bit clean, so the pattern is nul-terminated
- * for now. There's just no other solution.
- */
- MALLOC(sp, *ptrnp, char *, plen + 1);
- if (*ptrnp != NULL) {
- memcpy(*ptrnp, ptrn, plen);
- (*ptrnp)[plen] = '\0';
- }
-
- /* Free up conversion-routine-allocated memory. */
- if (replaced)
- FREE_SPACE(sp, ptrn, 0);
-
- if (*ptrnp == NULL)
- return (1);
-
- ptrn = *ptrnp;
- }
-
- /*
- * XXX
- * Regcomp isn't 8-bit clean, so we just lost if the pattern
- * contained a nul. Bummer!
- */
- if ((rval = regcomp(rep, ptrn, /* plen, */ reflags)) != 0) {
- if (!LF_ISSET(RE_C_SILENT))
- re_error(sp, rval, rep);
- return (1);
- }
-
- if (LF_ISSET(RE_C_SEARCH))
- F_SET(sp, SC_RE_SEARCH);
- if (LF_ISSET(RE_C_SUBST))
- F_SET(sp, SC_RE_SUBST);
-
- return (0);
-}
-
-/*
- * re_conv --
- * Convert vi's regular expressions into something that the
- * the POSIX 1003.2 RE functions can handle.
- *
- * There are three conversions we make to make vi's RE's (specifically
- * the global, search, and substitute patterns) work with POSIX RE's.
- *
- * 1: If O_MAGIC is not set, strip backslashes from the magic character
- * set (.[*~) that have them, and add them to the ones that don't.
- * 2: If O_MAGIC is not set, the string "\~" is replaced with the text
- * from the last substitute command's replacement string. If O_MAGIC
- * is set, it's the string "~".
- * 3: The pattern \<ptrn\> does "word" searches, convert it to use the
- * new RE escapes.
- *
- * !!!/XXX
- * This doesn't exactly match the historic behavior of vi because we do
- * the ~ substitution before calling the RE engine, so magic characters
- * in the replacement string will be expanded by the RE engine, and they
- * weren't historically. It's a bug.
- */
-static int
-re_conv(sp, ptrnp, plenp, replacedp)
- SCR *sp;
- char **ptrnp;
- size_t *plenp;
- int *replacedp;
-{
- size_t blen, len, needlen;
- int magic;
- char *bp, *p, *t;
-
- /*
- * First pass through, we figure out how much space we'll need.
- * We do it in two passes, on the grounds that most of the time
- * the user is doing a search and won't have magic characters.
- * That way we can skip most of the memory allocation and copies.
- */
- magic = 0;
- for (p = *ptrnp, len = *plenp, needlen = 0; len > 0; ++p, --len)
- switch (*p) {
- case '\\':
- if (len > 1) {
- --len;
- switch (*++p) {
- case '<':
- magic = 1;
- needlen += sizeof(RE_WSTART);
- break;
- case '>':
- magic = 1;
- needlen += sizeof(RE_WSTOP);
- break;
- case '~':
- if (!O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += sp->repl_len;
- }
- break;
- case '.':
- case '[':
- case '*':
- if (!O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += 1;
- }
- break;
- default:
- needlen += 2;
- }
- } else
- needlen += 1;
- break;
- case '~':
- if (O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += sp->repl_len;
- }
- break;
- case '.':
- case '[':
- case '*':
- if (!O_ISSET(sp, O_MAGIC)) {
- magic = 1;
- needlen += 2;
- }
- break;
- default:
- needlen += 1;
- break;
- }
-
- if (!magic) {
- *replacedp = 0;
- return (0);
- }
-
- /* Get enough memory to hold the final pattern. */
- *replacedp = 1;
- GET_SPACE_RET(sp, bp, blen, needlen);
-
- for (p = *ptrnp, len = *plenp, t = bp; len > 0; ++p, --len)
- switch (*p) {
- case '\\':
- if (len > 1) {
- --len;
- switch (*++p) {
- case '<':
- memcpy(t,
- RE_WSTART, sizeof(RE_WSTART) - 1);
- t += sizeof(RE_WSTART) - 1;
- break;
- case '>':
- memcpy(t,
- RE_WSTOP, sizeof(RE_WSTOP) - 1);
- t += sizeof(RE_WSTOP) - 1;
- break;
- case '~':
- if (O_ISSET(sp, O_MAGIC))
- *t++ = '~';
- else {
- memcpy(t,
- sp->repl, sp->repl_len);
- t += sp->repl_len;
- }
- break;
- case '.':
- case '[':
- case '*':
- if (O_ISSET(sp, O_MAGIC))
- *t++ = '\\';
- *t++ = *p;
- break;
- default:
- *t++ = '\\';
- *t++ = *p;
- }
- } else
- *t++ = '\\';
- break;
- case '~':
- if (O_ISSET(sp, O_MAGIC)) {
- memcpy(t, sp->repl, sp->repl_len);
- t += sp->repl_len;
- } else
- *t++ = '~';
- break;
- case '.':
- case '[':
- case '*':
- if (!O_ISSET(sp, O_MAGIC))
- *t++ = '\\';
- *t++ = *p;
- break;
- default:
- *t++ = *p;
- break;
- }
-
- *ptrnp = bp;
- *plenp = t - bp;
- return (0);
-}
-
-/*
- * re_tag_conv --
- * Convert a tags search path into something that the POSIX
- * 1003.2 RE functions can handle.
- */
-static int
-re_tag_conv(sp, ptrnp, plenp, replacedp)
- SCR *sp;
- char **ptrnp;
- size_t *plenp;
- int *replacedp;
-{
- size_t blen, len;
- int lastdollar;
- char *bp, *p, *t;
-
- len = *plenp;
-
- /* Max memory usage is 2 times the length of the string. */
- *replacedp = 1;
- GET_SPACE_RET(sp, bp, blen, len * 2);
-
- p = *ptrnp;
- t = bp;
-
- /* If the last character is a '/' or '?', we just strip it. */
- if (len > 0 && (p[len - 1] == '/' || p[len - 1] == '?'))
- --len;
-
- /* If the next-to-last or last character is a '$', it's magic. */
- if (len > 0 && p[len - 1] == '$') {
- --len;
- lastdollar = 1;
- } else
- lastdollar = 0;
-
- /* If the first character is a '/' or '?', we just strip it. */
- if (len > 0 && (p[0] == '/' || p[0] == '?')) {
- ++p;
- --len;
- }
-
- /* If the first or second character is a '^', it's magic. */
- if (p[0] == '^') {
- *t++ = *p++;
- --len;
- }
-
- /*
- * Escape every other magic character we can find, meanwhile stripping
- * the backslashes ctags inserts when escaping the search delimiter
- * characters.
- */
- for (; len > 0; --len) {
- if (p[0] == '\\' && (p[1] == '/' || p[1] == '?')) {
- ++p;
- --len;
- } else if (strchr("^.[]$*", p[0]))
- *t++ = '\\';
- *t++ = *p++;
- }
- if (lastdollar)
- *t++ = '$';
-
- *ptrnp = bp;
- *plenp = t - bp;
- return (0);
-}
-
-/*
- * re_cscope_conv --
- * Convert a cscope search path into something that the POSIX
- * 1003.2 RE functions can handle.
- */
-static int
-re_cscope_conv(sp, ptrnp, plenp, replacedp)
- SCR *sp;
- char **ptrnp;
- size_t *plenp;
- int *replacedp;
-{
- size_t blen, len, nspaces;
- char *bp, *p, *t;
-
- /*
- * Each space in the source line printed by cscope represents an
- * arbitrary sequence of spaces, tabs, and comments.
- */
-#define CSCOPE_RE_SPACE "([ \t]|/\\*([^*]|\\*/)*\\*/)*"
- for (nspaces = 0, p = *ptrnp, len = *plenp; len > 0; ++p, --len)
- if (*p == ' ')
- ++nspaces;
-
- /*
- * Allocate plenty of space:
- * the string, plus potential escaping characters;
- * nspaces + 2 copies of CSCOPE_RE_SPACE;
- * ^, $, nul terminator characters.
- */
- *replacedp = 1;
- len = (p - *ptrnp) * 2 + (nspaces + 2) * sizeof(CSCOPE_RE_SPACE) + 3;
- GET_SPACE_RET(sp, bp, blen, len);
-
- p = *ptrnp;
- t = bp;
-
- *t++ = '^';
- memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
- t += sizeof(CSCOPE_RE_SPACE) - 1;
-
- for (len = *plenp; len > 0; ++p, --len)
- if (*p == ' ') {
- memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
- t += sizeof(CSCOPE_RE_SPACE) - 1;
- } else {
- if (strchr("\\^.[]$*+?()|{}", *p))
- *t++ = '\\';
- *t++ = *p;
- }
-
- memcpy(t, CSCOPE_RE_SPACE, sizeof(CSCOPE_RE_SPACE) - 1);
- t += sizeof(CSCOPE_RE_SPACE) - 1;
- *t++ = '$';
-
- *ptrnp = bp;
- *plenp = t - bp;
- return (0);
-}
-
-/*
- * re_error --
- * Report a regular expression error.
- *
- * PUBLIC: void re_error __P((SCR *, int, regex_t *));
- */
-void
-re_error(sp, errcode, preg)
- SCR *sp;
- int errcode;
- regex_t *preg;
-{
- size_t s;
- char *oe;
-
- s = regerror(errcode, preg, "", 0);
- if ((oe = malloc(s)) == NULL)
- msgq(sp, M_SYSERR, NULL);
- else {
- (void)regerror(errcode, preg, oe, s);
- msgq(sp, M_ERR, "RE error: %s", oe);
- free(oe);
- }
-}
-
-/*
- * re_sub --
- * Do the substitution for a regular expression.
- */
-static int
-re_sub(sp, ip, lbp, lbclenp, lblenp, match)
- SCR *sp;
- char *ip; /* Input line. */
- char **lbp;
- size_t *lbclenp, *lblenp;
- regmatch_t match[10];
-{
- enum { C_NOTSET, C_LOWER, C_ONELOWER, C_ONEUPPER, C_UPPER } conv;
- size_t lbclen, lblen; /* Local copies. */
- size_t mlen; /* Match length. */
- size_t rpl; /* Remaining replacement length. */
- char *rp; /* Replacement pointer. */
- int ch;
- int no; /* Match replacement offset. */
- char *p, *t; /* Buffer pointers. */
- char *lb; /* Local copies. */
-
- lb = *lbp; /* Get local copies. */
- lbclen = *lbclenp;
- lblen = *lblenp;
-
- /*
- * QUOTING NOTE:
- *
- * There are some special sequences that vi provides in the
- * replacement patterns.
- * & string the RE matched (\& if nomagic set)
- * \# n-th regular subexpression
- * \E end \U, \L conversion
- * \e end \U, \L conversion
- * \l convert the next character to lower-case
- * \L convert to lower-case, until \E, \e, or end of replacement
- * \u convert the next character to upper-case
- * \U convert to upper-case, until \E, \e, or end of replacement
- *
- * Otherwise, since this is the lowest level of replacement, discard
- * all escaping characters. This (hopefully) matches historic practice.
- */
-#define OUTCH(ch, nltrans) { \
- CHAR_T __ch = (ch); \
- u_int __value = KEY_VAL(sp, __ch); \
- if (nltrans && (__value == K_CR || __value == K_NL)) { \
- NEEDNEWLINE(sp); \
- sp->newl[sp->newl_cnt++] = lbclen; \
- } else if (conv != C_NOTSET) { \
- switch (conv) { \
- case C_ONELOWER: \
- conv = C_NOTSET; \
- /* FALLTHROUGH */ \
- case C_LOWER: \
- if (isupper(__ch)) \
- __ch = tolower(__ch); \
- break; \
- case C_ONEUPPER: \
- conv = C_NOTSET; \
- /* FALLTHROUGH */ \
- case C_UPPER: \
- if (islower(__ch)) \
- __ch = toupper(__ch); \
- break; \
- default: \
- abort(); \
- } \
- } \
- NEEDSP(sp, 1, p); \
- *p++ = __ch; \
- ++lbclen; \
-}
- conv = C_NOTSET;
- for (rp = sp->repl, rpl = sp->repl_len, p = lb + lbclen; rpl--;) {
- switch (ch = *rp++) {
- case '&':
- if (O_ISSET(sp, O_MAGIC)) {
- no = 0;
- goto subzero;
- }
- break;
- case '\\':
- if (rpl == 0)
- break;
- --rpl;
- switch (ch = *rp) {
- case '&':
- ++rp;
- if (!O_ISSET(sp, O_MAGIC)) {
- no = 0;
- goto subzero;
- }
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- no = *rp++ - '0';
-subzero: if (match[no].rm_so == -1 ||
- match[no].rm_eo == -1)
- break;
- mlen = match[no].rm_eo - match[no].rm_so;
- for (t = ip + match[no].rm_so; mlen--; ++t)
- OUTCH(*t, 0);
- continue;
- case 'e':
- case 'E':
- ++rp;
- conv = C_NOTSET;
- continue;
- case 'l':
- ++rp;
- conv = C_ONELOWER;
- continue;
- case 'L':
- ++rp;
- conv = C_LOWER;
- continue;
- case 'u':
- ++rp;
- conv = C_ONEUPPER;
- continue;
- case 'U':
- ++rp;
- conv = C_UPPER;
- continue;
- default:
- ++rp;
- break;
- }
- }
- OUTCH(ch, 1);
- }
-
- *lbp = lb; /* Update caller's information. */
- *lbclenp = lbclen;
- *lblenp = lblen;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_tag.c b/contrib/nvi/ex/ex_tag.c
deleted file mode 100644
index 461b152..0000000
--- a/contrib/nvi/ex/ex_tag.c
+++ /dev/null
@@ -1,1324 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * David Hitz of Auspex Systems, Inc.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_tag.c 10.36 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/param.h>
-#include <sys/types.h> /* XXX: param.h may not have included types.h */
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#include <sys/queue.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-#include "tag.h"
-
-static char *binary_search __P((char *, char *, char *));
-static int compare __P((char *, char *, char *));
-static void ctag_file __P((SCR *, TAGF *, char *, char **, size_t *));
-static int ctag_search __P((SCR *, char *, size_t, char *));
-static int ctag_sfile __P((SCR *, TAGF *, TAGQ *, char *));
-static TAGQ *ctag_slist __P((SCR *, char *));
-static char *linear_search __P((char *, char *, char *));
-static int tag_copy __P((SCR *, TAG *, TAG **));
-static int tag_pop __P((SCR *, TAGQ *, int));
-static int tagf_copy __P((SCR *, TAGF *, TAGF **));
-static int tagf_free __P((SCR *, TAGF *));
-static int tagq_copy __P((SCR *, TAGQ *, TAGQ **));
-
-/*
- * ex_tag_first --
- * The tag code can be entered from main, e.g., "vi -t tag".
- *
- * PUBLIC: int ex_tag_first __P((SCR *, char *));
- */
-int
-ex_tag_first(sp, tagarg)
- SCR *sp;
- char *tagarg;
-{
- ARGS *ap[2], a;
- EXCMD cmd;
-
- /* Build an argument for the ex :tag command. */
- ex_cinit(&cmd, C_TAG, 0, OOBLNO, OOBLNO, 0, ap);
- ex_cadd(&cmd, &a, tagarg, strlen(tagarg));
-
- /*
- * XXX
- * Historic vi went ahead and created a temporary file when it failed
- * to find the tag. We match historic practice, but don't distinguish
- * between real error and failure to find the tag.
- */
- if (ex_tag_push(sp, &cmd))
- return (0);
-
- /* Display tags in the center of the screen. */
- F_CLR(sp, SC_SCR_TOP);
- F_SET(sp, SC_SCR_CENTER);
-
- return (0);
-}
-
-/*
- * ex_tag_push -- ^]
- * :tag[!] [string]
- *
- * Enter a new TAGQ context based on a ctag string.
- *
- * PUBLIC: int ex_tag_push __P((SCR *, EXCMD *));
- */
-int
-ex_tag_push(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- EX_PRIVATE *exp;
- FREF *frp;
- TAG *rtp;
- TAGQ *rtqp, *tqp;
- recno_t lno;
- size_t cno;
- long tl;
- int force, istmp;
-
- exp = EXP(sp);
- switch (cmdp->argc) {
- case 1:
- if (exp->tag_last != NULL)
- free(exp->tag_last);
-
- if ((exp->tag_last = strdup(cmdp->argv[0]->bp)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
-
- /* Taglength may limit the number of characters. */
- if ((tl =
- O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tag_last) > tl)
- exp->tag_last[tl] = '\0';
- break;
- case 0:
- if (exp->tag_last == NULL) {
- msgq(sp, M_ERR, "158|No previous tag entered");
- return (1);
- }
- break;
- default:
- abort();
- }
-
- /* Get the tag information. */
- if ((tqp = ctag_slist(sp, exp->tag_last)) == NULL)
- return (1);
-
- /*
- * Allocate all necessary memory before swapping screens. Initialize
- * flags so we know what to free.
- */
- rtp = NULL;
- rtqp = NULL;
- if (exp->tq.cqh_first == (void *)&exp->tq) {
- /* Initialize the `local context' tag queue structure. */
- CALLOC_GOTO(sp, rtqp, TAGQ *, 1, sizeof(TAGQ));
- CIRCLEQ_INIT(&rtqp->tagq);
-
- /* Initialize and link in its tag structure. */
- CALLOC_GOTO(sp, rtp, TAG *, 1, sizeof(TAG));
- CIRCLEQ_INSERT_HEAD(&rtqp->tagq, rtp, q);
- rtqp->current = rtp;
- }
-
- /*
- * Stick the current context information in a convenient place, we're
- * about to lose it. Note, if we're called on editor startup, there
- * will be no FREF structure.
- */
- frp = sp->frp;
- lno = sp->lno;
- cno = sp->cno;
- istmp = frp == NULL ||
- F_ISSET(frp, FR_TMPFILE) && !F_ISSET(cmdp, E_NEWSCREEN);
-
- /* Try to switch to the tag. */
- force = FL_ISSET(cmdp->iflags, E_C_FORCE);
- if (F_ISSET(cmdp, E_NEWSCREEN)) {
- if (ex_tag_Nswitch(sp, tqp->tagq.cqh_first, force))
- goto err;
-
- /* Everything else gets done in the new screen. */
- sp = sp->nextdisp;
- exp = EXP(sp);
- } else
- if (ex_tag_nswitch(sp, tqp->tagq.cqh_first, force))
- goto err;
-
- /*
- * If this is the first tag, put a `current location' queue entry
- * in place, so we can pop all the way back to the current mark.
- * Note, it doesn't point to much of anything, it's a placeholder.
- */
- if (exp->tq.cqh_first == (void *)&exp->tq) {
- CIRCLEQ_INSERT_HEAD(&exp->tq, rtqp, q);
- } else
- rtqp = exp->tq.cqh_first;
-
- /* Link the new TAGQ structure into place. */
- CIRCLEQ_INSERT_HEAD(&exp->tq, tqp, q);
-
- (void)ctag_search(sp,
- tqp->current->search, tqp->current->slen, tqp->tag);
-
- /*
- * Move the current context from the temporary save area into the
- * right structure.
- *
- * If we were in a temporary file, we don't have a context to which
- * we can return, so just make it be the same as what we're moving
- * to. It will be a little odd that ^T doesn't change anything, but
- * I don't think it's a big deal.
- */
- if (istmp) {
- rtqp->current->frp = sp->frp;
- rtqp->current->lno = sp->lno;
- rtqp->current->cno = sp->cno;
- } else {
- rtqp->current->frp = frp;
- rtqp->current->lno = lno;
- rtqp->current->cno = cno;
- }
- return (0);
-
-err:
-alloc_err:
- if (rtqp != NULL)
- free(rtqp);
- if (rtp != NULL)
- free(rtp);
- tagq_free(sp, tqp);
- return (1);
-}
-
-/*
- * ex_tag_next --
- * Switch context to the next TAG.
- *
- * PUBLIC: int ex_tag_next __P((SCR *, EXCMD *));
- */
-int
-ex_tag_next(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- EX_PRIVATE *exp;
- TAG *tp;
- TAGQ *tqp;
-
- exp = EXP(sp);
- if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
- tag_msg(sp, TAG_EMPTY, NULL);
- return (1);
- }
- if ((tp = tqp->current->q.cqe_next) == (void *)&tqp->tagq) {
- msgq(sp, M_ERR, "282|Already at the last tag of this group");
- return (1);
- }
- if (ex_tag_nswitch(sp, tp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
- return (1);
- tqp->current = tp;
-
- if (F_ISSET(tqp, TAG_CSCOPE))
- (void)cscope_search(sp, tqp, tp);
- else
- (void)ctag_search(sp, tp->search, tp->slen, tqp->tag);
- return (0);
-}
-
-/*
- * ex_tag_prev --
- * Switch context to the next TAG.
- *
- * PUBLIC: int ex_tag_prev __P((SCR *, EXCMD *));
- */
-int
-ex_tag_prev(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- EX_PRIVATE *exp;
- TAG *tp;
- TAGQ *tqp;
-
- exp = EXP(sp);
- if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
- tag_msg(sp, TAG_EMPTY, NULL);
- return (0);
- }
- if ((tp = tqp->current->q.cqe_prev) == (void *)&tqp->tagq) {
- msgq(sp, M_ERR, "255|Already at the first tag of this group");
- return (1);
- }
- if (ex_tag_nswitch(sp, tp, FL_ISSET(cmdp->iflags, E_C_FORCE)))
- return (1);
- tqp->current = tp;
-
- if (F_ISSET(tqp, TAG_CSCOPE))
- (void)cscope_search(sp, tqp, tp);
- else
- (void)ctag_search(sp, tp->search, tp->slen, tqp->tag);
- return (0);
-}
-
-/*
- * ex_tag_nswitch --
- * Switch context to the specified TAG.
- *
- * PUBLIC: int ex_tag_nswitch __P((SCR *, TAG *, int));
- */
-int
-ex_tag_nswitch(sp, tp, force)
- SCR *sp;
- TAG *tp;
- int force;
-{
- /* Get a file structure. */
- if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL)
- return (1);
-
- /* If not changing files, return, we're done. */
- if (tp->frp == sp->frp)
- return (0);
-
- /* Check for permission to leave. */
- if (file_m1(sp, force, FS_ALL | FS_POSSIBLE))
- return (1);
-
- /* Initialize the new file. */
- if (file_init(sp, tp->frp, NULL, FS_SETALT))
- return (1);
-
- /* Display tags in the center of the screen. */
- F_CLR(sp, SC_SCR_TOP);
- F_SET(sp, SC_SCR_CENTER);
-
- /* Switch. */
- F_SET(sp, SC_FSWITCH);
- return (0);
-}
-
-/*
- * ex_tag_Nswitch --
- * Switch context to the specified TAG in a new screen.
- *
- * PUBLIC: int ex_tag_Nswitch __P((SCR *, TAG *, int));
- */
-int
-ex_tag_Nswitch(sp, tp, force)
- SCR *sp;
- TAG *tp;
- int force;
-{
- SCR *new;
-
- /* Get a file structure. */
- if (tp->frp == NULL && (tp->frp = file_add(sp, tp->fname)) == NULL)
- return (1);
-
- /* Get a new screen. */
- if (screen_init(sp->gp, sp, &new))
- return (1);
- if (vs_split(sp, new, 0)) {
- (void)file_end(new, new->ep, 1);
- (void)screen_end(new);
- return (1);
- }
-
- /* Get a backing file. */
- if (tp->frp == sp->frp) {
- /* Copy file state. */
- new->ep = sp->ep;
- ++new->ep->refcnt;
-
- new->frp = tp->frp;
- new->frp->flags = sp->frp->flags;
- } else if (file_init(new, tp->frp, NULL, force)) {
- (void)vs_discard(new, NULL);
- (void)screen_end(new);
- return (1);
- }
-
- /* Create the argument list. */
- new->cargv = new->argv = ex_buildargv(sp, NULL, tp->frp->name);
-
- /* Display tags in the center of the screen. */
- F_CLR(new, SC_SCR_TOP);
- F_SET(new, SC_SCR_CENTER);
-
- /* Switch. */
- sp->nextdisp = new;
- F_SET(sp, SC_SSWITCH);
-
- return (0);
-}
-
-/*
- * ex_tag_pop -- ^T
- * :tagp[op][!] [number | file]
- *
- * Pop to a previous TAGQ context.
- *
- * PUBLIC: int ex_tag_pop __P((SCR *, EXCMD *));
- */
-int
-ex_tag_pop(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- EX_PRIVATE *exp;
- TAGQ *tqp, *dtqp;
- size_t arglen;
- long off;
- char *arg, *p, *t;
-
- /* Check for an empty stack. */
- exp = EXP(sp);
- if (exp->tq.cqh_first == (void *)&exp->tq) {
- tag_msg(sp, TAG_EMPTY, NULL);
- return (1);
- }
-
- /* Find the last TAG structure that we're going to DISCARD! */
- switch (cmdp->argc) {
- case 0: /* Pop one tag. */
- dtqp = exp->tq.cqh_first;
- break;
- case 1: /* Name or number. */
- arg = cmdp->argv[0]->bp;
- off = strtol(arg, &p, 10);
- if (*p != '\0')
- goto filearg;
-
- /* Number: pop that many queue entries. */
- if (off < 1)
- return (0);
- for (tqp = exp->tq.cqh_first;
- tqp != (void *)&exp->tq && --off > 1;
- tqp = tqp->q.cqe_next);
- if (tqp == (void *)&exp->tq) {
- msgq(sp, M_ERR,
- "159|Less than %s entries on the tags stack; use :display t[ags]",
- arg);
- return (1);
- }
- dtqp = tqp;
- break;
-
- /* File argument: pop to that queue entry. */
-filearg: arglen = strlen(arg);
- for (tqp = exp->tq.cqh_first;
- tqp != (void *)&exp->tq;
- dtqp = tqp, tqp = tqp->q.cqe_next) {
- /* Don't pop to the current file. */
- if (tqp == exp->tq.cqh_first)
- continue;
- p = tqp->current->frp->name;
- if ((t = strrchr(p, '/')) == NULL)
- t = p;
- else
- ++t;
- if (!strncmp(arg, t, arglen))
- break;
- }
- if (tqp == (void *)&exp->tq) {
- msgq_str(sp, M_ERR, arg,
- "160|No file %s on the tags stack to return to; use :display t[ags]");
- return (1);
- }
- if (tqp == exp->tq.cqh_first)
- return (0);
- break;
- default:
- abort();
- }
-
- return (tag_pop(sp, dtqp, FL_ISSET(cmdp->iflags, E_C_FORCE)));
-}
-
-/*
- * ex_tag_top -- :tagt[op][!]
- * Clear the tag stack.
- *
- * PUBLIC: int ex_tag_top __P((SCR *, EXCMD *));
- */
-int
-ex_tag_top(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- EX_PRIVATE *exp;
-
- exp = EXP(sp);
-
- /* Check for an empty stack. */
- if (exp->tq.cqh_first == (void *)&exp->tq) {
- tag_msg(sp, TAG_EMPTY, NULL);
- return (1);
- }
-
- /* Return to the oldest information. */
- return (tag_pop(sp,
- exp->tq.cqh_last->q.cqe_prev, FL_ISSET(cmdp->iflags, E_C_FORCE)));
-}
-
-/*
- * tag_pop --
- * Pop up to and including the specified TAGQ context.
- */
-static int
-tag_pop(sp, dtqp, force)
- SCR *sp;
- TAGQ *dtqp;
- int force;
-{
- EX_PRIVATE *exp;
- TAG *tp;
- TAGQ *tqp;
-
- exp = EXP(sp);
-
- /*
- * Update the cursor from the saved TAG information of the TAG
- * structure we're moving to.
- */
- tp = dtqp->q.cqe_next->current;
- if (tp->frp == sp->frp) {
- sp->lno = tp->lno;
- sp->cno = tp->cno;
- } else {
- if (file_m1(sp, force, FS_ALL | FS_POSSIBLE))
- return (1);
-
- tp->frp->lno = tp->lno;
- tp->frp->cno = tp->cno;
- F_SET(sp->frp, FR_CURSORSET);
- if (file_init(sp, tp->frp, NULL, FS_SETALT))
- return (1);
-
- F_SET(sp, SC_FSWITCH);
- }
-
- /* Pop entries off the queue up to and including dtqp. */
- do {
- tqp = exp->tq.cqh_first;
- if (tagq_free(sp, tqp))
- return (0);
- } while (tqp != dtqp);
-
- /*
- * If only a single tag left, we've returned to the first tag point,
- * and the stack is now empty.
- */
- if (exp->tq.cqh_first->q.cqe_next == (void *)&exp->tq)
- tagq_free(sp, exp->tq.cqh_first);
-
- return (0);
-}
-
-/*
- * ex_tag_display --
- * Display the list of tags.
- *
- * PUBLIC: int ex_tag_display __P((SCR *));
- */
-int
-ex_tag_display(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- TAG *tp;
- TAGQ *tqp;
- int cnt;
- size_t len;
- char *p, *sep;
-
- exp = EXP(sp);
- if ((tqp = exp->tq.cqh_first) == (void *)&exp->tq) {
- tag_msg(sp, TAG_EMPTY, NULL);
- return (0);
- }
-
- /*
- * We give the file name 20 columns and the search string the rest.
- * If there's not enough room, we don't do anything special, it's
- * not worth the effort, it just makes the display more confusing.
- *
- * We also assume that characters in file names map 1-1 to printing
- * characters. This might not be true, but I don't think it's worth
- * fixing. (The obvious fix is to pass the filenames through the
- * msg_print function.)
- */
-#define L_NAME 30 /* Name. */
-#define L_SLOP 4 /* Leading number plus trailing *. */
-#define L_SPACE 5 /* Spaces after name, before tag. */
-#define L_TAG 20 /* Tag. */
- if (sp->cols <= L_NAME + L_SLOP) {
- msgq(sp, M_ERR, "292|Display too small.");
- return (0);
- }
-
- /*
- * Display the list of tags for each queue entry. The first entry
- * is numbered, and the current tag entry has an asterisk appended.
- */
- for (cnt = 1, tqp = exp->tq.cqh_first; !INTERRUPTED(sp) &&
- tqp != (void *)&exp->tq; ++cnt, tqp = tqp->q.cqe_next)
- for (tp = tqp->tagq.cqh_first;
- tp != (void *)&tqp->tagq; tp = tp->q.cqe_next) {
- if (tp == tqp->tagq.cqh_first)
- (void)ex_printf(sp, "%2d ", cnt);
- else
- (void)ex_printf(sp, " ");
- p = tp->frp == NULL ? tp->fname : tp->frp->name;
- if ((len = strlen(p)) > L_NAME) {
- len = len - (L_NAME - 4);
- (void)ex_printf(sp, " ... %*.*s",
- L_NAME - 4, L_NAME - 4, p + len);
- } else
- (void)ex_printf(sp,
- " %*.*s", L_NAME, L_NAME, p);
- if (tqp->current == tp)
- (void)ex_printf(sp, "*");
-
- if (tp == tqp->tagq.cqh_first && tqp->tag != NULL &&
- (sp->cols - L_NAME) >= L_TAG + L_SPACE) {
- len = strlen(tqp->tag);
- if (len > sp->cols - (L_NAME + L_SPACE))
- len = sp->cols - (L_NAME + L_SPACE);
- (void)ex_printf(sp, "%s%.*s",
- tqp->current == tp ? " " : " ",
- (int)len, tqp->tag);
- }
- (void)ex_printf(sp, "\n");
- }
- return (0);
-}
-
-/*
- * ex_tag_copy --
- * Copy a screen's tag structures.
- *
- * PUBLIC: int ex_tag_copy __P((SCR *, SCR *));
- */
-int
-ex_tag_copy(orig, sp)
- SCR *orig, *sp;
-{
- EX_PRIVATE *oexp, *nexp;
- TAGQ *aqp, *tqp;
- TAG *ap, *tp;
- TAGF *atfp, *tfp;
-
- oexp = EXP(orig);
- nexp = EXP(sp);
-
- /* Copy tag queue and tags stack. */
- for (aqp = oexp->tq.cqh_first;
- aqp != (void *)&oexp->tq; aqp = aqp->q.cqe_next) {
- if (tagq_copy(sp, aqp, &tqp))
- return (1);
- for (ap = aqp->tagq.cqh_first;
- ap != (void *)&aqp->tagq; ap = ap->q.cqe_next) {
- if (tag_copy(sp, ap, &tp))
- return (1);
- /* Set the current pointer. */
- if (aqp->current == ap)
- tqp->current = tp;
- CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
- }
- CIRCLEQ_INSERT_TAIL(&nexp->tq, tqp, q);
- }
-
- /* Copy list of tag files. */
- for (atfp = oexp->tagfq.tqh_first;
- atfp != NULL; atfp = atfp->q.tqe_next) {
- if (tagf_copy(sp, atfp, &tfp))
- return (1);
- TAILQ_INSERT_TAIL(&nexp->tagfq, tfp, q);
- }
-
- /* Copy the last tag. */
- if (oexp->tag_last != NULL &&
- (nexp->tag_last = strdup(oexp->tag_last)) == NULL) {
- msgq(sp, M_SYSERR, NULL);
- return (1);
- }
- return (0);
-}
-
-/*
- * tagf_copy --
- * Copy a TAGF structure and return it in new memory.
- */
-static int
-tagf_copy(sp, otfp, tfpp)
- SCR *sp;
- TAGF *otfp, **tfpp;
-{
- TAGF *tfp;
-
- MALLOC_RET(sp, tfp, TAGF *, sizeof(TAGF));
- *tfp = *otfp;
-
- /* XXX: Allocate as part of the TAGF structure!!! */
- if ((tfp->name = strdup(otfp->name)) == NULL)
- return (1);
-
- *tfpp = tfp;
- return (0);
-}
-
-/*
- * tagq_copy --
- * Copy a TAGQ structure and return it in new memory.
- */
-static int
-tagq_copy(sp, otqp, tqpp)
- SCR *sp;
- TAGQ *otqp, **tqpp;
-{
- TAGQ *tqp;
- size_t len;
-
- len = sizeof(TAGQ);
- if (otqp->tag != NULL)
- len += otqp->tlen + 1;
- MALLOC_RET(sp, tqp, TAGQ *, len);
- memcpy(tqp, otqp, len);
-
- CIRCLEQ_INIT(&tqp->tagq);
- tqp->current = NULL;
- if (otqp->tag != NULL)
- tqp->tag = tqp->buf;
-
- *tqpp = tqp;
- return (0);
-}
-
-/*
- * tag_copy --
- * Copy a TAG structure and return it in new memory.
- */
-static int
-tag_copy(sp, otp, tpp)
- SCR *sp;
- TAG *otp, **tpp;
-{
- TAG *tp;
- size_t len;
-
- len = sizeof(TAG);
- if (otp->fname != NULL)
- len += otp->fnlen + 1;
- if (otp->search != NULL)
- len += otp->slen + 1;
- MALLOC_RET(sp, tp, TAG *, len);
- memcpy(tp, otp, len);
-
- if (otp->fname != NULL)
- tp->fname = tp->buf;
- if (otp->search != NULL)
- tp->search = tp->fname + otp->fnlen + 1;
-
- *tpp = tp;
- return (0);
-}
-
-/*
- * tagf_free --
- * Free a TAGF structure.
- */
-static int
-tagf_free(sp, tfp)
- SCR *sp;
- TAGF *tfp;
-{
- EX_PRIVATE *exp;
-
- exp = EXP(sp);
- TAILQ_REMOVE(&exp->tagfq, tfp, q);
- free(tfp->name);
- free(tfp);
- return (0);
-}
-
-/*
- * tagq_free --
- * Free a TAGQ structure (and associated TAG structures).
- *
- * PUBLIC: int tagq_free __P((SCR *, TAGQ *));
- */
-int
-tagq_free(sp, tqp)
- SCR *sp;
- TAGQ *tqp;
-{
- EX_PRIVATE *exp;
- TAG *tp;
-
- exp = EXP(sp);
- while ((tp = tqp->tagq.cqh_first) != (void *)&tqp->tagq) {
- CIRCLEQ_REMOVE(&tqp->tagq, tp, q);
- free(tp);
- }
- /*
- * !!!
- * If allocated and then the user failed to switch files, the TAGQ
- * structure was never attached to any list.
- */
- if (tqp->q.cqe_next != NULL)
- CIRCLEQ_REMOVE(&exp->tq, tqp, q);
- free(tqp);
- return (0);
-}
-
-/*
- * tag_msg
- * A few common messages.
- *
- * PUBLIC: void tag_msg __P((SCR *, tagmsg_t, char *));
- */
-void
-tag_msg(sp, msg, tag)
- SCR *sp;
- tagmsg_t msg;
- char *tag;
-{
- switch (msg) {
- case TAG_BADLNO:
- msgq_str(sp, M_ERR, tag,
- "164|%s: the tag's line number is past the end of the file");
- break;
- case TAG_EMPTY:
- msgq(sp, M_INFO, "165|The tags stack is empty");
- break;
- case TAG_SEARCH:
- msgq_str(sp, M_ERR, tag, "166|%s: search pattern not found");
- break;
- default:
- abort();
- }
-}
-
-/*
- * ex_tagf_alloc --
- * Create a new list of ctag files.
- *
- * PUBLIC: int ex_tagf_alloc __P((SCR *, char *));
- */
-int
-ex_tagf_alloc(sp, str)
- SCR *sp;
- char *str;
-{
- EX_PRIVATE *exp;
- TAGF *tfp;
- size_t len;
- char *p, *t;
-
- /* Free current queue. */
- exp = EXP(sp);
- while ((tfp = exp->tagfq.tqh_first) != NULL)
- tagf_free(sp, tfp);
-
- /* Create new queue. */
- for (p = t = str;; ++p) {
- if (*p == '\0' || isblank(*p)) {
- if ((len = p - t) > 1) {
- MALLOC_RET(sp, tfp, TAGF *, sizeof(TAGF));
- MALLOC(sp, tfp->name, char *, len + 1);
- if (tfp->name == NULL) {
- free(tfp);
- return (1);
- }
- memcpy(tfp->name, t, len);
- tfp->name[len] = '\0';
- tfp->flags = 0;
- TAILQ_INSERT_TAIL(&exp->tagfq, tfp, q);
- }
- t = p + 1;
- }
- if (*p == '\0')
- break;
- }
- return (0);
-}
- /* Free previous queue. */
-/*
- * ex_tag_free --
- * Free the ex tag information.
- *
- * PUBLIC: int ex_tag_free __P((SCR *));
- */
-int
-ex_tag_free(sp)
- SCR *sp;
-{
- EX_PRIVATE *exp;
- TAGF *tfp;
- TAGQ *tqp;
-
- /* Free up tag information. */
- exp = EXP(sp);
- while ((tqp = exp->tq.cqh_first) != (void *)&exp->tq)
- tagq_free(sp, tqp);
- while ((tfp = exp->tagfq.tqh_first) != NULL)
- tagf_free(sp, tfp);
- if (exp->tag_last != NULL)
- free(exp->tag_last);
- return (0);
-}
-
-/*
- * ctag_search --
- * Search a file for a tag.
- */
-static int
-ctag_search(sp, search, slen, tag)
- SCR *sp;
- char *search, *tag;
- size_t slen;
-{
- MARK m;
- char *p;
-
- /*
- * !!!
- * The historic tags file format (from a long, long time ago...)
- * used a line number, not a search string. I got complaints, so
- * people are still using the format. POSIX 1003.2 permits it.
- */
- if (isdigit(search[0])) {
- m.lno = atoi(search);
- if (!db_exist(sp, m.lno)) {
- tag_msg(sp, TAG_BADLNO, tag);
- return (1);
- }
- } else {
- /*
- * Search for the tag; cheap fallback for C functions
- * if the name is the same but the arguments have changed.
- */
- m.lno = 1;
- m.cno = 0;
- if (f_search(sp, &m, &m,
- search, slen, NULL, SEARCH_FILE | SEARCH_TAG))
- if ((p = strrchr(search, '(')) != NULL) {
- slen = p - search;
- if (f_search(sp, &m, &m, search, slen,
- NULL, SEARCH_FILE | SEARCH_TAG))
- goto notfound;
- } else {
-notfound: tag_msg(sp, TAG_SEARCH, tag);
- return (1);
- }
- /*
- * !!!
- * Historically, tags set the search direction if it wasn't
- * already set.
- */
- if (sp->searchdir == NOTSET)
- sp->searchdir = FORWARD;
- }
-
- /*
- * !!!
- * Tags move to the first non-blank, NOT the search pattern start.
- */
- sp->lno = m.lno;
- sp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- return (0);
-}
-
-/*
- * ctag_slist --
- * Search the list of tags files for a tag, and return tag queue.
- */
-static TAGQ *
-ctag_slist(sp, tag)
- SCR *sp;
- char *tag;
-{
- EX_PRIVATE *exp;
- TAGF *tfp;
- TAGQ *tqp;
- size_t len;
- int echk;
-
- exp = EXP(sp);
-
- /* Allocate and initialize the tag queue structure. */
- len = strlen(tag);
- CALLOC_GOTO(sp, tqp, TAGQ *, 1, sizeof(TAGQ) + len + 1);
- CIRCLEQ_INIT(&tqp->tagq);
- tqp->tag = tqp->buf;
- memcpy(tqp->tag, tag, (tqp->tlen = len) + 1);
-
- /*
- * Find the tag, only display missing file messages once, and
- * then only if we didn't find the tag.
- */
- for (echk = 0,
- tfp = exp->tagfq.tqh_first; tfp != NULL; tfp = tfp->q.tqe_next)
- if (ctag_sfile(sp, tfp, tqp, tag)) {
- echk = 1;
- F_SET(tfp, TAGF_ERR);
- } else
- F_CLR(tfp, TAGF_ERR | TAGF_ERR_WARN);
-
- /* Check to see if we found anything. */
- if (tqp->tagq.cqh_first == (void *)&tqp->tagq) {
- msgq_str(sp, M_ERR, tag, "162|%s: tag not found");
- if (echk)
- for (tfp = exp->tagfq.tqh_first;
- tfp != NULL; tfp = tfp->q.tqe_next)
- if (F_ISSET(tfp, TAGF_ERR) &&
- !F_ISSET(tfp, TAGF_ERR_WARN)) {
- errno = tfp->errnum;
- msgq_str(sp, M_SYSERR, tfp->name, "%s");
- F_SET(tfp, TAGF_ERR_WARN);
- }
- free(tqp);
- return (NULL);
- }
-
- tqp->current = tqp->tagq.cqh_first;
- return (tqp);
-
-alloc_err:
- return (NULL);
-}
-
-/*
- * ctag_sfile --
- * Search a tags file for a tag, adding any found to the tag queue.
- */
-static int
-ctag_sfile(sp, tfp, tqp, tname)
- SCR *sp;
- TAGF *tfp;
- TAGQ *tqp;
- char *tname;
-{
- struct stat sb;
- TAG *tp;
- size_t dlen, nlen, slen;
- int fd, i, nf1, nf2;
- char *back, *cname, *dname, *front, *map, *name, *p, *search, *t;
-
- if ((fd = open(tfp->name, O_RDONLY, 0)) < 0) {
- tfp->errnum = errno;
- return (1);
- }
-
- /*
- * XXX
- * Some old BSD systems require MAP_FILE as an argument when mapping
- * regular files.
- */
-#ifndef MAP_FILE
-#define MAP_FILE 0
-#endif
- /*
- * XXX
- * We'd like to test if the file is too big to mmap. Since we don't
- * know what size or type off_t's or size_t's are, what the largest
- * unsigned integral type is, or what random insanity the local C
- * compiler will perpetrate, doing the comparison in a portable way
- * is flatly impossible. Hope mmap fails if the file is too large.
- */
- if (fstat(fd, &sb) != 0 ||
- (map = mmap(NULL, (size_t)sb.st_size, PROT_READ | PROT_WRITE,
- MAP_FILE | MAP_PRIVATE, fd, (off_t)0)) == (caddr_t)-1) {
- tfp->errnum = errno;
- (void)close(fd);
- return (1);
- }
-
- front = map;
- back = front + sb.st_size;
- front = binary_search(tname, front, back);
- front = linear_search(tname, front, back);
- if (front == NULL)
- goto done;
-
- /*
- * Initialize and link in the tag structure(s). The historic ctags
- * file format only permitted a single tag location per tag. The
- * obvious extension to permit multiple tags locations per tag is to
- * output multiple records in the standard format. Unfortunately,
- * this won't work correctly with historic ex/vi implementations,
- * because their binary search assumes that there's only one record
- * per tag, and so will use a random tag entry if there si more than
- * one. This code handles either format.
- *
- * The tags file is in the following format:
- *
- * <tag> <filename> <line number> | <pattern>
- *
- * Figure out how long everything is so we can allocate in one swell
- * foop, but discard anything that looks wrong.
- */
- for (;;) {
- /* Nul-terminate the end of the line. */
- for (p = front; p < back && *p != '\n'; ++p);
- if (p == back || *p != '\n')
- break;
- *p = '\0';
-
- /* Update the pointers for the next time. */
- t = p + 1;
- p = front;
- front = t;
-
- /* Break the line into tokens. */
- for (i = 0; i < 2 && (t = strsep(&p, "\t ")) != NULL; ++i)
- switch (i) {
- case 0: /* Tag. */
- cname = t;
- break;
- case 1: /* Filename. */
- name = t;
- nlen = strlen(name);
- break;
- }
-
- /* Check for corruption. */
- if (i != 2 || p == NULL || t == NULL)
- goto corrupt;
-
- /* The rest of the string is the search pattern. */
- search = p;
- if ((slen = strlen(p)) == 0) {
-corrupt: p = msg_print(sp, tname, &nf1);
- t = msg_print(sp, tfp->name, &nf2);
- msgq(sp, M_ERR, "163|%s: corrupted tag in %s", p, t);
- if (nf1)
- FREE_SPACE(sp, p, 0);
- if (nf2)
- FREE_SPACE(sp, t, 0);
- continue;
- }
-
- /* Check for passing the last entry. */
- if (strcmp(tname, cname))
- break;
-
- /* Resolve the file name. */
- ctag_file(sp, tfp, name, &dname, &dlen);
-
- CALLOC_GOTO(sp, tp,
- TAG *, 1, sizeof(TAG) + dlen + 2 + nlen + 1 + slen + 1);
- tp->fname = tp->buf;
- if (dlen != 0) {
- memcpy(tp->fname, dname, dlen);
- tp->fname[dlen] = '/';
- ++dlen;
- }
- memcpy(tp->fname + dlen, name, nlen + 1);
- tp->fnlen = dlen + nlen;
- tp->search = tp->fname + tp->fnlen + 1;
- memcpy(tp->search, search, (tp->slen = slen) + 1);
- CIRCLEQ_INSERT_TAIL(&tqp->tagq, tp, q);
- }
-
-alloc_err:
-done: if (munmap(map, (size_t)sb.st_size))
- msgq(sp, M_SYSERR, "munmap");
- if (close(fd))
- msgq(sp, M_SYSERR, "close");
- return (0);
-}
-
-/*
- * ctag_file --
- * Search for the right path to this file.
- */
-static void
-ctag_file(sp, tfp, name, dirp, dlenp)
- SCR *sp;
- TAGF *tfp;
- char *name, **dirp;
- size_t *dlenp;
-{
- struct stat sb;
- size_t len;
- char *p, buf[MAXPATHLEN];
-
- /*
- * !!!
- * If the tag file path is a relative path, see if it exists. If it
- * doesn't, look relative to the tags file path. It's okay for a tag
- * file to not exist, and historically, vi simply displayed a "new"
- * file. However, if the path exists relative to the tag file, it's
- * pretty clear what's happening, so we may as well get it right.
- */
- *dlenp = 0;
- if (name[0] != '/' &&
- stat(name, &sb) && (p = strrchr(tfp->name, '/')) != NULL) {
- *p = '\0';
- len = snprintf(buf, sizeof(buf), "%s/%s", tfp->name, name);
- *p = '/';
- if (stat(buf, &sb) == 0) {
- *dirp = tfp->name;
- *dlenp = strlen(*dirp);
- }
- }
-}
-
-/*
- * Binary search for "string" in memory between "front" and "back".
- *
- * This routine is expected to return a pointer to the start of a line at
- * *or before* the first word matching "string". Relaxing the constraint
- * this way simplifies the algorithm.
- *
- * Invariants:
- * front points to the beginning of a line at or before the first
- * matching string.
- *
- * back points to the beginning of a line at or after the first
- * matching line.
- *
- * Base of the Invariants.
- * front = NULL;
- * back = EOF;
- *
- * Advancing the Invariants:
- *
- * p = first newline after halfway point from front to back.
- *
- * If the string at "p" is not greater than the string to match,
- * p is the new front. Otherwise it is the new back.
- *
- * Termination:
- *
- * The definition of the routine allows it return at any point,
- * since front is always at or before the line to print.
- *
- * In fact, it returns when the chosen "p" equals "back". This
- * implies that there exists a string is least half as long as
- * (back - front), which in turn implies that a linear search will
- * be no more expensive than the cost of simply printing a string or two.
- *
- * Trying to continue with binary search at this point would be
- * more trouble than it's worth.
- */
-#define EQUAL 0
-#define GREATER 1
-#define LESS (-1)
-
-#define SKIP_PAST_NEWLINE(p, back) while (p < back && *p++ != '\n');
-
-static char *
-binary_search(string, front, back)
- register char *string, *front, *back;
-{
- register char *p;
-
- p = front + (back - front) / 2;
- SKIP_PAST_NEWLINE(p, back);
-
- while (p != back) {
- if (compare(string, p, back) == GREATER)
- front = p;
- else
- back = p;
- p = front + (back - front) / 2;
- SKIP_PAST_NEWLINE(p, back);
- }
- return (front);
-}
-
-/*
- * Find the first line that starts with string, linearly searching from front
- * to back.
- *
- * Return NULL for no such line.
- *
- * This routine assumes:
- *
- * o front points at the first character in a line.
- * o front is before or at the first line to be printed.
- */
-static char *
-linear_search(string, front, back)
- char *string, *front, *back;
-{
- while (front < back) {
- switch (compare(string, front, back)) {
- case EQUAL: /* Found it. */
- return (front);
- case LESS: /* No such string. */
- return (NULL);
- case GREATER: /* Keep going. */
- break;
- }
- SKIP_PAST_NEWLINE(front, back);
- }
- return (NULL);
-}
-
-/*
- * Return LESS, GREATER, or EQUAL depending on how the string1 compares
- * with string2 (s1 ??? s2).
- *
- * o Matches up to len(s1) are EQUAL.
- * o Matches up to len(s2) are GREATER.
- *
- * The string "s1" is null terminated. The string s2 is '\t', space, (or
- * "back") terminated.
- *
- * !!!
- * Reasonably modern ctags programs use tabs as separators, not spaces.
- * However, historic programs did use spaces, and, I got complaints.
- */
-static int
-compare(s1, s2, back)
- register char *s1, *s2, *back;
-{
- for (; *s1 && s2 < back && (*s2 != '\t' && *s2 != ' '); ++s1, ++s2)
- if (*s1 != *s2)
- return (*s1 < *s2 ? LESS : GREATER);
- return (*s1 ? GREATER : s2 < back &&
- (*s2 != '\t' && *s2 != ' ') ? LESS : EQUAL);
-}
diff --git a/contrib/nvi/ex/ex_tcl.c b/contrib/nvi/ex/ex_tcl.c
deleted file mode 100644
index 06736a7..0000000
--- a/contrib/nvi/ex/ex_tcl.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- * Copyright (c) 1995
- * George V. Neville-Neil. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_tcl.c 8.10 (Berkeley) 9/15/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-#ifdef HAVE_TCL_INTERP
-#include <tcl.h>
-#endif
-
-/*
- * ex_tcl -- :[line [,line]] tcl [command]
- * Run a command through the tcl interpreter.
- *
- * PUBLIC: int ex_tcl __P((SCR*, EXCMD *));
- */
-int
-ex_tcl(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
-#ifdef HAVE_TCL_INTERP
- CHAR_T *p;
- GS *gp;
- size_t len;
- char buf[128];
-
- /* Initialize the interpreter. */
- gp = sp->gp;
- if (gp->tcl_interp == NULL && tcl_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(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
-
- (void)snprintf(buf, sizeof(buf),
- "set viScreenId %d\nset viStartLine %lu\nset viStopLine %lu",
- sp->id, cmdp->addr1.lno, cmdp->addr2.lno);
- if (Tcl_Eval(gp->tcl_interp, buf) == TCL_OK &&
- Tcl_Eval(gp->tcl_interp, cmdp->argv[0]->bp) == TCL_OK)
- return (0);
-
- msgq(sp, M_ERR, "Tcl: %s", ((Tcl_Interp *)gp->tcl_interp)->result);
- return (1);
-#else
- msgq(sp, M_ERR, "302|Vi was not loaded with a Tcl interpreter");
- return (1);
-#endif /* HAVE_TCL_INTERP */
-}
diff --git a/contrib/nvi/ex/ex_txt.c b/contrib/nvi/ex/ex_txt.c
deleted file mode 100644
index 2f62ff5..0000000
--- a/contrib/nvi/ex/ex_txt.c
+++ /dev/null
@@ -1,430 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_txt.c 10.17 (Berkeley) 10/10/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * !!!
- * The backslash characters was special when it preceded a newline as part of
- * a substitution replacement pattern. For example, the input ":a\<cr>" would
- * failed immediately with an error, as the <cr> wasn't part of a substitution
- * replacement pattern. This implies a frightening integration of the editor
- * and the parser and/or the RE engine. There's no way I'm going to reproduce
- * those semantics.
- *
- * So, if backslashes are special, this code inserts the backslash and the next
- * character into the string, without regard for the character or the command
- * being entered. Since "\<cr>" was illegal historically (except for the one
- * special case), and the command will fail eventually, no historical scripts
- * should break (presuming they didn't depend on the failure mode itself or the
- * characters remaining when failure occurred.
- */
-
-static int txt_dent __P((SCR *, TEXT *));
-static void txt_prompt __P((SCR *, TEXT *, ARG_CHAR_T, u_int32_t));
-
-/*
- * ex_txt --
- * Get lines from the terminal for ex.
- *
- * PUBLIC: int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t));
- */
-int
-ex_txt(sp, tiqh, prompt, flags)
- SCR *sp;
- TEXTH *tiqh;
- ARG_CHAR_T prompt;
- u_int32_t flags;
-{
- EVENT ev;
- GS *gp;
- TEXT ait, *ntp, *tp;
- carat_t carat_st;
- size_t cnt;
- int rval;
-
- rval = 0;
-
- /*
- * Get a TEXT structure with some initial buffer space, reusing the
- * last one if it's big enough. (All TEXT bookkeeping fields default
- * to 0 -- text_init() handles this.)
- */
- if (tiqh->cqh_first != (void *)tiqh) {
- tp = tiqh->cqh_first;
- if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < 32) {
- text_lfree(tiqh);
- goto newtp;
- }
- tp->len = 0;
- } else {
-newtp: if ((tp = text_init(sp, NULL, 0, 32)) == NULL)
- goto err;
- CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
- }
-
- /* Set the starting line number. */
- tp->lno = sp->lno + 1;
-
- /*
- * If it's a terminal, set up autoindent, put out the prompt, and
- * set it up so we know we were suspended. Otherwise, turn off
- * the autoindent flag, as that requires less special casing below.
- *
- * XXX
- * Historic practice is that ^Z suspended command mode (but, because
- * it ran in cooked mode, it was unaffected by the autowrite option.)
- * On restart, any "current" input was discarded, whether in insert
- * mode or not, and ex was in command mode. This code matches historic
- * practice, but not 'cause it's easier.
- */
- gp = sp->gp;
- if (F_ISSET(gp, G_SCRIPTED))
- LF_CLR(TXT_AUTOINDENT);
- else {
- if (LF_ISSET(TXT_AUTOINDENT)) {
- LF_SET(TXT_EOFCHAR);
- if (v_txt_auto(sp, sp->lno, NULL, 0, tp))
- goto err;
- }
- txt_prompt(sp, tp, prompt, flags);
- }
-
- for (carat_st = C_NOTSET;;) {
- if (v_event_get(sp, &ev, 0, 0))
- goto err;
-
- /* Deal with all non-character events. */
- switch (ev.e_event) {
- case E_CHARACTER:
- break;
- case E_ERR:
- goto err;
- case E_REPAINT:
- case E_WRESIZE:
- continue;
- case E_EOF:
- rval = 1;
- /* FALLTHROUGH */
- case E_INTERRUPT:
- /*
- * Handle EOF/SIGINT events by discarding partially
- * entered text and returning. EOF returns failure,
- * E_INTERRUPT returns success.
- */
- goto notlast;
- default:
- v_event_err(sp, &ev);
- goto notlast;
- }
-
- /*
- * Deal with character events.
- *
- * Check to see if the character fits into the input buffer.
- * (Use tp->len, ignore overwrite and non-printable chars.)
- */
- BINC_GOTO(sp, tp->lb, tp->lb_len, tp->len + 1);
-
- switch (ev.e_value) {
- case K_CR:
- /*
- * !!!
- * Historically, <carriage-return>'s in the command
- * weren't special, so the ex parser would return an
- * unknown command error message. However, if they
- * terminated the command if they were in a map. I'm
- * pretty sure this still isn't right, but it handles
- * what I've seen so far.
- */
- if (!F_ISSET(&ev.e_ch, CH_MAPPED))
- goto ins_ch;
- /* FALLTHROUGH */
- case K_NL:
- /*
- * '\' can escape <carriage-return>/<newline>. We
- * don't discard the backslash because we need it
- * to get the <newline> through the ex parser.
- */
- if (LF_ISSET(TXT_BACKSLASH) &&
- tp->len != 0 && tp->lb[tp->len - 1] == '\\')
- goto ins_ch;
-
- /*
- * CR returns from the ex command line.
- *
- * XXX
- * Terminate with a nul, needed by filter.
- */
- if (LF_ISSET(TXT_CR)) {
- tp->lb[tp->len] = '\0';
- goto done;
- }
-
- /*
- * '.' may terminate text input mode; free the current
- * TEXT.
- */
- if (LF_ISSET(TXT_DOTTERM) && tp->len == tp->ai + 1 &&
- tp->lb[tp->len - 1] == '.') {
-notlast: CIRCLEQ_REMOVE(tiqh, tp, q);
- text_free(tp);
- goto done;
- }
-
- /* Set up bookkeeping for the new line. */
- if ((ntp = text_init(sp, NULL, 0, 32)) == NULL)
- goto err;
- ntp->lno = tp->lno + 1;
-
- /*
- * Reset the autoindent line value. 0^D keeps the ai
- * line from changing, ^D changes the level, even if
- * there were no characters in the old line. Note, if
- * using the current tp structure, use the cursor as
- * the length, the autoindent characters may have been
- * erased.
- */
- if (LF_ISSET(TXT_AUTOINDENT)) {
- if (carat_st == C_NOCHANGE) {
- if (v_txt_auto(sp,
- OOBLNO, &ait, ait.ai, ntp))
- goto err;
- free(ait.lb);
- } else
- if (v_txt_auto(sp,
- OOBLNO, tp, tp->len, ntp))
- goto err;
- carat_st = C_NOTSET;
- }
- txt_prompt(sp, ntp, prompt, flags);
-
- /*
- * Swap old and new TEXT's, and insert the new TEXT
- * into the queue.
- */
- tp = ntp;
- CIRCLEQ_INSERT_TAIL(tiqh, tp, q);
- break;
- case K_CARAT: /* Delete autoindent chars. */
- if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
- carat_st = C_CARATSET;
- goto ins_ch;
- case K_ZERO: /* Delete autoindent chars. */
- if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
- carat_st = C_ZEROSET;
- goto ins_ch;
- case K_CNTRLD: /* Delete autoindent char. */
- /*
- * !!!
- * Historically, the ^D command took (but then ignored)
- * a count. For simplicity, we don't return it unless
- * it's the first character entered. The check for len
- * equal to 0 is okay, TXT_AUTOINDENT won't be set.
- */
- if (LF_ISSET(TXT_CNTRLD)) {
- for (cnt = 0; cnt < tp->len; ++cnt)
- if (!isblank(tp->lb[cnt]))
- break;
- if (cnt == tp->len) {
- tp->len = 1;
- tp->lb[0] = ev.e_c;
- tp->lb[1] = '\0';
-
- /*
- * Put out a line separator, in case
- * the command fails.
- */
- (void)putchar('\n');
- goto done;
- }
- }
-
- /*
- * POSIX 1003.1b-1993, paragraph 7.1.1.9, states that
- * the EOF characters are discarded if there are other
- * characters to process in the line, i.e. if the EOF
- * is not the first character in the line. For this
- * reason, historic ex discarded the EOF characters,
- * even if occurring in the middle of the input line.
- * We match that historic practice.
- *
- * !!!
- * The test for discarding in the middle of the line is
- * done in the switch, because the CARAT forms are N+1,
- * not N.
- *
- * !!!
- * There's considerable magic to make the terminal code
- * return the EOF character at all. See that code for
- * details.
- */
- if (!LF_ISSET(TXT_AUTOINDENT) || tp->len == 0)
- continue;
- switch (carat_st) {
- case C_CARATSET: /* ^^D */
- if (tp->len > tp->ai + 1)
- continue;
-
- /* Save the ai string for later. */
- ait.lb = NULL;
- ait.lb_len = 0;
- BINC_GOTO(sp, ait.lb, ait.lb_len, tp->ai);
- memcpy(ait.lb, tp->lb, tp->ai);
- ait.ai = ait.len = tp->ai;
-
- carat_st = C_NOCHANGE;
- goto leftmargin;
- case C_ZEROSET: /* 0^D */
- if (tp->len > tp->ai + 1)
- continue;
-
- carat_st = C_NOTSET;
-leftmargin: (void)gp->scr_ex_adjust(sp, EX_TERM_CE);
- tp->ai = tp->len = 0;
- break;
- case C_NOTSET: /* ^D */
- if (tp->len > tp->ai)
- continue;
-
- if (txt_dent(sp, tp))
- goto err;
- break;
- default:
- abort();
- }
-
- /* Clear and redisplay the line. */
- (void)gp->scr_ex_adjust(sp, EX_TERM_CE);
- txt_prompt(sp, tp, prompt, flags);
- break;
- default:
- /*
- * See the TXT_BEAUTIFY comment in vi/v_txt_ev.c.
- *
- * Silently eliminate any iscntrl() character that was
- * not already handled specially, except for <tab> and
- * <ff>.
- */
-ins_ch: if (LF_ISSET(TXT_BEAUTIFY) && iscntrl(ev.e_c) &&
- ev.e_value != K_FORMFEED && ev.e_value != K_TAB)
- break;
-
- tp->lb[tp->len++] = ev.e_c;
- break;
- }
- }
- /* NOTREACHED */
-
-done: return (rval);
-
-err:
-alloc_err:
- return (1);
-}
-
-/*
- * txt_prompt --
- * Display the ex prompt, line number, ai characters. Characters had
- * better be printable by the terminal driver, but that's its problem,
- * not ours.
- */
-static void
-txt_prompt(sp, tp, prompt, flags)
- SCR *sp;
- TEXT *tp;
- ARG_CHAR_T prompt;
- u_int32_t flags;
-{
- /* Display the prompt. */
- if (LF_ISSET(TXT_PROMPT))
- (void)printf("%c", prompt);
-
- /* Display the line number. */
- if (LF_ISSET(TXT_NUMBER) && O_ISSET(sp, O_NUMBER))
- (void)printf("%6lu ", (u_long)tp->lno);
-
- /* Print out autoindent string. */
- if (LF_ISSET(TXT_AUTOINDENT))
- (void)printf("%.*s", (int)tp->ai, tp->lb);
- (void)fflush(stdout);
-}
-
-/*
- * txt_dent --
- * Handle ^D outdents.
- *
- * Ex version of vi/v_ntext.c:txt_dent(). See that code for the (usual)
- * ranting and raving. This is a fair bit simpler as ^T isn't special.
- */
-static int
-txt_dent(sp, tp)
- SCR *sp;
- TEXT *tp;
-{
- u_long sw, ts;
- size_t cno, off, scno, spaces, tabs;
-
- ts = O_VAL(sp, O_TABSTOP);
- sw = O_VAL(sp, O_SHIFTWIDTH);
-
- /* Get the current screen column. */
- for (off = scno = 0; off < tp->len; ++off)
- if (tp->lb[off] == '\t')
- scno += COL_OFF(scno, ts);
- else
- ++scno;
-
- /* Get the previous shiftwidth column. */
- cno = scno;
- scno -= --scno % sw;
-
- /*
- * Since we don't know what comes before the character(s) being
- * deleted, we have to resolve the autoindent characters . The
- * example is a <tab>, which doesn't take up a full shiftwidth
- * number of columns because it's preceded by <space>s. This is
- * easy to get if the user sets shiftwidth to a value less than
- * tabstop, and then uses ^T to indent, and ^D to outdent.
- *
- * Count up spaces/tabs needed to get to the target.
- */
- for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
- cno += COL_OFF(cno, ts);
- spaces = scno - cno;
-
- /* Make sure there's enough room. */
- BINC_RET(sp, tp->lb, tp->lb_len, tabs + spaces + 1);
-
- /* Adjust the final ai character count. */
- tp->ai = tabs + spaces;
-
- /* Enter the replacement characters. */
- for (tp->len = 0; tabs > 0; --tabs)
- tp->lb[tp->len++] = '\t';
- for (; spaces > 0; --spaces)
- tp->lb[tp->len++] = ' ';
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_undo.c b/contrib/nvi/ex/ex_undo.c
deleted file mode 100644
index 0b0b5b2..0000000
--- a/contrib/nvi/ex/ex_undo.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_undo.c 10.6 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../common/common.h"
-
-/*
- * ex_undo -- u
- * Undo the last change.
- *
- * PUBLIC: int ex_undo __P((SCR *, EXCMD *));
- */
-int
-ex_undo(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- EXF *ep;
- MARK m;
-
- /*
- * !!!
- * Historic undo always set the previous context mark.
- */
- m.lno = sp->lno;
- m.cno = sp->cno;
- if (mark_set(sp, ABSMARK1, &m, 1))
- return (1);
-
- /*
- * !!!
- * Multiple undo isn't available in ex, as there's no '.' command.
- * Whether 'u' is undo or redo is toggled each time, unless there
- * was a change since the last undo, in which case it's an undo.
- */
- ep = sp->ep;
- if (!F_ISSET(ep, F_UNDO)) {
- F_SET(ep, F_UNDO);
- ep->lundo = FORWARD;
- }
- switch (ep->lundo) {
- case BACKWARD:
- if (log_forward(sp, &m))
- return (1);
- ep->lundo = FORWARD;
- break;
- case FORWARD:
- if (log_backward(sp, &m))
- return (1);
- ep->lundo = BACKWARD;
- break;
- case NOTSET:
- abort();
- }
- sp->lno = m.lno;
- sp->cno = m.cno;
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_usage.c b/contrib/nvi/ex/ex_usage.c
deleted file mode 100644
index cddf7a6..0000000
--- a/contrib/nvi/ex/ex_usage.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_usage.c 10.13 (Berkeley) 5/3/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-/*
- * ex_help -- :help
- * Display help message.
- *
- * PUBLIC: int ex_help __P((SCR *, EXCMD *));
- */
-int
-ex_help(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- (void)ex_puts(sp,
- "To see the list of vi commands, enter \":viusage<CR>\"\n");
- (void)ex_puts(sp,
- "To see the list of ex commands, enter \":exusage<CR>\"\n");
- (void)ex_puts(sp,
- "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n");
- (void)ex_puts(sp,
- "For a vi key usage statement enter \":viusage [key]<CR>\"\n");
- (void)ex_puts(sp, "To exit, enter \":q!\"\n");
- return (0);
-}
-
-/*
- * ex_usage -- :exusage [cmd]
- * Display ex usage strings.
- *
- * PUBLIC: int ex_usage __P((SCR *, EXCMD *));
- */
-int
-ex_usage(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- ARGS *ap;
- EXCMDLIST const *cp;
- int newscreen;
- char *name, *p, nb[MAXCMDNAMELEN + 5];
-
- switch (cmdp->argc) {
- case 1:
- ap = cmdp->argv[0];
- if (isupper(ap->bp[0])) {
- newscreen = 1;
- ap->bp[0] = tolower(ap->bp[0]);
- } else
- newscreen = 0;
- for (cp = cmds; cp->name != NULL &&
- memcmp(ap->bp, cp->name, ap->len); ++cp);
- if (cp->name == NULL ||
- newscreen && !F_ISSET(cp, E_NEWSCREEN)) {
- if (newscreen)
- ap->bp[0] = toupper(ap->bp[0]);
- (void)ex_printf(sp, "The %.*s command is unknown\n",
- (int)ap->len, ap->bp);
- } else {
- (void)ex_printf(sp,
- "Command: %s\n Usage: %s\n", cp->help, cp->usage);
- /*
- * !!!
- * The "visual" command has two modes, one from ex,
- * one from the vi colon line. Don't ask.
- */
- if (cp != &cmds[C_VISUAL_EX] &&
- cp != &cmds[C_VISUAL_VI])
- break;
- if (cp == &cmds[C_VISUAL_EX])
- cp = &cmds[C_VISUAL_VI];
- else
- cp = &cmds[C_VISUAL_EX];
- (void)ex_printf(sp,
- "Command: %s\n Usage: %s\n", cp->help, cp->usage);
- }
- break;
- case 0:
- for (cp = cmds; cp->name != NULL && !INTERRUPTED(sp); ++cp) {
- /*
- * The ^D command has an unprintable name.
- *
- * XXX
- * We display both capital and lower-case versions of
- * the appropriate commands -- no need to add in extra
- * room, they're all short names.
- */
- if (cp == &cmds[C_SCROLL])
- name = "^D";
- else if (F_ISSET(cp, E_NEWSCREEN)) {
- nb[0] = '[';
- nb[1] = toupper(cp->name[0]);
- nb[2] = cp->name[0];
- nb[3] = ']';
- for (name = cp->name + 1,
- p = nb + 4; (*p++ = *name++) != '\0';);
- name = nb;
- } else
- name = cp->name;
- (void)ex_printf(sp,
- "%*s: %s\n", MAXCMDNAMELEN, name, cp->help);
- }
- break;
- default:
- abort();
- }
- return (0);
-}
-
-/*
- * ex_viusage -- :viusage [key]
- * Display vi usage strings.
- *
- * PUBLIC: int ex_viusage __P((SCR *, EXCMD *));
- */
-int
-ex_viusage(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- GS *gp;
- VIKEYS const *kp;
- int key;
-
- gp = sp->gp;
- switch (cmdp->argc) {
- case 1:
- if (cmdp->argv[0]->len != 1) {
- ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
- key = cmdp->argv[0]->bp[0];
- if (key > MAXVIKEY)
- goto nokey;
-
- /* Special case: '[' and ']' commands. */
- if ((key == '[' || key == ']') && cmdp->argv[0]->bp[1] != key)
- goto nokey;
-
- /* Special case: ~ command. */
- if (key == '~' && O_ISSET(sp, O_TILDEOP))
- kp = &tmotion;
- else
- kp = &vikeys[key];
-
- if (kp->usage == NULL)
-nokey: (void)ex_printf(sp,
- "The %s key has no current meaning\n",
- KEY_NAME(sp, key));
- else
- (void)ex_printf(sp,
- " Key:%s%s\nUsage: %s\n",
- isblank(*kp->help) ? "" : " ", kp->help, kp->usage);
- break;
- case 0:
- for (key = 0; key <= MAXVIKEY && !INTERRUPTED(sp); ++key) {
- /* Special case: ~ command. */
- if (key == '~' && O_ISSET(sp, O_TILDEOP))
- kp = &tmotion;
- else
- kp = &vikeys[key];
- if (kp->help != NULL)
- (void)ex_printf(sp, "%s\n", kp->help);
- }
- break;
- default:
- abort();
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_util.c b/contrib/nvi/ex/ex_util.c
deleted file mode 100644
index 6c4772e..0000000
--- a/contrib/nvi/ex/ex_util.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_util.c 10.23 (Berkeley) 6/19/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <bitstring.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-/*
- * ex_cinit --
- * Create an EX command structure.
- *
- * PUBLIC: void ex_cinit __P((EXCMD *,
- * PUBLIC: int, int, recno_t, recno_t, int, ARGS **));
- */
-void
-ex_cinit(cmdp, cmd_id, naddr, lno1, lno2, force, ap)
- EXCMD *cmdp;
- int cmd_id, force, naddr;
- recno_t lno1, lno2;
- ARGS **ap;
-{
- memset(cmdp, 0, sizeof(EXCMD));
- cmdp->cmd = &cmds[cmd_id];
- cmdp->addrcnt = naddr;
- cmdp->addr1.lno = lno1;
- cmdp->addr2.lno = lno2;
- cmdp->addr1.cno = cmdp->addr2.cno = 1;
- if (force)
- cmdp->iflags |= E_C_FORCE;
- cmdp->argc = 0;
- if ((cmdp->argv = ap) != NULL)
- cmdp->argv[0] = NULL;
-}
-
-/*
- * ex_cadd --
- * Add an argument to an EX command structure.
- *
- * PUBLIC: void ex_cadd __P((EXCMD *, ARGS *, char *, size_t));
- */
-void
-ex_cadd(cmdp, ap, arg, len)
- EXCMD *cmdp;
- ARGS *ap;
- char *arg;
- size_t len;
-{
- cmdp->argv[cmdp->argc] = ap;
- ap->bp = arg;
- ap->len = len;
- cmdp->argv[++cmdp->argc] = NULL;
-}
-
-/*
- * ex_getline --
- * Return a line from the file.
- *
- * PUBLIC: int ex_getline __P((SCR *, FILE *, size_t *));
- */
-int
-ex_getline(sp, fp, lenp)
- SCR *sp;
- FILE *fp;
- size_t *lenp;
-{
- EX_PRIVATE *exp;
- size_t off;
- int ch;
- char *p;
-
- exp = EXP(sp);
- for (errno = 0, off = 0, p = exp->ibp;;) {
- if (off >= exp->ibp_len) {
- BINC_RET(sp, exp->ibp, exp->ibp_len, off + 1);
- p = exp->ibp + off;
- }
- if ((ch = getc(fp)) == EOF && !feof(fp)) {
- if (errno == EINTR) {
- errno = 0;
- clearerr(fp);
- continue;
- }
- return (1);
- }
- if (ch == EOF || ch == '\n') {
- if (ch == EOF && !off)
- return (1);
- *lenp = off;
- return (0);
- }
- *p++ = ch;
- ++off;
- }
- /* NOTREACHED */
-}
-
-/*
- * ex_ncheck --
- * Check for more files to edit.
- *
- * PUBLIC: int ex_ncheck __P((SCR *, int));
- */
-int
-ex_ncheck(sp, force)
- SCR *sp;
- int force;
-{
- char **ap;
-
- /*
- * !!!
- * Historic practice: quit! or two quit's done in succession
- * (where ZZ counts as a quit) didn't check for other files.
- */
- if (!force && sp->ccnt != sp->q_ccnt + 1 &&
- sp->cargv != NULL && sp->cargv[1] != NULL) {
- sp->q_ccnt = sp->ccnt;
-
- for (ap = sp->cargv + 1; *ap != NULL; ++ap);
- msgq(sp, M_ERR,
- "167|%d more files to edit", (ap - sp->cargv) - 1);
-
- return (1);
- }
- return (0);
-}
-
-/*
- * ex_init --
- * Init the screen for ex.
- *
- * PUBLIC: int ex_init __P((SCR *));
- */
-int
-ex_init(sp)
- SCR *sp;
-{
- GS *gp;
-
- gp = sp->gp;
-
- if (gp->scr_screen(sp, SC_EX))
- return (1);
- (void)gp->scr_attr(sp, SA_ALTERNATE, 0);
-
- sp->rows = O_VAL(sp, O_LINES);
- sp->cols = O_VAL(sp, O_COLUMNS);
-
- F_CLR(sp, SC_VI);
- F_SET(sp, SC_EX | SC_SCR_EX);
- return (0);
-}
-
-/*
- * ex_emsg --
- * Display a few common ex and vi error messages.
- *
- * PUBLIC: void ex_emsg __P((SCR *, char *, exm_t));
- */
-void
-ex_emsg(sp, p, which)
- SCR *sp;
- char *p;
- exm_t which;
-{
- switch (which) {
- case EXM_EMPTYBUF:
- msgq(sp, M_ERR, "168|Buffer %s is empty", p);
- break;
- case EXM_FILECOUNT:
- msgq_str(sp, M_ERR, p,
- "144|%s: expanded into too many file names");
- break;
- case EXM_NOCANON:
- msgq(sp, M_ERR,
- "283|The %s command requires the ex terminal interface", p);
- break;
- case EXM_NOCANON_F:
- msgq(sp, M_ERR,
- "272|That form of %s requires the ex terminal interface",
- p);
- break;
- case EXM_NOFILEYET:
- if (p == NULL)
- msgq(sp, M_ERR,
- "274|Command failed, no file read in yet.");
- else
- msgq(sp, M_ERR,
- "173|The %s command requires that a file have already been read in", p);
- break;
- case EXM_NOPREVBUF:
- msgq(sp, M_ERR, "171|No previous buffer to execute");
- break;
- case EXM_NOPREVRE:
- msgq(sp, M_ERR, "172|No previous regular expression");
- break;
- case EXM_NOSUSPEND:
- msgq(sp, M_ERR, "230|This screen may not be suspended");
- break;
- case EXM_SECURE:
- msgq(sp, M_ERR,
-"290|The %s command is not supported when the secure edit option is set", p);
- break;
- case EXM_SECURE_F:
- msgq(sp, M_ERR,
-"284|That form of %s is not supported when the secure edit option is set", p);
- break;
- case EXM_USAGE:
- msgq(sp, M_ERR, "174|Usage: %s", p);
- break;
- }
-}
diff --git a/contrib/nvi/ex/ex_version.c b/contrib/nvi/ex/ex_version.c
deleted file mode 100644
index d7363c8..0000000
--- a/contrib/nvi/ex/ex_version.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1991, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_version.c 10.31 (Berkeley) 8/22/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-#include "version.h"
-
-/*
- * ex_version -- :version
- * Display the program version.
- *
- * PUBLIC: int ex_version __P((SCR *, EXCMD *));
- */
-int
-ex_version(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- msgq(sp, M_INFO, VI_VERSION);
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_visual.c b/contrib/nvi/ex/ex_visual.c
deleted file mode 100644
index 82e503d..0000000
--- a/contrib/nvi/ex/ex_visual.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_visual.c 10.13 (Berkeley) 6/28/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/time.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-#include "../vi/vi.h"
-
-/*
- * ex_visual -- :[line] vi[sual] [^-.+] [window_size] [flags]
- * Switch to visual mode.
- *
- * PUBLIC: int ex_visual __P((SCR *, EXCMD *));
- */
-int
-ex_visual(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- SCR *tsp;
- size_t len;
- int pos;
- char buf[256];
-
- /* If open option off, disallow visual command. */
- if (!O_ISSET(sp, O_OPEN)) {
- msgq(sp, M_ERR,
- "175|The visual command requires that the open option be set");
- return (1);
- }
-
- /* Move to the address. */
- sp->lno = cmdp->addr1.lno == 0 ? 1 : cmdp->addr1.lno;
-
- /*
- * Push a command based on the line position flags. If no
- * flag specified, the line goes at the top of the screen.
- */
- switch (FL_ISSET(cmdp->iflags,
- E_C_CARAT | E_C_DASH | E_C_DOT | E_C_PLUS)) {
- case E_C_CARAT:
- pos = '^';
- break;
- case E_C_DASH:
- pos = '-';
- break;
- case E_C_DOT:
- pos = '.';
- break;
- case E_C_PLUS:
- pos = '+';
- break;
- default:
- sp->frp->lno = sp->lno;
- sp->frp->cno = 0;
- (void)nonblank(sp, sp->lno, &sp->cno);
- F_SET(sp->frp, FR_CURSORSET);
- goto nopush;
- }
-
- if (FL_ISSET(cmdp->iflags, E_C_COUNT))
- len = snprintf(buf, sizeof(buf),
- "%luz%c%lu", sp->lno, pos, cmdp->count);
- else
- len = snprintf(buf, sizeof(buf), "%luz%c", sp->lno, pos);
- (void)v_event_push(sp, NULL, buf, len, CH_NOMAP | CH_QUOTED);
-
- /*
- * !!!
- * Historically, if no line address was specified, the [p#l] flags
- * caused the cursor to be moved to the last line of the file, which
- * was then positioned as described above. This seems useless, so
- * I haven't implemented it.
- */
- switch (FL_ISSET(cmdp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT)) {
- case E_C_HASH:
- O_SET(sp, O_NUMBER);
- break;
- case E_C_LIST:
- O_SET(sp, O_LIST);
- break;
- case E_C_PRINT:
- break;
- }
-
-nopush: /*
- * !!!
- * You can call the visual part of the editor from within an ex
- * global command.
- *
- * XXX
- * Historically, undoing a visual session was a single undo command,
- * i.e. you could undo all of the changes you made in visual mode.
- * We don't get this right; I'm waiting for the new logging code to
- * be available.
- *
- * It's explicit, don't have to wait for the user, unless there's
- * already a reason to wait.
- */
- if (!F_ISSET(sp, SC_SCR_EXWROTE))
- F_SET(sp, SC_EX_WAIT_NO);
-
- if (F_ISSET(sp, SC_EX_GLOBAL)) {
- /*
- * When the vi screen(s) exit, we don't want to lose our hold
- * on this screen or this file, otherwise we're going to fail
- * fairly spectacularly.
- */
- ++sp->refcnt;
- ++sp->ep->refcnt;
-
- /*
- * Fake up a screen pointer -- vi doesn't get to change our
- * underlying file, regardless.
- */
- tsp = sp;
- if (vi(&tsp))
- return (1);
-
- /*
- * !!!
- * Historically, if the user exited the vi screen(s) using an
- * ex quit command (e.g. :wq, :q) ex/vi exited, it was only if
- * they exited vi using the Q command that ex continued. Some
- * early versions of nvi continued in ex regardless, but users
- * didn't like the semantic.
- *
- * Reset the screen.
- */
- if (ex_init(sp))
- return (1);
-
- /* Move out of the vi screen. */
- (void)ex_puts(sp, "\n");
- } else {
- F_CLR(sp, SC_EX | SC_SCR_EX);
- F_SET(sp, SC_VI);
- }
- return (0);
-}
diff --git a/contrib/nvi/ex/ex_write.c b/contrib/nvi/ex/ex_write.c
deleted file mode 100644
index b3122e3..0000000
--- a/contrib/nvi/ex/ex_write.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_write.c 10.30 (Berkeley) 7/12/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-#include <sys/stat.h>
-
-#include <bitstring.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../common/common.h"
-
-enum which {WN, WQ, WRITE, XIT};
-static int exwr __P((SCR *, EXCMD *, enum which));
-
-/*
- * ex_wn -- :wn[!] [>>] [file]
- * Write to a file and switch to the next one.
- *
- * PUBLIC: int ex_wn __P((SCR *, EXCMD *));
- */
-int
-ex_wn(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- if (exwr(sp, cmdp, WN))
- return (1);
- if (file_m3(sp, 0))
- return (1);
-
- /* The file name isn't a new file to edit. */
- cmdp->argc = 0;
-
- return (ex_next(sp, cmdp));
-}
-
-/*
- * ex_wq -- :wq[!] [>>] [file]
- * Write to a file and quit.
- *
- * PUBLIC: int ex_wq __P((SCR *, EXCMD *));
- */
-int
-ex_wq(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- int force;
-
- if (exwr(sp, cmdp, WQ))
- return (1);
- if (file_m3(sp, 0))
- return (1);
-
- force = FL_ISSET(cmdp->iflags, E_C_FORCE);
-
- if (ex_ncheck(sp, force))
- return (1);
-
- F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
- return (0);
-}
-
-/*
- * ex_write -- :write[!] [>>] [file]
- * :write [!] [cmd]
- * Write to a file.
- *
- * PUBLIC: int ex_write __P((SCR *, EXCMD *));
- */
-int
-ex_write(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- return (exwr(sp, cmdp, WRITE));
-}
-
-
-/*
- * ex_xit -- :x[it]! [file]
- * Write out any modifications and quit.
- *
- * PUBLIC: int ex_xit __P((SCR *, EXCMD *));
- */
-int
-ex_xit(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- int force;
-
- NEEDFILE(sp, cmdp);
-
- if (F_ISSET(sp->ep, F_MODIFIED) && exwr(sp, cmdp, XIT))
- return (1);
- if (file_m3(sp, 0))
- return (1);
-
- force = FL_ISSET(cmdp->iflags, E_C_FORCE);
-
- if (ex_ncheck(sp, force))
- return (1);
-
- F_SET(sp, force ? SC_EXIT_FORCE : SC_EXIT);
- return (0);
-}
-
-/*
- * exwr --
- * The guts of the ex write commands.
- */
-static int
-exwr(sp, cmdp, cmd)
- SCR *sp;
- EXCMD *cmdp;
- enum which cmd;
-{
- MARK rm;
- int flags;
- char *name, *p;
-
- NEEDFILE(sp, cmdp);
-
- /* All write commands can have an associated '!'. */
- LF_INIT(FS_POSSIBLE);
- if (FL_ISSET(cmdp->iflags, E_C_FORCE))
- LF_SET(FS_FORCE);
-
- /* Skip any leading whitespace. */
- if (cmdp->argc != 0)
- for (p = cmdp->argv[0]->bp; *p != '\0' && isblank(*p); ++p);
-
- /* If "write !" it's a pipe to a utility. */
- if (cmdp->argc != 0 && cmd == WRITE && *p == '!') {
- /* Secure means no shell access. */
- if (O_ISSET(sp, O_SECURE)) {
- ex_emsg(sp, cmdp->cmd->name, EXM_SECURE_F);
- return (1);
- }
-
- /* Expand the argument. */
- for (++p; *p && isblank(*p); ++p);
- if (*p == '\0') {
- ex_emsg(sp, cmdp->cmd->usage, EXM_USAGE);
- return (1);
- }
- if (argv_exp1(sp, cmdp, p, strlen(p), 1))
- return (1);
-
- /*
- * Historically, vi waited after a write filter even if there
- * wasn't any output from the command. People complained when
- * nvi waited only if there was output, wanting the visual cue
- * that the program hadn't written anything.
- */
- F_SET(sp, SC_EX_WAIT_YES);
-
- /*
- * !!!
- * Ignore the return cursor position, the cursor doesn't
- * move.
- */
- if (ex_filter(sp, cmdp, &cmdp->addr1,
- &cmdp->addr2, &rm, cmdp->argv[1]->bp, FILTER_WRITE))
- return (1);
-
- /* Ex terminates with a bang, even if the command fails. */
- if (!F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_EX_SILENT))
- (void)ex_puts(sp, "!\n");
-
- return (0);
- }
-
- /* Set the FS_ALL flag if we're writing the entire file. */
- 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. */
- if (cmdp->argc != 0 && cmd != XIT && p[0] == '>' && p[1] == '>') {
- LF_SET(FS_APPEND);
-
- /* Skip ">>" and whitespace. */
- for (p += 2; *p && isblank(*p); ++p);
- }
-
- /* If no other arguments, just write the file back. */
- if (cmdp->argc == 0 || *p == '\0')
- return (file_write(sp,
- &cmdp->addr1, &cmdp->addr2, NULL, flags));
-
- /* Build an argv so we get an argument count and file expansion. */
- if (argv_exp2(sp, cmdp, p, strlen(p)))
- return (1);
-
- /*
- * 0 args: impossible.
- * 1 args: impossible (I hope).
- * 2 args: read it.
- * >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.
- */
- switch (cmdp->argc) {
- case 0:
- case 1:
- abort();
- /* NOTREACHED */
- case 2:
- name = cmdp->argv[1]->bp;
-
- /*
- * !!!
- * Historically, the read and write commands renamed
- * "unnamed" files, or, if the file had a name, set
- * the alternate file name.
- */
- if (F_ISSET(sp->frp, FR_TMPFILE) &&
- !F_ISSET(sp->frp, FR_EXNAMED)) {
- if ((p = v_strdup(sp,
- cmdp->argv[1]->bp, cmdp->argv[1]->len)) != NULL) {
- free(sp->frp->name);
- sp->frp->name = p;
- }
- /*
- * The file has a real name, it's no longer a
- * temporary, clear the temporary file flags.
- *
- * !!!
- * If we're writing the whole file, FR_NAMECHANGE
- * will be cleared by the write routine -- this is
- * historic practice.
- */
- F_CLR(sp->frp, FR_TMPEXIT | FR_TMPFILE);
- F_SET(sp->frp, FR_NAMECHANGE | FR_EXNAMED);
-
- /* Notify the screen. */
- (void)sp->gp->scr_rename(sp, sp->frp->name, 1);
- } else
- set_alt_name(sp, name);
- break;
- default:
- ex_emsg(sp, p, EXM_FILECOUNT);
- return (1);
- }
-
- return (file_write(sp, &cmdp->addr1, &cmdp->addr2, name, flags));
-}
-
-/*
- * ex_writefp --
- * Write a range of lines to a FILE *.
- *
- * PUBLIC: int ex_writefp __P((SCR *,
- * PUBLIC: char *, FILE *, MARK *, MARK *, u_long *, u_long *, int));
- */
-int
-ex_writefp(sp, name, fp, fm, tm, nlno, nch, silent)
- SCR *sp;
- char *name;
- FILE *fp;
- MARK *fm, *tm;
- u_long *nlno, *nch;
- int silent;
-{
- struct stat sb;
- GS *gp;
- u_long ccnt; /* XXX: can't print off_t portably. */
- recno_t fline, tline, lcnt;
- size_t len;
- int rval;
- char *msg, *p;
-
- gp = sp->gp;
- fline = fm->lno;
- tline = tm->lno;
-
- if (nlno != NULL) {
- *nch = 0;
- *nlno = 0;
- }
-
- /*
- * The vi filter code has multiple processes running simultaneously,
- * and one of them calls ex_writefp(). The "unsafe" function calls
- * in this code are to db_get() and msgq(). Db_get() is safe, see
- * the comment in ex_filter.c:ex_filter() for details. We don't call
- * msgq if the multiple process bit in the EXF is set.
- *
- * !!!
- * Historic vi permitted files of 0 length to be written. However,
- * since the way vi got around dealing with "empty" files was to
- * always have a line in the file no matter what, it wrote them as
- * files of a single, empty line. We write empty files.
- *
- * "Alex, I'll take vi trivia for $1000."
- */
- ccnt = 0;
- lcnt = 0;
- msg = "253|Writing...";
- if (tline != 0)
- for (; fline <= tline; ++fline, ++lcnt) {
- /* Caller has to provide any interrupt message. */
- if ((lcnt + 1) % INTERRUPT_CHECK == 0) {
- if (INTERRUPTED(sp))
- break;
- if (!silent) {
- gp->scr_busy(sp, msg, msg == NULL ?
- BUSY_UPDATE : BUSY_ON);
- msg = NULL;
- }
- }
- if (db_get(sp, fline, DBG_FATAL, &p, &len))
- goto err;
- if (fwrite(p, 1, len, fp) != len)
- goto err;
- ccnt += len;
- if (putc('\n', fp) != '\n')
- break;
- ++ccnt;
- }
-
- if (fflush(fp))
- goto err;
- /*
- * XXX
- * I don't trust NFS -- check to make sure that we're talking to
- * a regular file and sync so that NFS is forced to flush.
- */
- if (!fstat(fileno(fp), &sb) &&
- S_ISREG(sb.st_mode) && fsync(fileno(fp)))
- goto err;
-
- if (fclose(fp))
- goto err;
-
- rval = 0;
- if (0) {
-err: if (!F_ISSET(sp->ep, F_MULTILOCK))
- msgq_str(sp, M_SYSERR, name, "%s");
- (void)fclose(fp);
- rval = 1;
- }
-
- if (!silent)
- gp->scr_busy(sp, NULL, BUSY_OFF);
-
- /* Report the possibly partial transfer. */
- if (nlno != NULL) {
- *nch = ccnt;
- *nlno = lcnt;
- }
- return (rval);
-}
diff --git a/contrib/nvi/ex/ex_yank.c b/contrib/nvi/ex/ex_yank.c
deleted file mode 100644
index 778dc7d..0000000
--- a/contrib/nvi/ex/ex_yank.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_yank.c 10.7 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-
-#include "../common/common.h"
-
-/*
- * ex_yank -- :[line [,line]] ya[nk] [buffer] [count]
- * Yank the lines into a buffer.
- *
- * PUBLIC: int ex_yank __P((SCR *, EXCMD *));
- */
-int
-ex_yank(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- NEEDFILE(sp, cmdp);
-
- /*
- * !!!
- * Historically, yanking lines in ex didn't count toward the
- * number-of-lines-yanked report.
- */
- return (cut(sp,
- FL_ISSET(cmdp->iflags, E_C_BUFFER) ? &cmdp->buffer : NULL,
- &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE));
-}
diff --git a/contrib/nvi/ex/ex_z.c b/contrib/nvi/ex/ex_z.c
deleted file mode 100644
index 41b72ad..0000000
--- a/contrib/nvi/ex/ex_z.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- */
-
-#include "config.h"
-
-#ifndef lint
-static const char sccsid[] = "@(#)ex_z.c 10.10 (Berkeley) 3/6/96";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/queue.h>
-
-#include <bitstring.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../common/common.h"
-
-/*
- * ex_z -- :[line] z [^-.+=] [count] [flags]
- * Adjust window.
- *
- * PUBLIC: int ex_z __P((SCR *, EXCMD *));
- */
-int
-ex_z(sp, cmdp)
- SCR *sp;
- EXCMD *cmdp;
-{
- MARK abs;
- recno_t cnt, equals, lno;
- int eofcheck;
-
- NEEDFILE(sp, cmdp);
-
- /*
- * !!!
- * If no count specified, use either two times the size of the
- * scrolling region, or the size of the window option. POSIX
- * 1003.2 claims that the latter is correct, but historic ex/vi
- * documentation and practice appear to use the scrolling region.
- * I'm using the window size as it means that the entire screen
- * is used instead of losing a line to roundoff. Note, we drop
- * a line from the cnt if using the window size to leave room for
- * the next ex prompt.
- */
- if (FL_ISSET(cmdp->iflags, E_C_COUNT))
- cnt = cmdp->count;
- else
-#ifdef HISTORIC_PRACTICE
- cnt = O_VAL(sp, O_SCROLL) * 2;
-#else
- cnt = O_VAL(sp, O_WINDOW) - 1;
-#endif
-
- equals = 0;
- eofcheck = 0;
- lno = cmdp->addr1.lno;
-
- switch (FL_ISSET(cmdp->iflags,
- E_C_CARAT | E_C_DASH | E_C_DOT | E_C_EQUAL | E_C_PLUS)) {
- case E_C_CARAT: /* Display cnt * 2 before the line. */
- eofcheck = 1;
- if (lno > cnt * 2)
- cmdp->addr1.lno = (lno - cnt * 2) + 1;
- else
- cmdp->addr1.lno = 1;
- cmdp->addr2.lno = (cmdp->addr1.lno + cnt) - 1;
- break;
- case E_C_DASH: /* Line goes at the bottom of the screen. */
- cmdp->addr1.lno = lno > cnt ? (lno - cnt) + 1 : 1;
- cmdp->addr2.lno = lno;
- break;
- case E_C_DOT: /* Line goes in the middle of the screen. */
- /*
- * !!!
- * Historically, the "middleness" of the line overrode the
- * count, so that "3z.19" or "3z.20" would display the first
- * 12 lines of the file, i.e. (N - 1) / 2 lines before and
- * after the specified line.
- */
- eofcheck = 1;
- cnt = (cnt - 1) / 2;
- cmdp->addr1.lno = lno > cnt ? lno - cnt : 1;
- cmdp->addr2.lno = lno + cnt;
-
- /*
- * !!!
- * Historically, z. set the absolute cursor mark.
- */
- abs.lno = sp->lno;
- abs.cno = sp->cno;
- (void)mark_set(sp, ABSMARK1, &abs, 1);
- break;
- case E_C_EQUAL: /* Center with hyphens. */
- /*
- * !!!
- * Strangeness. The '=' flag is like the '.' flag (see the
- * above comment, it applies here as well) but with a special
- * little hack. Print out lines of hyphens before and after
- * the specified line. Additionally, the cursor remains set
- * on that line.
- */
- eofcheck = 1;
- cnt = (cnt - 1) / 2;
- cmdp->addr1.lno = lno > cnt ? lno - cnt : 1;
- cmdp->addr2.lno = lno - 1;
- if (ex_pr(sp, cmdp))
- return (1);
- (void)ex_puts(sp, "----------------------------------------\n");
- cmdp->addr2.lno = cmdp->addr1.lno = equals = lno;
- if (ex_pr(sp, cmdp))
- return (1);
- (void)ex_puts(sp, "----------------------------------------\n");
- cmdp->addr1.lno = lno + 1;
- cmdp->addr2.lno = (lno + cnt) - 1;
- break;
- default:
- /* If no line specified, move to the next one. */
- if (F_ISSET(cmdp, E_ADDR_DEF))
- ++lno;
- /* FALLTHROUGH */
- case E_C_PLUS: /* Line goes at the top of the screen. */
- eofcheck = 1;
- cmdp->addr1.lno = lno;
- cmdp->addr2.lno = (lno + cnt) - 1;
- break;
- }
-
- if (eofcheck) {
- if (db_last(sp, &lno))
- return (1);
- if (cmdp->addr2.lno > lno)
- cmdp->addr2.lno = lno;
- }
-
- if (ex_pr(sp, cmdp))
- return (1);
- if (equals)
- sp->lno = equals;
- return (0);
-}
diff --git a/contrib/nvi/ex/script.h b/contrib/nvi/ex/script.h
deleted file mode 100644
index e29f633..0000000
--- a/contrib/nvi/ex/script.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*-
- * Copyright (c) 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- *
- * @(#)script.h 10.2 (Berkeley) 3/6/96
- */
-
-struct _script {
- pid_t sh_pid; /* Shell pid. */
- int sh_master; /* Master pty fd. */
- int sh_slave; /* Slave pty fd. */
- char *sh_prompt; /* Prompt. */
- size_t sh_prompt_len; /* Prompt length. */
- char sh_name[64]; /* Pty name */
-#ifdef TIOCGWINSZ
- struct winsize sh_win; /* Window size. */
-#endif
- struct termios sh_term; /* Terminal information. */
-};
diff --git a/contrib/nvi/ex/tag.h b/contrib/nvi/ex/tag.h
deleted file mode 100644
index aee3dd2..0000000
--- a/contrib/nvi/ex/tag.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * Copyright (c) 1992, 1993, 1994, 1995, 1996
- * Keith Bostic. All rights reserved.
- * Copyright (c) 1994, 1996
- * Rob Mayoff. All rights reserved.
- *
- * See the LICENSE file for redistribution information.
- *
- * @(#)tag.h 10.5 (Berkeley) 5/15/96
- */
-
-/*
- * Cscope connection information. One of these is maintained per cscope
- * connection, linked from the EX_PRIVATE structure.
- */
-struct _csc {
- LIST_ENTRY(_csc) q; /* Linked list of cscope connections. */
-
- char *dname; /* Base directory of this cscope connection. */
- size_t dlen; /* Length of base directory. */
- pid_t pid; /* PID of the connected cscope process. */
- time_t mtime; /* Last modification time of cscope database. */
-
- FILE *from_fp; /* from cscope: FILE. */
- int from_fd; /* from cscope: file descriptor. */
- FILE *to_fp; /* to cscope: FILE. */
- int to_fd; /* to cscope: file descriptor. */
-
- char **paths; /* Array of search paths for this cscope. */
- char *pbuf; /* Search path buffer. */
- size_t pblen; /* Search path buffer length. */
-
- char buf[1]; /* Variable length buffer. */
-};
-
-/*
- * Tag file information. One of these is maintained per tag file, linked
- * from the EXPRIVATE structure.
- */
-struct _tagf { /* Tag files. */
- TAILQ_ENTRY(_tagf) q; /* Linked list of tag files. */
- char *name; /* Tag file name. */
- int errnum; /* Errno. */
-
-#define TAGF_ERR 0x01 /* Error occurred. */
-#define TAGF_ERR_WARN 0x02 /* Error reported. */
- u_int8_t flags;
-};
-
-/*
- * Tags are structured internally as follows:
- *
- * +----+ +----+ +----+ +----+
- * | EP | -> | Q1 | <-- | T1 | <-- | T2 |
- * +----+ +----+ --> +----+ --> +----+
- * |
- * +----+ +----+
- * | Q2 | <-- | T1 |
- * +----+ --> +----+
- * |
- * +----+ +----+
- * | Q3 | <-- | T1 |
- * +----+ --> +----+
- *
- * Each Q is a TAGQ, or tag "query", which is the result of one tag or cscope
- * command. Each Q references one or more TAG's, or tagged file locations.
- *
- * tag: put a new Q at the head (^])
- * tagnext: T1 -> T2 inside Q (^N)
- * tagprev: T2 -> T1 inside Q (^P)
- * tagpop: discard Q (^T)
- * tagtop: discard all Q
- */
-struct _tag { /* Tag list. */
- CIRCLEQ_ENTRY(_tag) q; /* Linked list of tags. */
-
- /* Tag pop/return information. */
- FREF *frp; /* Saved file. */
- recno_t lno; /* Saved line number. */
- size_t cno; /* Saved column number. */
-
- char *fname; /* Filename. */
- size_t fnlen; /* Filename length. */
- recno_t slno; /* Search line number. */
- char *search; /* Search string. */
- size_t slen; /* Search string length. */
-
- char buf[1]; /* Variable length buffer. */
-};
-
-struct _tagq { /* Tag queue. */
- CIRCLEQ_ENTRY(_tagq) q; /* Linked list of tag queues. */
- /* This queue's tag list. */
- CIRCLEQ_HEAD(_tagqh, _tag) tagq;
-
- TAG *current; /* Current TAG within the queue. */
-
- char *tag; /* Tag string. */
- size_t tlen; /* Tag string length. */
-
-#define TAG_CSCOPE 0x01 /* Cscope tag. */
- u_int8_t flags;
-
- char buf[1]; /* Variable length buffer. */
-};
diff --git a/contrib/nvi/ex/version.h b/contrib/nvi/ex/version.h
deleted file mode 100644
index 7d657b6..0000000
--- a/contrib/nvi/ex/version.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define VI_VERSION \
- "Version 1.79 (10/23/96) The CSRG, University of California, Berkeley."
OpenPOWER on IntegriCloud