diff options
Diffstat (limited to 'usr.bin/vi/ex')
50 files changed, 0 insertions, 12566 deletions
diff --git a/usr.bin/vi/ex/ex.c b/usr.bin/vi/ex/ex.c deleted file mode 100644 index 77666ca0..0000000 --- a/usr.bin/vi/ex/ex.c +++ /dev/null @@ -1,1866 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex.c 8.157 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -static void badlno __P((SCR *, recno_t)); -static __inline EXCMDLIST const * - ex_comm_search __P((char *, size_t)); -static int ep_line __P((SCR *, EXF *, MARK *, char **, size_t *, int *)); -static int ep_range __P((SCR *, EXF *, EXCMDARG *, char **, size_t *)); - -/* - * ex -- - * Read an ex command and execute it. - */ -int -ex(sp, ep) - SCR *sp; - EXF *ep; -{ - enum input irval; - TEXT *tp; - u_int flags, saved_mode; - int eval; - - if (ex_init(sp, ep)) - return (1); - - if (sp->s_refresh(sp, ep)) - return (ex_end(sp)); - - /* If reading from a file, messages should have line info. */ - if (!F_ISSET(sp->gp, G_STDIN_TTY)) { - sp->if_lno = 1; - sp->if_name = strdup("input"); - } - - /* - * !!! - * Historically, the beautify option applies to ex command input read - * from a file. In addition, the first time a ^H was discarded from - * the input, a message "^H discarded" was displayed. We don't bother. - */ - LF_INIT(TXT_BACKSLASH | TXT_CNTRLD | TXT_CR | TXT_EXSUSPEND); - - for (eval = 0;; ++sp->if_lno) { - /* Set the flags that the user can change. */ - if (O_ISSET(sp, O_BEAUTIFY)) - LF_SET(TXT_BEAUTIFY); - else - LF_CLR(TXT_BEAUTIFY); - if (O_ISSET(sp, O_PROMPT)) - LF_SET(TXT_PROMPT); - else - LF_CLR(TXT_PROMPT); - - /* - * Get the next command. Interrupt flag manipulation is - * safe because ex_icmd clears them all. - */ - CLR_INTERRUPT(sp); - F_SET(sp, S_INTERRUPTIBLE); - irval = sp->s_get(sp, ep, sp->tiqp, ':', flags); - if (INTERRUPTED(sp)) { - (void)fputc('\n', stdout); - (void)fflush(stdout); - goto refresh; - } - switch (irval) { - case INP_OK: - break; - case INP_EOF: - case INP_ERR: - F_SET(sp, S_EXIT_FORCE); - /* FALLTHROUGH */ - case INP_INTR: - goto ret; - } - - /* - * If the user entered a carriage return, send ex_cmd() - * a separator -- it discards single newlines. - */ - tp = sp->tiqp->cqh_first; - if (tp->len == 0) { - tp->len = 1; - tp->lb[0] = ' '; - } - - saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE); - if (ex_icmd(sp, ep, - tp->lb, tp->len, 1) && !F_ISSET(sp->gp, G_STDIN_TTY)) - F_SET(sp, S_EXIT_FORCE); - (void)msg_rpt(sp, 0); - if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE)) - break; - -refresh: if (sp->s_refresh(sp, ep)) { - eval = 1; - break; - } - } -ret: if (sp->if_name != NULL) { - FREE(sp->if_name, strlen(sp->if_name) + 1); - sp->if_name = NULL; - } - return (ex_end(sp) || eval); -} - -/* - * ex_cfile -- - * Execute ex commands from a file. - */ -int -ex_cfile(sp, ep, filename, needsep) - SCR *sp; - EXF *ep; - char *filename; - int needsep; -{ - struct stat sb; - int fd, len, rval; - char *bp; - - bp = NULL; - if ((fd = open(filename, O_RDONLY, 0)) < 0 || fstat(fd, &sb)) - goto err; - - /* - * XXX - * We'd like to test if the file is too big 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. Hope that malloc fails if the file is too - * large. - */ - MALLOC(sp, bp, char *, (size_t)sb.st_size + 1); - if (bp == NULL) - goto err; - - len = read(fd, bp, (int)sb.st_size); - if (len == -1 || len != sb.st_size) { - if (len != sb.st_size) - errno = EIO; -err: rval = 1; - msgq(sp, M_SYSERR, filename); - } else { - bp[sb.st_size] = '\0'; /* XXX */ - - /* - * Run the command. Messages include file/line information, - * but we don't care if we can't get space. - */ - sp->if_lno = 1; - sp->if_name = strdup(filename); - F_SET(sp, S_VLITONLY); - rval = ex_icmd(sp, ep, bp, len, needsep); - F_CLR(sp, S_VLITONLY); - free(sp->if_name); - sp->if_name = NULL; - } - - /* - * !!! - * THE UNDERLYING EXF MAY HAVE CHANGED. - */ - if (bp != NULL) - FREE(bp, sb.st_size); - if (fd >= 0) - (void)close(fd); - return (rval); -} - -/* - * ex_icmd -- - * Call ex_cmd() after turning off interruptible bits. - */ -int -ex_icmd(sp, ep, cmd, len, needsep) - SCR *sp; - EXF *ep; - char *cmd; - size_t len; - int needsep; -{ - /* - * Ex goes through here for each vi :colon command and for each ex - * command, however, globally executed commands don't go through - * here, instead, they call ex_cmd directly. So, reset all of the - * interruptible flags now. - * - * !!! - * Previous versions of nvi cleared mapped characters on error. This - * feature was removed when users complained that it wasn't historic - * practice. - */ - CLR_INTERRUPT(sp); - return (ex_cmd(sp, ep, cmd, len, needsep)); -} - -/* Special command structure for :s as a repeat substitution command. */ -static EXCMDLIST const cmd_subagain = - {"s", ex_subagain, E_ADDR2|E_NORC, - "s", - "[line [,line]] s [cgr] [count] [#lp]", - "repeat the last subsitution"}; - -/* Special command structure for :d[flags]. */ -static EXCMDLIST const cmd_del2 = - {"delete", ex_delete, E_ADDR2|E_AUTOPRINT|E_NORC, - "1bca1", - "[line [,line]] d[elete][flags] [buffer] [count] [flags]", - "delete lines from the file"}; - -/* - * ex_cmd -- - * Parse and execute a string containing ex commands. - */ -int -ex_cmd(sp, ep, cmd, cmdlen, needsep) - SCR *sp; - EXF *ep; - char *cmd; - size_t cmdlen; - int needsep; -{ - enum { NOTSET, NEEDSEP_N, NEEDSEP_NR, NONE } sep; - EX_PRIVATE *exp; - EXCMDARG exc; - EXCMDLIST const *cp; - MARK cur; - recno_t lno, num; - size_t arg1_len, len, save_cmdlen; - long flagoff; - u_int saved_mode; - int blank, ch, cnt, delim, flags, namelen, nl; - int optnum, uselastcmd, tmp, vi_address; - char *arg1, *save_cmd, *p, *s, *t; - - /* Init. */ - nl = 0; - sep = needsep ? NOTSET : NONE; -loop: if (nl) { - nl = 0; - ++sp->if_lno; - } - arg1 = NULL; - save_cmdlen = 0; - - /* It's possible that we've been interrupted during a command. */ - if (INTERRUPTED(sp)) - return (0); - - /* Skip <blank>s, empty lines. */ - for (blank = 0; cmdlen > 0; ++cmd, --cmdlen) - if ((ch = *cmd) == '\n') - ++sp->if_lno; - else if (isblank(ch)) - blank = 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 (cmdlen != 0 && ch == ':') { - if (sep == NOTSET) - sep = NEEDSEP_N; - while (--cmdlen > 0 && (ch = *++cmd) == ':'); - } - - /* - * 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 (cmdlen != 0 && ch == '"') { - while (--cmdlen > 0 && *++cmd != '\n'); - if (*cmd == '\n') { - nl = 1; - ++cmd; - --cmdlen; - } - goto loop; - } - - /* Skip whitespace. */ - for (; cmdlen > 0; ++cmd, --cmdlen) { - ch = *cmd; - 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, and discard lines containing only <blank> characters from - * .exrc files. - */ - if (cmdlen == 0 && (!IN_EX_MODE(sp) || ep == NULL || !blank)) - return (0); - - /* Initialize the structure passed to underlying functions. */ - memset(&exc, 0, sizeof(EXCMDARG)); - exp = EXP(sp); - if (argv_init(sp, ep, &exc)) - goto err; - - /* - * Check to see if this is a command for which we may want to output - * a \r separator instead of a \n. (The command :1<CR> puts out a \n, - * but the command :<CR> puts out a \r.) If the line is empty except - * for <blank>s, <carriage-return> or <eof>, we'll probably want to - * output \r. 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 (sep == NOTSET) - sep = cmdlen == 0 || cmdlen == 1 && cmd[0] == '\004' ? - NEEDSEP_NR : NEEDSEP_N; - - /* Parse command addresses. */ - if (ep_range(sp, ep, &exc, &cmd, &cmdlen)) - goto err; - - /* Skip whitespace. */ - for (; cmdlen > 0; ++cmd, --cmdlen) { - ch = *cmd; - if (!isblank(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!#&*<=>@~" - if (cmdlen != 0 && cmd[0] != '|' && cmd[0] != '\n') { - if (strchr(SINGLE_CHAR_COMMANDS, *cmd)) { - p = cmd; - ++cmd; - --cmdlen; - namelen = 1; - } else { - for (p = cmd; cmdlen > 0; --cmdlen, ++cmd) - if (!isalpha(*cmd)) - break; - if ((namelen = cmd - p) == 0) { - msgq(sp, M_ERR, "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. - * - * !!! - * Note, adding commands that start with 'd', and match - * "delete" up to a l, p, +, - or # character can break - * this code. - */ - if (p[0] == '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] == '#') { - len = (cmd - p) - (s - p); - cmd -= len; - cmdlen += len; - cp = &cmd_del2; - goto skip; - } - } - - /* - * 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 pretty much anything to follow the - * substitute command, e.g. "s/e/E/|s|sgc3p" was fine. Make - * the command "sgc" work. - */ - if ((cp = ex_comm_search(p, namelen)) == NULL) - switch (p[0]) { - case 's': - cmd -= namelen - 1; - cmdlen += namelen - 1; - cp = &cmd_subagain; - break; - case 'k': - if (p[1] && !p[2]) { - cmd -= namelen - 1; - cmdlen += namelen - 1; - cp = &cmds[C_K]; - break; - } - /* FALLTHROUGH */ - default: - msgq(sp, M_ERR, - "The %.*s command is unknown", namelen, p); - goto err; - } - - /* Some commands are either not implemented or turned off. */ -skip: if (F_ISSET(cp, E_NOPERM)) { - msgq(sp, M_ERR, - "The %s command is not currently supported", - cp->name); - goto err; - } - - /* Some commands aren't okay in globals. */ - if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) { - msgq(sp, M_ERR, - "The %s command can't be used as part of a global command", - cp->name); - goto err; - } - - /* - * Multiple < and > characters; another "feature". Note, - * The string passed to the underlying function may not be - * nul terminated in this case. - */ - if ((cp == &cmds[C_SHIFTL] && *p == '<') || - (cp == &cmds[C_SHIFTR] && *p == '>')) { - for (ch = *p; cmdlen > 0; --cmdlen, ++cmd) - if (*cmd != ch) - break; - if (argv_exp0(sp, ep, &exc, p, cmd - p)) - goto err; - } - - /* - * The visual command has a different syntax when called - * from ex than when called from a vi colon command. FMH. - */ - if (cp == &cmds[C_VISUAL_EX] && IN_VI_MODE(sp)) - cp = &cmds[C_VISUAL_VI]; - - /* Set the format style flags for the next command. */ - if (cp == &cmds[C_HASH]) - exp->fdef = E_F_HASH; - else if (cp == &cmds[C_LIST]) - exp->fdef = E_F_LIST; - else if (cp == &cmds[C_PRINT]) - exp->fdef = E_F_PRINT; - uselastcmd = 0; - } else { - /* Print is the default command. */ - cp = &cmds[C_PRINT]; - - /* Set the saved format flags. */ - F_SET(&exc, exp->fdef); - - /* - * !!! - * If no address was specified, and it's not a global command, - * we up the address by one. (I have not an idea why global - * commands are exempted, but it's (ahem) historic practice. - */ - if (exc.addrcnt == 0 && !F_ISSET(sp, S_GLOBAL)) { - exc.addrcnt = 1; - exc.addr1.lno = sp->lno + 1; - exc.addr1.cno = sp->cno; - } - - uselastcmd = 1; - } - - /* - * !!! - * 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)) { - optnum = 1; - F_SET(&exc, E_F_HASH); - } else - optnum = 0; - - /* Initialize local flags to the command flags. */ - LF_INIT(cp->flags); - - /* - * File state must be checked throughout this code, because it is - * called when reading the .exrc file and similar things. There's - * this little chicken and egg problem -- if we read the file first, - * we won't know how to display it. If we read/set the exrc stuff - * first, we can't allow any command that requires file state. We - * don't have a "reading an rc" bit, because we want the commands - * to work when the user source's the rc file later. Historic vi - * generally took the easy way out and dropped core. - */ - if (LF_ISSET(E_NORC) && ep == NULL) { - msgq(sp, M_ERR, - "The %s command requires that a file have already been read in", - cp->name); - goto err; - } - - /* - * There are three normal termination cases for an ex command. They - * are the end of the string (cmdlen), or unescaped (by literal next - * characters) newline or '|' characters. As we're past any addresses, - * we can now determine how long the command is, so we don't have to - * look for all the possible terminations. There are three exciting - * special cases: - * - * 1: The bang, global, vglobal and the filter versions of the read and - * write commands are delimited by newlines (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 substitute 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 substitute commands didn't delimit the command. - * And, in the filter cases for read and write, and the bang, global - * and vglobal commands, they did not delimit the command at all. - * - * For example, the following commands were legal: - * - * :edit +25|s/abc/ABC/ file.c - * :substitute s/|/PIPE/ - * :read !spell % | columnate - * :global/pattern/p|l - * - * It's not quite as simple as it sounds, however. The command: - * - * :substitute s/a/b/|s/c/d|set - * - * was also legal, i.e. the historic ex parser (using the word loosely, - * since "parser" implies some regularity) delimited the RE's based on - * its delimiter and not anything so irretrievably vulgar as a command - * syntax. - * - * One thing that makes this easier is that we can ignore most of the - * command termination conditions for the commands that want to take - * the command up to the next newline. None of them are legal in .exrc - * files, so if we're here, we only dealing with a single line, and we - * can just eat it. - * - * 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. - */ - arg1_len = 0; - save_cmd = cmd; - if (cp == &cmds[C_EDIT] || cp == &cmds[C_EX] || - cp == &cmds[C_NEXT] || cp == &cmds[C_VISUAL_VI]) { - /* - * Move to the next non-whitespace character. A '!' - * immediately following the command is eaten as a - * force flag. - */ - if (cmdlen > 0 && *cmd == '!') { - ++cmd; - --cmdlen; - F_SET(&exc, E_FORCE); - - /* Reset, don't reparse. */ - save_cmd = cmd; - } - for (tmp = 0; cmdlen > 0; --cmdlen, ++cmd) - if (!isblank(*cmd)) - 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 by a literal - * next character. The literal next characters are stripped - * as they're no longer useful. - */ - if (cmdlen > 0 && *cmd == '+') { - ++cmd; - --cmdlen; - for (arg1 = p = cmd; cmdlen > 0; --cmdlen, ++cmd) { - ch = *cmd; - if (IS_ESCAPE(sp, ch) && cmdlen > 1) { - --cmdlen; - ch = *++cmd; - } else if (isblank(ch)) - break; - *p++ = ch; - } - arg1_len = cmd - arg1; - - /* Reset, so the first argument isn't reparsed. */ - save_cmd = cmd; - } - } else if (cp == &cmds[C_BANG] || - cp == &cmds[C_GLOBAL] || cp == &cmds[C_VGLOBAL]) { - cmd += cmdlen; - cmdlen = 0; - } else if (cp == &cmds[C_READ] || cp == &cmds[C_WRITE]) { - /* - * Move to the next character. If it's a '!', it's a filter - * command and we want to eat it all, otherwise, we're done. - */ - for (; cmdlen > 0; --cmdlen, ++cmd) { - ch = *cmd; - if (!isblank(ch)) - break; - } - if (cmdlen > 0 && ch == '!') { - cmd += cmdlen; - cmdlen = 0; - } - } else if (cp == &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 substitute - * command. - */ - for (; cmdlen > 0; --cmdlen, ++cmd) - if (!isblank(cmd[0])) - break; - - if (isalnum(cmd[0]) || cmd[0] == '|') - cp = &cmd_subagain; - else if (cmdlen > 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 = *cmd; - ++cmd; - --cmdlen; - for (cnt = 2; cmdlen > 0 && cnt; --cmdlen, ++cmd) - if (cmd[0] == '\\' && cmdlen > 1) { - ++cmd; - --cmdlen; - } else if (cmd[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 as they're - * no longer useful. - */ - vi_address = cmdlen != 0 && cmd[0] != '\n'; - for (p = cmd, cnt = 0; cmdlen > 0; --cmdlen, ++cmd) { - ch = cmd[0]; - if (IS_ESCAPE(sp, ch) && cmdlen > 1) { - tmp = cmd[1]; - if (tmp == '\n' || tmp == '|') { - if (tmp == '\n') - ++sp->if_lno; - --cmdlen; - ++cmd; - ++cnt; - ch = tmp; - } - } else if (ch == '\n' || ch == '|') { - if (ch == '\n') - nl = 1; - --cmdlen; - break; - } - *p++ = ch; - } - - /* - * Save off the next command information, go back to the - * original start of the command. - */ - p = cmd + 1; - cmd = save_cmd; - save_cmd = p; - save_cmdlen = cmdlen; - cmdlen = ((save_cmd - cmd) - 1) - cnt; - - /* - * !!! - * 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 (cp == &cmds[C_SET]) - for (p = cmd, len = cmdlen; 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_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 of if we just used - * the current cursor. - */ - switch (LF_ISSET(E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) { - case E_ADDR1: /* One address: */ - switch (exc.addrcnt) { - case 0: /* Default cursor/empty file. */ - exc.addrcnt = 1; - F_SET(&exc, E_ADDRDEF); - if (LF_ISSET(E_ZERODEF)) { - if (file_lline(sp, ep, &lno)) - goto err; - if (lno == 0) { - exc.addr1.lno = 0; - LF_SET(E_ZERO); - } else - exc.addr1.lno = sp->lno; - } else - exc.addr1.lno = sp->lno; - exc.addr1.cno = sp->cno; - break; - case 1: - break; - case 2: /* Lose the first address. */ - exc.addrcnt = 1; - exc.addr1 = exc.addr2; - } - break; - case E_ADDR2_NONE: /* Zero/two addresses: */ - if (exc.addrcnt == 0) /* Default to nothing. */ - break; - goto two; - case E_ADDR2_ALL: /* Zero/two addresses: */ - if (exc.addrcnt == 0) { /* Default entire/empty file. */ - exc.addrcnt = 2; - F_SET(&exc, E_ADDRDEF); - if (file_lline(sp, ep, &exc.addr2.lno)) - goto err; - if (LF_ISSET(E_ZERODEF) && exc.addr2.lno == 0) { - exc.addr1.lno = 0; - LF_SET(E_ZERO); - } else - exc.addr1.lno = 1; - exc.addr1.cno = exc.addr2.cno = 0; - F_SET(&exc, E_ADDR2_ALL); - break; - } - /* FALLTHROUGH */ - case E_ADDR2: /* Two addresses: */ -two: switch (exc.addrcnt) { - case 0: /* Default cursor/empty file. */ - exc.addrcnt = 2; - F_SET(&exc, E_ADDRDEF); - if (LF_ISSET(E_ZERODEF) && sp->lno == 1) { - if (file_lline(sp, ep, &lno)) - goto err; - if (lno == 0) { - exc.addr1.lno = exc.addr2.lno = 0; - LF_SET(E_ZERO); - } else - exc.addr1.lno = exc.addr2.lno = sp->lno; - } else - exc.addr1.lno = exc.addr2.lno = sp->lno; - exc.addr1.cno = exc.addr2.cno = sp->cno; - break; - case 1: /* Default to first address. */ - exc.addrcnt = 2; - exc.addr2 = exc.addr1; - break; - case 2: - break; - } - break; - default: - if (exc.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 (cp == &cmds[C_SCROLL]) { - exc.addrcnt = 2; - exc.addr1.lno = sp->lno + 1; - exc.addr2.lno = sp->lno + O_VAL(sp, O_SCROLL); - exc.addr1.cno = exc.addr2.cno = sp->cno; - if (file_lline(sp, ep, &lno)) - goto err; - if (lno != 0 && lno > sp->lno && exc.addr2.lno > lno) - exc.addr2.lno = lno; - } - - flagoff = 0; - for (p = cp->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 (cmdlen > 0 && *cmd == '!') { - ++cmd; - --cmdlen; - F_SET(&exc, E_FORCE); - } - continue; - } - - /* Skip leading <blank>s. */ - for (; cmdlen > 0; --cmdlen, ++cmd) - if (!isblank(*cmd)) - break; - - /* - * Quit when reach the end of the command, unless it's a - * command that does its own parsing, in which case we want - * to build a reasonable argv for it. This code guarantees - * that there will be an argv when the function gets called, - * so the correct test is for a length of 0, not for the - * argc > 0. Since '!' can precede commands that do their - * own parsing, we have to have already handled it. - */ - if (cmdlen == 0 && *p != 'S' && *p != 's') - 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 (; cmdlen; --cmdlen, ++cmd) - switch (*cmd) { - case '+': - ++flagoff; - break; - case '-': - --flagoff; - break; - case '#': - optnum = 0; - F_SET(&exc, E_F_HASH); - exp->fdef |= E_F_HASH; - break; - case 'l': - F_SET(&exc, E_F_LIST); - exp->fdef |= E_F_LIST; - break; - case 'p': - F_SET(&exc, E_F_PRINT); - exp->fdef |= E_F_PRINT; - break; - default: - goto end1; - } -end1: break; - case '2': /* -, ., +, ^ */ - case '3': /* -, ., +, ^, = */ - for (; cmdlen; --cmdlen, ++cmd) - switch (*cmd) { - case '-': - F_SET(&exc, E_F_DASH); - break; - case '.': - F_SET(&exc, E_F_DOT); - break; - case '+': - F_SET(&exc, E_F_PLUS); - break; - case '^': - F_SET(&exc, E_F_CARAT); - break; - case '=': - if (*p == '3') { - F_SET(&exc, E_F_EQUAL); - break; - } - /* FALLTHROUGH */ - default: - goto end2; - } -end2: 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 ((cmd[0] == '+' || cmd[0] == '-' || cmd[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(cmd[0])) { - exc.buffer = *cmd; - ++cmd; - --cmdlen; - F_SET(&exc, E_BUFFER); - } - break; - case 'c': /* count [01+a] */ - ++p; - /* Validate any signed value. */ - if (!isdigit(*cmd) && - (*p != '+' || (*cmd != '+' && *cmd != '-'))) - break; - /* If a signed value, set appropriate flags. */ - if (*cmd == '-') - F_SET(&exc, E_COUNT_NEG); - else if (*cmd == '+') - F_SET(&exc, E_COUNT_POS); -/* 8-bit XXX */ if ((lno = strtol(cmd, &t, 10)) == 0 && *p != '0') { - msgq(sp, M_ERR, "Count may not be zero"); - goto err; - } - cmdlen -= (t - cmd); - cmd = t; - /* - * Count 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') { - exc.addr1 = exc.addr2; - exc.addr2.lno = exc.addr1.lno + lno - 1; - } else - exc.count = lno; - F_SET(&exc, E_COUNT); - break; - case 'f': /* file */ - if (argv_exp2(sp, ep, - &exc, cmd, cmdlen, cp == &cmds[C_BANG])) - goto err; - goto countchk; - case 'l': /* line */ - if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp)) - goto err; - /* Line specifications are always required. */ - if (!tmp) { - msgq(sp, M_ERR, - "%s: bad line specification", cmd); - goto err; - } - /* The line must exist for these commands. */ - if (file_lline(sp, ep, &lno)) - goto err; - if (cur.lno > lno) { - badlno(sp, lno); - goto err; - } - exc.lineno = cur.lno; - break; - case 'S': /* string, file exp. */ - if (argv_exp1(sp, ep, - &exc, cmd, cmdlen, cp == &cmds[C_BANG])) - goto err; - goto addr2; - case 's': /* string */ - if (argv_exp0(sp, ep, &exc, cmd, cmdlen)) - goto err; - goto addr2; - 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 = cmd; cmdlen > 0; --cmdlen, ++cmd) { - ch = *cmd; - if (IS_ESCAPE(sp, ch) && cmdlen > 1) { - --cmdlen; - *p++ = *++cmd; - } else if (isblank(ch)) { - ++cmd; - --cmdlen; - break; - } else - *p++ = ch; - } - if (argv_exp0(sp, ep, &exc, t, p - t)) - goto err; - - /* Delete intervening whitespace. */ - for (; cmdlen > 0; --cmdlen, ++cmd) { - ch = *cmd; - if (!isblank(ch)) - break; - } - if (cmdlen == 0) - goto usage; - - /* Followed by the string. */ - for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd, ++p) { - ch = *cmd; - if (IS_ESCAPE(sp, ch) && cmdlen > 1) { - --cmdlen; - *p = *++cmd; - } else - *p = ch; - } - if (argv_exp0(sp, ep, &exc, t, p - t)) - goto err; - goto addr2; - case 'w': /* word */ - if (argv_exp3(sp, ep, &exc, cmd, cmdlen)) - goto err; -countchk: if (*++p != 'N') { /* N */ - /* - * If a number is specified, must either be - * 0 or that number, if optional, and that - * number, if required. - */ - num = *p - '0'; - if ((*++p != 'o' || exp->argsoff != 0) && - exp->argsoff != num) - goto usage; - } - goto addr2; - default: - msgq(sp, M_ERR, - "Internal syntax table error (%s: %c)", - cp->name, *p); - } - } - - /* Skip trailing whitespace. */ - for (; cmdlen; --cmdlen) { - ch = *cmd++; - 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 (cmdlen || strpbrk(p, "lr")) { -usage: msgq(sp, M_ERR, "Usage: %s", cp->usage); - goto err; - } - - /* Verify that the addresses are legal. */ -addr2: switch (exc.addrcnt) { - case 2: - if (file_lline(sp, ep, &lno)) - goto err; - /* - * 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 (exc.addr2.lno > lno) - if (F_ISSET(&exc, E_COUNT)) - exc.addr2.lno = lno; - else { - badlno(sp, lno); - goto err; - } - /* FALLTHROUGH */ - case 1: - num = exc.addr1.lno; - /* - * If it's a "default vi command", zero is okay. Historic - * vi allowed this, note, it's also the hack that allows - * "vi +100 nonexistent_file" to work. - */ - if (num == 0 && (IN_EX_MODE(sp) || uselastcmd != 1) && - !LF_ISSET(E_ZERO)) { - msgq(sp, M_ERR, - "The %s command doesn't permit an address of 0", - cp->name); - goto err; - } - if (file_lline(sp, ep, &lno)) - goto err; - if (num > lno) { - badlno(sp, lno); - 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. - * - * !!! - * 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 (IN_VI_MODE(sp) && uselastcmd && vi_address == 0) { - switch (exc.addrcnt) { - case 2: - sp->lno = exc.addr2.lno ? exc.addr2.lno : 1; - sp->cno = exc.addr2.cno; - break; - case 1: - sp->lno = exc.addr1.lno ? exc.addr1.lno : 1; - sp->cno = exc.addr1.cno; - break; - } - cmd = save_cmd; - cmdlen = 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(exp, EX_ABSMARK)) { - cur.lno = sp->lno; - cur.cno = sp->cno; - F_CLR(exp, EX_ABSMARK); - if (mark_set(sp, ep, ABSMARK1, &cur, 1)) - goto err; - } - - /* Final setup for the command. */ - exc.cmd = cp; - -#if defined(DEBUG) && 0 - TRACE(sp, "ex_cmd: %s", exc.cmd->name); - if (exc.addrcnt > 0) { - TRACE(sp, "\taddr1 %d", exc.addr1.lno); - if (exc.addrcnt > 1) - TRACE(sp, " addr2: %d", exc.addr2.lno); - TRACE(sp, "\n"); - } - if (exc.lineno) - TRACE(sp, "\tlineno %d", exc.lineno); - if (exc.flags) - TRACE(sp, "\tflags %0x", exc.flags); - if (F_ISSET(&exc, E_BUFFER)) - TRACE(sp, "\tbuffer %c", exc.buffer); - TRACE(sp, "\n"); - if (exc.argc) { - for (cnt = 0; cnt < exc.argc; ++cnt) - TRACE(sp, "\targ %d: {%s}", cnt, exc.argv[cnt]); - TRACE(sp, "\n"); - } -#endif - /* Clear autoprint flag. */ - F_CLR(exp, EX_AUTOPRINT); - - /* Increment the command count if not called from vi. */ - if (IN_EX_MODE(sp)) - ++sp->ccnt; - - /* - * If file state available, and not doing a global command, - * log the start of an action. - */ - if (ep != NULL && !F_ISSET(sp, S_GLOBAL)) - (void)log_cursor(sp, ep); - - /* - * !!! - * 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 erase the prompt character with a '\r'. Else, - * we put out a newline character to separate the command from the - * output from the command. It's OK if vi calls us -- we won't be in - * ex mode so we'll do nothing. - * - * !!! - * Historically, ex only put out a \r, so, if the displayed line was - * only a single character long, and <eof> was represented as ^D, the - * output wouldn't overwrite the user's input. Sex currently doesn't - * display the <eof> character if it's going to be the scroll command, - * i.e. if it's the first non-<blank> character in the line. If sex - * is changed to run in cooked mode, i.e. <eof> is displayed, this code - * will have to overwrite it. We also don't treat lines with extra - * prompt characters as empty -- it's not worth the effort since we'd - * have to overwrite some indeterminate number of columns with spaces - * to clean up. For now, put out enough spaces to overwrite the prompt. - */ - if (sep != NONE) { - if (ep != NULL && - IN_EX_MODE(sp) && F_ISSET(sp->gp, G_STDIN_TTY)) - if (sep == NEEDSEP_NR && - (uselastcmd || cp == &cmds[C_SCROLL])) { - (void)putchar('\r'); - for (len = KEY_LEN(sp, PROMPTCHAR); len--;) - (void)putchar(' '); - (void)putchar('\r'); - } else - (void)putchar('\n'); - sep = NONE; - } - - /* Save the current mode. */ - saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE); - - /* Do the command. */ - if (cp->fn(sp, ep, &exc)) - goto err; - -#ifdef DEBUG - /* Make sure no function left the temporary space locked. */ - if (F_ISSET(sp->gp, G_TMP_INUSE)) { - F_CLR(sp->gp, G_TMP_INUSE); - msgq(sp, M_ERR, "Error: ex: temporary buffer not released"); - goto err; - } -#endif - if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE)) { - /* - * Only here if the mode of the underlying file changed, e.g. - * the user switched files or is exiting. Two things that we - * might have to save: first, any "+cmd" field set up for an - * ex/edit command will have to be saved for later, also, any - * part of the current ex command that hasn't been executed - * yet. For example: - * - * :edit +25 file.c|s/abc/ABC/|1 - * - * !!! - * The historic vi just hung, of course; nvi handles it by - * pushing the keys onto the tty queue. Since the commands - * are intended as ex commands, add additional characters - * to make it all work if we're switching modes to vi. Also, - * + commands were oriented to the last line in the file, - * historically, make the cursor start out there. - * - * 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 - */ - if (arg1_len == 0 && save_cmdlen == 0) - return (0); - if (term_push(sp, "\n", 1, 0)) - goto err; - if (save_cmdlen != 0) - if (term_push(sp, save_cmd, save_cmdlen, 0)) - goto err; - if (arg1 != NULL) { - if (IN_VI_MODE(sp) && save_cmdlen != 0 && - term_push(sp, "|", 1, 0)) - goto err; - if (term_push(sp, arg1, arg1_len, 0)) - goto err; - if (file_lline(sp, ep, &sp->frp->lno)) - goto err; - F_SET(sp->frp, FR_CURSORSET); - } - if (IN_VI_MODE(sp) && term_push(sp, ":", 1, 0)) - goto err; - return (0); - } - - /* - * Integrate any offset parsed by the underlying command, and make - * sure the referenced line exists. - * - * XXX - * May not match historic practice (I've never been able to completely - * figure it 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 probably know. - */ - if (ep != NULL && (flagoff += exc.flagoff)) { - if (flagoff < 0) { - if (sp->lno <= -flagoff) { - msgq(sp, M_ERR, "Flag offset before line 1"); - goto err; - } - } else { - if (file_lline(sp, ep, &lno)) - goto err; - if (sp->lno + flagoff > lno) { - msgq(sp, M_ERR, "Flag offset past end-of-file"); - goto err; - } - } - sp->lno += flagoff; - } - - /* - * If the command was successful and we're in ex command mode, we - * may want to display a line. Make sure there's a line to display. - */ - if (ep != NULL && - IN_EX_MODE(sp) && !F_ISSET(sp, S_GLOBAL) && sp->lno != 0) { - /* - * The print commands have already handled the `print' flags. - * If so, clear them. - */ - if (LF_ISSET(E_F_PRCLEAR)) - F_CLR(&exc, E_F_HASH | E_F_LIST | E_F_PRINT); - - /* If hash only set because of the number option, discard it. */ - if (optnum) - F_CLR(&exc, E_F_HASH); - - /* - * If there was an explicit flag to display the new cursor - * line, or we're in ex mode, autoprint is set, and a change - * was made, display the line. If any print flags set use - * them, otherwise default to print. - */ - LF_INIT(F_ISSET(&exc, E_F_HASH | E_F_LIST | E_F_PRINT)); - if (!LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT) && - O_ISSET(sp, O_AUTOPRINT) && - (F_ISSET(exp, EX_AUTOPRINT) || F_ISSET(cp, E_AUTOPRINT))) - LF_INIT(E_F_PRINT); - - if (LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT)) { - memset(&exc, 0, sizeof(EXCMDARG)); - exc.addrcnt = 2; - exc.addr1.lno = exc.addr2.lno = sp->lno; - exc.addr1.cno = exc.addr2.cno = sp->cno; - (void)ex_print(sp, ep, &exc.addr1, &exc.addr2, flags); - } - } - - cmd = save_cmd; - cmdlen = save_cmdlen; - goto loop; - /* NOTREACHED */ - - /* - * If we haven't put out a separator line, do it now. For more - * detailed comments, see above. - */ -err: if (sep != NONE && - ep != NULL && IN_EX_MODE(sp) && F_ISSET(sp->gp, G_STDIN_TTY)) - (void)fputc('\n', stdout); - /* - * On error, we discard any keys we have left, as well as any keys - * that were mapped. The test of save_cmdlen isn't necessarily - * correct. If we fail early enough we don't know if the entire - * string was a single command or not. Try and guess, it's useful - * to know if part of the command was discarded. - */ - if (save_cmdlen == 0) - for (; cmdlen; --cmdlen) { - ch = *cmd++; - if (IS_ESCAPE(sp, ch) && cmdlen > 1) { - --cmdlen; - ++cmd; - } else if (ch == '\n' || ch == '|') { - if (cmdlen > 1) - save_cmdlen = 1; - break; - } - } - if (save_cmdlen != 0) - msgq(sp, M_ERR, - "Ex command failed: remaining command input discarded"); - /* - * !!! - * Previous versions of nvi cleared mapped characters on error. This - * feature was removed when users complained that it wasn't historic - * practice. - */ - return (1); -} - -/* - * ep_range -- - * Get a line range for ex commands. - */ -static int -ep_range(sp, ep, excp, cmdp, cmdlenp) - SCR *sp; - EXF *ep; - EXCMDARG *excp; - char **cmdp; - size_t *cmdlenp; -{ - MARK cur, savecursor; - size_t cmdlen; - int savecursor_set, tmp; - char *cmd; - - /* Percent character is all lines in the file. */ - cmd = *cmdp; - cmdlen = *cmdlenp; - if (*cmd == '%') { - excp->addr1.lno = 1; - if (file_lline(sp, ep, &excp->addr2.lno)) - return (1); - - /* If an empty file, then the first line is 0, not 1. */ - if (excp->addr2.lno == 0) - excp->addr1.lno = 0; - excp->addr1.cno = excp->addr2.cno = 0; - excp->addrcnt = 2; - - ++*cmdp; - --*cmdlenp; - return (0); - } - - /* Parse comma or semi-colon delimited line specs. */ - for (savecursor_set = 0, excp->addrcnt = 0; cmdlen > 0;) - switch (*cmd) { - case ';': /* Semi-colon delimiter. */ - /* - * Comma delimiters delimit; semi-colon delimiters - * change the current address for the 2nd address - * to be the first address. Trailing or multiple - * delimiters are discarded. - */ - if (excp->addrcnt == 0) - goto done; - if (!savecursor_set) { - savecursor.lno = sp->lno; - savecursor.cno = sp->cno; - sp->lno = excp->addr1.lno; - sp->cno = excp->addr1.cno; - savecursor_set = 1; - } - ++cmd; - --cmdlen; - break; - case ',': /* Comma delimiter. */ - /* If no addresses yet, defaults to ".". */ - if (excp->addrcnt == 0) { - excp->addr1.lno = sp->lno; - excp->addr1.cno = sp->cno; - excp->addrcnt = 1; - } - /* FALLTHROUGH */ - case ' ': /* Whitespace. */ - case '\t': /* Whitespace. */ - ++cmd; - --cmdlen; - break; - default: - if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp)) - return (1); - if (!tmp) - goto done; - - /* - * Extra addresses are discarded, starting with - * the first. - */ - switch (excp->addrcnt) { - case 0: - excp->addr1 = cur; - excp->addrcnt = 1; - break; - case 1: - excp->addr2 = cur; - excp->addrcnt = 2; - break; - case 2: - excp->addr1 = excp->addr2; - excp->addr2 = cur; - break; - } - break; - } - - /* - * XXX - * This is probably not the right behavior for savecursor -- - * need to figure out what the historical ex did for ";,;,;5p" - * or similar stupidity. - */ -done: if (savecursor_set) { - sp->lno = savecursor.lno; - sp->cno = savecursor.cno; - } - if (excp->addrcnt == 2 && excp->addr2.lno < excp->addr1.lno) { - msgq(sp, M_ERR, - "The second address is smaller than the first"); - return (1); - } - *cmdp = cmd; - *cmdlenp = cmdlen; - return (0); -} - -/* - * 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 not exactly historic practice, although it's fairly close. - */ -static int -ep_line(sp, ep, cur, cmdp, cmdlenp, addr_found) - SCR *sp; - EXF *ep; - MARK *cur; - char **cmdp; - size_t *cmdlenp; - int *addr_found; -{ - EX_PRIVATE *exp; - MARK m; - long total; - u_int flags; - size_t cmdlen; - int (*sf) __P((SCR *, EXF *, MARK *, MARK *, char *, char **, u_int *)); - char *cmd, *endp; - - exp = EXP(sp); - *addr_found = 0; - - cmd = *cmdp; - cmdlen = *cmdlenp; - switch (*cmd) { - case '$': /* Last line in the file. */ - *addr_found = 1; - F_SET(exp, EX_ABSMARK); - - cur->cno = 0; - if (file_lline(sp, ep, &cur->lno)) - return (1); - ++cmd; - --cmdlen; - break; /* Absolute line number. */ - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - *addr_found = 1; - F_SET(exp, EX_ABSMARK); - - cur->cno = 0; -/* 8-bit XXX */ cur->lno = strtol(cmd, &endp, 10); - cmdlen -= (endp - cmd); - cmd = endp; - break; - case '\'': /* Use a mark. */ - *addr_found = 1; - F_SET(exp, EX_ABSMARK); - - if (cmdlen == 1) { - msgq(sp, M_ERR, "No mark name supplied"); - return (1); - } - if (mark_get(sp, ep, cmd[1], cur)) - return (1); - cmd += 2; - cmdlen -= 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 (cmdlen < 2 || cmd[1] != '/' && cmd[1] != '?') { - msgq(sp, M_ERR, "\\ not followed by / or ?"); - return (1); - } - ++cmd; - --cmdlen; - sf = cmd[0] == '/' ? f_search : b_search; - goto search; - case '/': /* Search forward. */ - sf = f_search; - goto search; - case '?': /* Search backward. */ - sf = b_search; -search: F_SET(exp, EX_ABSMARK); - - if (ep == NULL) { - msgq(sp, M_ERR, - "A search address requires that a file have already been read in"); - return (1); - } - *addr_found = 1; - m.lno = sp->lno; - m.cno = sp->cno; - flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET; - if (sf(sp, ep, &m, &m, cmd, &endp, &flags)) - return (1); - cur->lno = m.lno; - cur->cno = m.cno; - cmdlen -= (endp - cmd); - cmd = endp; - break; - case '.': /* Current position. */ - *addr_found = 1; - cur->cno = sp->cno; - - /* If an empty file, then '.' is 0, not 1. */ - if (sp->lno == 1) { - if (file_lline(sp, ep, &cur->lno)) - return (1); - if (cur->lno != 0) - cur->lno = 1; - } else - cur->lno = sp->lno; - ++cmd; - --cmdlen; - break; - } - - /* - * Evaluate any offset. Offsets are +/- any number, or any number - * of +/- signs, or any combination thereof. If no address found - * yet, offset is relative to ".". - */ - for (total = 0; cmdlen > 0 && (cmd[0] == '-' || cmd[0] == '+');) { - if (!*addr_found) { - cur->lno = sp->lno; - cur->cno = sp->cno; - *addr_found = 1; - } - - if (cmdlen > 1 && isdigit(cmd[1])) { -/* 8-bit XXX */ total += strtol(cmd, &endp, 10); - cmdlen -= (endp - cmd); - cmd = endp; - } else { - total += cmd[0] == '-' ? -1 : 1; - --cmdlen; - ++cmd; - } - } - - if (*addr_found) { - if (total < 0 && -total > cur->lno) { - msgq(sp, M_ERR, - "Reference to a line number less than 0"); - return (1); - } - cur->lno += total; - - *cmdp = cmd; - *cmdlenp = cmdlen; - } - return (0); -} - -/* - * 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. - * Usual ranting in the vi/v_ntext:txt_abbrev() routine. - */ -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. Usual - * ranting in the vi/v_ntext:txt_unmap() routine. - */ -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]); -} - -static __inline 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); -} - -static void -badlno(sp, lno) - SCR *sp; - recno_t lno; -{ - if (lno == 0) - msgq(sp, M_ERR, "Illegal address: the file is empty"); - else - msgq(sp, M_ERR, "Illegal address: only %lu line%s in the file", - lno, lno > 1 ? "s" : ""); -} diff --git a/usr.bin/vi/ex/ex_abbrev.c b/usr.bin/vi/ex/ex_abbrev.c deleted file mode 100644 index 1360030..0000000 --- a/usr.bin/vi/ex/ex_abbrev.c +++ /dev/null @@ -1,129 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_abbrev.c 8.14 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "../vi/vcmd.h" - -/* - * ex_abbr -- :abbreviate [key replacement] - * Create an abbreviation or display abbreviations. - */ -int -ex_abbr(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - CHAR_T *p; - size_t len; - - switch (cmdp->argc) { - case 0: - if (seq_dump(sp, SEQ_ABBREV, 0) == 0) - msgq(sp, M_INFO, "No abbreviations to display"); - return (0); - case 2: - break; - default: - abort(); - } - - /* Check for illegal characters. */ - for (p = cmdp->argv[0]->bp, len = cmdp->argv[0]->len; len--; ++p) - if (!inword(*p)) { - msgq(sp, M_ERR, - "%s may not be part of an abbreviated word", - KEY_NAME(sp, *p)); - 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. - */ -int -ex_unabbr(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - ARGS *ap; - - ap = cmdp->argv[0]; - if (!F_ISSET(sp->gp, G_ABBREV) || - seq_delete(sp, ap->bp, ap->len, SEQ_ABBREV)) { - msgq(sp, M_ERR, "\"%s\" is not an abbreviation", ap->bp); - return (1); - } - return (0); -} - -/* - * abbr_save -- - * Save the abbreviation sequences to a file. - */ -int -abbr_save(sp, fp) - SCR *sp; - FILE *fp; -{ - return (seq_save(sp, fp, "abbreviate ", SEQ_ABBREV)); -} diff --git a/usr.bin/vi/ex/ex_append.c b/usr.bin/vi/ex/ex_append.c deleted file mode 100644 index b819f5a..0000000 --- a/usr.bin/vi/ex/ex_append.c +++ /dev/null @@ -1,220 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_append.c 8.24 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "../sex/sex_screen.h" - -enum which {APPEND, CHANGE, INSERT}; - -static int aci __P((SCR *, EXF *, EXCMDARG *, 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. - */ -int -ex_append(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (aci(sp, ep, cmdp, APPEND)); -} - -/* - * ex_change -- :[line[,line]] c[hange][!] [count] - * Change one or more lines to the input text. - */ -int -ex_change(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (aci(sp, ep, 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. - */ -int -ex_insert(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (aci(sp, ep, cmdp, INSERT)); -} - -static int -aci(sp, ep, cmdp, cmd) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; - enum which cmd; -{ - MARK m; - TEXTH *sv_tiqp, tiq; - TEXT *tp; - struct termios t; - u_int flags; - int rval; - - rval = 0; - - /* - * Set input flags; the ! flag turns off autoindent for append, - * change and insert. - */ - LF_INIT(TXT_DOTTERM | TXT_NLECHO); - if (!F_ISSET(cmdp, E_FORCE) && O_ISSET(sp, O_AUTOINDENT)) - LF_SET(TXT_AUTOINDENT); - if (O_ISSET(sp, O_BEAUTIFY)) - LF_SET(TXT_BEAUTIFY); - - /* Input is interruptible. */ - F_SET(sp, S_INTERRUPTIBLE); - - /* - * If this code is called by vi, the screen TEXTH structure (sp->tiqp) - * may already be in use, e.g. ":append|s/abc/ABC/" would fail as we're - * only halfway through the line when the append code fires. Use the - * local structure instead. - * - * If this code is called by vi, we want to reset the terminal and use - * ex's s_get() routine. It actually works fine if we use vi's 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. - */ - if (IN_VI_MODE(sp)) { - memset(&tiq, 0, sizeof(TEXTH)); - CIRCLEQ_INIT(&tiq); - sv_tiqp = sp->tiqp; - sp->tiqp = &tiq; - - if (F_ISSET(sp->gp, G_STDIN_TTY)) - SEX_RAW(t); - (void)write(STDOUT_FILENO, "\n", 1); - LF_SET(TXT_NLECHO); - - } - - /* Set the line number, so that autoindent works correctly. */ - sp->lno = cmdp->addr1.lno; - - if (sex_get(sp, ep, sp->tiqp, 0, flags) != INP_OK) - goto err; - - /* - * 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 just appends, and inserts are the same as appends to the - * previous line. - * - * !!! - * Adjust the current line number for the commands to match historic - * practice if the user doesn't enter anything, and set the address - * to which we'll append. This is safe because an address of 0 is - * illegal for change and insert. - */ - m = cmdp->addr1; - switch (cmd) { - case INSERT: - --m.lno; - /* FALLTHROUGH */ - case APPEND: - if (sp->lno == 0) - sp->lno = 1; - break; - case CHANGE: - --m.lno; - if (sp->lno != 1) - --sp->lno; - break; - } - - /* - * !!! - * Cut into the unnamed buffer. - */ - if (cmd == CHANGE && - (cut(sp, ep, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) || - delete(sp, ep, &cmdp->addr1, &cmdp->addr2, 1))) - goto err; - - for (tp = sp->tiqp->cqh_first; - tp != (TEXT *)sp->tiqp; tp = tp->q.cqe_next) { - if (file_aline(sp, ep, 1, m.lno, tp->lb, tp->len)) { -err: rval = 1; - break; - } - sp->lno = ++m.lno; - } - - if (IN_VI_MODE(sp)) { - sp->tiqp = sv_tiqp; - text_lfree(&tiq); - - /* Reset the terminal state. */ - if (F_ISSET(sp->gp, G_STDIN_TTY)) { - if (SEX_NORAW(t)) - rval = 1; - F_SET(sp, S_REFRESH); - } - } - return (rval); -} diff --git a/usr.bin/vi/ex/ex_args.c b/usr.bin/vi/ex/ex_args.c deleted file mode 100644 index 74f94f3..0000000 --- a/usr.bin/vi/ex/ex_args.c +++ /dev/null @@ -1,263 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_args.c 8.29 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * 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. - */ -int -ex_next(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - ARGS **argv, **pc; - FREF *frp; - int noargs; - char **ap; - - if (file_m1(sp, ep, F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE)) - return (1); - - /* - * If the first argument is a plus sign, '+', it's an initial - * ex command. - */ - argv = cmdp->argv; - if (cmdp->argc && argv[0]->bp[0] == '+') { - --cmdp->argc; - pc = argv++; - } else - pc = NULL; - - /* Any other arguments are a replacement file list. */ - if (cmdp->argc) { - /* Free the current list. */ - if (!F_ISSET(sp, S_ARGNOFREE) && sp->argv != NULL) { - for (ap = sp->argv; *ap != NULL; ++ap) - free(*ap); - free(sp->argv); - } - F_CLR(sp, S_ARGNOFREE | S_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 one. */ - sp->cargv = sp->argv; - if ((frp = file_add(sp, *sp->cargv)) == NULL) - return (1); - noargs = 0; - } else { - if (sp->cargv == NULL || sp->cargv[1] == NULL) { - msgq(sp, M_ERR, "No more files to edit"); - return (1); - } - if ((frp = file_add(sp, sp->cargv[1])) == NULL) - return (1); - if (F_ISSET(sp, S_ARGRECOVER)) - F_SET(frp, FR_RECOVER); - noargs = 1; - } - - if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE))) - return (1); - if (noargs) - ++sp->cargv; - - /* Push the initial command onto the stack. */ - if (pc != NULL) - if (IN_EX_MODE(sp)) - (void)term_push(sp, pc[0]->bp, pc[0]->len, 0); - else if (IN_VI_MODE(sp)) { - (void)term_push(sp, "\n", 1, 0); - (void)term_push(sp, pc[0]->bp, pc[0]->len, 0); - (void)term_push(sp, ":", 1, 0); - (void)file_lline(sp, sp->ep, &sp->frp->lno); - F_SET(sp->frp, FR_CURSORSET); - } - - F_SET(sp, S_FSWITCH); - return (0); -} - -/* - * ex_prev -- :prev - * Edit the previous file. - */ -int -ex_prev(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - FREF *frp; - - if (file_m1(sp, ep, F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE)) - return (1); - - if (sp->cargv == sp->argv) { - msgq(sp, M_ERR, "No previous files to edit"); - return (1); - } - if ((frp = file_add(sp, sp->cargv[-1])) == NULL) - return (1); - - if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE))) - return (1); - - --sp->cargv; - F_SET(sp, S_FSWITCH); - return (0); -} - -/* - * ex_rew -- :rew - * Re-edit the list of files. - */ -int -ex_rew(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - FREF *frp; - - /* - * !!! - * Historic practice -- you can rewind to the current file. - */ - if (sp->argv == NULL) { - msgq(sp, M_ERR, "No previous files to rewind"); - return (1); - } - - if (file_m1(sp, ep, F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE)) - return (1); - - /* - * !!! - * Historic practice, start at the beginning of the file. - */ - for (frp = sp->frefq.cqh_first; - frp != (FREF *)&sp->frefq; frp = frp->q.cqe_next) - F_CLR(frp, FR_CURSORSET | FR_FNONBLANK); - - /* 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, F_ISSET(cmdp, E_FORCE))) - return (1); - - F_SET(sp, S_FSWITCH); - return (0); -} - -/* - * ex_args -- :args - * Display the list of files. - */ -int -ex_args(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - int cnt, col, len, sep; - char **ap; - - if (sp->argv == NULL) { - (void)ex_printf(EXCOOKIE, "No file list to display.\n"); - return (0); - } - - 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_printf(EXCOOKIE, "\n"); - } else if (cnt != 1) { - sep = 1; - (void)ex_printf(EXCOOKIE, " "); - } - ++cnt; - - if (ap == sp->cargv) - (void)ex_printf(EXCOOKIE, "[%s]", *ap); - else - (void)ex_printf(EXCOOKIE, "%s", *ap); - } - (void)ex_printf(EXCOOKIE, "\n"); - return (0); -} diff --git a/usr.bin/vi/ex/ex_argv.c b/usr.bin/vi/ex/ex_argv.c deleted file mode 100644 index bb033e2..0000000 --- a/usr.bin/vi/ex/ex_argv.c +++ /dev/null @@ -1,609 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_argv.c 8.38 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -static int argv_alloc __P((SCR *, size_t)); -static int argv_fexp __P((SCR *, EXCMDARG *, - char *, size_t, char *, size_t *, char **, size_t *, int)); -static int argv_sexp __P((SCR *, char **, size_t *, size_t *)); - -/* - * argv_init -- - * Build a prototype arguments list. - */ -int -argv_init(sp, ep, excp) - SCR *sp; - EXF *ep; - EXCMDARG *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. - */ -int -argv_exp0(sp, ep, excp, cmd, cmdlen) - SCR *sp; - EXF *ep; - EXCMDARG *excp; - char *cmd; - size_t cmdlen; -{ - EX_PRIVATE *exp; - - exp = EXP(sp); - argv_alloc(sp, cmdlen); - memmove(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. - */ -int -argv_exp1(sp, ep, excp, cmd, cmdlen, is_bang) - SCR *sp; - EXF *ep; - EXCMDARG *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, ep, 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. - */ -int -argv_exp2(sp, ep, excp, cmd, cmdlen, is_bang) - SCR *sp; - EXF *ep; - EXCMDARG *excp; - char *cmd; - size_t cmdlen; - int is_bang; -{ - 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) - memmove(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, is_bang)) { - 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. - */ - for (p = mp = O_STR(sp, O_META); *p != '\0'; ++p) - if (isblank(*p) || isalnum(*p)) - break; - if (*p != '\0') { - for (p = bp, n = len; n > 0; --n, ++p) - if (strchr(mp, *p) != NULL) - break; - } else - for (p = bp, n = len; n > 0; --n, ++p) - if (!isblank(*p) && - !isalnum(*p) && strchr(mp, *p) != NULL) - break; - if (n > 0) { - if (argv_sexp(sp, &bp, &blen, &len)) { - rval = 1; - goto err; - } - p = bp; - } else { - p = bp + SHELLOFFSET; - len -= SHELLOFFSET; - } - -#if defined(DEBUG) && 0 - TRACE(sp, "after shell: %d: {%s}\n", len, bp); -#endif - - rval = argv_exp3(sp, ep, excp, p, len); - -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. - */ -int -argv_exp3(sp, ep, excp, cmd, cmdlen) - SCR *sp; - EXF *ep; - EXCMDARG *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, 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, *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; - EXCMDARG *excp; - char *cmd, *p, **bpp; - size_t cmdlen, *lenp, *blenp; - int is_bang; -{ - EX_PRIVATE *exp; - char *bp, *t; - size_t blen, len, 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, - "No previous command to replace \"!\""); - return (1); - } - len += tlen = strlen(exp->lastbcomm); - ADD_SPACE_RET(sp, bp, blen, len); - memmove(p, exp->lastbcomm, tlen); - p += tlen; - F_SET(excp, E_MODIFY); - break; - case '%': - if ((t = sp->frp->name) == NULL) { - msgq(sp, M_ERR, - "No filename to substitute for %%"); - return (1); - } - tlen = strlen(t); - len += tlen; - ADD_SPACE_RET(sp, bp, blen, len); - memmove(p, t, tlen); - p += tlen; - F_SET(excp, E_MODIFY); - break; - case '#': - if ((t = sp->alt_name) == NULL) { - msgq(sp, M_ERR, - "No filename to substitute for #"); - return (1); - } - len += tlen = strlen(t); - ADD_SPACE_RET(sp, bp, blen, len); - memmove(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; - --cmdlen; - } - /* FALLTHROUGH */ - default: -ins_ch: ++len; - ADD_SPACE_RET(sp, bp, blen, len); - *p++ = *cmd; - } - - /* Nul termination. */ - ++len; - ADD_SPACE_RET(sp, bp, blen, len); - *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[off], 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. - */ -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], sizeof(ARGS)); - } - FREE(exp->args, exp->argscnt * sizeof(ARGS *)); - } - exp->args = NULL; - exp->argscnt = 0; - exp->argsoff = 0; - return (0); -} - -/* - * 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; -{ - FILE *ifp; - pid_t pid; - size_t blen, len; - int ch, rval, output[2]; - char *bp, *p, *sh, *sh_path; - - bp = *bpp; - blen = *blenp; - - sh_path = O_STR(sp, O_SHELL); - if ((sh = strrchr(sh_path, '/')) == NULL) - sh = sh_path; - else - ++sh; - - /* - * There are two different processes running through this code. - * They are named the utility and the parent. The utility reads - * from standard input and writes to the parent. The parent reads - * from the utility and writes into the buffer. The parent reads - * from output[0], and the utility writes to output[1]. - */ - if (pipe(output) < 0) { - msgq(sp, M_SYSERR, "pipe"); - return (1); - } - if ((ifp = fdopen(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. Hopefully. - */ - SIGBLOCK(sp->gp); - switch (pid = vfork()) { - case -1: /* Error. */ - SIGUNBLOCK(sp->gp); - - msgq(sp, M_SYSERR, "vfork"); -err: (void)close(output[0]); - (void)close(output[1]); - return (1); - case 0: /* Utility. */ - /* The utility has default signal behavior. */ - sig_end(); - - /* Redirect stdout/stderr to the write end of the pipe. */ - (void)dup2(output[1], STDOUT_FILENO); - (void)dup2(output[1], STDERR_FILENO); - - /* Close the utility's file descriptors. */ - (void)close(output[0]); - (void)close(output[1]); - - /* Assumes that all shells have -c. */ - execl(sh_path, sh, "-c", bp, NULL); - msgq(sp, M_ERR, - "Error: execl: %s: %s", sh_path, strerror(errno)); - _exit(127); - default: /* Parent. */ - SIGUNBLOCK(sp->gp); - - /* Close the pipe end the parent won't use. */ - (void)close(output[1]); - break; - } - - rval = 0; - - /* - * Copy process 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, blen, *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')) { - --len; - *--p = '\0'; - } else - *p = '\0'; - *lenp = len; - - if (ferror(ifp)) { - msgq(sp, M_ERR, "I/O error: %s", sh); -binc_err: rval = 1; - } - (void)fclose(ifp); - - *bpp = bp; /* *blenp is already updated. */ - - /* Wait for the process. */ - return (proc_wait(sp, (long)pid, sh, 0) || rval); -} diff --git a/usr.bin/vi/ex/ex_at.c b/usr.bin/vi/ex/ex_at.c deleted file mode 100644 index 147261d..0000000 --- a/usr.bin/vi/ex/ex_at.c +++ /dev/null @@ -1,118 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_at.c 8.27 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_at -- :@[@ | buffer] - * :*[* | buffer] - * - * Execute the contents of the buffer. - */ -int -ex_at(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - CB *cbp; - EX_PRIVATE *exp; - TEXT *tp; - int name; - - exp = EXP(sp); - - /* - * !!! - * Historically, [@*]<carriage-return> and [@*][@*] executed the most - * recently executed buffer in ex mode. In vi mode, only @@ repeated - * the last buffer. We change historic practice and make @* work from - * vi mode as well, it's simpler and more consistent. - */ - name = F_ISSET(cmdp, E_BUFFER) ? cmdp->buffer : '@'; - if (name == '@' || name == '*') { - if (!exp->at_lbuf_set) { - msgq(sp, M_ERR, "No previous buffer to execute"); - return (1); - } - name = exp->at_lbuf; - } - - CBNAME(sp, cbp, name); - if (cbp == NULL) { - msgq(sp, M_ERR, "Buffer %s is empty", KEY_NAME(sp, name)); - return (1); - } - - /* Save for reuse. */ - exp->at_lbuf = name; - exp->at_lbuf_set = 1; - - /* - * !!! - * Historic practice is that if the buffer was cut in line mode, - * <newlines> were appended to each line as it was pushed onto - * the stack. If the buffer was cut in character mode, <newlines> - * were appended to all lines but the last one. - */ - for (tp = cbp->textq.cqh_last; - tp != (void *)&cbp->textq; tp = tp->q.cqe_prev) - if ((F_ISSET(cbp, CB_LMODE) || - tp->q.cqe_next != (void *)&cbp->textq) && - term_push(sp, "\n", 1, 0) || - term_push(sp, tp->lb, tp->len, 0)) - return (1); - return (0); -} diff --git a/usr.bin/vi/ex/ex_bang.c b/usr.bin/vi/ex/ex_bang.c deleted file mode 100644 index d2ffaa4..0000000 --- a/usr.bin/vi/ex/ex_bang.c +++ /dev/null @@ -1,242 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_bang.c 8.35 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "../sex/sex_screen.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. - */ -int -ex_bang(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - enum filtertype ftype; - ARGS *ap; - EX_PRIVATE *exp; - MARK rm; - recno_t lno; - size_t blen; - int rval; - char *bp, *msg; - - ap = cmdp->argv[0]; - if (ap->len == 0) { - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); - } - - /* Set the last bang command. */ - 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, we redisplay it. - * Redisplaying it in vi mode is tricky, and handled separately - * in each case below. If we're in ex mode, it's easy, so we just - * do it here. - */ - bp = NULL; - if (F_ISSET(cmdp, E_MODIFY) && !F_ISSET(sp, S_EXSILENT)) { - if (IN_EX_MODE(sp)) { - (void)ex_printf(EXCOOKIE, "!%s\n", ap->bp); - (void)ex_fflush(EXCOOKIE); - } - /* - * Vi: Display the command if modified. Historic vi displayed - * the command if it was modified due to file name and/or bang - * expansion. If piping lines, it was immediately overwritten - * by any error or line change reporting. We don't the user to - * have to page through the responses, so we only post it until - * it's erased by something else. Otherwise, pass it on to the - * ex_exec_proc routine to display after the screen has been - * cleaned up. - */ - if (IN_VI_MODE(sp)) { - GET_SPACE_RET(sp, bp, blen, ap->len + 3); - bp[0] = '!'; - memmove(bp + 1, ap->bp, ap->len); - bp[ap->len + 1] = '\n'; - bp[ap->len + 2] = '\0'; - } - } - - /* - * 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 by only the stdout lines. This makes - * no sense to me, so nvi makes it consistent for both, and matches - * vi's historic behavior. - */ - if (cmdp->addrcnt != 0) { - /* Autoprint is set historically, even if the command fails. */ - F_SET(exp, EX_AUTOPRINT); - - /* Vi gets a busy message. */ - if (bp != NULL) - (void)sp->s_busy(sp, bp); - - /* - * !!! - * Historical vi permitted "!!" in an empty file. When it - * happens, we get called with two addresses of 1,1 and a - * bad attitude. The simple solution is to turn it into a - * FILTER_READ operation, but that means that we don't put - * an empty line into the default cut buffer as did historic - * vi. Tough. - */ - ftype = FILTER; - if (cmdp->addr1.lno == 1 && cmdp->addr2.lno == 1) { - if (file_lline(sp, ep, &lno)) - return (1); - if (lno == 0) { - cmdp->addr1.lno = cmdp->addr2.lno = 0; - ftype = FILTER_READ; - } - } - rval = filtercmd(sp, ep, - &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, so we do it. - */ - if (rval == 0) { - sp->lno = rm.lno; - if (IN_VI_MODE(sp)) { - sp->cno = 0; - (void)nonblank(sp, ep, sp->lno, &sp->cno); - } - } - goto ret2; - } - - /* - * If no addresses were specified, run the command. If the file - * has 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. - */ - msg = NULL; - if (F_ISSET(ep, F_MODIFIED)) - if (O_ISSET(sp, O_AUTOWRITE)) { - if (file_write(sp, ep, NULL, NULL, NULL, FS_ALL)) { - rval = 1; - goto ret1; - } - } else if (O_ISSET(sp, O_WARN) && !F_ISSET(sp, S_EXSILENT)) - msg = "File modified since last write.\n"; - - /* Run the command. */ - rval = ex_exec_proc(sp, ap->bp, bp, msg); - - /* Vi requires user permission to continue. */ - if (IN_VI_MODE(sp)) - F_SET(sp, S_CONTINUE); - -ret2: if (IN_EX_MODE(sp)) { - /* - * Put ex error messages out so they aren't confused with - * the autoprint output. - */ - if (rval) - (void)sex_refresh(sp, sp->ep); - - /* Ex terminates with a bang, even if the command fails. */ - if (!F_ISSET(sp, S_EXSILENT)) - (void)write(STDOUT_FILENO, "!\n", 2); - } - - /* Free the extra space. */ -ret1: if (bp != NULL) - FREE_SPACE(sp, bp, blen); - - /* - * XXX - * The ! commands never return an error, so that autoprint always - * happens in the ex parser. - */ - return (0); -} diff --git a/usr.bin/vi/ex/ex_cd.c b/usr.bin/vi/ex/ex_cd.c deleted file mode 100644 index 8a3d0f1b..0000000 --- a/usr.bin/vi/ex/ex_cd.c +++ /dev/null @@ -1,223 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_cd.c 8.18 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <errno.h> -#include <limits.h> -#include <pwd.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_cd -- :cd[!] [directory] - * Change directories. - */ -int -ex_cd(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - struct passwd *pw; - ARGS *ap; - CDPATH *cdp; - char *dir; /* 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(ep, F_MODIFIED) && - !F_ISSET(cmdp, E_FORCE) && sp->frp->name[0] != '/') { - msgq(sp, M_ERR, - "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, - "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 (!chdir(dir)) - goto ret; - - /* - * 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; - - /* If the user has a CDPATH variable, try its elements. */ - for (cdp = EXP(sp)->cdq.tqh_first; cdp != NULL; cdp = cdp->q.tqe_next) { - (void)snprintf(buf, sizeof(buf), "%s/%s", cdp->path, dir); - if (!chdir(buf)) { -ret: if (getcwd(buf, sizeof(buf)) != NULL) - msgq(sp, M_INFO, "New directory: %s", buf); - return (0); - } - } -err: msgq(sp, M_SYSERR, "%s", dir); - return (1); -} - -#define FREE_CDPATH(cdp) { \ - TAILQ_REMOVE(&exp->cdq, (cdp), q); \ - free((cdp)->path); \ - FREE((cdp), sizeof(CDPATH)); \ -} -/* - * ex_cdalloc -- - * Create a new list of cd paths. - */ -int -ex_cdalloc(sp, str) - SCR *sp; - char *str; -{ - EX_PRIVATE *exp; - CDPATH *cdp; - size_t len; - int founddot; - char *p, *t; - - /* Free current queue. */ - exp = EXP(sp); - while ((cdp = exp->cdq.tqh_first) != NULL) - FREE_CDPATH(cdp); - - /* - * Create new queue. The CDPATH environmental variable (and the - * user's manual entry) are delimited by colon characters. - */ - for (p = t = str, founddot = 0;; ++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 the length is zero, then it's either ":XXX", - * "XXX::XXXX" , "XXX:", or "", and the only failure - * mode is the last one. Note, the string ":" gives - * us two entries of '.', so we only include one of - * them. - */ - if ((len = p - t) == 0) { - if (p == str && *p == '\0') - break; - if (founddot) { - if (*p == '\0') - break; - continue; - } - len = 1; - t = "."; - founddot = 1; - } - MALLOC_RET(sp, cdp, CDPATH *, sizeof(CDPATH)); - MALLOC(sp, cdp->path, char *, len + 1); - if (cdp->path == NULL) { - free(cdp); - return (1); - } - memmove(cdp->path, t, len); - cdp->path[len] = '\0'; - TAILQ_INSERT_TAIL(&exp->cdq, cdp, q); - t = p + 1; - } - if (*p == '\0') - break; - } - return (0); -} - /* Free previous queue. */ -/* - * ex_cdfree -- - * Free the cd path list. - */ -int -ex_cdfree(sp) - SCR *sp; -{ - EX_PRIVATE *exp; - CDPATH *cdp; - - /* Free up cd path information. */ - exp = EXP(sp); - while ((cdp = exp->cdq.tqh_first) != NULL) - FREE_CDPATH(cdp); - return (0); -} diff --git a/usr.bin/vi/ex/ex_delete.c b/usr.bin/vi/ex/ex_delete.c deleted file mode 100644 index 4e1d241..0000000 --- a/usr.bin/vi/ex/ex_delete.c +++ /dev/null @@ -1,92 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_delete.c 8.14 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_delete: [line [,line]] d[elete] [buffer] [count] [flags] - * - * Delete lines from the file. - */ -int -ex_delete(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - recno_t lno; - - /* - * !!! - * 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, ep, - F_ISSET(cmdp, E_BUFFER) ? &cmdp->buffer : NULL, - &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE)) - return (1); - - /* Delete the lines. */ - if (delete(sp, ep, &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 (file_lline(sp, ep, &lno)) - return (1); - if (sp->lno > lno) - sp->lno = lno; - return (0); -} diff --git a/usr.bin/vi/ex/ex_digraph.c b/usr.bin/vi/ex/ex_digraph.c deleted file mode 100644 index 0db20bb..0000000 --- a/usr.bin/vi/ex/ex_digraph.c +++ /dev/null @@ -1,324 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_digraph.c 8.8 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#ifndef NO_DIGRAPH -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <curses.h> -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -static void do_digraph __P((SCR *, EXF *, int, u_char *)); - -/* This stuff is used to build the default digraphs table. */ -static u_char digtable[][4] = { -# ifdef CS_IBMPC - "C,\200", "u\"\1", "e'\2", "a^\3", - "a\"\4", "a`\5", "a@\6", "c,\7", - "e^\10", "e\"\211", "e`\12", "i\"\13", - "i^\14", "i`\15", "A\"\16", "A@\17", - "E'\20", "ae\21", "AE\22", "o^\23", - "o\"\24", "o`\25", "u^\26", "u`\27", - "y\"\30", "O\"\31", "U\"\32", "a'\240", - "i'!", "o'\"", "u'#", "n~$", - "N~%", "a-&", "o-'", "~?(", - "~!-", "\"<.", "\">/", -# ifdef CS_SPECIAL - "2/+", "4/,", "^+;", "^q<", - "^c=", "^r>", "^t?", "pp]", - "^^^", "oo_", "*a`", "*ba", - "*pc", "*Sd", "*se", "*uf", - "*tg", "*Ph", "*Ti", "*Oj", - "*dk", "*Hl", "*hm", "*En", - "*No", "eqp", "pmq", "ger", - "les", "*It", "*iu", "*/v", - "*=w", "sq{", "^n|", "^2}", - "^3~", "^_\377", -# endif /* CS_SPECIAL */ -# endif /* CS_IBMPC */ -# ifdef CS_LATIN1 - "~!!", "a-*", "\">+", "o-:", - "\"<>", "~??", - - "A`@", "A'A", "A^B", "A~C", - "A\"D", "A@E", "AEF", "C,G", - "E`H", "E'I", "E^J", "E\"K", - "I`L", "I'M", "I^N", "I\"O", - "-DP", "N~Q", "O`R", "O'S", - "O^T", "O~U", "O\"V", "O/X", - "U`Y", "U'Z", "U^[", "U\"\\", - "Y'_", - - "a``", "a'a", "a^b", "a~c", - "a\"d", "a@e", "aef", "c,g", - "e`h", "e'i", "e^j", "e\"k", - "i`l", "i'm", "i^n", "i\"o", - "-dp", "n~q", "o`r", "o's", - "o^t", "o~u", "o\"v", "o/x", - "u`y", "u'z", "u^{", "u\"|", - "y'~", -# endif /* CS_LATIN1 */ - "" -}; - -int -digraph_init(sp) - SCR *sp; -{ - int i; - - for (i = 0; *digtable[i]; i++) - do_digraph(sp, NULL, 0, digtable[i]); - do_digraph(sp, NULL, 0, NULL); - return (0); -} - -int -ex_digraph(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - do_digraph(sp, ep, F_ISSET(cmdp, E_FORCE), cmdp->argv[0]->bp); - return (0); -} - -static struct _DIG -{ - struct _DIG *next; - char key1; - char key2; - char dig; - char save; -} *digs; - -int -digraph(sp, key1, key2) - SCR *sp; - char key1; /* the underlying character */ - char key2; /* the second character */ -{ - int new_key; - register struct _DIG *dp; - - /* if digraphs are disabled, then just return the new char */ - if (O_ISSET(sp, O_DIGRAPH)) - { - return key2; - } - - /* remember the new key, so we can return it if this isn't a digraph */ - new_key = key2; - - /* sort key1 and key2, so that their original order won't matter */ - if (key1 > key2) - { - key2 = key1; - key1 = new_key; - } - - /* scan through the digraph chart */ - for (dp = digs; - dp && (dp->key1 != key1 || dp->key2 != key2); - dp = dp->next) - { - } - - /* if this combination isn't in there, just use the new key */ - if (!dp) - { - return new_key; - } - - /* else use the digraph key */ - return dp->dig; -} - -/* this function lists or defines digraphs */ -static void -do_digraph(sp, ep, bang, extra) - SCR *sp; - EXF *ep; - int bang; - u_char *extra; -{ - int dig; - register struct _DIG *dp; - struct _DIG *prev; - static int user_defined = 0; /* boolean: are all later digraphs user-defined? */ - char listbuf[8]; - - /* if "extra" is NULL, then we've reached the end of the built-ins */ - if (!extra) - { - user_defined = 1; - return; - } - - /* if no args, then display the existing digraphs */ - if (*extra < ' ') - { - listbuf[0] = listbuf[1] = listbuf[2] = listbuf[5] = ' '; - listbuf[7] = '\0'; - for (dig = 0, dp = digs; dp; dp = dp->next) - { - if (dp->save || bang) - { - dig += 7; - if (dig >= sp->cno) - { - addch('\n'); - refresh(); - dig = 7; - } - listbuf[3] = dp->key1; - listbuf[4] = dp->key2; - listbuf[6] = dp->dig; - addstr(listbuf); - } - } - addch('\n'); - refresh(); - return; - } - - /* make sure we have at least two characters */ - if (!extra[1]) - { - msgq(sp, M_ERR, - "Digraphs must be composed of two characters"); - return; - } - - /* sort key1 and key2, so that their original order won't matter */ - if (extra[0] > extra[1]) - { - dig = extra[0]; - extra[0] = extra[1]; - extra[1] = dig; - } - - /* locate the new digraph character */ - for (dig = 2; extra[dig] == ' ' || extra[dig] == '\t'; dig++) - { - } - dig = extra[dig]; - if (!bang && dig) - { - dig |= 0x80; - } - - /* search for the digraph */ - for (prev = (struct _DIG *)0, dp = digs; - dp && (dp->key1 != extra[0] || dp->key2 != extra[1]); - prev = dp, dp = dp->next) - { - } - - /* deleting the digraph? */ - if (!dig) - { - if (!dp) - { -#ifndef CRUNCH - msgq(sp, M_ERR, - "%c%c not a digraph", extra[0], extra[1]); -#endif - return; - } - if (prev) - prev->next = dp->next; - else - digs = dp->next; - free(dp); - return; - } - - /* if necessary, create a new digraph struct for the new digraph */ - if (dig && !dp) - { - MALLOC(sp, dp, struct _DIG *, sizeof(struct _DIG)); - if (dp == NULL) - return; - if (prev) - prev->next = dp; - else - digs = dp; - dp->next = (struct _DIG *)0; - } - - /* assign it the new digraph value */ - dp->key1 = extra[0]; - dp->key2 = extra[1]; - dp->dig = dig; - dp->save = user_defined; -} - -void -digraph_save(sp, fd) - SCR *sp; - int fd; -{ - static char buf[] = "digraph! XX Y\n"; - register struct _DIG *dp; - - for (dp = digs; dp; dp = dp->next) - { - if (dp->save) - { - buf[9] = dp->key1; - buf[10] = dp->key2; - buf[12] = dp->dig; - write(fd, buf, (unsigned)14); - } - } -} -#endif diff --git a/usr.bin/vi/ex/ex_display.c b/usr.bin/vi/ex/ex_display.c deleted file mode 100644 index 7f90ef2..0000000 --- a/usr.bin/vi/ex/ex_display.c +++ /dev/null @@ -1,169 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_display.c 8.23 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "tag.h" -#include "excmd.h" - -static int bdisplay __P((SCR *, EXF *)); -static void db __P((SCR *, CB *, CHAR_T *)); - -/* - * ex_display -- :display b[uffers] | s[creens] | t[ags] - * - * Display buffers, tags or screens. - */ -int -ex_display(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *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, ep)); - 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, ep)); - 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_tagdisplay(sp, ep)); - } - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); -} - -/* - * bdisplay -- - * - * Display buffers. - */ -static int -bdisplay(sp, ep) - SCR *sp; - EXF *ep; -{ - CB *cbp; - - if (sp->gp->cutq.lh_first == NULL && sp->gp->dcbp == NULL) { - (void)ex_printf(EXCOOKIE, "No cut buffers to display.\n"); - return (0); - } - - /* Buffers can be infinitely long, make it interruptible. */ - F_SET(sp, S_INTERRUPTIBLE); - - /* 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; - TEXT *tp; - size_t len; - - (void)ex_printf(EXCOOKIE, "********** %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_printf(EXCOOKIE, "%s", KEY_NAME(sp, *p)); - if (INTERRUPTED(sp)) - return; - } - (void)ex_printf(EXCOOKIE, "\n"); - } -} diff --git a/usr.bin/vi/ex/ex_edit.c b/usr.bin/vi/ex/ex_edit.c deleted file mode 100644 index 5a54e73..0000000 --- a/usr.bin/vi/ex/ex_edit.c +++ /dev/null @@ -1,122 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_edit.c 8.20 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_edit -- :e[dit][!] [+cmd] [file] - * :vi[sual][!] [+cmd] [file] - * - * Edit a file; if none specified, re-edit the current file. The second - * 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. - */ -int -ex_edit(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - ARGS *ap; - FREF *frp; - - frp = sp->frp; - 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, - * create another one. The reason for this is that we do - * special exit processing of temporary files, and reusing - * them is tricky. - */ - if (F_ISSET(frp, FR_TMPFILE)) { - if ((frp = file_add(sp, NULL)) == NULL) - return (1); - } else { - if ((frp = file_add(sp, frp->name)) == NULL) - return (1); - set_alt_name(sp, sp->frp->name); - } - break; - case 1: - ap = cmdp->argv[0]; - if ((frp = file_add(sp, ap->bp)) == NULL) - return (1); - set_alt_name(sp, ap->bp); - break; - default: - abort(); - } - - /* - * Check for modifications. - * - * !!! - * Contrary to POSIX 1003.2-1992, autowrite did not affect :edit. - */ - if (file_m2(sp, ep, F_ISSET(cmdp, E_FORCE))) - return (1); - - /* Switch files. */ - if (file_init(sp, frp, NULL, F_ISSET(cmdp, E_FORCE))) - return (1); - F_SET(sp, S_FSWITCH); - return (0); -} diff --git a/usr.bin/vi/ex/ex_equal.c b/usr.bin/vi/ex/ex_equal.c deleted file mode 100644 index ec979a0..0000000 --- a/usr.bin/vi/ex/ex_equal.c +++ /dev/null @@ -1,86 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_equal.c 8.8 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_equal -- :address = - */ -int -ex_equal(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - recno_t lno; - - /* - * 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_ADDRDEF)) { - if (file_lline(sp, ep, &lno)) - return (1); - } else - lno = cmdp->addr1.lno; - - (void)ex_printf(EXCOOKIE, "%ld\n", lno); - return (0); -} diff --git a/usr.bin/vi/ex/ex_exit.c b/usr.bin/vi/ex/ex_exit.c deleted file mode 100644 index 79c4039..0000000 --- a/usr.bin/vi/ex/ex_exit.c +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_exit.c 8.15 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_quit -- :quit[!] - * Quit. - */ -int -ex_quit(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - int force; - - force = F_ISSET(cmdp, E_FORCE); - - /* Check for modifications. */ - if (file_m2(sp, ep, force)) - return (1); - - /* Check for more files to edit. */ - if (ex_ncheck(sp, force)) - return (1); - - F_SET(sp, force ? S_EXIT_FORCE : S_EXIT); - return (0); -} diff --git a/usr.bin/vi/ex/ex_file.c b/usr.bin/vi/ex/ex_file.c deleted file mode 100644 index cf5f329..0000000 --- a/usr.bin/vi/ex/ex_file.c +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_file.c 8.12 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_file -- :f[ile] [name] - * Change the file's name and display the status line. - */ -int -ex_file(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - CHAR_T *p; - FREF *frp; - - 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 read-only bit follows the file name; clear it. - * The file has a real name, it's no longer a temporary. - */ - F_CLR(frp, FR_RDONLY | FR_TMPFILE); - - /* Have to force a write if the file exists, next time. */ - F_SET(frp, FR_NAMECHANGE); - break; - default: - abort(); - } - return (msg_status(sp, ep, sp->lno, 1)); -} diff --git a/usr.bin/vi/ex/ex_global.c b/usr.bin/vi/ex/ex_global.c deleted file mode 100644 index 5fb134d..0000000 --- a/usr.bin/vi/ex/ex_global.c +++ /dev/null @@ -1,400 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_global.c 8.43 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -enum which {GLOBAL, VGLOBAL}; - -static int global __P((SCR *, EXF *, EXCMDARG *, enum which)); - -/* - * ex_global -- [line [,line]] g[lobal][!] /pattern/ [commands] - * Exec on lines matching a pattern. - */ -int -ex_global(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (global(sp, ep, - cmdp, F_ISSET(cmdp, E_FORCE) ? VGLOBAL : GLOBAL)); -} - -/* - * ex_vglobal -- [line [,line]] v[global] /pattern/ [commands] - * Exec on lines not matching a pattern. - */ -int -ex_vglobal(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (global(sp, ep, cmdp, VGLOBAL)); -} - -static int -global(sp, ep, cmdp, cmd) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; - enum which cmd; -{ - MARK abs; - RANGE *rp; - EX_PRIVATE *exp; - recno_t elno, lno; - regmatch_t match[1]; - regex_t *re, lre; - size_t clen, len; - int delim, eval, reflags, replaced, rval; - char *cb, *ptrn, *p, *t; - - /* - * Skip leading white space. Historic vi allowed any non- - * alphanumeric to serve as the global command delimiter. - */ - for (p = cmdp->argv[0]->bp; isblank(*p); ++p); - if (*p == '\0' || isalnum(*p)) { - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->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] == '\\' && p[1] == delim) - ++p; - *t++ = *p++; - } - - /* If the pattern string is empty, use the last one. */ - if (*ptrn == '\0') { - if (!F_ISSET(sp, S_SRE_SET)) { - msgq(sp, M_ERR, "No previous regular expression"); - return (1); - } - re = &sp->sre; - } else { - /* Set RE flags. */ - reflags = 0; - if (O_ISSET(sp, O_EXTENDED)) - reflags |= REG_EXTENDED; - if (O_ISSET(sp, O_IGNORECASE)) - reflags |= REG_ICASE; - - /* Convert vi-style RE's to POSIX 1003.2 RE's. */ - if (re_conv(sp, &ptrn, &replaced)) - return (1); - - /* Compile the RE. */ - re = &lre; - eval = regcomp(re, ptrn, reflags); - - /* Free up any allocated memory. */ - if (replaced) - FREE_SPACE(sp, ptrn, 0); - - if (eval) { - re_error(sp, eval, re); - return (1); - } - - /* - * Set saved RE. Historic practice is that - * globals set direction as well as the RE. - */ - sp->sre = lre; - sp->searchdir = FORWARD; - F_SET(sp, S_SRE_SET); - } - - /* - * 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. - */ - if ((clen = strlen(p)) == 0) { - p = "p"; - clen = 1; - } - MALLOC_RET(sp, cb, char *, clen); - memmove(cb, p, clen); - - /* - * The global commands sets the substitute RE as well as - * the everything-else RE. - */ - sp->subre = sp->sre; - F_SET(sp, S_SUBRE_SET); - - /* Set the global flag. */ - F_SET(sp, S_GLOBAL); - - /* The global commands always set the previous context mark. */ - abs.lno = sp->lno; - abs.cno = sp->cno; - if (mark_set(sp, ep, ABSMARK1, &abs, 1)) - goto err; - - /* - * 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. - */ - exp = EXP(sp); - for (rval = 0, lno = cmdp->addr1.lno, - elno = cmdp->addr2.lno; lno <= elno; ++lno) { - /* Someone's unhappy, time to stop. */ - if (INTERRUPTED(sp)) - goto interrupted; - - /* Get the line and search for a match. */ - if ((t = file_gline(sp, ep, lno, &len)) == NULL) { - GETLINE_ERR(sp, lno); - goto err; - } - match[0].rm_so = 0; - match[0].rm_eo = len; - switch(eval = regexec(re, t, 1, match, REG_STARTEND)) { - case 0: - if (cmd == VGLOBAL) - continue; - break; - case REG_NOMATCH: - if (cmd == GLOBAL) - continue; - break; - default: - re_error(sp, eval, re); - goto err; - } - - /* If follows the last entry, extend the last entry's range. */ - if ((rp = exp->rangeq.cqh_last) != (void *)&exp->rangeq && - rp->stop == lno - 1) { - ++rp->stop; - continue; - } - - /* Allocate a new range, and append it to the list. */ - CALLOC(sp, rp, RANGE *, 1, sizeof(RANGE)); - if (rp == NULL) - goto err; - rp->start = rp->stop = lno; - CIRCLEQ_INSERT_TAIL(&exp->rangeq, rp, q); - } - - exp = EXP(sp); - exp->range_lno = OOBLNO; - for (;;) { - /* - * Start at the beginning of the range each time, it may have - * been changed (or exhausted) if lines were inserted/deleted. - */ - if ((rp = exp->rangeq.cqh_first) == (void *)&exp->rangeq) - break; - if (rp->start > rp->stop) { - CIRCLEQ_REMOVE(&exp->rangeq, exp->rangeq.cqh_first, q); - free(rp); - continue; - } - - /* - * Execute the command, setting the cursor to the line so that - * relative addressing works. This means that the cursor moves - * to the last line sent to the command, by default, even if - * the command fails. - */ - exp->range_lno = sp->lno = rp->start++; - if (ex_cmd(sp, ep, cb, clen, 0)) - goto err; - - /* Someone's unhappy, time to stop. */ - if (INTERRUPTED(sp)) { -interrupted: msgq(sp, M_INFO, "Interrupted"); - break; - } - } - - /* Set the cursor to the new value, making sure it exists. */ - if (exp->range_lno != OOBLNO) { - if (file_lline(sp, ep, &lno)) - return (1); - sp->lno = - lno < exp->range_lno ? (lno ? lno : 1) : exp->range_lno; - } - if (0) { -err: rval = 1; - } - - /* Command we ran may have set the autoprint flag, clear it. */ - F_CLR(exp, EX_AUTOPRINT); - - /* Clear the global flag. */ - F_CLR(sp, S_GLOBAL); - - /* Free any remaining ranges and the command buffer. */ - while ((rp = exp->rangeq.cqh_first) != (void *)&exp->rangeq) { - CIRCLEQ_REMOVE(&exp->rangeq, exp->rangeq.cqh_first, q); - free(rp); - } - free(cb); - return (rval); -} - -/* - * global_insdel -- - * Update the ranges based on an insertion or deletion. - */ -void -global_insdel(sp, ep, op, lno) - SCR *sp; - EXF *ep; - enum operation op; - recno_t lno; -{ - EX_PRIVATE *exp; - RANGE *nrp, *rp; - - exp = EXP(sp); - - switch (op) { - case LINE_APPEND: - return; - case LINE_DELETE: - for (rp = exp->rangeq.cqh_first; - rp != (void *)&exp->rangeq; 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 range. */ - if (rp->start > lno) { - --rp->start; - --rp->stop; - continue; - } - /* Lno is inside the range, decrement the end point. */ - if (rp->start > --rp->stop) { - CIRCLEQ_REMOVE(&exp->rangeq, rp, q); - free(rp); - } - } - break; - case LINE_INSERT: - for (rp = exp->rangeq.cqh_first; - rp != (void *)&exp->rangeq; rp = rp->q.cqe_next) { - /* If range less than the line, ignore it. */ - if (rp->stop < lno) - continue; - /* If range greater than the line, increment range. */ - if (rp->start >= lno) { - ++rp->start; - ++rp->stop; - continue; - } - /* - * Lno is inside the range, so the range must be split. - * Since we're inserting a new element, neither range - * can be exhausted. - */ - CALLOC(sp, nrp, RANGE *, 1, sizeof(RANGE)); - if (nrp == NULL) { - F_SET(sp, S_INTERRUPTED); - return; - } - nrp->start = lno + 1; - nrp->stop = rp->stop + 1; - rp->stop = lno - 1; - CIRCLEQ_INSERT_AFTER(&exp->rangeq, rp, nrp, q); - rp = nrp; - } - break; - case LINE_RESET: - return; - } - /* - * If the command deleted/inserted lines, the cursor moves to - * the line after the deleted/inserted line. - */ - exp->range_lno = lno; -} diff --git a/usr.bin/vi/ex/ex_init.c b/usr.bin/vi/ex/ex_init.c deleted file mode 100644 index 46f9c37..0000000 --- a/usr.bin/vi/ex/ex_init.c +++ /dev/null @@ -1,202 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_init.c 8.18 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "tag.h" - -/* - * ex_screen_copy -- - * Copy ex screen. - */ -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. */ - TAILQ_INIT(&nexp->tagq); - TAILQ_INIT(&nexp->tagfq); - TAILQ_INIT(&nexp->cdq); - CIRCLEQ_INIT(&nexp->rangeq); - - if (orig == NULL) { - nexp->at_lbuf_set = 0; - } else { - oexp = EXP(orig); - - nexp->at_lbuf = oexp->at_lbuf; - nexp->at_lbuf_set = oexp->at_lbuf_set; - - if (oexp->lastbcomm != NULL && - (nexp->lastbcomm = strdup(oexp->lastbcomm)) == NULL) { - msgq(sp, M_SYSERR, NULL); - return(1); - } - - if (ex_tagcopy(orig, sp)) - return (1); - } - return (0); -} - -/* - * ex_screen_end -- - * End a vi screen. - */ -int -ex_screen_end(sp) - SCR *sp; -{ - EX_PRIVATE *exp; - int rval; - - rval = 0; - exp = EXP(sp); - - if (argv_free(sp)) - rval = 1; - - if (exp->ibp != NULL) - FREE(exp->ibp, exp->ibp_len); - - if (exp->lastbcomm != NULL) - FREE(exp->lastbcomm, strlen(exp->lastbcomm) + 1); - - if (ex_tagfree(sp)) - rval = 1; - - if (ex_cdfree(sp)) - rval = 1; - - /* Free private memory. */ - FREE(exp, sizeof(EX_PRIVATE)); - sp->ex_private = NULL; - - return (rval); -} - -/* - * ex_init -- - * Initialize ex. - */ -int -ex_init(sp, ep) - SCR *sp; - EXF *ep; -{ - size_t len; - - /* - * The default address is the last line of the file. If the address - * set bit is on for this file, load the address, ensuring that it - * exists. - */ - if (F_ISSET(sp->frp, FR_CURSORSET)) { - sp->lno = sp->frp->lno; - sp->cno = sp->frp->cno; - - if (file_gline(sp, ep, sp->lno, &len) == NULL) { - if (file_lline(sp, ep, &sp->lno)) - return (1); - if (sp->lno == 0) - sp->lno = 1; - sp->cno = 0; - } else if (sp->cno >= len) - sp->cno = 0; - } else { - if (file_lline(sp, ep, &sp->lno)) - return (1); - if (sp->lno == 0) - sp->lno = 1; - sp->cno = 0; - } - - /* Display the status line. */ - return (msg_status(sp, ep, sp->lno, 0)); -} - -/* - * ex_end -- - * End ex session. - */ -int -ex_end(sp) - SCR *sp; -{ - return (0); -} - -/* - * ex_optchange -- - * Handle change of options for vi. - */ -int -ex_optchange(sp, opt) - SCR *sp; - int opt; -{ - switch (opt) { - case O_CDPATH: - return (ex_cdalloc(sp, O_STR(sp, O_CDPATH))); - case O_TAGS: - return (ex_tagalloc(sp, O_STR(sp, O_TAGS))); - } - return (0); -} diff --git a/usr.bin/vi/ex/ex_join.c b/usr.bin/vi/ex/ex_join.c deleted file mode 100644 index 4ac045b..0000000 --- a/usr.bin/vi/ex/ex_join.c +++ /dev/null @@ -1,200 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_join.c 8.14 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_join -- :[line [,line]] j[oin][!] [count] [flags] - * Join lines. - */ -int -ex_join(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - recno_t from, to; - size_t blen, clen, len, tlen; - int echar, extra, first; - char *bp, *p, *tbp; - - from = cmdp->addr1.lno; - to = cmdp->addr2.lno; - - /* Check for no lines to join. */ - if ((p = file_gline(sp, ep, from + 1, &len)) == NULL) { - msgq(sp, M_ERR, "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 (F_ISSET(cmdp, E_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 ((p = file_gline(sp, ep, from, &len)) == NULL) { - 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 ., ? or !, insert two spaces. - * Else, insert one space. - * - * Echar is the last character in the last line joined. - */ - extra = 0; - if (!first && !F_ISSET(cmdp, E_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) { - memmove(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 (file_dline(sp, ep, to)) - goto err; - - /* If the original line changed, reset it. */ - if (!first && file_sline(sp, ep, 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/usr.bin/vi/ex/ex_map.c b/usr.bin/vi/ex/ex_map.c deleted file mode 100644 index ec67dbd..0000000 --- a/usr.bin/vi/ex/ex_map.c +++ /dev/null @@ -1,160 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_map.c 8.19 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <curses.h> -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.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. - */ -int -ex_map(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - enum seqtype stype; - CHAR_T *input, *p; - - stype = F_ISSET(cmdp, E_FORCE) ? SEQ_INPUT : SEQ_COMMAND; - - switch (cmdp->argc) { - case 0: - if (seq_dump(sp, stype, 1) == 0) - msgq(sp, M_INFO, "No %s map entries", - stype == SEQ_INPUT ? "input" : "command"); - 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, and call the screen specific routine. - * Note, if the screen specific routine is able to create the - * mapping, the SEQ_FUNCMAP type stays around, maybe the next screen - * type can get it right. - */ - if (input[0] == '#') { - for (p = input + 1; 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)) - return (1); - return (sp->s_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, "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. - */ -int -ex_unmap(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (seq_delete(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len, - F_ISSET(cmdp, E_FORCE) ? SEQ_INPUT : SEQ_COMMAND)) { - msgq(sp, M_INFO, "\"%s\" isn't mapped", cmdp->argv[0]->bp); - return (1); - } - return (0); -} - -/* - * map_save -- - * Save the mapped sequences to a file. - */ -int -map_save(sp, fp) - SCR *sp; - FILE *fp; -{ - if (seq_save(sp, fp, "map ", SEQ_COMMAND)) - return (1); - return (seq_save(sp, fp, "map! ", SEQ_INPUT)); -} diff --git a/usr.bin/vi/ex/ex_mark.c b/usr.bin/vi/ex/ex_mark.c deleted file mode 100644 index b74bfb1..0000000 --- a/usr.bin/vi/ex/ex_mark.c +++ /dev/null @@ -1,66 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_mark.c 8.8 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -int -ex_mark(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (cmdp->argv[0]->len != 1) { - msgq(sp, M_ERR, "Mark names must be a single character"); - return (1); - } - return (mark_set(sp, ep, cmdp->argv[0]->bp[0], &cmdp->addr1, 1)); -} diff --git a/usr.bin/vi/ex/ex_mkexrc.c b/usr.bin/vi/ex/ex_mkexrc.c deleted file mode 100644 index 158fb23..0000000 --- a/usr.bin/vi/ex/ex_mkexrc.c +++ /dev/null @@ -1,130 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_mkexrc.c 8.14 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> -#include <pathnames.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_mkexrc -- :mkexrc[!] [file] - * - * Create (or overwrite) a .exrc file with the current info. - */ -int -ex_mkexrc(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *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 (!F_ISSET(cmdp, E_FORCE) && !stat(fname, &sb)) { - msgq(sp, M_ERR, - "%s exists, not written; use ! to override", fname); - 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(sp, M_SYSERR, fname); - return (1); - } - - if ((fp = fdopen(fd, "w")) == NULL) { - sverrno = errno; - (void)close(fd); - errno = sverrno; - goto e2; - } - - if (abbr_save(sp, fp) || ferror(fp)) - goto e1; - if (map_save(sp, fp) || ferror(fp)) - goto e1; - if (opts_save(sp, fp) || ferror(fp)) - goto e1; -#ifndef NO_DIGRAPH - digraph_save(sp, fd); -#endif - if (fclose(fp)) - goto e2; - - msgq(sp, M_INFO, "New .exrc file: %s. ", fname); - return (0); - -e1: sverrno = errno; - (void)fclose(fp); - errno = sverrno; -e2: msgq(sp, M_ERR, "%s: incomplete: %s", fname, strerror(errno)); - return (1); -} diff --git a/usr.bin/vi/ex/ex_move.c b/usr.bin/vi/ex/ex_move.c deleted file mode 100644 index 52a8f53..0000000 --- a/usr.bin/vi/ex/ex_move.c +++ /dev/null @@ -1,222 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_move.c 8.19 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_copy -- :[line [,line]] co[py] line [flags] - * Copy selected lines. - */ -int -ex_copy(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - CB cb; - MARK fm1, fm2, m, tm; - recno_t cnt; - int rval; - - rval = 0; - - /* - * 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, ep, 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, ep, &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. - */ -int -ex_move(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - LMARK *lmp; - MARK fm1, fm2; - recno_t cnt, diff, fl, tl, mfl, mtl; - size_t blen, len; - int mark_reset; - char *bp, *p; - - /* - * 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, "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 = 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, ep, 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 ((p = file_gline(sp, ep, fl, &len)) == NULL) - return (1); - BINC_RET(sp, bp, blen, len); - memmove(bp, p, len); - if (file_aline(sp, ep, 1, tl, bp, len)) - return (1); - if (mark_reset) - for (lmp = ep->marks.lh_first; - lmp != NULL; lmp = lmp->q.le_next) - if (lmp->name != ABSMARK1 && - lmp->lno == fl) - lmp->lno = tl + 1; - if (file_dline(sp, ep, fl)) - return (1); - } - } else { /* Destination < source. */ - mfl = tl; - mtl = tl + diff; - for (cnt = diff; cnt--;) { - if ((p = file_gline(sp, ep, fl, &len)) == NULL) - return (1); - BINC_RET(sp, bp, blen, len); - memmove(bp, p, len); - if (file_aline(sp, ep, 1, tl++, bp, len)) - return (1); - if (mark_reset) - for (lmp = ep->marks.lh_first; - lmp != NULL; lmp = lmp->q.le_next) - if (lmp->name != ABSMARK1 && - lmp->lno == fl) - lmp->lno = tl; - ++fl; - if (file_dline(sp, ep, 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 = 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, ep, lmp); - - - sp->rptlines[L_MOVED] += diff; - return (0); -} diff --git a/usr.bin/vi/ex/ex_open.c b/usr.bin/vi/ex/ex_open.c deleted file mode 100644 index 187a29b..0000000 --- a/usr.bin/vi/ex/ex_open.c +++ /dev/null @@ -1,75 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_open.c 8.6 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_open -- :[line] o[pen] [/pattern/] [flags] - * - * Switch to single line "open" mode. - */ -int -ex_open(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - /* If open option off, disallow open command. */ - if (!O_ISSET(sp, O_OPEN)) { - msgq(sp, M_ERR, - "The open command requires that the open option be set"); - return (1); - } - - msgq(sp, M_ERR, "The open command is not yet implemented"); - return (1); -} diff --git a/usr.bin/vi/ex/ex_preserve.c b/usr.bin/vi/ex/ex_preserve.c deleted file mode 100644 index 7bef07e..0000000 --- a/usr.bin/vi/ex/ex_preserve.c +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_preserve.c 8.14 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_preserve -- :pre[serve] - * Push the file to recovery. - */ -int -ex_preserve(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - recno_t lno; - - if (!F_ISSET(ep, F_RCV_ON)) { - msgq(sp, M_ERR, "Preservation of this file not possible"); - return (1); - } - - /* If recovery not initialized, do so. */ - if (F_ISSET(ep, F_FIRSTMODIFY) && rcv_init(sp, ep)) - return (1); - - /* Force the file to be read in, in case it hasn't yet. */ - if (file_lline(sp, ep, &lno)) - return (1); - - /* Sync to disk. */ - if (rcv_sync(sp, ep, RCV_SNAPSHOT)) - return (1); - - msgq(sp, M_INFO, "File preserved"); - return (0); -} - -/* - * ex_recover -- :rec[over][!] file - * - * Recover the file. - */ -int -ex_recover(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *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, ep, F_ISSET(cmdp, E_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, F_ISSET(cmdp, E_FORCE))) - return (1); - F_SET(sp, S_FSWITCH); - return (0); -} diff --git a/usr.bin/vi/ex/ex_print.c b/usr.bin/vi/ex/ex_print.c deleted file mode 100644 index 6bcab28..0000000 --- a/usr.bin/vi/ex/ex_print.c +++ /dev/null @@ -1,212 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_print.c 8.16 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_list -- :[line [,line]] l[ist] [count] [flags] - * - * Display the addressed lines such that the output is unambiguous. - */ -int -ex_list(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (ex_print(sp, ep, - &cmdp->addr1, &cmdp->addr2, cmdp->flags | E_F_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. - */ -int -ex_number(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (ex_print(sp, ep, - &cmdp->addr1, &cmdp->addr2, cmdp->flags | E_F_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. - */ -int -ex_pr(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (ex_print(sp, ep, &cmdp->addr1, &cmdp->addr2, cmdp->flags)) - return (1); - sp->lno = cmdp->addr2.lno; - sp->cno = cmdp->addr2.cno; - return (0); -} - -/* - * ex_print -- - * Print the selected lines. - */ -int -ex_print(sp, ep, fp, tp, flags) - SCR *sp; - EXF *ep; - MARK *fp, *tp; - register int flags; -{ - recno_t from, to; - size_t col, len; - char *p; - - F_SET(sp, S_INTERRUPTIBLE); - for (from = fp->lno, to = tp->lno; from <= to; ++from) { - /* - * 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_F_HASH)) - if (from <= 999999) - col = ex_printf(EXCOOKIE, "%6ld ", from); - else - col = ex_printf(EXCOOKIE, "TOOBIG "); - else - col = 0; - - /* - * Display the line. The format for E_F_PRINT isn't very good, - * especially in handling end-of-line tabs, but they're almost - * backward compatible. - */ - if ((p = file_gline(sp, ep, from, &len)) == NULL) { - GETLINE_ERR(sp, from); - return (1); - } - - if (len == 0 && !LF_ISSET(E_F_LIST)) - (void)ex_printf(EXCOOKIE, "\n"); - else if (ex_ldisplay(sp, p, len, col, flags)) - return (1); - - if (INTERRUPTED(sp)) - break; - } - - return (0); -} - -/* - * ex_ldisplay -- - * Display a line. - */ -int -ex_ldisplay(sp, lp, len, col, flags) - SCR *sp; - CHAR_T *lp; - size_t len, col; - u_int flags; -{ - CHAR_T ch, *kp; - u_long ts; - size_t tlen; - - ts = O_VAL(sp, O_TABSTOP); - for (;; --len) { - if (len > 0) - ch = *lp++; - else if (LF_ISSET(E_F_LIST)) - ch = '$'; - else - break; - if (ch == '\t' && !LF_ISSET(E_F_LIST)) - for (tlen = ts - col % ts; - col < sp->cols && tlen--; ++col) - (void)ex_printf(EXCOOKIE, " "); - else { - kp = KEY_NAME(sp, ch); - tlen = KEY_LEN(sp, ch); - if (col + tlen < sp->cols) { - (void)ex_printf(EXCOOKIE, "%s", kp); - col += tlen; - } else - for (; tlen--; ++kp, ++col) { - if (col == sp->cols) { - col = 0; - (void)ex_printf(EXCOOKIE, "\n"); - } - (void)ex_printf(EXCOOKIE, "%c", *kp); - } - } - if (len == 0) - break; - } - (void)ex_printf(EXCOOKIE, "\n"); - return (0); -} diff --git a/usr.bin/vi/ex/ex_put.c b/usr.bin/vi/ex/ex_put.c deleted file mode 100644 index a947d85..0000000 --- a/usr.bin/vi/ex/ex_put.c +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_put.c 8.8 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_put -- [line] pu[t] [buffer] - * - * Append a cut buffer into the file. - */ -int -ex_put(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - MARK m; - - m.lno = sp->lno; - m.cno = sp->cno; - if (put(sp, ep, NULL, F_ISSET(cmdp, E_BUFFER) ? &cmdp->buffer : NULL, - &cmdp->addr1, &m, 1)) - return (1); - sp->lno = m.lno; - sp->cno = m.cno; - return (0); -} diff --git a/usr.bin/vi/ex/ex_read.c b/usr.bin/vi/ex/ex_read.c deleted file mode 100644 index cef1e3a..0000000 --- a/usr.bin/vi/ex/ex_read.c +++ /dev/null @@ -1,300 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_read.c 8.41 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.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. - */ -int -ex_read(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - struct stat sb; - CHAR_T *arg, *name; - EX_PRIVATE *exp; - FILE *fp; - MARK rm; - recno_t nlines; - size_t arglen, blen, len; - int btear, farg, rval; - char *p; - - /* - * 0 args: we're done. - * 1 args: check for "read !arg". - * 2 args: check for "read ! arg". - * >2 args: object, too many args. - */ - farg = 0; - switch (cmdp->argc) { - case 0: - break; - case 1: - arg = cmdp->argv[0]->bp; - arglen = cmdp->argv[0]->len; - if (*arg == '!') { - ++arg; - --arglen; - farg = 1; - } - break; - case 2: - if (cmdp->argv[0]->len == 1 && cmdp->argv[0]->bp[0] == '!') { - arg = cmdp->argv[1]->bp; - arglen = cmdp->argv[1]->len; - farg = 2; - break; - } - /* FALLTHROUGH */ - default: - goto badarg; - } - - if (farg != 0) { - /* File name and bang expand the user's argument. */ - if (argv_exp1(sp, ep, cmdp, arg, arglen, 1)) - return (1); - - /* If argc unchanged, there wasn't anything to expand. */ - if (cmdp->argc == farg) - goto usage; - - /* Set the last bang command. */ - exp = EXP(sp); - if (exp->lastbcomm != NULL) - free(exp->lastbcomm); - if ((exp->lastbcomm = strdup(cmdp->argv[farg]->bp)) == NULL) { - msgq(sp, M_SYSERR, NULL); - return (1); - } - - /* Redisplay the user's argument if it's changed. */ - if (F_ISSET(cmdp, E_MODIFY) && IN_VI_MODE(sp)) { - len = cmdp->argv[farg]->len; - GET_SPACE_RET(sp, p, blen, len + 2); - p[0] = '!'; - memmove(p + 1, - cmdp->argv[farg]->bp, cmdp->argv[farg]->len + 1); - (void)sp->s_busy(sp, p); - FREE_SPACE(sp, p, blen); - } - - if (filtercmd(sp, ep, &cmdp->addr1, - NULL, &rm, cmdp->argv[farg]->bp, FILTER_READ)) - return (1); - - /* The filter version of read set the autoprint flag. */ - F_SET(EXP(sp), EX_AUTOPRINT); - - /* If in vi mode, move to the first nonblank. */ - sp->lno = rm.lno; - if (IN_VI_MODE(sp)) { - sp->cno = 0; - (void)nonblank(sp, ep, sp->lno, &sp->cno); - } - return (0); - } - - /* Shell and file name expand the user's argument. */ - if (argv_exp2(sp, ep, cmdp, arg, arglen, 0)) - return (1); - - /* - * 0 args: no arguments, read the current file, don't set the - * alternate file name. - * 1 args: read it, switching to it or settgin the alternate file - * name. - * >1 args: object, too many args. - */ - switch (cmdp->argc) { - case 1: - name = sp->frp->name; - break; - case 2: - name = cmdp->argv[1]->bp; - /* - * !!! - * Historically, if you had an "unnamed" file, the read command - * renamed the file. - */ - if (F_ISSET(sp->frp, FR_TMPFILE) && - !F_ISSET(sp->frp, FR_READNAMED)) { - if ((p = v_strdup(sp, - cmdp->argv[1]->bp, cmdp->argv[1]->len)) != NULL) { - free(sp->frp->name); - sp->frp->name = p; - } - F_SET(sp->frp, FR_NAMECHANGE | FR_READNAMED); - } else - set_alt_name(sp, name); - break; - default: -badarg: msgq(sp, M_ERR, - "%s expanded into too many file names", cmdp->argv[0]->bp); -usage: msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); - } - - /* - * !!! - * 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. - */ - if ((fp = fopen(name, "r")) == NULL || fstat(fileno(fp), &sb)) { - msgq(sp, M_SYSERR, "%s", name); - return (1); - } - if (!S_ISREG(sb.st_mode)) { - (void)fclose(fp); - msgq(sp, M_ERR, "Only regular files may be read"); - return (1); - } - - /* Turn on busy message. */ - btear = F_ISSET(sp, S_EXSILENT) ? 0 : !busy_on(sp, "Reading..."); - rval = ex_readfp(sp, ep, name, fp, &cmdp->addr1, &nlines, 1); - if (btear) - busy_off(sp); - - /* - * 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.) - */ - sp->lno = cmdp->addr1.lno; - if (nlines) - ++sp->lno; - - return (rval); -} - -/* - * ex_readfp -- - * Read lines into the file. - */ -int -ex_readfp(sp, ep, name, fp, fm, nlinesp, success_msg) - SCR *sp; - EXF *ep; - char *name; - FILE *fp; - MARK *fm; - recno_t *nlinesp; - int success_msg; -{ - EX_PRIVATE *exp; - recno_t lcnt, lno; - size_t len; - u_long ccnt; /* XXX: can't print off_t portably. */ - int rval; - - rval = 0; - exp = EXP(sp); - - /* - * Add in the lines from the output. Insertion starts at the line - * following the address. - */ - ccnt = 0; - lcnt = 0; - for (lno = fm->lno; !ex_getline(sp, fp, &len); ++lno, ++lcnt) { - if (INTERRUPTED(sp)) { - if (!success_msg) - msgq(sp, M_INFO, "Interrupted"); - break; - } - if (file_aline(sp, ep, 1, lno, exp->ibp, len)) { - rval = 1; - break; - } - ccnt += len; - } - - if (ferror(fp)) { - msgq(sp, M_SYSERR, "%s", name); - rval = 1; - } - - if (fclose(fp)) { - msgq(sp, M_SYSERR, "%s", name); - return (1); - } - - if (rval) - return (1); - - /* Return the number of lines read in. */ - if (nlinesp != NULL) - *nlinesp = lcnt; - - if (success_msg) - msgq(sp, M_INFO, "%s%s: %lu line%s, %lu characters", - INTERRUPTED(sp) ? "Interrupted read: " : "", - name, lcnt, lcnt == 1 ? "" : "s", ccnt); - - return (0); -} diff --git a/usr.bin/vi/ex/ex_screen.c b/usr.bin/vi/ex/ex_screen.c deleted file mode 100644 index e190588..0000000 --- a/usr.bin/vi/ex/ex_screen.c +++ /dev/null @@ -1,155 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_screen.c 8.15 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_split -- :s[plit] [file ...] - * Split the screen, optionally setting the file list. - */ -int -ex_split(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (sp->s_split(sp, cmdp->argc ? cmdp->argv : NULL, cmdp->argc)); -} - -/* - * ex_bg -- :bg - * Hide the screen. - */ -int -ex_bg(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (sp->s_bg(sp)); -} - -/* - * ex_fg -- :fg [file] - * Show the screen. - */ -int -ex_fg(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (sp->s_fg(sp, cmdp->argc ? cmdp->argv[0]->bp : NULL)); -} - -/* - * ex_resize -- :resize [+-]rows - * Change the screen size. - */ -int -ex_resize(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - enum adjust adj; - - if (!F_ISSET(cmdp, E_COUNT)) { - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); - } - if (F_ISSET(cmdp, E_COUNT_NEG)) - adj = A_DECREASE; - else if (F_ISSET(cmdp, E_COUNT_POS)) - adj = A_INCREASE; - else - adj = A_SET; - return (sp->s_rabs(sp, cmdp->count, adj)); -} - -/* - * ex_sdisplay -- - * Display the list of screens. - */ -int -ex_sdisplay(sp, ep) - SCR *sp; - EXF *ep; -{ - SCR *tsp; - int cnt, col, len, sep; - - if ((tsp = sp->gp->hq.cqh_first) == (void *)&sp->gp->hq) { - (void)ex_printf(EXCOOKIE, - "No backgrounded screens to display.\n"); - return (0); - } - - col = len = sep = 0; - for (cnt = 1; tsp != (void *)&sp->gp->hq; tsp = tsp->q.cqe_next) { - col += len = strlen(tsp->frp->name) + sep; - if (col >= sp->cols - 1) { - col = len; - sep = 0; - (void)ex_printf(EXCOOKIE, "\n"); - } else if (cnt != 1) { - sep = 1; - (void)ex_printf(EXCOOKIE, " "); - } - (void)ex_printf(EXCOOKIE, "%s", tsp->frp->name); - ++cnt; - } - (void)ex_printf(EXCOOKIE, "\n"); - return (0); -} diff --git a/usr.bin/vi/ex/ex_script.c b/usr.bin/vi/ex/ex_script.c deleted file mode 100644 index a364e2b..0000000 --- a/usr.bin/vi/ex/ex_script.c +++ /dev/null @@ -1,582 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_script.c 8.19 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/queue.h> -#include <sys/time.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 <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "script.h" - -/* - * XXX - */ -int openpty __P((int *, int *, char *, struct termios *, struct winsize *)); - -static int sscr_getprompt __P((SCR *, EXF *)); -static int sscr_init __P((SCR *, EXF *)); -static int sscr_matchprompt __P((SCR *, char *, size_t, size_t *)); -static int sscr_setprompt __P((SCR *, char *, size_t)); - -/* - * ex_script -- : sc[ript][!] [file] - * - * Switch to script mode. - */ -int -ex_script(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - /* Vi only command. */ - if (!IN_VI_MODE(sp)) { - msgq(sp, M_ERR, - "The script command is only available in vi mode"); - return (1); - } - - /* Switch to the new file. */ - if (cmdp->argc != 0 && ex_edit(sp, ep, cmdp)) - return (1); - - /* - * Create the shell, figure out the prompt. - * - * !!! - * The files just switched, use sp->ep. - */ - if (sscr_init(sp, sp->ep)) - return (1); - - return (0); -} - -/* - * sscr_init -- - * Create a pty setup for a shell. - */ -static int -sscr_init(sp, ep) - SCR *sp; - EXF *ep; -{ - SCRIPT *sc; - char *sh, *sh_path; - - 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); - - if (ioctl(STDIN_FILENO, TIOCGWINSZ, &sc->sh_win) == -1) { - msgq(sp, M_SYSERR, "tcgetattr"); - goto err; - } - - if (openpty(&sc->sh_master, - &sc->sh_slave, sc->sh_name, &sc->sh_term, &sc->sh_win) == -1) { - msgq(sp, M_SYSERR, "openpty"); - goto err; - } - - /* - * Don't use vfork() here, because the signal semantics differ from - * implementation to implementation. - */ - SIGBLOCK(sp->gp); - switch (sc->sh_pid = fork()) { - case -1: /* Error. */ - SIGUNBLOCK(sp->gp); - - 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. */ - /* The utility has default signal behavior. */ - sig_end(); - - /* - * XXX - * So that shells that do command line editing turn it off. - */ - (void)putenv("TERM=emacs"); - (void)putenv("TERMCAP=emacs:"); - (void)putenv("EMACS=t"); - - (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(sp, M_ERR, - "Error: execl: %s: %s", sh_path, strerror(errno)); - _exit(127); - default: /* Parent. */ - SIGUNBLOCK(sp->gp); - break; - } - - if (sscr_getprompt(sp, ep)) - return (1); - - F_SET(sp, S_REDRAW | S_SCRIPT); - 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, ep) - SCR *sp; - EXF *ep; -{ - 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 (file_lline(sp, ep, &lline) || - file_aline(sp, ep, 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 (file_lline(sp, ep, &lline) || - file_aline(sp, ep, 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. - */ -int -sscr_exec(sp, ep, lno) - SCR *sp; - EXF *ep; - recno_t lno; -{ - SCRIPT *sc; - recno_t last_lno; - size_t blen, len, last_len, tlen; - int matchprompt, nw, rval; - char *bp, *p; - - /* If there's a prompt on the last line, append the command. */ - if (file_lline(sp, ep, &last_lno)) - return (1); - if ((p = file_gline(sp, ep, last_lno, &last_len)) == NULL) { - GETLINE_ERR(sp, last_lno); - 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 ((p = file_gline(sp, ep, lno, &len)) == NULL) { - if (file_lline(sp, ep, &lno)) - goto err1; - if (lno == 0) - goto empty; - else - GETLINE_ERR(sp, lno); - 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, "Nothing 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 (file_sline(sp, ep, last_lno, bp, last_len + len)) -err1: rval = 1; - } - if (matchprompt) - FREE_SPACE(sp, bp, blen); - return (rval); -} - -/* - * sscr_input -- - * Take a line from the shell and insert it into the file. - */ -int -sscr_input(sp) - SCR *sp; -{ - struct timeval tv; - CHAR_T *endp, *p, *t; - EXF *ep; - SCRIPT *sc; - 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. */ - ep = sp->ep; - if (file_lline(sp, ep, &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); - F_CLR(sp, S_SCRIPT); - 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 (file_aline(sp, ep, 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_SET(sc->sh_master, &sp->rdfd); - FD_CLR(STDIN_FILENO, &sp->rdfd); - if (select(sc->sh_master + 1, - &sp->rdfd, NULL, NULL, &tv) == 1) { - memmove(bp, t, len); - endp = bp + len; - goto more; - } - } - if (sscr_setprompt(sp, t, len)) - return (1); - if (file_aline(sp, ep, 1, lno++, t, len)) - goto ret; - } - - /* The cursor moves to EOF. */ - sp->lno = lno; - sp->cno = len ? len - 1 : 0; - rval = sp->s_refresh(sp, ep); - -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, sc->sh_prompt_len); - 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. - */ -int -sscr_end(sp) - SCR *sp; -{ - SCRIPT *sc; - int rval; - - if ((sc = sp->script) == NULL) - return (0); - - /* Turn off the script flag. */ - F_CLR(sp, S_SCRIPT); - - /* 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. */ - rval = proc_wait(sp, (long)sc->sh_pid, "script-shell", 0); - - /* Free memory. */ - FREE(sc->sh_prompt, sc->sh_prompt_len); - FREE(sc, sizeof(SCRIPT)); - sp->script = NULL; - - return (rval); -} diff --git a/usr.bin/vi/ex/ex_set.c b/usr.bin/vi/ex/ex_set.c deleted file mode 100644 index a2abb08..0000000 --- a/usr.bin/vi/ex/ex_set.c +++ /dev/null @@ -1,70 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_set.c 8.6 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -int -ex_set(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - switch(cmdp->argc) { - case 0: - opts_dump(sp, CHANGED_DISPLAY); - break; - default: - opts_set(sp, cmdp->cmd->usage, cmdp->argv); - break; - } - return (0); -} diff --git a/usr.bin/vi/ex/ex_shell.c b/usr.bin/vi/ex/ex_shell.c deleted file mode 100644 index b6f9aed..0000000 --- a/usr.bin/vi/ex/ex_shell.c +++ /dev/null @@ -1,150 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_shell.c 8.26 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "../svi/svi_screen.h" - -/* - * ex_shell -- :sh[ell] - * Invoke the program named in the SHELL environment variable - * with the argument -i. - */ -int -ex_shell(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - char buf[MAXPATHLEN]; - - (void)snprintf(buf, sizeof(buf), "%s -i", O_STR(sp, O_SHELL)); - return (ex_exec_proc(sp, buf, "\n", NULL)); -} - -/* - * ex_exec_proc -- - * Run a separate process. - */ -int -ex_exec_proc(sp, cmd, p1, p2) - SCR *sp; - char *cmd, *p1, *p2; -{ - const char *name; - pid_t pid; - int rval, teardown; - - /* Clear the rest of the screen. */ - if (sp->s_clear(sp)) - return (1); - - /* Save ex/vi terminal settings, and restore the original ones. */ - teardown = !ex_sleave(sp); - - /* - * Flush waiting messages (autowrite, for example) so the output - * matches historic practice. - */ - (void)sex_refresh(sp, sp->ep); - - /* Put out various messages. */ - if (p1 != NULL) - (void)write(STDOUT_FILENO, p1, strlen(p1)); - if (p2 != NULL) - (void)write(STDOUT_FILENO, p2, strlen(p2)); - - SIGBLOCK(sp->gp); - switch (pid = vfork()) { - case -1: /* Error. */ - SIGUNBLOCK(sp->gp); - - msgq(sp, M_SYSERR, "vfork"); - rval = 1; - break; - case 0: /* Utility. */ - /* The utility has default signal behavior. */ - sig_end(); - - 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(sp, M_ERR, "Error: execl: %s: %s", - O_STR(sp, O_SHELL), strerror(errno)); - _exit(127); - /* NOTREACHED */ - default: /* Parent. */ - SIGUNBLOCK(sp->gp); - - rval = proc_wait(sp, (long)pid, cmd, 0); - break; - } - - /* Restore ex/vi terminal settings. */ - if (teardown) - ex_rleave(sp); - - /* - * XXX - * Stat of the tty structures (see ex_sleave, ex_rleave) only give - * us 1-second resolution on the tty changes. A fast '!' command, - * e.g. ":!pwd" can beat us to the refresh. When there's better - * resolution from the stat(2) timers, this can go away. - */ - F_SET(sp, S_REFRESH); - - return (rval); -} diff --git a/usr.bin/vi/ex/ex_shift.c b/usr.bin/vi/ex/ex_shift.c deleted file mode 100644 index 61264c0..0000000 --- a/usr.bin/vi/ex/ex_shift.c +++ /dev/null @@ -1,204 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_shift.c 8.16 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -enum which {LEFT, RIGHT}; -static int shift __P((SCR *, EXF *, EXCMDARG *, enum which)); - -int -ex_shiftl(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (shift(sp, ep, cmdp, LEFT)); -} - -int -ex_shiftr(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (shift(sp, ep, cmdp, RIGHT)); -} - -static int -shift(sp, ep, cmdp, rl) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; - enum which rl; -{ - recno_t from, to; - size_t blen, len, newcol, newidx, oldcol, oldidx, sw; - int curset; - char *p, *bp, *tbp; - - if (O_VAL(sp, O_SHIFTWIDTH) == 0) { - msgq(sp, M_INFO, "shiftwidth option set to 0"); - return (0); - } - - /* - * 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 ((p = file_gline(sp, ep, from, &len)) == NULL) - 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. */ - memmove(tbp, p + oldidx, len - oldidx); - - /* Set the replacement line. */ - if (file_sline(sp, ep, 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, ep, to, &sp->cno); - } - - FREE_SPACE(sp, bp, blen); - - sp->rptlines[rl == RIGHT ? L_RSHIFT : L_LSHIFT] += - cmdp->addr2.lno - cmdp->addr1.lno + 1; - return (0); -} diff --git a/usr.bin/vi/ex/ex_source.c b/usr.bin/vi/ex/ex_source.c deleted file mode 100644 index b8af556..0000000 --- a/usr.bin/vi/ex/ex_source.c +++ /dev/null @@ -1,66 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_source.c 8.7 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_source -- :source file - * Execute ex commands from a file. - */ -int -ex_source(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (ex_cfile(sp, ep, cmdp->argv[0]->bp, 0)); -} diff --git a/usr.bin/vi/ex/ex_stop.c b/usr.bin/vi/ex/ex_stop.c deleted file mode 100644 index 543f649..0000000 --- a/usr.bin/vi/ex/ex_stop.c +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_stop.c 8.9 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "../sex/sex_screen.h" - -/* - * ex_stop -- :stop[!] - * :suspend[!] - * Suspend execution. - */ -int -ex_stop(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - /* For some strange reason, the force flag turns off autowrite. */ - if (!F_ISSET(cmdp, E_FORCE) && - F_ISSET(ep, F_MODIFIED) && O_ISSET(sp, O_AUTOWRITE) && - file_write(sp, ep, NULL, NULL, NULL, FS_ALL)) - return (1); - return (sp->s_suspend(sp)); -} diff --git a/usr.bin/vi/ex/ex_subst.c b/usr.bin/vi/ex/ex_subst.c deleted file mode 100644 index 5e52e79..0000000 --- a/usr.bin/vi/ex/ex_subst.c +++ /dev/null @@ -1,1001 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_subst.c 8.59 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -#define SUB_FIRST 0x01 /* The 'r' flag isn't reasonable. */ -#define SUB_MUSTSETR 0x02 /* The 'r' flag is required. */ - -static __inline int regsub __P((SCR *, char *, - char **, size_t *, size_t *, regmatch_t [10])); -static int substitute __P((SCR *, EXF *, - EXCMDARG *, char *, regex_t *, u_int)); - -/* - * ex_substitute -- - * [line [,line]] s[ubstitute] [[/;]pat[/;]/repl[/;] [cgr] [count] [#lp]] - * - * Substitute on lines matching a pattern. - */ -int -ex_substitute(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - regex_t *re, lre; - size_t blen, len; - u_int flags; - int delim, eval, reflags, replaced; - 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. - */ - for (p = cmdp->argv[0]->bp, - len = cmdp->argv[0]->len; len > 0; --len, ++p) { - if (!isblank(*p)) - break; - } - if (len == 0) - return (ex_subagain(sp, ep, cmdp)); - delim = *p++; - if (isalnum(delim)) - return (substitute(sp, ep, - cmdp, p, &sp->subre, 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 escaped 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 escape character if it escapes a delimiter. - * This means that "s/A/\\\\f" replaces "A" with "\\f". It - * would be nice to be more regular, i.e. for each layer of - * escaping a single escape character is removed, but that's - * 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 (!F_ISSET(sp, S_SRE_SET)) { - msgq(sp, M_ERR, "No previous regular expression"); - return (1); - } - re = &sp->sre; - flags = 0; - } else { - /* Set RE flags. */ - reflags = 0; - if (O_ISSET(sp, O_EXTENDED)) - reflags |= REG_EXTENDED; - if (O_ISSET(sp, O_IGNORECASE)) - reflags |= REG_ICASE; - - /* Convert vi-style RE's to POSIX 1003.2 RE's. */ - if (re_conv(sp, &ptrn, &replaced)) - return (1); - - /* Compile the RE. */ - eval = regcomp(&lre, (char *)ptrn, reflags); - - /* Free up any allocated memory. */ - if (replaced) - FREE_SPACE(sp, ptrn, 0); - - if (eval) { - re_error(sp, eval, &lre); - return (1); - } - - /* - * Set saved RE. - * - * !!! - * Historic practice is that substitutes set the search - * direction as well as both substitute and search RE's. - */ - sp->searchdir = FORWARD; - sp->sre = lre; - F_SET(sp, S_SRE_SET); - sp->subre = lre; - F_SET(sp, S_SUBRE_SET); - - re = &lre; - flags = SUB_FIRST; - } - - /* - * 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 - * regsub(). - * - * 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 escape 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_len); - 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; - memmove(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); - } - memmove(sp->repl, bp, len); - } - FREE_SPACE(sp, bp, blen); - } - return (substitute(sp, ep, cmdp, p, re, flags)); -} - -/* - * ex_subagain -- - * [line [,line]] & [cgr] [count] [#lp]] - * - * Substitute using the last substitute RE and replacement pattern. - */ -int -ex_subagain(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (!F_ISSET(sp, S_SUBRE_SET)) { - msgq(sp, M_ERR, "No previous regular expression"); - return (1); - } - return (substitute(sp, ep, cmdp, cmdp->argv[0]->bp, &sp->subre, 0)); -} - -/* - * ex_subtilde -- - * [line [,line]] ~ [cgr] [count] [#lp]] - * - * Substitute using the last RE and last substitute replacement pattern. - */ -int -ex_subtilde(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (!F_ISSET(sp, S_SRE_SET)) { - msgq(sp, M_ERR, "No previous regular expression"); - return (1); - } - return (substitute(sp, ep, cmdp, cmdp->argv[0]->bp, &sp->sre, 0)); -} - -/* - * 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 pretty 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); \ - } \ - } \ - memmove(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; \ - } \ -} - -/* - * substitute -- - * 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. - */ -static int -substitute(sp, ep, cmdp, s, re, flags) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; - char *s; - regex_t *re; - u_int flags; -{ - MARK from, to; - recno_t elno, lno; - regmatch_t match[10]; - size_t blen, cnt, last, lbclen, lblen, len, llen, offset, saved_offset; - int cflag, lflag, nflag, pflag, rflag; - int didsub, do_eol_match, eflags, empty_ok, eval; - int linechanged, matched, quit, rval; - char *bp, *lb; - - /* - * !!! - * 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_substitute()). - */ - 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; - 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, "Count overflow"); - else if (lno == LONG_MIN) - msgq(sp, M_ERR, "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; - break; - case '#': - nflag = 1; - break; - case 'c': - sp->c_suffix = !sp->c_suffix; - 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, - "Regular expression specified; r flag meaningless"); - return (1); - } - if (!F_ISSET(sp, S_SRE_SET)) { - msgq(sp, M_ERR, - "No previous regular expression"); - return (1); - } - rflag = 1; - re = &sp->sre; - break; - default: - goto usage; - } - - if (*s != '\0' || !rflag && LF_ISSET(SUB_MUSTSETR)) { -usage: msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); - } - - if (IN_VI_MODE(sp) && sp->c_suffix && (lflag || nflag || pflag)) { - msgq(sp, M_ERR, - "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)) { - if (!F_ISSET(sp, S_GLOBAL)) - msgq(sp, M_INFO, "Interrupted"); - break; - } - - /* Get the line. */ - if ((s = file_gline(sp, ep, lno, &llen)) == NULL) { - GETLINE_ERR(sp, lno); - goto ret1; - } - - /* - * 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); - memmove(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 ret1; - } - 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. - * - * XXX - * We may want to "fix" this in the confirm routine, - * if the confirm routine should be able to display - * a cursor past EOL. - */ - from.lno = to.lno = lno; - from.cno = match[0].rm_so + offset; - to.cno = match[0].rm_eo; - if (llen == 0) - from.cno = to.cno = 0; - else { - if (to.cno >= llen) - to.cno = llen - 1; - if (from.cno >= llen) - from.cno = llen - 1; - } - switch (sp->s_confirm(sp, ep, &from, &to)) { - case CONF_YES: - break; - case CONF_NO: - didsub = 0; - BUILD(sp, s +offset, match[0].rm_eo); - goto skip; - case CONF_QUIT: - /* Set the quit flag. */ - quit = 1; - - /* If interruptible, pass the info back. */ - if (F_ISSET(sp, S_INTERRUPTIBLE)) - F_SET(sp, S_INTERRUPTED); - - /* - * If any changes, resolve them, otherwise - * return to the main loop. - */ - goto endmatch; - } - } - - /* 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 (regsub(sp, s + offset, &lb, &lbclen, &lblen, match)) - goto ret1; - - /* 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 (file_iline(sp, ep, lno, - lb + last, sp->newl[cnt] - last)) - goto ret1; - last = sp->newl[cnt] + 1; - ++sp->rptlines[L_ADDED]; - } - lbclen -= last; - offset -= last; - sp->newl_cnt = 0; - } - - /* Store and retrieve the line. */ - if (file_sline(sp, ep, lno, lb + last, lbclen)) - goto ret1; - if ((s = file_gline(sp, ep, lno, &llen)) == NULL) { - GETLINE_ERR(sp, lno); - goto ret1; - } - ADD_SPACE_RET(sp, bp, blen, llen) - memmove(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 (file_iline(sp, ep, - lno, lb + last, sp->newl[cnt] - last)) - goto ret1; - last = sp->newl[cnt] + 1; - ++sp->rptlines[L_ADDED]; - } - lbclen -= last; - sp->newl_cnt = 0; - } - - /* Store the changed line. */ - if (file_sline(sp, ep, lno, lb + last, lbclen)) - goto ret1; - - /* 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) - ex_print(sp, ep, &from, &to, E_F_LIST); - if (nflag) - ex_print(sp, ep, &from, &to, E_F_HASH); - if (pflag) - ex_print(sp, ep, &from, &to, E_F_PRINT); - } - - if (!sp->c_suffix) - sp->lno = lno; - - /* - * !!! - * Move the cursor to the last line changed. - */ - if (!sp->c_suffix) - sp->lno = lno; - } - - /* - * !!! - * Move the cursor to the first non-blank of the last line change. - * - * XXX - * This is NOT backward compatible with historic vi, which always - * moved to the last line actually changed. - */ - if (!sp->c_suffix) { - sp->cno = 0; - (void)nonblank(sp, ep, 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. - */ - if (!matched) { - if (!F_ISSET(sp, S_GLOBAL)) - msgq(sp, M_INFO, "No match found"); - } else if (!lflag && !nflag && !pflag) - F_SET(EXP(sp), EX_AUTOPRINT); - - rval = 0; - if (0) { -ret1: rval = 1; - } - - if (bp != NULL) - FREE_SPACE(sp, bp, blen); - if (lb != NULL) - free(lb); - return (rval); -} - -/* - * regsub -- - * Do the substitution for a regular expression. - */ -static __inline int -regsub(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 escape characters. This (hopefully) follows historic practice. - */ -#define ADDCH(ch) { \ - CHAR_T __ch = (ch); \ - u_int __value = KEY_VAL(sp, __ch); \ - if (__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) - ADDCH(*t); - 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; - } - } - ADDCH(ch); - } - - *lbp = lb; /* Update caller's information. */ - *lbclenp = lbclen; - *lblenp = lblen; - return (0); -} diff --git a/usr.bin/vi/ex/ex_tag.c b/usr.bin/vi/ex/ex_tag.c deleted file mode 100644 index 4378803..0000000 --- a/usr.bin/vi/ex/ex_tag.c +++ /dev/null @@ -1,905 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * David Hitz of Auspex Systems, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_tag.c 8.45 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/mman.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 <signal.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "tag.h" - -static char *binary_search __P((char *, char *, char *)); -static int compare __P((char *, char *, char *)); -static char *linear_search __P((char *, char *, char *)); -static int search __P((SCR *, char *, char *, char **)); -static int tag_get __P((SCR *, char *, char **, char **, char **)); - -/* - * ex_tagfirst -- - * The tag code can be entered from main, i.e. "vi -t tag". - */ -int -ex_tagfirst(sp, tagarg) - SCR *sp; - char *tagarg; -{ - FREF *frp; - MARK m; - long tl; - u_int flags; - int sval; - char *p, *tag, *name, *search; - - /* Taglength may limit the number of characters. */ - if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(tagarg) > tl) - tagarg[tl] = '\0'; - - /* Get the tag information. */ - if (tag_get(sp, tagarg, &tag, &name, &search)) - return (1); - - /* Create the file entry. */ - if ((frp = file_add(sp, name)) == NULL) - return (1); - if (file_init(sp, frp, NULL, 0)) - return (1); - - /* - * !!! - * 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. - */ - if (isdigit(search[0])) { - m.lno = atoi(search); - m.cno = 0; - } 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; - flags = SEARCH_FILE | SEARCH_TAG | SEARCH_TERM; - sval = f_search(sp, sp->ep, &m, &m, search, NULL, &flags); - if (sval && (p = strrchr(search, '(')) != NULL) { - p[1] = '\0'; - sval = f_search(sp, sp->ep, - &m, &m, search, NULL, &flags); - } - if (sval) - msgq(sp, M_ERR, "%s: search pattern not found", tag); - } - - /* Set up the screen. */ - frp->lno = m.lno; - frp->cno = m.cno; - F_SET(frp, FR_CURSORSET); - - /* Might as well make this the default tag. */ - if ((EXP(sp)->tlast = strdup(tagarg)) == NULL) { - msgq(sp, M_SYSERR, NULL); - return (1); - } - return (0); -} - -/* Free a tag or tagf structure from a queue. */ -#define FREETAG(tp) { \ - TAILQ_REMOVE(&exp->tagq, (tp), q); \ - if ((tp)->search != NULL) \ - free((tp)->search); \ - FREE((tp), sizeof(TAGF)); \ -} -#define FREETAGF(tfp) { \ - TAILQ_REMOVE(&exp->tagfq, (tfp), q); \ - free((tfp)->name); \ - FREE((tfp), sizeof(TAGF)); \ -} - -/* - * ex_tagpush -- :tag [file] - * Move to a new tag. - * - * The tags stacks in nvi are a bit tricky. Each tag contains a file name, - * search string, and line/column numbers. The search string is only used - * for the first access and for user display. The first record on the stack - * is the place where we first did a tag, so it has no search string. The - * second record is the first tag, and so on. Note, this means that the - * "current" tag is always on the stack. Each tag has a line/column which is - * the location from which the user tagged the following TAG entry, and which - * is used as the return location. - */ -int -ex_tagpush(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - enum {TC_CHANGE, TC_CURRENT} which; - EX_PRIVATE *exp; - FREF *frp; - MARK m; - TAG *tp; - u_int flags; - int sval; - long tl; - char *name, *p, *search, *tag; - - exp = EXP(sp); - switch (cmdp->argc) { - case 1: - if (exp->tlast != NULL) - FREE(exp->tlast, strlen(exp->tlast) + 1); - if ((exp->tlast = strdup(cmdp->argv[0]->bp)) == NULL) { - msgq(sp, M_SYSERR, NULL); - return (1); - } - break; - case 0: - if (exp->tlast == NULL) { - msgq(sp, M_ERR, "No previous tag entered"); - return (1); - } - break; - default: - abort(); - } - - /* Taglength may limit the number of characters. */ - if ((tl = O_VAL(sp, O_TAGLENGTH)) != 0 && strlen(exp->tlast) > tl) - exp->tlast[tl] = '\0'; - - /* Get the tag information. */ - if (tag_get(sp, exp->tlast, &tag, &name, &search)) - return (1); - - /* Get the (possibly new) FREF structure. */ - if ((frp = file_add(sp, name)) == NULL) - goto err; - - if (sp->frp == frp) - which = TC_CURRENT; - else { - if (file_m1(sp, sp->ep, - F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE)) - goto err; - which = TC_CHANGE; - } - - /* - * Get a tag structure -- if this is the first tag, push it on the - * stack as a placeholder and get another tag structure. Set the - * line/column of the most recent element on the stack to be the - * current values, including the file pointer. Then push the new - * TAG onto the stack with the new file and search string for user - * display. - */ - CALLOC(sp, tp, TAG *, 1, sizeof(TAG)); - if (tp != NULL && exp->tagq.tqh_first == NULL) { - TAILQ_INSERT_HEAD(&exp->tagq, tp, q); - CALLOC(sp, tp, TAG *, 1, sizeof(TAG)); - } - if (exp->tagq.tqh_first != NULL) { - exp->tagq.tqh_first->frp = sp->frp; - exp->tagq.tqh_first->lno = sp->lno; - exp->tagq.tqh_first->cno = sp->cno; - } - if (tp != NULL) { - if ((tp->search = strdup(search)) == NULL) - msgq(sp, M_SYSERR, NULL); - else - tp->slen = strlen(search); - tp->frp = frp; - TAILQ_INSERT_HEAD(&exp->tagq, tp, q); - } - - /* Switch files. */ - if (which == TC_CHANGE && file_init(sp, frp, NULL, 0)) { - if (tp != NULL) - FREETAG(tp); - /* Handle special, first-tag case. */ - if (exp->tagq.tqh_first->q.tqe_next == NULL) - TAILQ_REMOVE(&exp->tagq, exp->tagq.tqh_first, q); -err: free(tag); - return (1); - } - - /* - * !!! - * Historic vi accepted a line number as well as a search - * string, and people are apparently still using the format. - */ - if (isdigit(search[0])) { - m.lno = atoi(search); - m.cno = 0; - sval = 0; - } 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; - flags = SEARCH_FILE | SEARCH_TAG | SEARCH_TERM; - sval = f_search(sp, sp->ep, &m, &m, search, NULL, &flags); - if (sval && (p = strrchr(search, '(')) != NULL) { - p[1] = '\0'; - sval = f_search(sp, sp->ep, - &m, &m, search, NULL, &flags); - p[1] = '('; - } - if (sval) - msgq(sp, M_ERR, "%s: search pattern not found", tag); - } - free(tag); - - switch (which) { - case TC_CHANGE: - frp->lno = m.lno; - frp->cno = m.cno; - F_SET(frp, FR_CURSORSET); - F_SET(sp, S_FSWITCH); - break; - case TC_CURRENT: - if (sval) - return (1); - sp->lno = m.lno; - sp->cno = m.cno; - break; - } - return (0); -} - -/* - * ex_tagpop -- :tagp[op][!] [number | file] - * Pop the tag stack. - */ -int -ex_tagpop(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - EX_PRIVATE *exp; - TAG *ntp, *tp; - long off; - size_t arglen; - char *arg, *p, *t; - - /* Check for an empty stack. */ - exp = EXP(sp); - if (exp->tagq.tqh_first == NULL) { - msgq(sp, M_INFO, "The tags stack is empty"); - return (1); - } - - switch (cmdp->argc) { - case 0: /* Pop one tag. */ - ntp = exp->tagq.tqh_first; - break; - case 1: /* Name or number. */ - arg = cmdp->argv[0]->bp; - off = strtol(arg, &p, 10); - if (*p == '\0') { - if (off < 1) - return (0); - for (tp = exp->tagq.tqh_first; - tp != NULL && --off > 1; tp = tp->q.tqe_next); - if (tp == NULL) { - msgq(sp, M_ERR, -"Less than %s entries on the tags stack; use :display to see the tags stack", - arg); - return (1); - } - ntp = tp; - } else { - arglen = strlen(arg); - for (tp = exp->tagq.tqh_first; - tp != NULL; ntp = tp, tp = tp->q.tqe_next) { - /* Use the user's original file name. */ - p = tp->frp->name; - if ((t = strrchr(p, '/')) == NULL) - t = p; - else - ++t; - if (!strncmp(arg, t, arglen)) - break; - } - if (tp == NULL) { - msgq(sp, M_ERR, -"No file named %s on the tags stack; use :display to see the tags stack", - arg); - return (1); - } - } - break; - default: - abort(); - } - - /* Update the cursor from the saved TAG information. */ - tp = ntp->q.tqe_next; - if (tp->frp == sp->frp) { - sp->lno = tp->lno; - sp->cno = tp->cno; - } else { - if (file_m1(sp, ep, - F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE)) - return (1); - if (file_init(sp, tp->frp, NULL, 0)) - return (1); - - tp->frp->lno = tp->lno; - tp->frp->cno = tp->cno; - F_SET(sp->frp, FR_CURSORSET); - - F_SET(sp, S_FSWITCH); - } - - /* Pop entries off the queue up to ntp. */ - for (;;) { - tp = exp->tagq.tqh_first; - FREETAG(tp); - if (tp == ntp) - break; - } - - /* If returning to the first tag, the stack is now empty. */ - if (exp->tagq.tqh_first->q.tqe_next == NULL) - TAILQ_REMOVE(&exp->tagq, exp->tagq.tqh_first, q); - return (0); -} - -/* - * ex_tagtop -- :tagt[op][!] - * Clear the tag stack. - */ -int -ex_tagtop(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - EX_PRIVATE *exp; - TAG *tp; - - /* Find oldest saved information. */ - exp = EXP(sp); - for (tp = exp->tagq.tqh_first; - tp != NULL && tp->q.tqe_next != NULL; tp = tp->q.tqe_next); - if (tp == NULL) { - msgq(sp, M_INFO, "The tags stack is empty"); - return (1); - } - - /* If not switching files, it's easy; else do the work. */ - if (tp->frp == sp->frp) { - sp->lno = tp->lno; - sp->cno = tp->cno; - } else { - if (file_m1(sp, sp->ep, - F_ISSET(cmdp, E_FORCE), FS_ALL | FS_POSSIBLE)) - return (1); - if (file_init(sp, tp->frp, NULL, 0)) - return (1); - - tp->frp->lno = tp->lno; - tp->frp->cno = tp->cno; - - F_SET(sp->frp, FR_CURSORSET); - F_SET(sp, S_FSWITCH); - } - - /* Empty out the queue. */ - while ((tp = exp->tagq.tqh_first) != NULL) - FREETAG(tp); - return (0); -} - -/* - * ex_tagdisplay -- - * Display the list of tags. - */ -int -ex_tagdisplay(sp, ep) - SCR *sp; - EXF *ep; -{ - EX_PRIVATE *exp; - TAG *tp; - size_t len, maxlen; - int cnt; - char *name; - - exp = EXP(sp); - if ((tp = exp->tagq.tqh_first) == NULL) { - (void)ex_printf(EXCOOKIE, "No tags to display.\n"); - return (0); - } - - /* - * Figure out the formatting. MNOC is the maximum - * number of file name columns before we split the line. - */ -#define MNOC 15 - for (maxlen = 0, - tp = exp->tagq.tqh_first; tp != NULL; tp = tp->q.tqe_next) { - len = strlen(name = tp->frp->name); /* The original name. */ - if (maxlen < len && len < MNOC) - maxlen = len; - } - - for (cnt = 1, tp = exp->tagq.tqh_first; tp != NULL; - ++cnt, tp = tp->q.tqe_next) { - len = strlen(name = tp->frp->name); /* The original name. */ - if (len > maxlen || len + tp->slen > sp->cols) - if (tp == NULL || tp->search == NULL) - (void)ex_printf(EXCOOKIE, - "%2d %s\n", cnt, name); - else - (void)ex_printf(EXCOOKIE, - "%2d %s\n** %*.*s %s\n", cnt, name, - (int)maxlen, (int)maxlen, "", tp->search); - else - if (tp == NULL || tp->search == NULL) - (void)ex_printf(EXCOOKIE, "%2d %*.*s\n", - cnt, (int)maxlen, (int)len, name); - else - (void)ex_printf(EXCOOKIE, "%2d %*.*s %s\n", - cnt, (int)maxlen, (int)len, name, - tp->search); - } - return (0); -} - -/* - * ex_tagalloc -- - * Create a new list of tag files. - */ -int -ex_tagalloc(sp, str) - SCR *sp; - char *str; -{ - EX_PRIVATE *exp; - TAGF *tp; - size_t len; - char *p, *t; - - /* Free current queue. */ - exp = EXP(sp); - while ((tp = exp->tagfq.tqh_first) != NULL) - FREETAGF(tp); - - /* Create new queue. */ - for (p = t = str;; ++p) { - if (*p == '\0' || isblank(*p)) { - if ((len = p - t) > 1) { - MALLOC_RET(sp, tp, TAGF *, sizeof(TAGF)); - MALLOC(sp, tp->name, char *, len + 1); - if (tp->name == NULL) { - FREE(tp, sizeof(TAGF)); - return (1); - } - memmove(tp->name, t, len); - tp->name[len] = '\0'; - tp->flags = 0; - TAILQ_INSERT_TAIL(&exp->tagfq, tp, q); - } - t = p + 1; - } - if (*p == '\0') - break; - } - return (0); -} - /* Free previous queue. */ -/* - * ex_tagfree -- - * Free the tags file list. - */ -int -ex_tagfree(sp) - SCR *sp; -{ - EX_PRIVATE *exp; - TAG *tp; - TAGF *tfp; - - /* Free up tag information. */ - exp = EXP(sp); - while ((tp = exp->tagq.tqh_first) != NULL) - FREETAG(tp); - while ((tfp = exp->tagfq.tqh_first) != NULL) - FREETAGF(tfp); - if (exp->tlast != NULL) - free(exp->tlast); - return (0); -} - -/* - * ex_tagcopy -- - * Copy a screen's tag structures. - */ -int -ex_tagcopy(orig, sp) - SCR *orig, *sp; -{ - EX_PRIVATE *oexp, *nexp; - TAG *ap, *tp; - TAGF *atfp, *tfp; - - /* Copy tag stack. */ - oexp = EXP(orig); - nexp = EXP(sp); - for (ap = oexp->tagq.tqh_first; ap != NULL; ap = ap->q.tqe_next) { - MALLOC(sp, tp, TAG *, sizeof(TAG)); - if (tp == NULL) - goto nomem; - *tp = *ap; - if (ap->search != NULL && - (tp->search = strdup(ap->search)) == NULL) - goto nomem; - TAILQ_INSERT_TAIL(&nexp->tagq, tp, q); - } - - /* Copy list of tag files. */ - for (atfp = oexp->tagfq.tqh_first; - atfp != NULL; atfp = atfp->q.tqe_next) { - MALLOC(sp, tfp, TAGF *, sizeof(TAGF)); - if (tfp == NULL) - goto nomem; - *tfp = *atfp; - if ((tfp->name = strdup(atfp->name)) == NULL) - goto nomem; - TAILQ_INSERT_TAIL(&nexp->tagfq, tfp, q); - } - - /* Copy the last tag. */ - if (oexp->tlast != NULL && - (nexp->tlast = strdup(oexp->tlast)) == NULL) { -nomem: msgq(sp, M_SYSERR, NULL); - return (1); - } - return (0); -} - -/* - * tag_get -- - * Get a tag from the tags files. - */ -static int -tag_get(sp, tag, tagp, filep, searchp) - SCR *sp; - char *tag, **tagp, **filep, **searchp; -{ - struct stat sb; - EX_PRIVATE *exp; - TAGF *tfp; - size_t plen, slen, tlen; - int dne; - char *p, pbuf[MAXPATHLEN]; - - /* - * Find the tag, only display missing file messages once, and - * then only if we didn't find the tag. - */ - dne = 0; - exp = EXP(sp); - for (p = NULL, tfp = exp->tagfq.tqh_first; - tfp != NULL && p == NULL; tfp = tfp->q.tqe_next) { - errno = 0; - F_CLR(tfp, TAGF_DNE); - if (search(sp, tfp->name, tag, &p)) - if (errno == ENOENT) { - if (!F_ISSET(tfp, TAGF_DNE_WARN)) { - dne = 1; - F_SET(tfp, TAGF_DNE); - } - } else - msgq(sp, M_SYSERR, tfp->name); - else - if (p != NULL) - break; - } - - if (p == NULL) { - msgq(sp, M_ERR, "%s: tag not found", tag); - if (dne) - for (tfp = exp->tagfq.tqh_first; - tfp != NULL; tfp = tfp->q.tqe_next) - if (F_ISSET(tfp, TAGF_DNE)) { - errno = ENOENT; - msgq(sp, M_SYSERR, tfp->name); - F_SET(tfp, TAGF_DNE_WARN); - } - return (1); - } - - /* - * Set the return pointers; tagp points to the tag, and, incidentally - * the allocated string, filep points to the file name, and searchp - * points to the search string. All three are nul-terminated. - */ - for (*tagp = p; *p && !isblank(*p); ++p); - if (*p == '\0') - goto malformed; - for (*p++ = '\0'; isblank(*p); ++p); - for (*filep = p; *p && !isblank(*p); ++p); - if (*p == '\0') - goto malformed; - for (*p++ = '\0'; isblank(*p); ++p); - *searchp = p; - if (*p == '\0') { -malformed: free(*tagp); - msgq(sp, M_ERR, "%s: corrupted tag in %s", tag, tfp->name); - return (1); - } - - /* - * !!! - * 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 do it right. - */ - if ((*filep)[0] != '/' - && stat(*filep, &sb) && (p = strrchr(tfp->name, '/')) != NULL) { - *p = '\0'; - plen = snprintf(pbuf, sizeof(pbuf), "%s/%s", tfp->name, *filep); - *p = '/'; - if (stat(pbuf, &sb) == 0) { - slen = strlen(*searchp); - tlen = strlen(*tagp); - MALLOC(sp, p, char *, plen + slen + tlen + 5); - if (p != NULL) { - memmove(p, *tagp, tlen); - free(*tagp); - *tagp = p; - *(p += tlen) = '\0'; - memmove(++p, pbuf, plen); - *filep = p; - *(p += plen) = '\0'; - memmove(++p, *searchp, slen); - *searchp = p; - *(p += slen) = '\0'; - } - } - } - return (0); -} - -#define EQUAL 0 -#define GREATER 1 -#define LESS (-1) - -/* - * search -- - * Search a file for a tag. - */ -static int -search(sp, name, tname, tag) - SCR *sp; - char *name, *tname, **tag; -{ - struct stat sb; - int fd, len; - char *endp, *back, *front, *map, *p; - - if ((fd = open(name, O_RDONLY, 0)) < 0) - return (1); - - /* - * 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 that malloc fails if the file is too - * large. - */ - if (fstat(fd, &sb) || (map = mmap(NULL, (size_t)sb.st_size, - PROT_READ, MAP_PRIVATE, fd, (off_t)0)) == (caddr_t)-1) { - (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 || (endp = strchr(front, '\n')) == NULL) { - *tag = NULL; - goto done; - } - - len = endp - front; - MALLOC(sp, p, char *, len + 1); - if (p == NULL) { - *tag = NULL; - goto done; - } - memmove(p, front, len); - p[len] = '\0'; - *tag = p; - -done: if (munmap(map, (size_t)sb.st_size)) - msgq(sp, M_SYSERR, "munmap"); - if (close(fd)) - msgq(sp, M_SYSERR, "close"); - return (0); -} - -/* - * 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 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/usr.bin/vi/ex/ex_undo.c b/usr.bin/vi/ex/ex_undo.c deleted file mode 100644 index 1b8ba69..0000000 --- a/usr.bin/vi/ex/ex_undo.c +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_undo.c 8.9 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_undo -- u - * Undo the last change. - */ -int -ex_undo(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - MARK m; - - /* - * !!! - * Historic undo always set the previous context mark. - */ - m.lno = sp->lno; - m.cno = sp->cno; - if (mark_set(sp, ep, 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. - */ - if (!F_ISSET(ep, F_UNDO)) { - F_SET(ep, F_UNDO); - ep->lundo = FORWARD; - } - switch (ep->lundo) { - case BACKWARD: - if (log_forward(sp, ep, &m)) - return (1); - ep->lundo = FORWARD; - break; - case FORWARD: - if (log_backward(sp, ep, &m)) - return (1); - ep->lundo = BACKWARD; - break; - case NOTSET: - abort(); - } - sp->lno = m.lno; - sp->cno = m.cno; - return (0); -} diff --git a/usr.bin/vi/ex/ex_usage.c b/usr.bin/vi/ex/ex_usage.c deleted file mode 100644 index 424b79b..0000000 --- a/usr.bin/vi/ex/ex_usage.c +++ /dev/null @@ -1,197 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_usage.c 8.21 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" -#include "../vi/vcmd.h" - -/* - * ex_help -- :help - * Display help message. - */ -int -ex_help(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - (void)ex_printf(EXCOOKIE, - "To see the list of vi commands, enter \":viusage<CR>\"\n"); - (void)ex_printf(EXCOOKIE, - "To see the list of ex commands, enter \":exusage<CR>\"\n"); - (void)ex_printf(EXCOOKIE, - "For an ex command usage statement enter \":exusage [cmd]<CR>\"\n"); - (void)ex_printf(EXCOOKIE, - "For a vi key usage statement enter \":viusage [key]<CR>\"\n"); - (void)ex_printf(EXCOOKIE, "To exit, enter \":q!\"\n"); - return (0); -} - -/* - * ex_usage -- :exusage [cmd] - * Display ex usage strings. - */ -int -ex_usage(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - ARGS *ap; - EXCMDLIST const *cp; - char *name; - - switch (cmdp->argc) { - case 1: - ap = cmdp->argv[0]; - for (cp = cmds; cp->name != NULL && - memcmp(ap->bp, cp->name, ap->len); ++cp); - if (cp->name == NULL) - (void)ex_printf(EXCOOKIE, - "The %.*s command is unknown", - (int)ap->len, ap->bp); - else { - (void)ex_printf(EXCOOKIE, - "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(EXCOOKIE, - "Command: %s\n Usage: %s\n", cp->help, cp->usage); - } - break; - case 0: - F_SET(sp, S_INTERRUPTIBLE); - for (cp = cmds; cp->name != NULL; ++cp) { - /* The ^D command has an unprintable name. */ - if (cp == &cmds[C_SCROLL]) - name = "^D"; - else - name = cp->name; - (void)ex_printf(EXCOOKIE, - "%*s: %s\n", MAXCMDNAMELEN, name, cp->help); - } - break; - default: - abort(); - } - return (0); -} - -/* - * ex_viusage -- :viusage [key] - * Display vi usage strings. - */ -int -ex_viusage(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - VIKEYS const *kp; - int key; - - switch (cmdp->argc) { - case 1: - if (cmdp->argv[0]->len != 1) { - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->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->func == NULL) -nokey: (void)ex_printf(EXCOOKIE, - "The %s key has no current meaning", - KEY_NAME(sp, key)); - else - (void)ex_printf(EXCOOKIE, - " Key:%s%s\nUsage: %s\n", - isblank(*kp->help) ? "" : " ", kp->help, kp->usage); - break; - case 0: - F_SET(sp, S_INTERRUPTIBLE); - for (key = 0; key <= MAXVIKEY; ++key) { - /* Special case: ~ command. */ - if (key == '~' && O_ISSET(sp, O_TILDEOP)) - kp = &tmotion; - else - kp = &vikeys[key]; - if (kp->help != NULL) - (void)ex_printf(EXCOOKIE, "%s\n", kp->help); - } - break; - default: - abort(); - } - return (0); -} diff --git a/usr.bin/vi/ex/ex_util.c b/usr.bin/vi/ex/ex_util.c deleted file mode 100644 index 67c1039..0000000 --- a/usr.bin/vi/ex/ex_util.c +++ /dev/null @@ -1,189 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_util.c 8.14 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_getline -- - * Return a line from the terminal. - */ -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_sleave -- - * Save the terminal/signal state, screen modification time. - * Specific to ex/filter.c and ex/ex_shell.c. - */ -int -ex_sleave(sp) - SCR *sp; -{ - struct stat sb; - EX_PRIVATE *exp; - - /* Ignore sessions not using tty's. */ - if (!F_ISSET(sp->gp, G_STDIN_TTY)) - return (1); - - exp = EXP(sp); - if (tcgetattr(STDIN_FILENO, &exp->leave_term)) { - msgq(sp, M_SYSERR, "tcgetattr"); - return (1); - } - if (tcsetattr(STDIN_FILENO, - TCSANOW | TCSASOFT, &sp->gp->original_termios)) { - msgq(sp, M_SYSERR, "tcsetattr"); - return (1); - } - /* - * The process may write to the terminal. Save the access time - * (read) and modification time (write) of the tty; if they have - * changed when we restore the modes, will have to refresh the - * screen. - */ - if (fstat(STDIN_FILENO, &sb)) { - msgq(sp, M_SYSERR, "stat: stdin"); - exp->leave_atime = exp->leave_mtime = 0; - } else { - exp->leave_atime = sb.st_atime; - exp->leave_mtime = sb.st_mtime; - } - return (0); -} - -/* - * ex_rleave -- - * Return the terminal/signal state, not screen modification time. - * Specific to ex/filter.c and ex/ex_shell.c. - */ -void -ex_rleave(sp) - SCR *sp; -{ - EX_PRIVATE *exp; - struct stat sb; - - exp = EXP(sp); - - /* Restore the terminal modes. */ - if (tcsetattr(STDIN_FILENO, TCSANOW | TCSASOFT, &exp->leave_term)) - msgq(sp, M_SYSERR, "tcsetattr"); - - /* If the terminal was used, refresh the screen. */ - if (fstat(STDIN_FILENO, &sb) || exp->leave_atime == 0 || - exp->leave_atime != sb.st_atime || exp->leave_mtime != sb.st_mtime) - F_SET(sp, S_REFRESH); -} - -/* - * ex_ncheck -- - * Check for more files to edit. - */ -int -ex_ncheck(sp, force) - SCR *sp; - int force; -{ - /* - * !!! - * 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; - msgq(sp, M_ERR, - "More files to edit; use n[ext] to go to the next file, q[uit]! to quit"); - return (1); - } - return (0); -} diff --git a/usr.bin/vi/ex/ex_version.c b/usr.bin/vi/ex/ex_version.c deleted file mode 100644 index 011c257..0000000 --- a/usr.bin/vi/ex/ex_version.c +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_version.c 8.66 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_version -- :version - * Display the program version. - */ -int -ex_version(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - static const time_t then = 777148668; - - (void)ex_printf(EXCOOKIE, -"Version 1.34, %sThe CSRG, University of California, Berkeley.\n", - ctime(&then)); - return (0); -} diff --git a/usr.bin/vi/ex/ex_visual.c b/usr.bin/vi/ex/ex_visual.c deleted file mode 100644 index acfd537..0000000 --- a/usr.bin/vi/ex/ex_visual.c +++ /dev/null @@ -1,137 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_visual.c 8.15 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_visual -- :[line] vi[sual] [^-.+] [window_size] [flags] - * - * Switch to visual mode. - */ -int -ex_visual(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - 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, - "The visual command requires that the open option be set"); - return (1); - } - - /* If a line specified, move to that line. */ - if (cmdp->addrcnt) - sp->lno = 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 (F_ISSET(cmdp, E_F_CARAT | E_F_DASH | E_F_DOT | E_F_PLUS)) { - case E_F_CARAT: - pos = '^'; - break; - case E_F_DASH: - pos = '-'; - break; - case E_F_DOT: - pos = '.'; - break; - case E_F_PLUS: - pos = '+'; - break; - default: - sp->frp->lno = sp->lno; - sp->frp->cno = 0; - F_SET(sp->frp, FR_CURSORSET | FR_FNONBLANK); - goto nopush; - } - - if (F_ISSET(cmdp, E_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)term_push(sp, 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 (F_ISSET(cmdp, E_F_HASH | E_F_LIST | E_F_PRINT)) { - case E_F_HASH: - O_SET(sp, O_NUMBER); - break; - case E_F_LIST: - O_SET(sp, O_LIST); - break; - case E_F_PRINT: - break; - } - - /* Switch modes. */ -nopush: F_CLR(sp, S_SCREENS); - F_SET(sp, sp->saved_vi_mode); - - return (0); -} diff --git a/usr.bin/vi/ex/ex_write.c b/usr.bin/vi/ex/ex_write.c deleted file mode 100644 index e5273e4..0000000 --- a/usr.bin/vi/ex/ex_write.c +++ /dev/null @@ -1,327 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_write.c 8.38 (Berkeley) 8/17/94"; -#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 <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -enum which {WN, WQ, WRITE, XIT}; - -static int exwr __P((SCR *, EXF *, EXCMDARG *, enum which)); - -/* - * ex_wn -- :wn[!] [>>] [file] - * Write to a file and switch to the next one. - */ -int -ex_wn(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - if (exwr(sp, ep, cmdp, WN)) - return (1); - if (file_m3(sp, ep, 0)) - return (1); - - /* The file name isn't a new file to edit. */ - cmdp->argc = 0; - - return (ex_next(sp, ep, cmdp)); -} - -/* - * ex_wq -- :wq[!] [>>] [file] - * Write to a file and quit. - */ -int -ex_wq(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - int force; - - if (exwr(sp, ep, cmdp, WQ)) - return (1); - if (file_m3(sp, ep, 0)) - return (1); - - force = F_ISSET(cmdp, E_FORCE); - - if (ex_ncheck(sp, force)) - return (1); - - F_SET(sp, force ? S_EXIT_FORCE : S_EXIT); - return (0); -} - -/* - * ex_write -- :write[!] [>>] [file] - * :write [!] [cmd] - * Write to a file. - */ -int -ex_write(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (exwr(sp, ep, cmdp, WRITE)); -} - - -/* - * ex_xit -- :x[it]! [file] - * - * Write out any modifications and quit. - */ -int -ex_xit(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - int force; - - if (F_ISSET((ep), F_MODIFIED) && exwr(sp, ep, cmdp, XIT)) - return (1); - if (file_m3(sp, ep, 0)) - return (1); - - force = F_ISSET(cmdp, E_FORCE); - - if (ex_ncheck(sp, force)) - return (1); - - F_SET(sp, force ? S_EXIT_FORCE : S_EXIT); - return (0); -} - -/* - * exwr -- - * The guts of the ex write commands. - */ -static int -exwr(sp, ep, cmdp, cmd) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; - enum which cmd; -{ - EX_PRIVATE *exp; - MARK rm; - int flags; - char *name, *p; - - /* All write commands can have an associated '!'. */ - LF_INIT(FS_POSSIBLE); - if (F_ISSET(cmdp, E_FORCE)) - LF_SET(FS_FORCE); - - /* Skip any leading whitespace. */ - if (cmdp->argc != 0) - for (p = cmdp->argv[0]->bp; *p && isblank(*p); ++p); - - /* If no arguments, just write the file back. */ - if (cmdp->argc == 0 || *p == '\0') { - if (F_ISSET(cmdp, E_ADDR2_ALL)) - LF_SET(FS_ALL); - return (file_write(sp, ep, - &cmdp->addr1, &cmdp->addr2, NULL, flags)); - } - - /* If "write !" it's a pipe to a utility. */ - exp = EXP(sp); - if (cmd == WRITE && *p == '!') { - for (++p; *p && isblank(*p); ++p); - if (*p == '\0') { - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); - } - /* Expand the argument. */ - if (argv_exp1(sp, ep, cmdp, p, strlen(p), 0)) - return (1); - if (filtercmd(sp, ep, &cmdp->addr1, &cmdp->addr2, - &rm, cmdp->argv[1]->bp, FILTER_WRITE)) - return (1); - sp->lno = rm.lno; - return (0); - } - - /* If "write >>" it's an append to a file. */ - if (cmd != XIT && p[0] == '>' && p[1] == '>') { - LF_SET(FS_APPEND); - - /* Skip ">>" and whitespace. */ - for (p += 2; *p && isblank(*p); ++p); - } - - /* Build an argv so we get an argument count and file expansion. */ - if (argv_exp2(sp, ep, cmdp, p, strlen(p), 0)) - return (1); - - switch (cmdp->argc) { - case 1: - /* - * Nothing to expand, write the current file. - * XXX - * Should never happen, already checked this case. - */ - name = NULL; - break; - case 2: - /* One new argument, write it. */ - name = cmdp->argv[exp->argsoff - 1]->bp; - set_alt_name(sp, name); - break; - default: - /* If expanded to more than one argument, object. */ - msgq(sp, M_ERR, "%s expanded into too many file names", - cmdp->argv[0]->bp); - msgq(sp, M_ERR, "Usage: %s", cmdp->cmd->usage); - return (1); - } - - if (F_ISSET(cmdp, E_ADDR2_ALL)) - LF_SET(FS_ALL); - return (file_write(sp, ep, &cmdp->addr1, &cmdp->addr2, name, flags)); -} - -/* - * ex_writefp -- - * Write a range of lines to a FILE *. - */ -int -ex_writefp(sp, ep, name, fp, fm, tm, nlno, nch) - SCR *sp; - EXF *ep; - char *name; - FILE *fp; - MARK *fm, *tm; - u_long *nlno, *nch; -{ - struct stat sb; - u_long ccnt; /* XXX: can't print off_t portably. */ - recno_t fline, tline, lcnt; - size_t len; - int sv_errno; - char *p; - - 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 file_gline() and msgq(). File_gline() is safe, - * see the comment in filter.c:filtercmd() 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; - if (tline != 0) { - for (; fline <= tline; ++fline, ++lcnt) { - /* Caller has to provide any interrupt message. */ - if (INTERRUPTED(sp)) - break; - if ((p = file_gline(sp, ep, fline, &len)) == NULL) - break; - if (fwrite(p, 1, len, fp) != len) { - msgq(sp, M_SYSERR, name); - (void)fclose(fp); - return (1); - } - ccnt += len; - if (putc('\n', fp) != '\n') - break; - ++ccnt; - } - } - - /* If it's a regular file, sync it so that NFS is forced to flush. */ - if (!fstat(fileno(fp), &sb) && - S_ISREG(sb.st_mode) && fsync(fileno(fp))) { - sv_errno = errno; - (void)fclose(fp); - errno = sv_errno; - goto err; - } - if (fclose(fp)) - goto err; - if (nlno != NULL) { - *nch = ccnt; - *nlno = lcnt; - } - return (0); - -err: if (!F_ISSET(ep, F_MULTILOCK)) - msgq(sp, M_SYSERR, name); - return (1); -} diff --git a/usr.bin/vi/ex/ex_yank.c b/usr.bin/vi/ex/ex_yank.c deleted file mode 100644 index aa44d2b..0000000 --- a/usr.bin/vi/ex/ex_yank.c +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_yank.c 8.7 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_yank -- :[line [,line]] ya[nk] [buffer] [count] - * - * Yank the lines into a buffer. - */ -int -ex_yank(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - return (cut(sp, ep, - F_ISSET(cmdp, E_BUFFER) ? &cmdp->buffer : NULL, - &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE)); -} diff --git a/usr.bin/vi/ex/ex_z.c b/usr.bin/vi/ex/ex_z.c deleted file mode 100644 index d130646..0000000 --- a/usr.bin/vi/ex/ex_z.c +++ /dev/null @@ -1,180 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)ex_z.c 8.8 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.h" - -/* - * ex_z -- :[line] z [^-.+=] [count] [flags] - * - * Adjust window. - */ -int -ex_z(sp, ep, cmdp) - SCR *sp; - EXF *ep; - EXCMDARG *cmdp; -{ - MARK abs; - recno_t cnt, equals, lno; - int eofcheck; - - /* - * !!! - * 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 (F_ISSET(cmdp, E_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 (F_ISSET(cmdp, - E_F_CARAT | E_F_DASH | E_F_DOT | E_F_EQUAL | E_F_PLUS)) { - case E_F_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_F_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_F_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, ep, ABSMARK1, &abs, 1); - break; - case E_F_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, ep, cmdp)) - return (1); - (void)ex_printf(EXCOOKIE, - "%s", "----------------------------------------\n"); - cmdp->addr2.lno = cmdp->addr1.lno = equals = lno; - if (ex_pr(sp, ep, cmdp)) - return (1); - (void)ex_printf(EXCOOKIE, - "%s", "----------------------------------------\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_ADDRDEF)) - ++lno; - /* FALLTHROUGH */ - case E_F_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 (file_lline(sp, ep, &lno)) - return (1); - if (cmdp->addr2.lno > lno) - cmdp->addr2.lno = lno; - } - - if (ex_pr(sp, ep, cmdp)) - return (1); - if (equals) - sp->lno = equals; - return (0); -} diff --git a/usr.bin/vi/ex/excmd.awk b/usr.bin/vi/ex/excmd.awk deleted file mode 100644 index 2890220..0000000 --- a/usr.bin/vi/ex/excmd.awk +++ /dev/null @@ -1,6 +0,0 @@ -# @(#)excmd.awk 8.1 (Berkeley) 4/17/94 - -/^\/\* C_[0-9A-Z_]* \*\/$/ { - printf("#define %s %d\n", $2, cnt++); - next; -} diff --git a/usr.bin/vi/ex/excmd.c b/usr.bin/vi/ex/excmd.c deleted file mode 100644 index 422578a..0000000 --- a/usr.bin/vi/ex/excmd.c +++ /dev/null @@ -1,458 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)excmd.c 8.60 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <termios.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> - -#include "vi.h" -#include "excmd.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|E_NORC, - "", - "^D", - "scroll lines"}, -/* C_BANG */ - {"!", ex_bang, E_ADDR2_NONE|E_NORC, - "S", - "[line [,line]] ! command", - "filter lines through commands or run commands"}, -/* C_HASH */ - {"#", ex_number, E_ADDR2|E_F_PRCLEAR|E_NORC, - "ca1", - "[line [,line]] # [count] [l]", - "display numbered lines"}, -/* C_SUBAGAIN */ - {"&", ex_subagain, E_ADDR2|E_NORC, - "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|E_NORC, - "ca1", - "[line [,line]] <[<...] [count] [flags]", - "shift lines left"}, -/* C_EQUAL */ - {"=", ex_equal, E_ADDR1|E_NORC|E_ZERO|E_ZERODEF, - "1", - "[line] = [flags]", - "display line number"}, -/* C_SHIFTR */ - {">", ex_shiftr, E_ADDR2|E_AUTOPRINT|E_NORC, - "ca1", - "[line [,line]] >[>...] [count] [flags]", - "shift lines right"}, -/* C_AT */ - {"@", ex_at, 0, - "b", - "@ [buffer]", - "execute a buffer"}, -/* C_APPEND */ - {"append", ex_append, E_ADDR1|E_NORC|E_ZERO|E_ZERODEF, - "!", - "[line] a[ppend][!]", - "append input to a line"}, -/* C_ABBR */ - {"abbreviate", ex_abbr, E_NOGLOBAL, - "W", - "ab[brev] [word replace]", - "specify an input abbreviation"}, -/* C_ARGS */ - {"args", ex_args, E_NOGLOBAL|E_NORC, - "", - "ar[gs]", - "display file argument list"}, -/* C_BG */ - {"bg", ex_bg, E_NOGLOBAL|E_NORC, - "", - "bg", - "background the current screen"}, -/* C_CHANGE */ - {"change", ex_change, E_ADDR2|E_NORC|E_ZERODEF, - "!ca", - "[line [,line]] c[hange][!] [count]", - "change lines to input"}, -/* C_CD */ - {"cd", ex_cd, E_NOGLOBAL, - "!f1o", - "cd[!] [directory]", - "change the current directory"}, -/* C_CHDIR */ - {"chdir", ex_cd, E_NOGLOBAL, - "!f1o", - "chd[ir][!] [directory]", - "change the current directory"}, -/* C_COPY */ - {"copy", ex_copy, E_ADDR2|E_AUTOPRINT|E_NORC, - "l1", - "[line [,line]] co[py] line [flags]", - "copy lines elsewhere in the file"}, -/* - * !!! - * 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|E_NORC, - "bca1", - "[line [,line]] d[elete][flags] [buffer] [count] [flags]", - "delete lines from the file"}, -/* C_DISPLAY */ - {"display", ex_display, E_NOGLOBAL|E_NORC, - "w1r", - "display b[uffers] | s[creens] | t[ags]", - "display buffers, screens or tags"}, -/* C_DIGRAPH */ - {"digraph", ex_digraph, E_NOGLOBAL|E_NOPERM|E_NORC, - "", - "digraph", - "specify digraphs (not implemented)"}, -/* C_EDIT */ - {"edit", ex_edit, E_NOGLOBAL|E_NORC, - "f1o", - "e[dit][!] [+cmd] [file]", - "begin editing another file"}, -/* C_EX */ - {"ex", ex_edit, E_NOGLOBAL|E_NORC, - "f1o", - "ex[!] [+cmd] [file]", - "begin editing another file"}, -/* C_EXUSAGE */ - {"exusage", ex_usage, E_NOGLOBAL|E_NORC, - "w1o", - "[exu]sage [command]", - "display ex command usage statement"}, -/* C_FILE */ - {"file", ex_file, E_NOGLOBAL|E_NORC, - "f1o", - "f[ile] [name]", - "display (and optionally set) file name"}, -/* C_FG */ - {"fg", ex_fg, E_NOGLOBAL|E_NORC, - "f1o", - "fg [file]", - "switch the current screen and a backgrounded screen"}, -/* C_GLOBAL */ - {"global", ex_global, E_ADDR2_ALL|E_NOGLOBAL|E_NORC, - "!s", - "[line [,line]] g[lobal][!] [;/]RE[;/] [commands]", - "execute a global command on lines matching an RE"}, -/* C_HELP */ - {"help", ex_help, E_NOGLOBAL|E_NORC, - "", - "he[lp]", - "display help statement"}, -/* C_INSERT */ - {"insert", ex_insert, E_ADDR1|E_NORC, - "!", - "[line] i[nsert][!]", - "insert input before a line"}, -/* C_JOIN */ - {"join", ex_join, E_ADDR2|E_AUTOPRINT|E_NORC, - "!ca1", - "[line [,line]] j[oin][!] [count] [flags]", - "join lines into a single line"}, -/* C_K */ - {"k", ex_mark, E_ADDR1|E_NORC, - "w1r", - "[line] k key", - "mark a line position"}, -/* C_LIST */ - {"list", ex_list, E_ADDR2|E_F_PRCLEAR|E_NORC, - "ca1", - "[line [,line]] l[ist] [count] [#]", - "display lines in an unambiguous form"}, -/* C_MOVE */ - {"move", ex_move, E_ADDR2|E_AUTOPRINT|E_NORC, - "l", - "[line [,line]] m[ove] line", - "move lines elsewhere in the file"}, -/* C_MARK */ - {"mark", ex_mark, E_ADDR1|E_NORC, - "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, E_NOGLOBAL|E_NORC, - "!f1r", - "mkexrc[!] file", - "write a .exrc file"}, -/* C_NEXT */ - {"next", ex_next, E_NOGLOBAL|E_NORC, - "!fN", - "n[ext][!] [+cmd] [file ...]", - "edit (and optionally specify) the next file"}, -/* C_NUMBER */ - {"number", ex_number, E_ADDR2|E_F_PRCLEAR|E_NORC, - "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_F_PRCLEAR|E_NORC, - "ca1", - "[line [,line]] p[rint] [count] [#l]", - "display lines"}, -/* C_PRESERVE */ - {"preserve", ex_preserve, E_NOGLOBAL|E_NORC, - "", - "pre[serve]", - "preserve an edit session for recovery"}, -/* C_PREVIOUS */ - {"previous", ex_prev, E_NOGLOBAL|E_NORC, - "!", - "prev[ious][!]", - "edit the previous file in the file argument list"}, -/* C_PUT */ - {"put", ex_put, E_ADDR1|E_AUTOPRINT|E_NORC|E_ZERO, - "b", - "[line] pu[t] [buffer]", - "append a cut buffer to the line"}, -/* C_QUIT */ - {"quit", ex_quit, E_NOGLOBAL|E_NORC, - "!", - "q[uit][!]", - "exit ex/vi"}, -/* C_READ */ - {"read", ex_read, E_ADDR1|E_NORC|E_ZERO|E_ZERODEF, - "s", - "[line] r[ead] [!cmd | [file]]", - "append input from a command or file to the line"}, -/* C_RECOVER */ - {"recover", ex_recover, E_NOGLOBAL|E_NORC, - "!f1r", - "recover[!] file", - "recover a saved file"}, -/* C_RESIZE */ - {"resize", ex_resize, E_NOGLOBAL|E_NORC, - "c+", - "resize [+-]rows", - "grow or shrink the current screen"}, -/* C_REWIND */ - {"rewind", ex_rew, E_NOGLOBAL|E_NORC, - "!", - "rew[ind][!]", - "re-edit all the files in the file argument list"}, -/* C_SUBSTITUTE */ - {"substitute", ex_substitute, E_ADDR2|E_NORC, - "s", -"[line [,line]] s[ubstitute] [[/;]RE[/;]/repl[/;] [cgr] [count] [#lp]]", - "substitute on lines matching an RE"}, -/* C_SCRIPT */ - {"script", ex_script, E_NOGLOBAL|E_NORC, - "!f1o", - "sc[ript][!] [file]", - "run a shell in a screen"}, -/* C_SET */ - {"set", ex_set, E_NOGLOBAL, - "wN", - "se[t] [option[=[value]]...] [nooption ...] [option? ...] [all]", - "set options (use \":set all\" to see all options)"}, -/* C_SHELL */ - {"shell", ex_shell, E_NOGLOBAL|E_NORC, - "", - "sh[ell]", - "suspend editing and run a shell"}, -/* C_SOURCE */ - {"source", ex_source, E_NOGLOBAL, - "f1r", - "so[urce] file", - "read a file of ex commands"}, -/* C_SPLIT */ - {"split", ex_split, E_NOGLOBAL|E_NORC, - "fNo", - "sp[lit] [file ...]", - "split the current screen into two screens"}, -/* C_STOP */ - {"stop", ex_stop, E_NOGLOBAL|E_NORC, - "!", - "st[op][!]", - "suspend the edit session"}, -/* C_SUSPEND */ - {"suspend", ex_stop, E_NOGLOBAL|E_NORC, - "!", - "su[spend][!]", - "suspend the edit session"}, -/* C_T */ - {"t", ex_copy, E_ADDR2|E_AUTOPRINT|E_NORC, - "l1", - "[line [,line]] t line [flags]", - "copy lines elsewhere in the file"}, -/* C_TAG */ - {"tag", ex_tagpush, E_NOGLOBAL, - "!w1o", - "ta[g][!] [string]", - "edit the file containing the tag"}, -/* C_TAGPOP */ - {"tagpop", ex_tagpop, E_NOGLOBAL|E_NORC, - "!w1o", - "tagp[op][!] [number | file]", - "return to a previous tag"}, -/* C_TAGTOP */ - {"tagtop", ex_tagtop, E_NOGLOBAL|E_NORC, - "!", - "tagt[op][!]", - "return to the first tag"}, -/* C_UNDO */ - {"undo", ex_undo, E_AUTOPRINT|E_NOGLOBAL|E_NORC, - "", - "u[ndo]", - "undo the most recent change"}, -/* C_UNABBREVIATE */ - {"unabbreviate",ex_unabbr, E_NOGLOBAL, - "w1r", - "una[bbrev] word", - "delete an abbreviation"}, -/* C_UNMAP */ - {"unmap", ex_unmap, E_NOGLOBAL, - "!w1r", - "unm[ap][!] word", - "delete an input or command map"}, -/* C_VGLOBAL */ - {"vglobal", ex_vglobal, E_ADDR2_ALL|E_NOGLOBAL|E_NORC, - "s", - "[line [,line]] v[global] [;/]RE[;/] [commands]", - "execute a global command on lines NOT matching an RE"}, -/* C_VERSION */ - {"version", ex_version, E_NOGLOBAL|E_NORC, - "", - "version", - "display the program version information"}, -/* C_VISUAL_EX */ - {"visual", ex_visual, E_ADDR1|E_NOGLOBAL|E_NORC|E_ZERODEF, - "2c11", - "[line] vi[sual] [-|.|+|^] [window_size] [flags]", - "enter visual (vi) mode from ex mode"}, -/* C_VISUAL_VI */ - {"visual", ex_edit, E_NOGLOBAL|E_NORC, - "f1o", - "vi[sual][!] [+cmd] [file]", - "edit another file (from vi mode only)"}, -/* C_VIUSAGE */ - {"viusage", ex_viusage, E_NOGLOBAL|E_NORC, - "w1o", - "[viu]sage [key]", - "display vi key usage statement"}, -/* C_WRITE */ - {"write", ex_write, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF, - "!s", - "[line [,line]] w[rite][!] [!cmd | [>>] [file]]", - "write the file"}, -/* C_WN */ - {"wn", ex_wn, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF, - "!s", - "[line [,line]] wn[!] [>>] [file]", - "write the file and switch to the next file"}, -/* C_WQ */ - {"wq", ex_wq, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF, - "!s", - "[line [,line]] wq[!] [>>] [file]", - "write the file and exit"}, -/* C_XIT */ - {"xit", ex_xit, E_ADDR2_ALL|E_NOGLOBAL|E_NORC|E_ZERODEF, - "!f1o", - "[line [,line]] x[it][!] [file]", - "exit"}, -/* C_YANK */ - {"yank", ex_yank, E_ADDR2|E_NORC, - "bca", - "[line [,line]] ya[nk] [buffer] [count]", - "copy lines to a cut buffer"}, -/* C_Z */ - {"z", ex_z, E_ADDR1|E_NOGLOBAL|E_NORC, - "3c01", - "[line] z [-|.|+|^|=] [count] [flags]", - "display different screens of the file"}, -/* C_SUBTILDE */ - {"~", ex_subtilde, E_ADDR2|E_NORC, - "s", - "[line [,line]] ~ [cgr] [count] [#lp]", - "replace previous RE with previous replacement string,"}, - {NULL}, -}; diff --git a/usr.bin/vi/ex/excmd.h.stub b/usr.bin/vi/ex/excmd.h.stub deleted file mode 100644 index 3b4051b..0000000 --- a/usr.bin/vi/ex/excmd.h.stub +++ /dev/null @@ -1,285 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)excmd.h.stub 8.73 (Berkeley) 8/9/94 - */ - -#define PROMPTCHAR ':' /* Prompt character. */ - -/* Ex command structure. */ -typedef struct _excmdlist { - char *name; /* Command name. */ - /* Underlying function. */ - int (*fn) __P((SCR *, EXF *, EXCMDARG *)); - -#define E_ADDR1 0x0000001 /* One address. */ -#define E_ADDR2 0x0000002 /* Two address. */ -#define E_ADDR2_ALL 0x0000004 /* Zero/two addresses; zero == all. */ -#define E_ADDR2_NONE 0x0000008 /* Zero/two addresses; zero == none. */ -#define E_ADDRDEF 0x0000010 /* Default addresses used. */ -#define E_AUTOPRINT 0x0000020 /* Command always sets autoprint. */ -#define E_BUFFER 0x0000040 /* Buffer name supplied. */ -#define E_COUNT 0x0000080 /* Count supplied. */ -#define E_COUNT_NEG 0x0000100 /* Count was signed negative. */ -#define E_COUNT_POS 0x0000200 /* Count was signed positive. */ -#define E_FORCE 0x0000400 /* ! */ - -#define E_F_CARAT 0x0000800 /* ^ flag. */ -#define E_F_DASH 0x0001000 /* - flag. */ -#define E_F_DOT 0x0002000 /* . flag. */ -#define E_F_EQUAL 0x0004000 /* = flag. */ -#define E_F_HASH 0x0008000 /* # flag. */ -#define E_F_LIST 0x0010000 /* l flag. */ -#define E_F_PLUS 0x0020000 /* + flag. */ -#define E_F_PRINT 0x0040000 /* p flag. */ - -#define E_F_PRCLEAR 0x0080000 /* Clear the print (#, l, p) flags. */ -#define E_MODIFY 0x0100000 /* File name expansion modified arg. */ -#define E_NOGLOBAL 0x0200000 /* Not in a global. */ -#define E_NOPERM 0x0400000 /* Permission denied for now. */ -#define E_NORC 0x0800000 /* Not from a .exrc or EXINIT. */ -#define E_ZERO 0x1000000 /* 0 is a legal addr1. */ -#define E_ZERODEF 0x2000000 /* 0 is default addr1 of empty files. */ - u_int32_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[]; /* List of ex commands. */ - -/* - * Structure passed around to functions implementing ex commands. - * There are several commands in vi that build one of these and - * call ex directly. See vi/v_ex.c for details. - */ -struct _excmdarg { - EXCMDLIST const *cmd; /* Command entry in command table. */ - CHAR_T buffer; /* Named buffer. */ - recno_t lineno; /* Line number. */ - long count; /* Signed, specified count. */ - long flagoff; /* Signed, flag offset parsed by command. */ - int addrcnt; /* Number of addresses (0, 1 or 2). */ - MARK addr1; /* 1st address. */ - MARK addr2; /* 2nd address. */ - ARGS **argv; /* Array of arguments. */ - int argc; /* Count of arguments. */ - u_int32_t flags; /* Selected flags from EXCMDLIST. */ -}; - -/* Global ranges. */ -typedef struct _range RANGE; -struct _range { - CIRCLEQ_ENTRY(_range) q; /* Linked list of ranges. */ - recno_t start, stop; /* Start/stop of the range. */ -}; - -/* Cd paths. */ -typedef struct _cdpath CDPATH; -struct _cdpath { - TAILQ_ENTRY(_cdpath) q; /* Linked list of cd paths. */ - char *path; /* Path. */ -}; - -/* Ex private, per-screen memory. */ -typedef struct _ex_private { - ARGS **args; /* Arguments. */ - int argscnt; /* Argument count. */ - int argsoff; /* Offset into arguments. */ - - CHAR_T at_lbuf; /* Last executed at buffer's name. */ - int at_lbuf_set; /* If at_lbuf is set. */ - - char *ibp; /* Line input buffer. */ - size_t ibp_len; /* Line input buffer length. */ - - u_int32_t fdef; /* Default command flags. */ - - CHAR_T *lastbcomm; /* Last bang command. */ - - struct termios leave_term; /* ex_[sr]leave tty state. */ - /* XXX: Should be struct timespec's, but time_t is more portable. */ - time_t leave_atime; /* ex_[sr]leave old access time. */ - time_t leave_mtime; /* ex_[sr]leave old mod time. */ - - TAILQ_HEAD(_tagh, _tag) tagq; /* Tag list (stack). */ - TAILQ_HEAD(_tagfh, _tagf) tagfq;/* Tag file list. */ - char *tlast; /* Saved last tag. */ - - TAILQ_HEAD(_cdh, _cdpath) cdq; /* Cd path list. */ - - /* Linked list of ranges. */ - CIRCLEQ_HEAD(_rangeh, _range) rangeq; - recno_t range_lno; /* Range set line number. */ - -#define EX_ABSMARK 0x01 /* Set the absolute mark. */ -#define EX_AUTOPRINT 0x02 /* Autoprint flag. */ - u_int8_t flags; -} EX_PRIVATE; -#define EXP(sp) ((EX_PRIVATE *)((sp)->ex_private)) - -/* - * !!! - * 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, ch) \ - (F_ISSET(sp, S_VLITONLY) ? \ - (ch) == CH_LITERAL : KEY_VAL(sp, ch) == K_VLNEXT) - -/* - * Filter actions: - * - * FILTER Filter text through the utility. - * FILTER_READ Read from the utility into the file. - * FILTER_WRITE Write to the utility, display its output. - */ -enum filtertype { FILTER, FILTER_READ, FILTER_WRITE }; -int filtercmd __P((SCR *, EXF *, - MARK *, MARK *, MARK *, char *, enum filtertype)); - -/* Argument expansion routines. */ -int argv_init __P((SCR *, EXF *, EXCMDARG *)); -int argv_exp0 __P((SCR *, EXF *, EXCMDARG *, char *, size_t)); -int argv_exp1 __P((SCR *, EXF *, EXCMDARG *, char *, size_t, int)); -int argv_exp2 __P((SCR *, EXF *, EXCMDARG *, char *, size_t, int)); -int argv_exp3 __P((SCR *, EXF *, EXCMDARG *, char *, size_t)); -int argv_free __P((SCR *)); - -/* Ex function prototypes. */ -int ex __P((SCR *, EXF *)); -int ex_cfile __P((SCR *, EXF *, char *, int)); -int ex_cmd __P((SCR *, EXF *, char *, size_t, int)); -int ex_cdalloc __P((SCR *, char *)); -int ex_cdfree __P((SCR *)); -int ex_end __P((SCR *)); -int ex_exec_proc __P((SCR *, char *, char *, char *)); -int ex_gb __P((SCR *, EXF *, TEXTH *, int, u_int)); -int ex_getline __P((SCR *, FILE *, size_t *)); -int ex_icmd __P((SCR *, EXF *, char *, size_t, int)); -int ex_init __P((SCR *, EXF *)); -int ex_is_abbrev __P((char *, size_t)); -int ex_is_unmap __P((char *, size_t)); -int ex_ldisplay __P((SCR *, CHAR_T *, size_t, size_t, u_int)); -int ex_ncheck __P((SCR *, int)); -int ex_optchange __P((SCR *, int)); -int ex_print __P((SCR *, EXF *, MARK *, MARK *, int)); -int ex_readfp __P((SCR *, EXF *, char *, FILE *, MARK *, recno_t *, int)); -void ex_refresh __P((SCR *, EXF *)); -void ex_rleave __P((SCR *)); -int ex_screen_copy __P((SCR *, SCR *)); -int ex_screen_end __P((SCR *)); -int ex_sdisplay __P((SCR *, EXF *)); -int ex_sleave __P((SCR *)); -int ex_suspend __P((SCR *)); -int ex_tdisplay __P((SCR *, EXF *)); -int ex_writefp __P((SCR *, EXF *, - char *, FILE *, MARK *, MARK *, u_long *, u_long *)); -void global_insdel __P((SCR *, EXF *, enum operation, recno_t)); -int proc_wait __P((SCR *, long, const char *, int)); -int sscr_end __P((SCR *)); -int sscr_exec __P((SCR *, EXF *, recno_t)); -int sscr_input __P((SCR *)); - -int abbr_save __P((SCR *, FILE *)); -int map_save __P((SCR *, FILE *)); - -#define EXPROTO(name) int name __P((SCR *, EXF *, EXCMDARG *)) -EXPROTO(ex_abbr); -EXPROTO(ex_append); -EXPROTO(ex_args); -EXPROTO(ex_at); -EXPROTO(ex_bang); -EXPROTO(ex_bg); -EXPROTO(ex_cd); -EXPROTO(ex_change); -EXPROTO(ex_color); -EXPROTO(ex_copy); -EXPROTO(ex_debug); -EXPROTO(ex_delete); -EXPROTO(ex_digraph); -EXPROTO(ex_display); -EXPROTO(ex_edit); -EXPROTO(ex_equal); -EXPROTO(ex_fg); -EXPROTO(ex_file); -EXPROTO(ex_global); -EXPROTO(ex_help); -EXPROTO(ex_insert); -EXPROTO(ex_join); -EXPROTO(ex_list); -EXPROTO(ex_map); -EXPROTO(ex_mark); -EXPROTO(ex_mkexrc); -EXPROTO(ex_move); -EXPROTO(ex_next); -EXPROTO(ex_number); -EXPROTO(ex_open); -EXPROTO(ex_pr); -EXPROTO(ex_preserve); -EXPROTO(ex_prev); -EXPROTO(ex_put); -EXPROTO(ex_quit); -EXPROTO(ex_read); -EXPROTO(ex_recover); -EXPROTO(ex_resize); -EXPROTO(ex_rew); -EXPROTO(ex_script); -EXPROTO(ex_set); -EXPROTO(ex_shell); -EXPROTO(ex_shiftl); -EXPROTO(ex_shiftr); -EXPROTO(ex_source); -EXPROTO(ex_split); -EXPROTO(ex_stop); -EXPROTO(ex_subagain); -EXPROTO(ex_substitute); -EXPROTO(ex_subtilde); -EXPROTO(ex_tagpop); -EXPROTO(ex_tagpush); -EXPROTO(ex_tagtop); -EXPROTO(ex_unabbr); -EXPROTO(ex_undo); -EXPROTO(ex_unmap); -EXPROTO(ex_usage); -EXPROTO(ex_validate); -EXPROTO(ex_version); -EXPROTO(ex_vglobal); -EXPROTO(ex_visual); -EXPROTO(ex_viusage); -EXPROTO(ex_wn); -EXPROTO(ex_wq); -EXPROTO(ex_write); -EXPROTO(ex_xit); -EXPROTO(ex_yank); -EXPROTO(ex_z); diff --git a/usr.bin/vi/ex/filter.c b/usr.bin/vi/ex/filter.c deleted file mode 100644 index abe7ca1..0000000 --- a/usr.bin/vi/ex/filter.c +++ /dev/null @@ -1,414 +0,0 @@ -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)filter.c 8.45 (Berkeley) 8/17/94"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> -#include <sys/wait.h> - -#include <bitstring.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "compat.h" -#include <db.h> -#include <regex.h> -#include <pathnames.h> - -#include "vi.h" -#include "excmd.h" - -static int filter_ldisplay __P((SCR *, FILE *)); - -/* - * filtercmd -- - * Run a range of lines through a filter utility and optionally - * replace the original text with the stdout/stderr output of - * the utility. - */ -int -filtercmd(sp, ep, fm, tm, rp, cmd, ftype) - SCR *sp; - EXF *ep; - 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, teardown; - char *name; - - /* Set return cursor position; guard against a line number of zero. */ - *rp = *fm; - if (fm->lno == 0) - rp->lno = 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]. - * - * In the FILTER_READ case, the utility isn't expected to want - * input. Redirect its input from /dev/null. Otherwise open - * up utility input pipe. - */ - teardown = 0; - ofp = NULL; - input[0] = input[1] = output[0] = output[1] = -1; - if (ftype == FILTER_READ) { - if ((input[0] = open(_PATH_DEVNULL, O_RDONLY, 0)) < 0) { - msgq(sp, M_ERR, - "filter: %s: %s", _PATH_DEVNULL, strerror(errno)); - return (1); - } - } else - if (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; - } - - /* - * Save ex/vi terminal settings, and restore the original ones. - * Restoration so that users can do things like ":r! cat /dev/tty". - */ - teardown = ftype != FILTER_WRITE && !ex_sleave(sp); - - /* Fork off the utility process. */ - SIGBLOCK(sp->gp); - switch (utility_pid = vfork()) { - case -1: /* Error. */ - SIGUNBLOCK(sp->gp); - - 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]); - rval = 1; - goto ret; - case 0: /* Utility. */ - /* The utility has default signal behavior. */ - sig_end(); - - /* - * 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 for both ex and vi for consistency. - */ - (void)dup2(input[0], STDIN_FILENO); - (void)dup2(output[1], STDOUT_FILENO); - (void)dup2(output[1], STDERR_FILENO); - - /* Close the utility's file descriptors. */ - (void)close(input[0]); - (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(sp, M_ERR, "Error: execl: %s: %s", - O_STR(sp, O_SHELL), strerror(errno)); - _exit (127); - /* NOTREACHED */ - default: /* Parent-reader, parent-writer. */ - SIGUNBLOCK(sp->gp); - - /* Close the pipe ends neither parent will use. */ - (void)close(input[0]); - (void)close(output[1]); - break; - } - - /* - * 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. - * - * !!! - * Set the return cursor to the last line read in. 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_READ) { - rval = ex_readfp(sp, ep, "filter", ofp, fm, &nread, 0); - sp->rptlines[L_ADDED] += nread; - if (fm->lno == 0) - rp->lno = nread; - else - rp->lno += nread; - goto uwait; - } - - /* - * FILTER, 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: - * 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:file_gline() code, based on the flag - * set here. - */ - rval = 0; - F_SET(ep, F_MULTILOCK); - - SIGBLOCK(sp->gp); - switch (parent_writer_pid = fork()) { - case -1: /* Error. */ - SIGUNBLOCK(sp->gp); - - 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, ep, "filter", ifp, fm, tm, NULL, NULL)); - - /* NOTREACHED */ - default: /* Parent-reader. */ - SIGUNBLOCK(sp->gp); - - (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. - */ - rval = filter_ldisplay(sp, ofp); - else { - /* - * Read the output from the read end of the output - * pipe. Ex_readfp appends to the MARK and closes - * ofp. - */ - rval = ex_readfp(sp, ep, "filter", ofp, tm, &nread, 0); - sp->rptlines[L_ADDED] += nread; - } - - /* Wait for the parent-writer. */ - rval |= proc_wait(sp, - (long)parent_writer_pid, "parent-writer", 1); - - /* Delete any lines written to the utility. */ - if (rval == 0 && ftype == FILTER && - (cut(sp, ep, NULL, fm, tm, CUT_LINEMODE) || - delete(sp, ep, 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 && file_gline(sp, ep, rp->lno, NULL) == NULL) - --rp->lno; - break; - } - F_CLR(ep, F_MULTILOCK); - -uwait: rval |= proc_wait(sp, (long)utility_pid, cmd, 0); - - /* Restore ex/vi terminal settings. */ -ret: if (teardown) - ex_rleave(sp); - return (rval); -} - -/* - * 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. - */ -int -proc_wait(sp, pid, cmd, okpipe) - SCR *sp; - long pid; - const char *cmd; - int okpipe; -{ - extern const char *const sys_siglist[]; - size_t len; - int pstat; - - /* - * Wait for the utility to finish. We can get interrupted - * by SIGALRM, just ignore it. - */ - for (;;) { - errno = 0; - if (waitpid((pid_t)pid, &pstat, 0) != -1) - break; - if (errno != EINTR) { - msgq(sp, M_SYSERR, "wait error"); - 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); - len = strlen(cmd); - msgq(sp, M_ERR, "%.*s%s: received signal: %s%s", - MIN(len, 20), cmd, len > 20 ? "..." : "", - sys_siglist[WTERMSIG(pstat)], - WCOREDUMP(pstat) ? "; core dumped" : ""); - return (1); - } - if (WIFEXITED(pstat) && WEXITSTATUS(pstat)) { - for (; isblank(*cmd); ++cmd); - len = strlen(cmd); - msgq(sp, M_ERR, "%.*s%s: exited with status %d", - MIN(len, 20), cmd, len > 20 ? "..." : "", - WEXITSTATUS(pstat)); - return (1); - } - return (0); -} - -/* - * 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; - - F_SET(sp, S_INTERRUPTIBLE); - for (exp = EXP(sp); !ex_getline(sp, fp, &len);) { - if (ex_ldisplay(sp, exp->ibp, len, 0, 0)) - break; - if (INTERRUPTED(sp)) - break; - } - if (ferror(fp)) - msgq(sp, M_SYSERR, "filter input"); - (void)fclose(fp); - return (0); -} diff --git a/usr.bin/vi/ex/script.h b/usr.bin/vi/ex/script.h deleted file mode 100644 index b21c63a..0000000 --- a/usr.bin/vi/ex/script.h +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)script.h 8.2 (Berkeley) 4/17/94 - */ - -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 */ - struct winsize sh_win; /* Window size. */ - struct termios sh_term; /* Terminal information. */ -}; diff --git a/usr.bin/vi/ex/tag.h b/usr.bin/vi/ex/tag.h deleted file mode 100644 index a9fd59d..0000000 --- a/usr.bin/vi/ex/tag.h +++ /dev/null @@ -1,58 +0,0 @@ -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tag.h 8.13 (Berkeley) 7/17/94 - */ - -struct _tagf { /* Tag file. */ - TAILQ_ENTRY(_tagf) q; /* Linked list of tag files. */ - char *name; /* Tag file name. */ - -#define TAGF_DNE 0x01 /* Didn't exist. */ -#define TAGF_DNE_WARN 0x02 /* DNE error reported. */ - u_int8_t flags; -}; - -struct _tag { /* Tag stack. */ - TAILQ_ENTRY(_tag) q; /* Linked list of tags. */ - FREF *frp; /* Saved file name. */ - recno_t lno; /* Saved line number. */ - size_t cno; /* Saved column number. */ - char *search; /* Search string. */ - size_t slen; /* Search string length. */ -}; - -int ex_tagalloc __P((SCR *, char *)); -int ex_tagcopy __P((SCR *, SCR *)); -int ex_tagdisplay __P((SCR *, EXF *)); -int ex_tagfirst __P((SCR *, char *)); -int ex_tagfree __P((SCR *)); |