This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.bin / vi / ex / ex.c
CommitLineData
395c4480
AM
1/*-
2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)ex.c 8.106 (Berkeley) 3/23/94";
36#endif /* not lint */
37
38#include <sys/types.h>
39#include <queue.h>
40#include <sys/stat.h>
41#include <sys/time.h>
42
43#include <bitstring.h>
44#include <ctype.h>
45#include <errno.h>
46#include <fcntl.h>
47#include <limits.h>
48#include <signal.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <termios.h>
53#include <unistd.h>
54
55#include <db.h>
56#include <regex.h>
57
58#include "vi.h"
59#include "excmd.h"
60
61static inline EXCMDLIST const *
62 ex_comm_search __P((char *, size_t));
63static int ep_line __P((SCR *, EXF *, MARK *, char **, size_t *, int *));
64static int ep_range __P((SCR *, EXF *, EXCMDARG *, char **, size_t *));
65
66#define DEFCOM ".+1"
67
68/*
69 * ex --
70 * Read an ex command and execute it.
71 */
72int
73ex(sp, ep)
74 SCR *sp;
75 EXF *ep;
76{
77 TEXT *tp;
78 u_int flags, saved_mode;
79 int eval;
80 char defcom[sizeof(DEFCOM)];
81
82 if (ex_init(sp, ep))
83 return (1);
84
85 if (sp->s_refresh(sp, ep))
86 return (ex_end(sp));
87
88 /* If reading from a file, messages should have line info. */
89 if (!F_ISSET(sp->gp, G_STDIN_TTY)) {
90 sp->if_lno = 1;
91 sp->if_name = strdup("input");
92 }
93
94 /*
95 * !!!
96 * Historically, the beautify option applies to ex command input read
97 * from a file. In addition, the first time a ^H was discarded from
98 * the input, a message "^H discarded" was displayed. We don't bother.
99 */
100 LF_INIT(TXT_CNTRLD | TXT_CR | TXT_PROMPT);
101 if (O_ISSET(sp, O_BEAUTIFY))
102 LF_SET(TXT_BEAUTIFY);
103
104 for (eval = 0;; ++sp->if_lno) {
105 /* Get the next command. */
106 switch (sp->s_get(sp, ep, &sp->tiq, ':', flags)) {
107 case INP_OK:
108 break;
109 case INP_EOF:
110 case INP_ERR:
111 F_SET(sp, S_EXIT_FORCE);
112 goto ret;
113 }
114
115 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
116 tp = sp->tiq.cqh_first;
117 if (tp->len == 0) {
118 if (F_ISSET(sp->gp, G_STDIN_TTY)) {
119 /* Special case \r command. */
120 (void)fputc('\r', stdout);
121 (void)fflush(stdout);
122 }
123 memmove(defcom, DEFCOM, sizeof(DEFCOM));
124 if (ex_icmd(sp, ep, defcom, sizeof(DEFCOM) - 1) &&
125 !F_ISSET(sp->gp, G_STDIN_TTY))
126 F_SET(sp, S_EXIT_FORCE);
127 } else {
128 if (F_ISSET(sp->gp, G_STDIN_TTY))
129 /* Special case ^D command. */
130 if (tp->len == 1 && tp->lb[0] == '\004') {
131 (void)fputc('\r', stdout);
132 (void)fflush(stdout);
133 } else
134 (void)fputc('\n', stdout);
135 if (ex_icmd(sp, ep, tp->lb, tp->len) &&
136 !F_ISSET(sp->gp, G_STDIN_TTY))
137 F_SET(sp, S_EXIT_FORCE);
138 }
139 (void)msg_rpt(sp, 0);
140 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
141 break;
142
143 if (sp->s_refresh(sp, ep)) {
144 eval = 1;
145 break;
146 }
147 }
148ret: if (sp->if_name != NULL) {
149 FREE(sp->if_name, strlen(sp->if_name) + 1);
150 sp->if_name = NULL;
151 }
152 return (ex_end(sp) || eval);
153}
154
155/*
156 * ex_cfile --
157 * Execute ex commands from a file.
158 */
159int
160ex_cfile(sp, ep, filename)
161 SCR *sp;
162 EXF *ep;
163 char *filename;
164{
165 struct stat sb;
166 int fd, len, rval;
167 char *bp;
168
169 bp = NULL;
170 if ((fd = open(filename, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
171 goto err;
172
173 /*
174 * XXX
175 * We'd like to test if the file is too big to malloc. Since we don't
176 * know what size or type off_t's or size_t's are, what the largest
177 * unsigned integral type is, or what random insanity the local C
178 * compiler will perpetrate, doing the comparison in a portable way
179 * is flatly impossible. Hope that malloc fails if the file is too
180 * large.
181 */
182 MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
183 if (bp == NULL)
184 goto err;
185
186 len = read(fd, bp, (int)sb.st_size);
187 if (len == -1 || len != sb.st_size) {
188 if (len != sb.st_size)
189 errno = EIO;
190err: rval = 1;
191 msgq(sp, M_SYSERR, filename);
192 } else {
193 bp[sb.st_size] = '\0'; /* XXX */
194
195 /*
196 * Run the command. Messages include file/line information,
197 * but we don't care if we can't get space.
198 */
199 sp->if_lno = 1;
200 sp->if_name = strdup(filename);
201 F_SET(sp, S_VLITONLY);
202 rval = ex_icmd(sp, ep, bp, len);
203 F_CLR(sp, S_VLITONLY);
204 free(sp->if_name);
205 sp->if_name = NULL;
206 }
207
208 /*
209 * !!!
210 * THE UNDERLYING EXF MAY HAVE CHANGED.
211 */
212 if (bp != NULL)
213 FREE(bp, sb.st_size);
214 if (fd >= 0)
215 (void)close(fd);
216 return (rval);
217}
218
219/*
220 * ex_icmd --
221 * Call ex_cmd() after turning off interruptible bits.
222 */
223int
224ex_icmd(sp, ep, cmd, len)
225 SCR *sp;
226 EXF *ep;
227 char *cmd;
228 size_t len;
229{
230 /*
231 * Ex goes through here for each vi :colon command and for each ex
232 * command, however, globally executed commands don't go through
233 * here, instead, they call ex_cmd directly. So, reset all of the
234 * interruptible flags now.
235 */
236 F_CLR(sp, S_INTERRUPTED | S_INTERRUPTIBLE);
237
238 return (ex_cmd(sp, ep, cmd, len));
239}
240
241/* Special command structure for :s as a repeat substitution command. */
242static EXCMDLIST const cmd_subagain =
243 {"s", ex_subagain, E_ADDR2|E_NORC,
244 "s",
245 "[line [,line]] s [cgr] [count] [#lp]",
246 "repeat the last subsitution"};
247
248/*
249 * ex_cmd --
250 * Parse and execute a string containing ex commands.
251 */
252int
253ex_cmd(sp, ep, cmd, cmdlen)
254 SCR *sp;
255 EXF *ep;
256 char *cmd;
257 size_t cmdlen;
258{
259 EX_PRIVATE *exp;
260 EXCMDARG exc;
261 EXCMDLIST const *cp;
262 MARK cur;
263 recno_t lno, num;
264 size_t arg1_len, len, save_cmdlen;
265 long flagoff;
266 u_int saved_mode;
267 int ch, cnt, delim, flags, namelen, nl, uselastcmd, tmp;
268 char *arg1, *save_cmd, *p, *t;
269
270 /* Init. */
271 nl = 0;
272loop: if (nl) {
273 nl = 0;
274 ++sp->if_lno;
275 }
276 arg1 = NULL;
277 save_cmdlen = 0;
278
279 /*
280 * It's possible that we've been interrupted during a
281 * command.
282 */
283 if (F_ISSET(sp, S_INTERRUPTED))
284 return (0);
285
286 /* Skip whitespace, separators, newlines. */
287 for (; cmdlen > 0; ++cmd, --cmdlen)
288 if ((ch = *cmd) == '\n')
289 ++sp->if_lno;
290 else if (!isblank(ch))
291 break;
292 if (cmdlen == 0)
293 return (0);
294
295 /* Command lines that start with a double-quote are comments. */
296 if (ch == '"') {
297 while (--cmdlen > 0 && *++cmd != '\n');
298 if (*cmd == '\n') {
299 ++cmd;
300 --cmdlen;
301 ++sp->if_lno;
302 }
303 goto loop;
304 }
305
306 /*
307 * !!!
308 * Permit extra colons at the start of the line. Historically,
309 * ex/vi allowed a single extra one. It's simpler not to count.
310 * The stripping is done here because, historically, any command
311 * could have preceding colons, e.g. ":g/pattern/:p" worked.
312 */
313 if (ch == ':')
314 while (--cmdlen > 0 && *++cmd == ':');
315
316 /* Skip whitespace. */
317 for (; cmdlen > 0; ++cmd, --cmdlen) {
318 ch = *cmd;
319 if (!isblank(ch))
320 break;
321 }
322
323 /* The last point at which an empty line means do nothing. */
324 if (cmdlen == 0)
325 return (0);
326
327 /* Initialize the structure passed to underlying functions. */
328 memset(&exc, 0, sizeof(EXCMDARG));
329 exp = EXP(sp);
330 if (argv_init(sp, ep, &exc))
331 goto err;
332
333 /* Parse command addresses. */
334 if (ep_range(sp, ep, &exc, &cmd, &cmdlen))
335 goto err;
336
337 /* Skip whitespace. */
338 for (; cmdlen > 0; ++cmd, --cmdlen) {
339 ch = *cmd;
340 if (!isblank(ch))
341 break;
342 }
343
344 /*
345 * If no command, ex does the last specified of p, l, or #, and vi
346 * moves to the line. Otherwise, determine the length of the command
347 * name by looking for the first non-alphabetic character. (There
348 * are a few non-alphabetic characters in command names, but they're
349 * all single character commands.) This isn't a great test, because
350 * it means that, for the command ":e +cut.c file", we'll report that
351 * the command "cut" wasn't known. However, it makes ":e+35 file" work
352 * correctly.
353 */
354#define SINGLE_CHAR_COMMANDS "\004!#&<=>@~"
355 if (cmdlen != 0 && cmd[0] != '|' && cmd[0] != '\n') {
356 if (strchr(SINGLE_CHAR_COMMANDS, *cmd)) {
357 p = cmd;
358 ++cmd;
359 --cmdlen;
360 namelen = 1;
361 } else {
362 for (p = cmd; cmdlen > 0; --cmdlen, ++cmd)
363 if (!isalpha(*cmd))
364 break;
365 if ((namelen = cmd - p) == 0) {
366 msgq(sp, M_ERR, "Unknown command name.");
367 goto err;
368 }
369 }
370
371 /*
372 * Search the table for the command.
373 *
374 * !!!
375 * Historic vi permitted the mark to immediately follow the
376 * 'k' in the 'k' command. Make it work.
377 *
378 * !!!
379 * Historic vi permitted pretty much anything to follow the
380 * substitute command, e.g. "s/e/E/|s|sgc3p" was fine. Make
381 * it work.
382 */
383 if ((cp = ex_comm_search(p, namelen)) == NULL)
384 if (p[0] == 'k' && p[1] && !p[2]) {
385 cmd -= namelen - 1;
386 cmdlen += namelen - 1;
387 cp = &cmds[C_K];
388 } else if (p[0] == 's') {
389 cmd -= namelen - 1;
390 cmdlen += namelen - 1;
391 cp = &cmd_subagain;
392 } else {
393 msgq(sp, M_ERR,
394 "The %.*s command is unknown.", namelen, p);
395 goto err;
396 }
397
398 /* Some commands are either not implemented or turned off. */
399 if (F_ISSET(cp, E_NOPERM)) {
400 msgq(sp, M_ERR,
401 "The %s command is not currently supported.",
402 cp->name);
403 goto err;
404 }
405
406 /* Some commands aren't okay in globals. */
407 if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) {
408 msgq(sp, M_ERR,
409 "The %s command can't be used as part of a global command.",
410 cp->name);
411 goto err;
412 }
413
414 /*
415 * Multiple < and > characters; another "feature". Note,
416 * The string passed to the underlying function may not be
417 * nul terminated in this case.
418 */
419 if ((cp == &cmds[C_SHIFTL] && *p == '<') ||
420 (cp == &cmds[C_SHIFTR] && *p == '>')) {
421 for (ch = *p; cmdlen > 0; --cmdlen, ++cmd)
422 if (*cmd != ch)
423 break;
424 if (argv_exp0(sp, ep, &exc, p, cmd - p))
425 goto err;
426 }
427
428 /*
429 * The visual command has a different syntax when called
430 * from ex than when called from a vi colon command. FMH.
431 */
432 if (cp == &cmds[C_VISUAL_EX] && IN_VI_MODE(sp))
433 cp = &cmds[C_VISUAL_VI];
434
435 uselastcmd = 0;
436 } else {
437 cp = exp->lastcmd;
438 uselastcmd = 1;
439 }
440
441 /* Initialize local flags to the command flags. */
442 LF_INIT(cp->flags);
443
444 /*
445 * File state must be checked throughout this code, because it is
446 * called when reading the .exrc file and similar things. There's
447 * this little chicken and egg problem -- if we read the file first,
448 * we won't know how to display it. If we read/set the exrc stuff
449 * first, we can't allow any command that requires file state. We
450 * don't have a "reading an rc" bit, because we want the commands
451 * to work when the user source's the rc file later. Historic vi
452 * generally took the easy way out and dropped core.
453 */
454 if (LF_ISSET(E_NORC) && ep == NULL) {
455 msgq(sp, M_ERR,
456 "The %s command requires that a file have already been read in.",
457 cp->name);
458 goto err;
459 }
460
461 /*
462 * There are three normal termination cases for an ex command. They
463 * are the end of the string (cmdlen), or unescaped (by literal next
464 * characters) newline or '|' characters. As we're past any addresses,
465 * we can now determine how long the command is, so we don't have to
466 * look for all the possible terminations. There are three exciting
467 * special cases:
468 *
469 * 1: The bang, global, vglobal and the filter versions of the read and
470 * write commands are delimited by newlines (they can contain shell
471 * pipes).
472 * 2: The ex, edit and visual in vi mode commands take ex commands as
473 * their first arguments.
474 * 3: The substitute command takes an RE as its first argument, and
475 * wants it to be specially delimited.
476 *
477 * Historically, '|' characters in the first argument of the ex, edit,
478 * and substitute commands did not delimit the command. And, in the
479 * filter cases for read and write, and the bang, global and vglobal
480 * commands, they did not delimit the command at all.
481 *
482 * For example, the following commands were legal:
483 *
484 * :edit +25|s/abc/ABC/ file.c
485 * :substitute s/|/PIPE/
486 * :read !spell % | columnate
487 * :global/pattern/p|l
488 *
489 * It's not quite as simple as it sounds, however. The command:
490 *
491 * :substitute s/a/b/|s/c/d|set
492 *
493 * was also legal, i.e. the historic ex parser (using the word loosely,
494 * since "parser" implies some regularity) delimited the RE's based on
495 * its delimiter and not anything so irretrievably vulgar as a command
496 * syntax.
497 *
498 * One thing that makes this easier is that we can ignore most of the
499 * command termination conditions for the commands that want to take
500 * the command up to the next newline. None of them are legal in .exrc
501 * files, so if we're here, we only dealing with a single line, and we
502 * can just eat it.
503 *
504 * Anyhow, the following code makes this all work. First, for the
505 * special cases we move past their special argument. Then, we do
506 * normal command processing on whatever is left. Barf-O-Rama.
507 */
508 arg1_len = 0;
509 save_cmd = cmd;
510 if (cp == &cmds[C_EDIT] ||
511 cp == &cmds[C_EX] || cp == &cmds[C_VISUAL_VI]) {
512 /*
513 * Move to the next non-whitespace character. As '+' must
514 * be the character after the command name, if there isn't
515 * one, we're done.
516 */
517 for (; cmdlen > 0; --cmdlen, ++cmd) {
518 ch = *cmd;
519 if (!isblank(ch))
520 break;
521 }
522 /*
523 * QUOTING NOTE:
524 *
525 * The historic implementation ignored all escape characters
526 * so there was no way to put a space or newline into the +cmd
527 * field. We do a simplistic job of fixing it by moving to the
528 * first whitespace character that isn't escaped by a literal
529 * next character. The literal next characters are stripped
530 * as they're no longer useful.
531 */
532 if (cmdlen > 0 && ch == '+') {
533 ++cmd;
534 --cmdlen;
535 for (arg1 = p = cmd; cmdlen > 0; --cmdlen, ++cmd) {
536 ch = *cmd;
537 if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
538 --cmdlen;
539 ch = *++cmd;
540 } else if (isblank(ch))
541 break;
542 *p++ = ch;
543 }
544 arg1_len = cmd - arg1;
545
546 /* Reset, so the first argument isn't reparsed. */
547 save_cmd = cmd;
548 }
549 } else if (cp == &cmds[C_BANG] ||
550 cp == &cmds[C_GLOBAL] || cp == &cmds[C_VGLOBAL]) {
551 cmd += cmdlen;
552 cmdlen = 0;
553 } else if (cp == &cmds[C_READ] || cp == &cmds[C_WRITE]) {
554 /*
555 * Move to the next character. If it's a '!', it's a filter
556 * command and we want to eat it all, otherwise, we're done.
557 */
558 for (; cmdlen > 0; --cmdlen, ++cmd) {
559 ch = *cmd;
560 if (!isblank(ch))
561 break;
562 }
563 if (cmdlen > 0 && ch == '!') {
564 cmd += cmdlen;
565 cmdlen = 0;
566 }
567 } else if (cp == &cmds[C_SUBSTITUTE]) {
568 /*
569 * Move to the next non-whitespace character, we'll use it as
570 * the delimiter. If the character isn't an alphanumeric or
571 * a '|', it's the delimiter, so parse it. Otherwise, we're
572 * into something like ":s g", so use the special substitute
573 * command.
574 */
575 for (; cmdlen > 0; --cmdlen, ++cmd)
576 if (!isblank(cmd[0]))
577 break;
578
579 if (isalnum(cmd[0]) || cmd[0] == '|')
580 cp = &cmd_subagain;
581 else if (cmdlen > 0) {
582 /*
583 * QUOTING NOTE:
584 *
585 * Backslashes quote delimiter characters for RE's.
586 * The backslashes are NOT removed since they'll be
587 * used by the RE code. Move to the third delimiter
588 * that's not escaped (or the end of the command).
589 */
590 delim = *cmd;
591 ++cmd;
592 --cmdlen;
593 for (cnt = 2; cmdlen > 0 && cnt; --cmdlen, ++cmd)
594 if (cmd[0] == '\\' && cmdlen > 1) {
595 ++cmd;
596 --cmdlen;
597 } else if (cmd[0] == delim)
598 --cnt;
599 }
600 }
601 /*
602 * Use normal quoting and termination rules to find the end
603 * of this command.
604 *
605 * QUOTING NOTE:
606 *
607 * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
608 * file. It was almost certainly a bug, but that's what bug-for-bug
609 * compatibility means, Grasshopper. Also, ^V's escape the command
610 * delimiters. Literal next quote characters in front of the newlines,
611 * '|' characters or literal next characters are stripped as as they're
612 * no longer useful.
613 */
614 for (p = cmd, cnt = 0; cmdlen > 0; --cmdlen, ++cmd) {
615 ch = cmd[0];
616 if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
617 tmp = cmd[1];
618 if (tmp == '\n' || tmp == '|') {
619 if (tmp == '\n')
620 ++sp->if_lno;
621 --cmdlen;
622 ++cmd;
623 ++cnt;
624 ch = tmp;
625 }
626 } else if (ch == '\n' || ch == '|') {
627 if (ch == '\n')
628 nl = 1;
629 --cmdlen;
630 break;
631 }
632 *p++ = ch;
633 }
634
635 /*
636 * Save off the next command information, go back to the
637 * original start of the command.
638 */
639 p = cmd + 1;
640 cmd = save_cmd;
641 save_cmd = p;
642 save_cmdlen = cmdlen;
643 cmdlen = ((save_cmd - cmd) - 1) - cnt;
644
645 /*
646 * !!!
647 * The "set tags" command historically used a backslash, not the
648 * user's literal next character, to escape whitespace. Handle
649 * it here instead of complicating the argv_exp3() code. Note,
650 * this isn't a particularly complex trap, and if backslashes were
651 * legal in set commands, this would have to be much more complicated.
652 */
653 if (cp == &cmds[C_SET])
654 for (p = cmd, len = cmdlen; len > 0; --len, ++p)
655 if (*p == '\\')
656 *p = LITERAL_CH;
657
658 /*
659 * Set the default addresses. It's an error to specify an address for
660 * a command that doesn't take them. If two addresses are specified
661 * for a command that only takes one, lose the first one. Two special
662 * cases here, some commands take 0 or 2 addresses. For most of them
663 * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
664 * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
665 *
666 * Also, if the file is empty, some commands want to use an address of
667 * 0, i.e. the entire file is 0 to 0, and the default first address is
668 * 0. Otherwise, an entire file is 1 to N and the default line is 1.
669 * Note, we also add the E_ZERO flag to the command flags, for the case
670 * where the 0 address is only valid if it's a default address.
671 *
672 * Also, set a flag if we set the default addresses. Some commands
673 * (ex: z) care if the user specified an address of if we just used
674 * the current cursor.
675 */
676 switch (LF_ISSET(E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) {
677 case E_ADDR1: /* One address: */
678 switch (exc.addrcnt) {
679 case 0: /* Default cursor/empty file. */
680 exc.addrcnt = 1;
681 F_SET(&exc, E_ADDRDEF);
682 if (LF_ISSET(E_ZERODEF)) {
683 if (file_lline(sp, ep, &lno))
684 goto err;
685 if (lno == 0) {
686 exc.addr1.lno = 0;
687 LF_SET(E_ZERO);
688 } else
689 exc.addr1.lno = sp->lno;
690 } else
691 exc.addr1.lno = sp->lno;
692 exc.addr1.cno = sp->cno;
693 break;
694 case 1:
695 break;
696 case 2: /* Lose the first address. */
697 exc.addrcnt = 1;
698 exc.addr1 = exc.addr2;
699 }
700 break;
701 case E_ADDR2_NONE: /* Zero/two addresses: */
702 if (exc.addrcnt == 0) /* Default to nothing. */
703 break;
704 goto two;
705 case E_ADDR2_ALL: /* Zero/two addresses: */
706 if (exc.addrcnt == 0) { /* Default entire/empty file. */
707 exc.addrcnt = 2;
708 F_SET(&exc, E_ADDRDEF);
709 if (file_lline(sp, ep, &exc.addr2.lno))
710 goto err;
711 if (LF_ISSET(E_ZERODEF) && exc.addr2.lno == 0) {
712 exc.addr1.lno = 0;
713 LF_SET(E_ZERO);
714 } else
715 exc.addr1.lno = 1;
716 exc.addr1.cno = exc.addr2.cno = 0;
717 F_SET(&exc, E_ADDR2_ALL);
718 break;
719 }
720 /* FALLTHROUGH */
721 case E_ADDR2: /* Two addresses: */
722two: switch (exc.addrcnt) {
723 case 0: /* Default cursor/empty file. */
724 exc.addrcnt = 2;
725 F_SET(&exc, E_ADDRDEF);
726 if (LF_ISSET(E_ZERODEF) && sp->lno == 1) {
727 if (file_lline(sp, ep, &lno))
728 goto err;
729 if (lno == 0) {
730 exc.addr1.lno = exc.addr2.lno = 0;
731 LF_SET(E_ZERO);
732 } else
733 exc.addr1.lno = exc.addr2.lno = sp->lno;
734 } else
735 exc.addr1.lno = exc.addr2.lno = sp->lno;
736 exc.addr1.cno = exc.addr2.cno = sp->cno;
737 break;
738 case 1: /* Default to first address. */
739 exc.addrcnt = 2;
740 exc.addr2 = exc.addr1;
741 break;
742 case 2:
743 break;
744 }
745 break;
746 default:
747 if (exc.addrcnt) /* Error. */
748 goto usage;
749 }
750
751 /*
752 * !!!
753 * The ^D scroll command historically scrolled half the screen size
754 * rows down, rounded down, or to EOF. It was an error if the cursor
755 * was already at EOF. (Leading addresses were permitted, but were
756 * then ignored.)
757 */
758 if (cp == &cmds[C_SCROLL]) {
759 exc.addrcnt = 2;
760 exc.addr1.lno = sp->lno + 1;
761 exc.addr2.lno = sp->lno + 1 + (O_VAL(sp, O_LINES) + 1) / 2;
762 exc.addr1.cno = exc.addr2.cno = sp->cno;
763 if (file_lline(sp, ep, &lno))
764 goto err;
765 if (lno != 0 && lno > sp->lno && exc.addr2.lno > lno)
766 exc.addr2.lno = lno;
767 }
768
769 flagoff = 0;
770 for (p = cp->syntax; *p != '\0'; ++p) {
771 /*
772 * The write command is sensitive to leading whitespace, e.g.
773 * "write !" is different from "write!". If not the write
774 * command, skip leading whitespace.
775 */
776 if (cp != &cmds[C_WRITE])
777 for (; cmdlen > 0; --cmdlen, ++cmd) {
778 ch = *cmd;
779 if (!isblank(ch))
780 break;
781 }
782
783 /*
784 * Quit when reach the end of the command, unless it's a
785 * command that does its own parsing, in which case we want
786 * to build a reasonable argv for it. This code guarantees
787 * that there will be an argv when the function gets called,
788 * so the correct test is for a length of 0, not for the
789 * argc > 0.
790 */
791 if (cmdlen == 0 && *p != '!' && *p != 'S' && *p != 's')
792 break;
793
794 switch (*p) {
795 case '!': /* ! */
796 if (*cmd == '!') {
797 ++cmd;
798 --cmdlen;
799 F_SET(&exc, E_FORCE);
800 }
801 break;
802 case '1': /* +, -, #, l, p */
803 /*
804 * !!!
805 * Historically, some flags were ignored depending
806 * on where they occurred in the command line. For
807 * example, in the command, ":3+++p--#", historic vi
808 * acted on the '#' flag, but ignored the '-' flags.
809 * It's unambiguous what the flags mean, so we just
810 * handle them regardless of the stupidity of their
811 * location.
812 */
813 for (; cmdlen; --cmdlen, ++cmd)
814 switch (*cmd) {
815 case '+':
816 ++flagoff;
817 break;
818 case '-':
819 --flagoff;
820 break;
821 case '#':
822 F_SET(&exc, E_F_HASH);
823 break;
824 case 'l':
825 F_SET(&exc, E_F_LIST);
826 break;
827 case 'p':
828 F_SET(&exc, E_F_PRINT);
829 break;
830 default:
831 goto end1;
832 }
833end1: break;
834 case '2': /* -, ., +, ^ */
835 case '3': /* -, ., +, ^, = */
836 for (; cmdlen; --cmdlen, ++cmd)
837 switch (*cmd) {
838 case '-':
839 F_SET(&exc, E_F_DASH);
840 break;
841 case '.':
842 F_SET(&exc, E_F_DOT);
843 break;
844 case '+':
845 F_SET(&exc, E_F_PLUS);
846 break;
847 case '^':
848 F_SET(&exc, E_F_CARAT);
849 break;
850 case '=':
851 if (*p == '3') {
852 F_SET(&exc, E_F_EQUAL);
853 break;
854 }
855 /* FALLTHROUGH */
856 default:
857 goto end2;
858 }
859end2: break;
860 case 'b': /* buffer */
861 /*
862 * Digits can't be buffer names in ex commands, or the
863 * command "d2" would be a delete into buffer '2', and
864 * not a two-line deletion.
865 */
866 if (!isdigit(cmd[0])) {
867 exc.buffer = *cmd;
868 ++cmd;
869 --cmdlen;
870 F_SET(&exc, E_BUFFER);
871 }
872 break;
873 case 'c': /* count [01+a] */
874 ++p;
875 /* Validate any signed value. */
876 if (!isdigit(*cmd) &&
877 (*p != '+' || (*cmd != '+' && *cmd != '-')))
878 break;
879 /* If a signed value, set appropriate flags. */
880 if (*cmd == '-')
881 F_SET(&exc, E_COUNT_NEG);
882 else if (*cmd == '+')
883 F_SET(&exc, E_COUNT_POS);
884/* 8-bit XXX */ if ((lno = strtol(cmd, &t, 10)) == 0 && *p != '0') {
885 msgq(sp, M_ERR, "Count may not be zero.");
886 goto err;
887 }
888 cmdlen -= (t - cmd);
889 cmd = t;
890 /*
891 * Count as address offsets occur in commands taking
892 * two addresses. Historic vi practice was to use
893 * the count as an offset from the *second* address.
894 *
895 * Set a count flag; some underlying commands (see
896 * join) do different things with counts than with
897 * line addresses.
898 */
899 if (*p == 'a') {
900 exc.addr1 = exc.addr2;
901 exc.addr2.lno = exc.addr1.lno + lno - 1;
902 } else
903 exc.count = lno;
904 F_SET(&exc, E_COUNT);
905 break;
906 case 'f': /* file */
907 if (argv_exp2(sp, ep,
908 &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
909 goto err;
910 goto countchk;
911 case 'l': /* line */
912 if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
913 goto err;
914 /* Line specifications are always required. */
915 if (!tmp) {
916 msgq(sp, M_ERR,
917 "%s: bad line specification", cmd);
918 goto err;
919 }
920 exc.lineno = cur.lno;
921 break;
922 case 'S': /* string, file exp. */
923 if (argv_exp1(sp, ep,
924 &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
925 goto err;
926 goto addr2;
927 case 's': /* string */
928 if (argv_exp0(sp, ep, &exc, cmd, cmdlen))
929 goto err;
930 goto addr2;
931 case 'W': /* word string */
932 /*
933 * QUOTING NOTE:
934 *
935 * Literal next characters escape the following
936 * character. Quoting characters are stripped
937 * here since they are no longer useful.
938 *
939 * First there was the word.
940 */
941 for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd) {
942 ch = *cmd;
943 if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
944 --cmdlen;
945 *p++ = *++cmd;
946 } else if (isblank(ch)) {
947 ++cmd;
948 --cmdlen;
949 break;
950 } else
951 *p++ = ch;
952 }
953 if (argv_exp0(sp, ep, &exc, t, p - t))
954 goto err;
955
956 /* Delete intervening whitespace. */
957 for (; cmdlen > 0; --cmdlen, ++cmd) {
958 ch = *cmd;
959 if (!isblank(ch))
960 break;
961 }
962 if (cmdlen == 0)
963 goto usage;
964
965 /* Followed by the string. */
966 for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd, ++p) {
967 ch = *cmd;
968 if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
969 --cmdlen;
970 *p = *++cmd;
971 } else
972 *p = ch;
973 }
974 if (argv_exp0(sp, ep, &exc, t, p - t))
975 goto err;
976 goto addr2;
977 case 'w': /* word */
978 if (argv_exp3(sp, ep, &exc, cmd, cmdlen))
979 goto err;
980countchk: if (*++p != 'N') { /* N */
981 /*
982 * If a number is specified, must either be
983 * 0 or that number, if optional, and that
984 * number, if required.
985 */
986 num = *p - '0';
987 if ((*++p != 'o' || exp->argsoff != 0) &&
988 exp->argsoff != num)
989 goto usage;
990 }
991 goto addr2;
992 default:
993 msgq(sp, M_ERR,
994 "Internal syntax table error (%s: %c).",
995 cp->name, *p);
996 }
997 }
998
999 /* Skip trailing whitespace. */
1000 for (; cmdlen; --cmdlen) {
1001 ch = *cmd++;
1002 if (!isblank(ch))
1003 break;
1004 }
1005
1006 /*
1007 * There shouldn't be anything left, and no more required
1008 * fields, i.e neither 'l' or 'r' in the syntax string.
1009 */
1010 if (cmdlen || strpbrk(p, "lr")) {
1011usage: msgq(sp, M_ERR, "Usage: %s.", cp->usage);
1012 goto err;
1013 }
1014
1015 /* Verify that the addresses are legal. */
1016addr2: switch (exc.addrcnt) {
1017 case 2:
1018 if (file_lline(sp, ep, &lno))
1019 goto err;
1020 /*
1021 * Historic ex/vi permitted commands with counts to go past
1022 * EOF. So, for example, if the file only had 5 lines, the
1023 * ex command "1,6>" would fail, but the command ">300"
1024 * would succeed. Since we don't want to have to make all
1025 * of the underlying commands handle random line numbers,
1026 * fix it here.
1027 */
1028 if (exc.addr2.lno > lno)
1029 if (F_ISSET(&exc, E_COUNT))
1030 exc.addr2.lno = lno;
1031 else {
1032 if (lno == 0)
1033 msgq(sp, M_ERR, "The file is empty.");
1034 else
1035 msgq(sp, M_ERR,
1036 "Only %lu line%s in the file",
1037 lno, lno > 1 ? "s" : "");
1038 goto err;
1039 }
1040 /* FALLTHROUGH */
1041 case 1:
1042 num = exc.addr1.lno;
1043 /*
1044 * If it's a "default vi command", zero is okay. Historic
1045 * vi allowed this, note, it's also the hack that allows
1046 * "vi + nonexistent_file" to work.
1047 */
1048 if (num == 0 && (!IN_VI_MODE(sp) || uselastcmd != 1) &&
1049 !LF_ISSET(E_ZERO)) {
1050 msgq(sp, M_ERR,
1051 "The %s command doesn't permit an address of 0.",
1052 cp->name);
1053 goto err;
1054 }
1055 if (file_lline(sp, ep, &lno))
1056 goto err;
1057 if (num > lno) {
1058 if (lno == 0)
1059 msgq(sp, M_ERR, "The file is empty.");
1060 else
1061 msgq(sp, M_ERR, "Only %lu line%s in the file",
1062 lno, lno > 1 ? "s" : "");
1063 goto err;
1064 }
1065 break;
1066 }
1067
1068 /* If doing a default command, vi just moves to the line. */
1069 if (IN_VI_MODE(sp) && uselastcmd) {
1070 switch (exc.addrcnt) {
1071 case 2:
1072 sp->lno = exc.addr2.lno ? exc.addr2.lno : 1;
1073 sp->cno = exc.addr2.cno;
1074 break;
1075 case 1:
1076 sp->lno = exc.addr1.lno ? exc.addr1.lno : 1;
1077 sp->cno = exc.addr1.cno;
1078 break;
1079 }
1080 cmd = save_cmd;
1081 cmdlen = save_cmdlen;
1082 goto loop;
1083 }
1084
1085 /* Reset "last" command. */
1086 if (LF_ISSET(E_SETLAST))
1087 exp->lastcmd = cp;
1088
1089 /* Final setup for the command. */
1090 exc.cmd = cp;
1091
1092#if defined(DEBUG) && 0
1093 TRACE(sp, "ex_cmd: %s", exc.cmd->name);
1094 if (exc.addrcnt > 0) {
1095 TRACE(sp, "\taddr1 %d", exc.addr1.lno);
1096 if (exc.addrcnt > 1)
1097 TRACE(sp, " addr2: %d", exc.addr2.lno);
1098 TRACE(sp, "\n");
1099 }
1100 if (exc.lineno)
1101 TRACE(sp, "\tlineno %d", exc.lineno);
1102 if (exc.flags)
1103 TRACE(sp, "\tflags %0x", exc.flags);
1104 if (F_ISSET(&exc, E_BUFFER))
1105 TRACE(sp, "\tbuffer %c", exc.buffer);
1106 TRACE(sp, "\n");
1107 if (exc.argc) {
1108 for (cnt = 0; cnt < exc.argc; ++cnt)
1109 TRACE(sp, "\targ %d: {%s}", cnt, exc.argv[cnt]);
1110 TRACE(sp, "\n");
1111 }
1112#endif
1113 /* Clear autoprint flag. */
1114 F_CLR(exp, EX_AUTOPRINT);
1115
1116 /* Increment the command count if not called from vi. */
1117 if (!IN_VI_MODE(sp))
1118 ++sp->ccnt;
1119
1120 /*
1121 * If file state and not doing a global command, log the start of
1122 * an action.
1123 */
1124 if (ep != NULL && !F_ISSET(sp, S_GLOBAL))
1125 (void)log_cursor(sp, ep);
1126
1127 /* Save the current mode. */
1128 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
1129
1130 /* Do the command. */
1131 if ((cp->fn)(sp, ep, &exc))
1132 goto err;
1133
1134#ifdef DEBUG
1135 /* Make sure no function left the temporary space locked. */
1136 if (F_ISSET(sp->gp, G_TMP_INUSE)) {
1137 F_CLR(sp->gp, G_TMP_INUSE);
1138 msgq(sp, M_ERR, "Error: ex: temporary buffer not released.");
1139 goto err;
1140 }
1141#endif
1142 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE)) {
1143 /*
1144 * Only here if the mode of the underlying file changed, e.g.
1145 * the user switched files or is exiting. There are two things
1146 * that we might have to save. First, any "+cmd" field set up
1147 * for an ex/edit command will have to be saved for later, also,
1148 * any not yet executed part of the current ex command.
1149 *
1150 * :edit +25 file.c|s/abc/ABC/|1
1151 *
1152 * for example.
1153 *
1154 * The historic vi just hung, of course; we handle by
1155 * pushing the keys onto the tty queue. If we're
1156 * switching modes to vi, since the commands are intended
1157 * as ex commands, add the extra characters to make it
1158 * work.
1159 *
1160 * For the fun of it, if you want to see if a vi clone got
1161 * the ex argument parsing right, try:
1162 *
1163 * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
1164 * vi
1165 * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
1166 */
1167 if (arg1_len == NULL && save_cmdlen == 0)
1168 return (0);
1169 if (IN_VI_MODE(sp) && term_push(sp, "\n", 1, 0, 0))
1170 goto err;
1171 if (save_cmdlen != 0)
1172 if (term_push(sp, save_cmd, save_cmdlen, 0, 0))
1173 goto err;
1174 if (arg1 != NULL) {
1175 if (IN_VI_MODE(sp) && save_cmdlen != 0 &&
1176 term_push(sp, "|", 1, 0, 0))
1177 goto err;
1178 if (term_push(sp, arg1, arg1_len, 0, 0))
1179 goto err;
1180 }
1181 if (IN_VI_MODE(sp) && term_push(sp, ":", 1, 0, 0))
1182 goto err;
1183 return (0);
1184 }
1185
1186 if (IN_EX_MODE(sp) && ep != NULL) {
1187 /*
1188 * The print commands have already handled the `print' flags.
1189 * If so, clear them. Don't return, autoprint may still have
1190 * stuff to print out.
1191 */
1192 if (LF_ISSET(E_F_PRCLEAR))
1193 F_CLR(&exc, E_F_HASH | E_F_LIST | E_F_PRINT);
1194
1195 /*
1196 * If the command was successful, and there was an explicit
1197 * flag to display the new cursor line, or we're in ex mode,
1198 * autoprint is set, and a change was made, display the line.
1199 */
1200 if (flagoff) {
1201 if (flagoff < 0) {
1202 if (sp->lno < -flagoff) {
1203 msgq(sp, M_ERR,
1204 "Flag offset before line 1.");
1205 goto err;
1206 }
1207 } else {
1208 if (file_lline(sp, ep, &lno))
1209 goto err;
1210 if (sp->lno + flagoff > lno) {
1211 msgq(sp, M_ERR,
1212 "Flag offset past end-of-file.");
1213 goto err;
1214 }
1215 }
1216 sp->lno += flagoff;
1217 }
1218
1219 if (O_ISSET(sp, O_AUTOPRINT) &&
1220 (F_ISSET(exp, EX_AUTOPRINT) || F_ISSET(cp, E_AUTOPRINT)))
1221 LF_INIT(E_F_PRINT);
1222 else
1223 LF_INIT(F_ISSET(&exc, E_F_HASH | E_F_LIST | E_F_PRINT));
1224
1225 memset(&exc, 0, sizeof(EXCMDARG));
1226 exc.addrcnt = 2;
1227 exc.addr1.lno = exc.addr2.lno = sp->lno;
1228 exc.addr1.cno = exc.addr2.cno = sp->cno;
1229 switch (LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT)) {
1230 case E_F_HASH:
1231 exc.cmd = &cmds[C_HASH];
1232 ex_number(sp, ep, &exc);
1233 break;
1234 case E_F_LIST:
1235 exc.cmd = &cmds[C_LIST];
1236 ex_list(sp, ep, &exc);
1237 break;
1238 case E_F_PRINT:
1239 exc.cmd = &cmds[C_PRINT];
1240 ex_pr(sp, ep, &exc);
1241 break;
1242 }
1243 }
1244
1245 cmd = save_cmd;
1246 cmdlen = save_cmdlen;
1247 goto loop;
1248 /* NOTREACHED */
1249
1250 /*
1251 * On error, we discard any keys we have left, as well as any keys
1252 * that were mapped. The test of save_cmdlen isn't necessarily
1253 * correct. If we fail early enough we don't know if the entire
1254 * string was a single command or not. Try and guess, it's useful
1255 * to know if part of the command was discarded.
1256 */
1257err: if (save_cmdlen == 0)
1258 for (; cmdlen; --cmdlen) {
1259 ch = *cmd++;
1260 if (IS_ESCAPE(sp, ch) && cmdlen > 1) {
1261 --cmdlen;
1262 ++cmd;
1263 } else if (ch == '\n' || ch == '|') {
1264 if (cmdlen > 1)
1265 save_cmdlen = 1;
1266 break;
1267 }
1268 }
1269 if (save_cmdlen != 0)
1270 msgq(sp, M_ERR,
1271 "Ex command failed: remaining command input discarded.");
1272 term_map_flush(sp, "Ex command failed");
1273 return (1);
1274}
1275
1276/*
1277 * ep_range --
1278 * Get a line range for ex commands.
1279 */
1280static int
1281ep_range(sp, ep, excp, cmdp, cmdlenp)
1282 SCR *sp;
1283 EXF *ep;
1284 EXCMDARG *excp;
1285 char **cmdp;
1286 size_t *cmdlenp;
1287{
1288 MARK cur, savecursor;
1289 size_t cmdlen;
1290 int savecursor_set, tmp;
1291 char *cmd;
1292
1293 /* Percent character is all lines in the file. */
1294 cmd = *cmdp;
1295 cmdlen = *cmdlenp;
1296 if (*cmd == '%') {
1297 excp->addr1.lno = 1;
1298 if (file_lline(sp, ep, &excp->addr2.lno))
1299 return (1);
1300
1301 /* If an empty file, then the first line is 0, not 1. */
1302 if (excp->addr2.lno == 0)
1303 excp->addr1.lno = 0;
1304 excp->addr1.cno = excp->addr2.cno = 0;
1305 excp->addrcnt = 2;
1306
1307 ++*cmdp;
1308 --*cmdlenp;
1309 return (0);
1310 }
1311
1312 /* Parse comma or semi-colon delimited line specs. */
1313 for (savecursor_set = 0, excp->addrcnt = 0; cmdlen > 0;)
1314 switch (*cmd) {
1315 case ';': /* Semi-colon delimiter. */
1316 /*
1317 * Comma delimiters delimit; semi-colon delimiters
1318 * change the current address for the 2nd address
1319 * to be the first address. Trailing or multiple
1320 * delimiters are discarded.
1321 */
1322 if (excp->addrcnt == 0)
1323 goto done;
1324 if (!savecursor_set) {
1325 savecursor.lno = sp->lno;
1326 savecursor.cno = sp->cno;
1327 sp->lno = excp->addr1.lno;
1328 sp->cno = excp->addr1.cno;
1329 savecursor_set = 1;
1330 }
1331 ++cmd;
1332 --cmdlen;
1333 break;
1334 case ',': /* Comma delimiter. */
1335 /* If no addresses yet, defaults to ".". */
1336 if (excp->addrcnt == 0) {
1337 excp->addr1.lno = sp->lno;
1338 excp->addr1.cno = sp->cno;
1339 excp->addrcnt = 1;
1340 }
1341 /* FALLTHROUGH */
1342 case ' ': /* Whitespace. */
1343 case '\t': /* Whitespace. */
1344 ++cmd;
1345 --cmdlen;
1346 break;
1347 default:
1348 if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
1349 return (1);
1350 if (!tmp)
1351 goto done;
1352
1353 /*
1354 * Extra addresses are discarded, starting with
1355 * the first.
1356 */
1357 switch (excp->addrcnt) {
1358 case 0:
1359 excp->addr1 = cur;
1360 excp->addrcnt = 1;
1361 break;
1362 case 1:
1363 excp->addr2 = cur;
1364 excp->addrcnt = 2;
1365 break;
1366 case 2:
1367 excp->addr1 = excp->addr2;
1368 excp->addr2 = cur;
1369 break;
1370 }
1371 break;
1372 }
1373
1374 /*
1375 * XXX
1376 * This is probably not right behavior for savecursor -- need
1377 * to figure out what the historical ex did for ";,;,;5p" or
1378 * similar stupidity.
1379 */
1380done: if (savecursor_set) {
1381 sp->lno = savecursor.lno;
1382 sp->cno = savecursor.cno;
1383 }
1384 if (excp->addrcnt == 2 &&
1385 (excp->addr2.lno < excp->addr1.lno ||
1386 excp->addr2.lno == excp->addr1.lno &&
1387 excp->addr2.cno < excp->addr1.cno)) {
1388 msgq(sp, M_ERR,
1389 "The second address is smaller than the first.");
1390 return (1);
1391 }
1392 *cmdp = cmd;
1393 *cmdlenp = cmdlen;
1394 return (0);
1395}
1396
1397/*
1398 * Get a single line address specifier.
1399 */
1400static int
1401ep_line(sp, ep, cur, cmdp, cmdlenp, addr_found)
1402 SCR *sp;
1403 EXF *ep;
1404 MARK *cur;
1405 char **cmdp;
1406 size_t *cmdlenp;
1407 int *addr_found;
1408{
1409 MARK m;
1410 long total;
1411 u_int flags;
1412 size_t cmdlen;
1413 int (*sf) __P((SCR *, EXF *, MARK *, MARK *, char *, char **, u_int *));
1414 char *cmd, *endp;
1415
1416 *addr_found = 0;
1417
1418 cmd = *cmdp;
1419 cmdlen = *cmdlenp;
1420 switch (*cmd) {
1421 case '$': /* Last line in the file. */
1422 *addr_found = 1;
1423 cur->cno = 0;
1424 if (file_lline(sp, ep, &cur->lno))
1425 return (1);
1426 ++cmd;
1427 --cmdlen;
1428 break; /* Absolute line number. */
1429 case '0': case '1': case '2': case '3': case '4':
1430 case '5': case '6': case '7': case '8': case '9':
1431 *addr_found = 1;
1432 /*
1433 * The way the vi "previous context" mark worked was that
1434 * "non-relative" motions set it. While vi wasn't totally
1435 * consistent about this, ANY numeric address was considered
1436 * non-relative, and set the value. Which is why we're
1437 * hacking marks down here.
1438 */
1439 if (IN_VI_MODE(sp)) {
1440 m.lno = sp->lno;
1441 m.cno = sp->cno;
1442 if (mark_set(sp, ep, ABSMARK1, &m, 1))
1443 return (1);
1444 }
1445 cur->cno = 0;
1446/* 8-bit XXX */ cur->lno = strtol(cmd, &endp, 10);
1447 cmdlen -= (endp - cmd);
1448 cmd = endp;
1449 break;
1450 case '\'': /* Use a mark. */
1451 *addr_found = 1;
1452 if (cmdlen == 1) {
1453 msgq(sp, M_ERR, "No mark name supplied.");
1454 return (1);
1455 }
1456 if (mark_get(sp, ep, cmd[1], cur))
1457 return (1);
1458 cmd += 2;
1459 cmdlen -= 2;
1460 break;
1461 case '\\': /* Search: forward/backward. */
1462 /*
1463 * !!!
1464 * I can't find any difference between // and \/ or
1465 * between ?? and \?. Mark Horton doesn't remember
1466 * there being any difference. C'est la vie.
1467 */
1468 if (cmdlen < 2 || cmd[1] != '/' && cmd[1] != '?') {
1469 msgq(sp, M_ERR, "\\ not followed by / or ?.");
1470 return (1);
1471 }
1472 ++cmd;
1473 --cmdlen;
1474 sf = cmd[0] == '/' ? f_search : b_search;
1475 goto search;
1476 case '/': /* Search forward. */
1477 sf = f_search;
1478 goto search;
1479 case '?': /* Search backward. */
1480 sf = b_search;
1481search: if (ep == NULL) {
1482 msgq(sp, M_ERR,
1483 "A search address requires that a file have already been read in.");
1484 return (1);
1485 }
1486 *addr_found = 1;
1487 m.lno = sp->lno;
1488 m.cno = sp->cno;
1489 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1490 if (sf(sp, ep, &m, &m, cmd, &endp, &flags))
1491 return (1);
1492 cur->lno = m.lno;
1493 cur->cno = m.cno;
1494 cmdlen -= (endp - cmd);
1495 cmd = endp;
1496 break;
1497 case '.': /* Current position. */
1498 *addr_found = 1;
1499 cur->cno = sp->cno;
1500
1501 /* If an empty file, then '.' is 0, not 1. */
1502 if (sp->lno == 1) {
1503 if (file_lline(sp, ep, &cur->lno))
1504 return (1);
1505 if (cur->lno != 0)
1506 cur->lno = 1;
1507 } else
1508 cur->lno = sp->lno;
1509 ++cmd;
1510 --cmdlen;
1511 break;
1512 }
1513
1514 /*
1515 * Evaluate any offset. Offsets are +/- any number, or any number
1516 * of +/- signs, or any combination thereof. If no address found
1517 * yet, offset is relative to ".".
1518 */
1519 for (total = 0; cmdlen > 0 && (cmd[0] == '-' || cmd[0] == '+');) {
1520 if (!*addr_found) {
1521 cur->lno = sp->lno;
1522 cur->cno = sp->cno;
1523 *addr_found = 1;
1524 }
1525
1526 if (cmdlen > 1 && isdigit(cmd[1])) {
1527/* 8-bit XXX */ total += strtol(cmd, &endp, 10);
1528 cmdlen -= (endp - cmd);
1529 cmd = endp;
1530 } else {
1531 total += cmd[0] == '-' ? -1 : 1;
1532 --cmdlen;
1533 ++cmd;
1534 }
1535 }
1536
1537 if (*addr_found) {
1538 if (total < 0 && -total > cur->lno) {
1539 msgq(sp, M_ERR,
1540 "Reference to a line number less than 0.");
1541 return (1);
1542 }
1543 cur->lno += total;
1544
1545 *cmdp = cmd;
1546 *cmdlenp = cmdlen;
1547 }
1548 return (0);
1549}
1550
1551/*
1552 * ex_is_abbrev -
1553 * The vi text input routine needs to know if ex thinks this is
1554 * an [un]abbreviate command, so it can turn off abbreviations.
1555 * Usual ranting in the vi/v_ntext:txt_abbrev() routine.
1556 */
1557int
1558ex_is_abbrev(name, len)
1559 char *name;
1560 size_t len;
1561{
1562 EXCMDLIST const *cp;
1563
1564 return ((cp = ex_comm_search(name, len)) != NULL &&
1565 (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
1566}
1567
1568/*
1569 * ex_is_unmap -
1570 * The vi text input routine needs to know if ex thinks this is
1571 * an unmap command, so it can turn off input mapping. Usual
1572 * ranting in the vi/v_ntext:txt_unmap() routine.
1573 */
1574int
1575ex_is_unmap(name, len)
1576 char *name;
1577 size_t len;
1578{
1579 EXCMDLIST const *cp;
1580
1581 /*
1582 * The command the vi input routines are really interested in
1583 * is "unmap!", not just unmap.
1584 */
1585 if (name[len - 1] != '!')
1586 return (0);
1587 --len;
1588 return ((cp = ex_comm_search(name, len)) != NULL &&
1589 cp == &cmds[C_UNMAP]);
1590}
1591
1592static inline EXCMDLIST const *
1593ex_comm_search(name, len)
1594 char *name;
1595 size_t len;
1596{
1597 EXCMDLIST const *cp;
1598
1599 for (cp = cmds; cp->name != NULL; ++cp) {
1600 if (cp->name[0] > name[0])
1601 return (NULL);
1602 if (cp->name[0] != name[0])
1603 continue;
1604 if (!memcmp(name, cp->name, len))
1605 return (cp);
1606 }
1607 return (NULL);
1608}