some changes got lost somewhere, make it consistent
[nvi.git] / ex / ex.c
blobd1d7d93fcb612e41ac4327e6acf4ffcd63cc0822
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: ex.c,v 8.83 1993/12/22 17:25:03 bostic Exp $ (Berkeley) $Date: 1993/12/22 17:25:03 $";
10 #endif /* not lint */
12 #include <sys/types.h>
13 #include <sys/stat.h>
15 #include <ctype.h>
16 #include <errno.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
22 #include "vi.h"
23 #include "excmd.h"
25 static inline EXCMDLIST const *
26 ex_comm_search __P((char *, size_t));
27 static int ep_line __P((SCR *, EXF *, MARK *, char **, size_t *, int *));
28 static int ep_range __P((SCR *, EXF *, EXCMDARG *, char **, size_t *));
30 #define DEFCOM ".+1"
33 * ex --
34 * Read an ex command and execute it.
36 int
37 ex(sp, ep)
38 SCR *sp;
39 EXF *ep;
41 TEXT *tp;
42 u_int saved_mode;
43 int eval;
44 char defcom[sizeof(DEFCOM)];
46 if (ex_init(sp, ep))
47 return (1);
49 if (sp->s_refresh(sp, ep))
50 return (ex_end(sp));
52 /* If reading from a file, messages should have line info. */
53 if (!F_ISSET(sp->gp, G_ISFROMTTY)) {
54 sp->if_lno = 1;
55 sp->if_name = strdup("input");
57 for (eval = 0;; ++sp->if_lno) {
58 /* Get the next command. */
59 switch (sp->s_get(sp, ep, &sp->tiq, ':', TXT_CR | TXT_PROMPT)) {
60 case INP_OK:
61 break;
62 case INP_EOF:
63 F_SET(sp, S_EXIT_FORCE);
64 goto ret;
65 case INP_ERR:
66 continue;
69 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
70 tp = sp->tiq.cqh_first;
71 if (tp->len == 0) {
72 if (F_ISSET(sp->gp, G_ISFROMTTY)) {
73 (void)fputc('\r', stdout);
74 (void)fflush(stdout);
76 memmove(defcom, DEFCOM, sizeof(DEFCOM));
77 (void)ex_icmd(sp, ep, defcom, sizeof(DEFCOM) - 1);
78 } else {
79 if (F_ISSET(sp->gp, G_ISFROMTTY))
80 (void)fputc('\n', stdout);
81 (void)ex_icmd(sp, ep, tp->lb, tp->len);
83 (void)msg_rpt(sp, 0);
85 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
86 break;
88 if (sp->s_refresh(sp, ep)) {
89 eval = 1;
90 break;
93 ret: if (sp->if_name != NULL) {
94 FREE(sp->if_name, strlen(sp->if_name) + 1);
95 sp->if_name = NULL;
97 return (ex_end(sp) || eval);
101 * ex_cfile --
102 * Execute ex commands from a file.
105 ex_cfile(sp, ep, filename)
106 SCR *sp;
107 EXF *ep;
108 char *filename;
110 struct stat sb;
111 int fd, len, rval;
112 char *bp;
114 bp = NULL;
115 if ((fd = open(filename, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
116 goto err;
119 * XXX
120 * We'd like to test if the file is too big to malloc. Since we don't
121 * know what size or type off_t's or size_t's are, what the largest
122 * unsigned integral type is, or what random insanity the local C
123 * compiler will perpetrate, doing the comparison in a portable way
124 * is flatly impossible. Hope that malloc fails if the file is too
125 * large.
127 MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
128 if (bp == NULL)
129 goto err;
131 len = read(fd, bp, (int)sb.st_size);
132 if (len == -1 || len != sb.st_size) {
133 if (len != sb.st_size)
134 errno = EIO;
135 err: rval = 1;
136 msgq(sp, M_SYSERR, filename);
137 } else {
138 bp[sb.st_size] = '\0'; /* XXX */
140 /* Run the command. Messages include file/line information. */
141 sp->if_lno = 1;
142 sp->if_name = strdup(filename);
143 rval = ex_icmd(sp, ep, bp, len);
144 FREE(sp->if_name, strlen(sp->if_name) + 1);
145 sp->if_name = NULL;
149 * !!!
150 * THE UNDERLYING EXF MAY HAVE CHANGED.
152 if (bp != NULL)
153 FREE(bp, sb.st_size);
154 if (fd >= 0)
155 (void)close(fd);
156 return (rval);
160 * ex_icmd --
161 * Call ex_cmd() after turning off interruptible bits.
164 ex_icmd(sp, ep, cmd, len)
165 SCR *sp;
166 EXF *ep;
167 char *cmd;
168 size_t len;
171 * Ex goes through here for each vi :colon command and for each ex
172 * command, however, globally executed commands don't go through
173 * here, instead, they call ex_cmd directly. So, reset all of the
174 * interruptible flags now.
176 F_CLR(sp, S_INTERRUPTED | S_INTERRUPTIBLE);
178 return (ex_cmd(sp, ep, cmd, len));
182 * ex_cmd --
183 * Parse and execute a string containing ex commands.
186 ex_cmd(sp, ep, cmd, cmdlen)
187 SCR *sp;
188 EXF *ep;
189 char *cmd;
190 size_t cmdlen;
192 CHAR_T vlit;
193 EX_PRIVATE *exp;
194 EXCMDARG exc;
195 EXCMDLIST const *cp;
196 MARK cur;
197 recno_t lno, num;
198 size_t arg1_len, len, save_cmdlen;
199 long flagoff;
200 u_int saved_mode;
201 int ch, cnt, delim, flags, namelen, nl, uselastcmd, tmp;
202 char *arg1, *save_cmd, *p, *t;
204 /* Init. */
205 nl = 0;
206 loop: if (nl) {
207 nl = 0;
208 ++sp->if_lno;
210 arg1 = NULL;
211 save_cmdlen = 0;
213 /* Skip whitespace, separators, newlines. */
214 for (; cmdlen > 0; ++cmd, --cmdlen)
215 if ((ch = *cmd) == '\n')
216 ++sp->if_lno;
217 else if (!isblank(ch))
218 break;
219 if (cmdlen == 0)
220 return (0);
222 /* Command lines that start with a double-quote are comments. */
223 if (ch == '"') {
224 while (--cmdlen > 0 && *++cmd != '\n');
225 if (*cmd == '\n') {
226 ++cmd;
227 --cmdlen;
228 ++sp->if_lno;
230 goto loop;
234 * !!!
235 * Permit extra colons at the start of the line. Historically,
236 * ex/vi allowed a single extra one. It's simpler not to count.
237 * The stripping is done here because, historically, any command
238 * could have preceding colons, e.g. ":g/pattern/:p" worked.
240 if (ch == ':')
241 while (--cmdlen > 0 && *++cmd == ':');
243 /* Skip whitespace. */
244 for (; cmdlen > 0; ++cmd, --cmdlen) {
245 ch = *cmd;
246 if (!isblank(ch))
247 break;
250 /* The last point at which an empty line means do nothing. */
251 if (cmdlen == 0)
252 return (0);
254 /* Initialize the structure passed to underlying functions. */
255 memset(&exc, 0, sizeof(EXCMDARG));
256 exp = EXP(sp);
257 if (argv_init(sp, ep, &exc))
258 goto err;
260 /* Parse command addresses. */
261 if (ep_range(sp, ep, &exc, &cmd, &cmdlen))
262 goto err;
264 /* Skip whitespace. */
265 for (; cmdlen > 0; ++cmd, --cmdlen) {
266 ch = *cmd;
267 if (!isblank(ch))
268 break;
272 * If no command, ex does the last specified of p, l, or #, and vi
273 * moves to the line. Otherwise, determine the length of the command
274 * name by looking for the first non-alphabetic character. (There
275 * a few non-alphabetic characters in command names, but they're all
276 * single character commands.) This isn't a great test, because it
277 * means that, for the command ":e +cut.c file", we'll report that the
278 * command "cut" wasn't known. However, it makes ":e+35 file" work
279 * correctly.
281 #define SINGLE_CHAR_COMMANDS "!#&<=>@~"
282 if (cmdlen != 0 && cmd[0] != '|' && cmd[0] != '\n') {
283 if (strchr(SINGLE_CHAR_COMMANDS, *cmd)) {
284 p = cmd;
285 ++cmd;
286 --cmdlen;
287 namelen = 1;
288 } else {
289 for (p = cmd; cmdlen > 0; --cmdlen, ++cmd)
290 if (!isalpha(*cmd))
291 break;
292 if ((namelen = cmd - p) == 0) {
293 msgq(sp, M_ERR, "Unknown command name.");
294 goto err;
299 * Search the table for the command.
301 * !!!
302 * Historic vi permitted the mark to immediately follow the
303 * 'k' in the 'k' command. Make it work.
305 * Use of msgq below is safe, command names are all alphabetics.
307 if ((cp = ex_comm_search(p, namelen)) == NULL)
308 if (p[0] == 'k' && p[1] && !p[2]) {
309 cmd -= namelen - 1;
310 cmdlen += namelen - 1;
311 cp = &cmds[C_K];
312 } else {
313 msgq(sp, M_ERR,
314 "The %.*s command is unknown.", namelen, p);
315 goto err;
318 /* Some commands are either not implemented or turned off. */
319 if (F_ISSET(cp, E_NOPERM)) {
320 msgq(sp, M_ERR,
321 "The %s command is not currently supported.",
322 cp->name);
323 goto err;
326 /* Some commands aren't okay in globals. */
327 if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) {
328 msgq(sp, M_ERR,
329 "The %s command can't be used as part of a global command.",
330 cp->name);
331 goto err;
335 * Multiple < and > characters; another "feature". Note,
336 * The string passed to the underlying function may not be
337 * nul terminated in this case.
339 if ((cp == &cmds[C_SHIFTL] && *p == '<') ||
340 (cp == &cmds[C_SHIFTR] && *p == '>')) {
341 for (ch = *p; cmdlen > 0; --cmdlen, ++cmd)
342 if (*cmd != ch)
343 break;
344 if (argv_exp0(sp, ep, &exc, p, cmd - p))
345 goto err;
349 * The visual command has a different syntax when called
350 * from ex than when called from a vi colon command. FMH.
352 if (cp == &cmds[C_VISUAL_EX] && IN_VI_MODE(sp))
353 cp = &cmds[C_VISUAL_VI];
355 uselastcmd = 0;
356 } else {
357 cp = exp->lastcmd;
358 uselastcmd = 1;
361 /* Initialize local flags to the command flags. */
362 LF_INIT(cp->flags);
365 * File state must be checked throughout this code, because it is
366 * called when reading the .exrc file and similar things. There's
367 * this little chicken and egg problem -- if we read the file first,
368 * we won't know how to display it. If we read/set the exrc stuff
369 * first, we can't allow any command that requires file state.
370 * Historic vi generally took the easy way out and dropped core.
372 if (LF_ISSET(E_NORC) && ep == NULL) {
373 msgq(sp, M_ERR,
374 "The %s command requires that a file already have been read in.",
375 cp->name);
376 goto err;
380 * There are three normal termination cases for an ex command. They
381 * are the end of the string (cmdlen), or unescaped (by literal next
382 * characters) newline or '|' characters. As we're past any addresses,
383 * we can now determine how long the command is, so we don't have to
384 * look for all the possible terminations. There are three exciting
385 * special cases:
387 * 1: The bang, global, vglobal and the filter versions of the read and
388 * write commands are delimited by newlines (they can contain shell
389 * pipes).
390 * 2: The ex, edit and visual in vi mode commands take ex commands as
391 * their first arguments.
392 * 3: The substitute command takes an RE as its first argument, and
393 * wants it to be specially delimited.
395 * Historically, '|' characters in the first argument of the ex, edit,
396 * and substitute commands did not delimit the command. And, in the
397 * filter cases for read and write, and the bang, global and vglobal
398 * commands, they did not delimit the command at all.
400 * For example, the following commands were legal:
402 * :edit +25|s/abc/ABC/ file.c
403 * :substitute s/|/PIPE/
404 * :read !spell % | columnate
405 * :global/pattern/p|l
407 * It's not quite as simple as it sounds, however. The command:
409 * :substitute s/a/b/|s/c/d|set
411 * was also legal, i.e. the historic ex parser (using the word loosely,
412 * since "parser" implies some regularity) delimited the RE's based on
413 * its delimiter and not anything so irretrievably vulgar as a command
414 * syntax.
416 * One thing that makes this easier is that we can ignore most of the
417 * command termination conditions for the commands that want to take
418 * the command up to the next newline. None of them are legal in .exrc
419 * files, so if we're here, we only dealing with a single line, and we
420 * can just eat it.
422 * Anyhow, the following code makes this all work. First, for the
423 * special cases we move past their special argument. Then, we do
424 * normal command processing on whatever is left. Barf-O-Rama.
426 save_cmd = cmd;
427 (void)term_key_ch(sp, K_VLNEXT, &vlit);
428 if (cp == &cmds[C_EDIT] ||
429 cp == &cmds[C_EX] || cp == &cmds[C_VISUAL_VI]) {
431 * Move to the next non-whitespace character. As '+' must
432 * be the character after the command name, if there isn't
433 * one, we're done.
435 for (; cmdlen > 0; --cmdlen, ++cmd) {
436 ch = *cmd;
437 if (!isblank(ch))
438 break;
441 * QUOTING NOTE:
443 * The historic implementation ignored all escape characters
444 * so there was no way to put a space or newline into the +cmd
445 * field. We do a simplistic job of fixing it by moving to the
446 * first whitespace character that isn't escaped by a literal
447 * next character. The literal next characters are stripped
448 * as they're no longer useful.
450 if (cmdlen > 0 && ch == '+') {
451 ++cmd;
452 --cmdlen;
453 for (arg1 = p = cmd; cmdlen > 0; --cmdlen, ++cmd) {
454 if ((ch = *cmd) == vlit && cmdlen > 1) {
455 --cmdlen;
456 ch = *++cmd;
457 } else if (isblank(ch))
458 break;
459 *p++ = ch;
461 arg1_len = cmd - arg1;
463 /* Reset, so the first argument isn't reparsed. */
464 save_cmd = cmd;
466 } else if (cp == &cmds[C_BANG] ||
467 cp == &cmds[C_GLOBAL] || cp == &cmds[C_VGLOBAL]) {
468 cmd += cmdlen;
469 cmdlen = 0;
470 } else if (cp == &cmds[C_READ] || cp == &cmds[C_WRITE]) {
472 * Move to the next character. If it's a '!', it's a filter
473 * command and we want to eat it all, otherwise, we're done.
475 for (; cmdlen > 0; --cmdlen, ++cmd) {
476 ch = *cmd;
477 if (!isblank(ch))
478 break;
480 if (cmdlen > 0 && ch == '!') {
481 cmd += cmdlen;
482 cmdlen = 0;
484 } else if (cp == &cmds[C_SUBSTITUTE]) {
486 * Move to the next non-whitespace character, we'll use it as
487 * the delimiter. Ignore if it's legal, the RE code will take
488 * care of it if it's not.
490 for (; cmdlen > 0; --cmdlen, ++cmd)
491 if (!isblank(*cmd))
492 break;
493 if (cmdlen > 0) {
495 * QUOTING NOTE:
497 * Backslashes quote delimiter characters for RE's.
498 * The backslashes are NOT removed since they'll be
499 * used by the RE code. Move to the third delimiter
500 * that's not escaped (or the end of the command).
502 delim = *cmd;
503 ++cmd;
504 --cmdlen;
505 for (cnt = 2; cmdlen > 0 && cnt; --cmdlen, ++cmd)
506 if (cmd[0] == '\\' && cmdlen > 1) {
507 ++cmd;
508 --cmdlen;
509 } else if (cmd[0] == delim)
510 --cnt;
514 * Use normal quoting and termination rules to find the end
515 * of this command.
517 * QUOTING NOTE:
519 * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
520 * file. It was almost certainly a bug, but that's what bug-for-bug
521 * compatibility means, Grasshopper. Also, ^V's escape the command
522 * delimiters. Literal next quote characters in front of the newlines,
523 * '|' characters or literal next characters are stripped as as they're
524 * no longer useful.
526 for (p = cmd, cnt = 0; cmdlen > 0; --cmdlen, ++cmd) {
527 if ((ch = cmd[0]) == vlit && cmdlen > 1) {
528 ch = cmd[1];
529 if (ch == '\n' || ch == '|') {
530 if (ch == '\n')
531 ++sp->if_lno;
532 --cmdlen;
533 ++cmd;
534 ++cnt;
535 } else
536 ch = vlit;
537 } else if (ch == '\n' || ch == '|') {
538 if (ch == '\n')
539 nl = 1;
540 --cmdlen;
541 break;
543 *p++ = ch;
547 * Save off the next command information, go back to the
548 * original start of the command.
550 p = cmd + 1;
551 cmd = save_cmd;
552 save_cmd = p;
553 save_cmdlen = cmdlen;
554 cmdlen = ((save_cmd - cmd) - 1) - cnt;
557 * !!!
558 * The "set tags" command historically used a backslash, not the
559 * user's literal next character, to escape whitespace. Handle
560 * it here instead of complicating the argv_exp3() code. Note,
561 * this isn't a particularly complex trap, and if backslashes were
562 * legal in set commands, this would have to be much more complicated.
564 if (cp == &cmds[C_SET])
565 for (p = cmd, len = cmdlen; len > 0; --len, ++p)
566 if (*p == '\\')
567 *p = vlit;
570 * Set the default addresses. It's an error to specify an address for
571 * a command that doesn't take them. If two addresses are specified
572 * for a command that only takes one, lose the first one. Two special
573 * cases here, some commands take 0 or 2 addresses. For most of them
574 * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
575 * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
577 * Also, if the file is empty, some commands want to use an address of
578 * 0, i.e. the entire file is 0 to 0, and the default first address is
579 * 0. Otherwise, an entire file is 1 to N and the default line is 1.
580 * Note, we also add the E_ZERO flag to the command flags, for the case
581 * where the 0 address is only valid if it's a default address.
583 * Also, set a flag if we set the default addresses. Some commands
584 * (ex: z) care if the user specified an address of if we just used
585 * the current cursor.
587 switch (LF_ISSET(E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) {
588 case E_ADDR1: /* One address: */
589 switch (exc.addrcnt) {
590 case 0: /* Default cursor/empty file. */
591 exc.addrcnt = 1;
592 F_SET(&exc, E_ADDRDEF);
593 if (LF_ISSET(E_ZERODEF)) {
594 if (file_lline(sp, ep, &lno))
595 goto err;
596 if (lno == 0) {
597 exc.addr1.lno = 0;
598 LF_SET(E_ZERO);
599 } else
600 exc.addr1.lno = sp->lno;
601 } else
602 exc.addr1.lno = sp->lno;
603 exc.addr1.cno = sp->cno;
604 break;
605 case 1:
606 break;
607 case 2: /* Lose the first address. */
608 exc.addrcnt = 1;
609 exc.addr1 = exc.addr2;
611 break;
612 case E_ADDR2_NONE: /* Zero/two addresses: */
613 if (exc.addrcnt == 0) /* Default to nothing. */
614 break;
615 goto two;
616 case E_ADDR2_ALL: /* Zero/two addresses: */
617 if (exc.addrcnt == 0) { /* Default entire/empty file. */
618 exc.addrcnt = 2;
619 F_SET(&exc, E_ADDRDEF);
620 if (file_lline(sp, ep, &exc.addr2.lno))
621 goto err;
622 if (LF_ISSET(E_ZERODEF) && exc.addr2.lno == 0) {
623 exc.addr1.lno = 0;
624 LF_SET(E_ZERO);
625 } else
626 exc.addr1.lno = 1;
627 exc.addr1.cno = exc.addr2.cno = 0;
628 F_SET(&exc, E_ADDR2_ALL);
629 break;
631 /* FALLTHROUGH */
632 case E_ADDR2: /* Two addresses: */
633 two: switch (exc.addrcnt) {
634 case 0: /* Default cursor/empty file. */
635 exc.addrcnt = 2;
636 F_SET(&exc, E_ADDRDEF);
637 if (LF_ISSET(E_ZERODEF) && sp->lno == 1) {
638 if (file_lline(sp, ep, &lno))
639 goto err;
640 if (lno == 0) {
641 exc.addr1.lno = exc.addr2.lno = 0;
642 LF_SET(E_ZERO);
643 } else
644 exc.addr1.lno = exc.addr2.lno = sp->lno;
645 } else
646 exc.addr1.lno = exc.addr2.lno = sp->lno;
647 exc.addr1.cno = exc.addr2.cno = sp->cno;
648 break;
649 case 1: /* Default to first address. */
650 exc.addrcnt = 2;
651 exc.addr2 = exc.addr1;
652 break;
653 case 2:
654 break;
656 break;
657 default:
658 if (exc.addrcnt) /* Error. */
659 goto usage;
662 flagoff = 0;
663 for (p = cp->syntax; *p != '\0'; ++p) {
665 * The write command is sensitive to leading whitespace, e.g.
666 * "write !" is different from "write!". If not the write
667 * command, skip leading whitespace.
669 if (cp != &cmds[C_WRITE])
670 for (; cmdlen > 0; --cmdlen, ++cmd) {
671 ch = *cmd;
672 if (!isblank(ch))
673 break;
677 * Quit when reach the end of the command, unless it's a
678 * command that does its own parsing, in which case we want
679 * to build a reasonable argv for it. This code guarantees
680 * that there will be an argv when the function gets called,
681 * so the correct test is for a length of 0, not for the
682 * argc > 0.
684 if (cmdlen == 0 && *p != '!' && *p != 'S' && *p != 's')
685 break;
687 switch (*p) {
688 case '!': /* ! */
689 if (*cmd == '!') {
690 ++cmd;
691 --cmdlen;
692 F_SET(&exc, E_FORCE);
694 break;
695 case '1': /* +, -, #, l, p */
697 * !!!
698 * Historically, some flags were ignored depending
699 * on where they occurred in the command line. For
700 * example, in the command, ":3+++p--#", historic vi
701 * acted on the '#' flag, but ignored the '-' flags.
702 * It's unambiguous what the flags mean, so we just
703 * handle them regardless of the stupidity of their
704 * location.
706 for (; cmdlen; --cmdlen, ++cmd)
707 switch (*cmd) {
708 case '+':
709 ++flagoff;
710 break;
711 case '-':
712 --flagoff;
713 break;
714 case '#':
715 F_SET(&exc, E_F_HASH);
716 break;
717 case 'l':
718 F_SET(&exc, E_F_LIST);
719 break;
720 case 'p':
721 F_SET(&exc, E_F_PRINT);
722 break;
723 default:
724 goto end1;
726 end1: break;
727 case '2': /* -, ., +, ^ */
728 case '3': /* -, ., +, ^, = */
729 for (; cmdlen; --cmdlen, ++cmd)
730 switch (*cmd) {
731 case '-':
732 F_SET(&exc, E_F_DASH);
733 break;
734 case '.':
735 F_SET(&exc, E_F_DOT);
736 break;
737 case '+':
738 F_SET(&exc, E_F_PLUS);
739 break;
740 case '^':
741 F_SET(&exc, E_F_CARAT);
742 break;
743 case '=':
744 if (*p == '3') {
745 F_SET(&exc, E_F_EQUAL);
746 break;
748 /* FALLTHROUGH */
749 default:
750 goto end2;
752 end2: break;
753 case 'b': /* buffer */
754 exc.buffer = *cmd;
755 ++cmd;
756 --cmdlen;
757 F_SET(&exc, E_BUFFER);
758 break;
759 case 'c': /* count [01+a] */
760 ++p;
761 if (!isdigit(*cmd) &&
762 (*p != '+' || (*cmd != '+' && *cmd != '-')))
763 break;
764 /* 8-bit XXX */ if ((lno = strtol(cmd, &t, 10)) == 0 && *p != '0') {
765 msgq(sp, M_ERR, "Count may not be zero.");
766 goto err;
768 cmdlen -= (t - cmd);
769 cmd = t;
771 * Count as address offsets occur in commands taking
772 * two addresses. Historic vi practice was to use
773 * the count as an offset from the *second* address.
775 * Set a count flag; some underlying commands (see
776 * join) do different things with counts than with
777 * line addresses.
779 if (*p == 'a') {
780 exc.addr1 = exc.addr2;
781 exc.addr2.lno = exc.addr1.lno + lno - 1;
782 } else
783 exc.count = lno;
784 F_SET(&exc, E_COUNT);
785 break;
786 case 'f': /* file */
787 if (argv_exp2(sp, ep,
788 &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
789 goto err;
790 goto countchk;
791 case 'l': /* line */
792 if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
793 goto err;
794 /* Line specifications are always required. */
795 if (!tmp) {
796 msgq(sp, M_ERR,
797 "%s: bad line specification", cmd);
798 goto err;
800 exc.lineno = cur.lno;
801 break;
802 case 'S': /* string, file exp. */
803 if (argv_exp1(sp, ep,
804 &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
805 goto err;
806 goto addr2;
807 case 's': /* string */
808 if (argv_exp0(sp, ep, &exc, cmd, cmdlen))
809 goto err;
810 goto addr2;
811 case 'W': /* word string */
813 * QUOTING NOTE:
815 * Literal next characters escape the following
816 * character. Quoting characters are stripped
817 * here since they are no longer useful.
819 * First there was the word.
821 for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd) {
822 if ((ch = *cmd) == vlit && cmdlen > 1) {
823 --cmdlen;
824 *p++ = *++cmd;
825 } else if (isblank(ch)) {
826 ++cmd;
827 --cmdlen;
828 break;
829 } else
830 *p++ = ch;
832 if (argv_exp0(sp, ep, &exc, t, p - t))
833 goto err;
835 /* Delete intervening whitespace. */
836 for (; cmdlen > 0; --cmdlen, ++cmd) {
837 ch = *cmd;
838 if (!isblank(ch))
839 break;
841 if (cmdlen == 0)
842 goto usage;
844 /* Followed by the string. */
845 for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd, ++p)
846 if ((ch = *cmd) == vlit && cmdlen > 1) {
847 --cmdlen;
848 *p = *++cmd;
849 } else
850 *p = ch;
851 if (argv_exp0(sp, ep, &exc, t, p - t))
852 goto err;
853 goto addr2;
854 case 'w': /* word */
855 if (argv_exp3(sp, ep, &exc, cmd, cmdlen))
856 goto err;
857 countchk: if (*++p != 'N') { /* N */
859 * If a number is specified, must either be
860 * 0 or that number, if optional, and that
861 * number, if required.
863 num = *p - '0';
864 if ((*++p != 'o' || exp->argsoff != 0) &&
865 exp->argsoff != num)
866 goto usage;
868 goto addr2;
869 default:
870 msgq(sp, M_ERR,
871 "Internal syntax table error (%s: %c).",
872 cp->name, *p);
876 /* Skip trailing whitespace. */
877 for (; cmdlen; --cmdlen) {
878 ch = *cmd++;
879 if (!isblank(ch))
880 break;
884 * There shouldn't be anything left, and no more required
885 * fields, i.e neither 'l' or 'r' in the syntax string.
887 if (cmdlen || strpbrk(p, "lr")) {
888 usage: msgq(sp, M_ERR, "Usage: %s.", cp->usage);
889 goto err;
892 /* Verify that the addresses are legal. */
893 addr2: switch (exc.addrcnt) {
894 case 2:
895 if (file_lline(sp, ep, &lno))
896 goto err;
898 * Historic ex/vi permitted commands with counts to go past
899 * EOF. So, for example, if the file only had 5 lines, the
900 * ex command "1,6>" would fail, but the command ">300"
901 * would succeed. Since we don't want to have to make all
902 * of the underlying commands handle random line numbers,
903 * fix it here.
905 if (exc.addr2.lno > lno)
906 if (F_ISSET(&exc, E_COUNT))
907 exc.addr2.lno = lno;
908 else {
909 if (lno == 0)
910 msgq(sp, M_ERR, "The file is empty.");
911 else
912 msgq(sp, M_ERR,
913 "Only %lu line%s in the file",
914 lno, lno > 1 ? "s" : "");
915 goto err;
917 /* FALLTHROUGH */
918 case 1:
919 num = exc.addr1.lno;
921 * If it's a "default vi command", zero is okay. Historic
922 * vi allowed this, note, it's also the hack that allows
923 * "vi + nonexistent_file" to work.
925 if (num == 0 && (!IN_VI_MODE(sp) || uselastcmd != 1) &&
926 !LF_ISSET(E_ZERO)) {
927 msgq(sp, M_ERR,
928 "The %s command doesn't permit an address of 0.",
929 cp->name);
930 goto err;
932 if (file_lline(sp, ep, &lno))
933 goto err;
934 if (num > lno) {
935 if (lno == 0)
936 msgq(sp, M_ERR, "The file is empty.");
937 else
938 msgq(sp, M_ERR, "Only %lu line%s in the file",
939 lno, lno > 1 ? "s" : "");
940 goto err;
942 break;
945 /* If doing a default command, vi just moves to the line. */
946 if (IN_VI_MODE(sp) && uselastcmd) {
947 switch (exc.addrcnt) {
948 case 2:
949 sp->lno = exc.addr2.lno ? exc.addr2.lno : 1;
950 sp->cno = exc.addr2.cno;
951 break;
952 case 1:
953 sp->lno = exc.addr1.lno ? exc.addr1.lno : 1;
954 sp->cno = exc.addr1.cno;
955 break;
957 cmd = save_cmd;
958 cmdlen = save_cmdlen;
959 goto loop;
962 /* Reset "last" command. */
963 if (LF_ISSET(E_SETLAST))
964 exp->lastcmd = cp;
966 /* Final setup for the command. */
967 exc.cmd = cp;
969 #if defined(DEBUG) && 0
970 TRACE(sp, "ex_cmd: %s", exc.cmd->name);
971 if (exc.addrcnt > 0) {
972 TRACE(sp, "\taddr1 %d", exc.addr1.lno);
973 if (exc.addrcnt > 1)
974 TRACE(sp, " addr2: %d", exc.addr2.lno);
975 TRACE(sp, "\n");
977 if (exc.lineno)
978 TRACE(sp, "\tlineno %d", exc.lineno);
979 if (exc.flags)
980 TRACE(sp, "\tflags %0x", exc.flags);
981 if (F_ISSET(&exc, E_BUFFER))
982 TRACE(sp, "\tbuffer %c", exc.buffer);
983 TRACE(sp, "\n");
984 if (exc.argc) {
985 for (cnt = 0; cnt < exc.argc; ++cnt)
986 TRACE(sp, "\targ %d: {%s}", cnt, exc.argv[cnt]);
987 TRACE(sp, "\n");
989 #endif
990 /* Clear autoprint. */
991 F_CLR(sp, S_AUTOPRINT);
993 /* Increment the command count if not called from vi. */
994 if (!IN_VI_MODE(sp))
995 ++sp->ccnt;
998 * If file state and not doing a global command, log the start of
999 * an action.
1001 if (ep != NULL && !F_ISSET(sp, S_GLOBAL))
1002 (void)log_cursor(sp, ep);
1004 /* Save the current mode. */
1005 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
1007 /* Do the command. */
1008 if ((cp->fn)(sp, ep, &exc))
1009 goto err;
1011 #ifdef DEBUG
1012 /* Make sure no function left the temporary space locked. */
1013 if (F_ISSET(sp->gp, G_TMP_INUSE)) {
1014 F_CLR(sp->gp, G_TMP_INUSE);
1015 msgq(sp, M_ERR, "Error: ex: temporary buffer not released.");
1016 goto err;
1018 #endif
1019 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE)) {
1021 * Only here if the mode of the underlying file changed, e.g.
1022 * the user switched files or is exiting. There are two things
1023 * that we might have to save. First, any "+cmd" field set up
1024 * for an ex/edit command will have to be saved for later, also,
1025 * any not yet executed part of the current ex command.
1027 * :edit +25 file.c|s/abc/ABC/|1
1029 * for example.
1031 * The historic vi just hung, of course; we handle by
1032 * pushing the keys onto the tty queue. If we're
1033 * switching modes to vi, since the commands are intended
1034 * as ex commands, add the extra characters to make it
1035 * work.
1037 * For the fun of it, if you want to see if a vi clone got
1038 * the ex argument parsing right, try:
1040 * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
1041 * vi
1042 * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
1044 if (arg1_len == NULL && save_cmdlen == 0)
1045 return (0);
1046 if (IN_VI_MODE(sp) && term_push(sp, "\n", 1, 0, 0))
1047 goto err;
1048 if (save_cmdlen != 0)
1049 if (term_push(sp, save_cmd, save_cmdlen, 0, 0))
1050 goto err;
1051 if (arg1 != NULL) {
1052 if (IN_VI_MODE(sp) && save_cmdlen != 0 &&
1053 term_push(sp, "|", 1, 0, 0))
1054 goto err;
1055 if (term_push(sp, arg1, arg1_len, 0, 0))
1056 goto err;
1058 if (IN_VI_MODE(sp) && term_push(sp, ":", 1, 0, 0))
1059 goto err;
1060 return (0);
1063 if (IN_EX_MODE(sp) && ep != NULL) {
1065 * The print commands have already handled the `print' flags.
1066 * If so, clear them. Don't return, autoprint may still have
1067 * stuff to print out.
1069 if (LF_ISSET(E_F_PRCLEAR))
1070 F_CLR(&exc, E_F_HASH | E_F_LIST | E_F_PRINT);
1073 * If the command was successful, and there was an explicit
1074 * flag to display the new cursor line, or we're in ex mode,
1075 * autoprint is set, and a change was made, display the line.
1077 if (flagoff) {
1078 if (flagoff < 0) {
1079 if (sp->lno < -flagoff) {
1080 msgq(sp, M_ERR,
1081 "Flag offset before line 1.");
1082 goto err;
1084 } else {
1085 if (file_lline(sp, ep, &lno))
1086 goto err;
1087 if (sp->lno + flagoff > lno) {
1088 msgq(sp, M_ERR,
1089 "Flag offset past end-of-file.");
1090 goto err;
1093 sp->lno += flagoff;
1096 if (F_ISSET(sp, S_AUTOPRINT) && O_ISSET(sp, O_AUTOPRINT))
1097 LF_INIT(E_F_PRINT);
1098 else
1099 LF_INIT(F_ISSET(&exc, E_F_HASH | E_F_LIST | E_F_PRINT));
1101 memset(&exc, 0, sizeof(EXCMDARG));
1102 exc.addrcnt = 2;
1103 exc.addr1.lno = exc.addr2.lno = sp->lno;
1104 exc.addr1.cno = exc.addr2.cno = sp->cno;
1105 switch (LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT)) {
1106 case E_F_HASH:
1107 exc.cmd = &cmds[C_HASH];
1108 ex_number(sp, ep, &exc);
1109 break;
1110 case E_F_LIST:
1111 exc.cmd = &cmds[C_LIST];
1112 ex_list(sp, ep, &exc);
1113 break;
1114 case E_F_PRINT:
1115 exc.cmd = &cmds[C_PRINT];
1116 ex_pr(sp, ep, &exc);
1117 break;
1121 cmd = save_cmd;
1122 cmdlen = save_cmdlen;
1123 goto loop;
1124 /* NOTREACHED */
1127 * On error, we discard any keys we have left, as well as any keys
1128 * that were mapped. The test of save_cmdlen isn't necessarily
1129 * correct. If we fail early enough we don't know if the entire
1130 * string was a single command or not. Try and guess, it's useful
1131 * to know if part of the command was discarded.
1133 if (save_cmdlen == 0)
1134 for (; cmdlen; --cmdlen)
1135 if ((ch = *cmd++) == vlit && cmdlen > 1) {
1136 --cmdlen;
1137 ++cmd;
1138 } else if (ch == '\n' || ch == '|') {
1139 if (cmdlen > 1)
1140 save_cmdlen = 1;
1141 break;
1143 if (save_cmdlen != 0)
1144 msgq(sp, M_ERR,
1145 "Ex command failed: remaining command input discarded.");
1146 err: term_map_flush(sp, "Ex command failed");
1147 return (1);
1151 * ep_range --
1152 * Get a line range for ex commands.
1154 static int
1155 ep_range(sp, ep, excp, cmdp, cmdlenp)
1156 SCR *sp;
1157 EXF *ep;
1158 EXCMDARG *excp;
1159 char **cmdp;
1160 size_t *cmdlenp;
1162 MARK cur, savecursor;
1163 size_t cmdlen;
1164 int savecursor_set, tmp;
1165 char *cmd;
1167 /* Percent character is all lines in the file. */
1168 cmd = *cmdp;
1169 cmdlen = *cmdlenp;
1170 if (*cmd == '%') {
1171 excp->addr1.lno = 1;
1172 if (file_lline(sp, ep, &excp->addr2.lno))
1173 return (1);
1175 /* If an empty file, then the first line is 0, not 1. */
1176 if (excp->addr2.lno == 0)
1177 excp->addr1.lno = 0;
1178 excp->addr1.cno = excp->addr2.cno = 0;
1179 excp->addrcnt = 2;
1181 ++*cmdp;
1182 --*cmdlenp;
1183 return (0);
1186 /* Parse comma or semi-colon delimited line specs. */
1187 for (savecursor_set = 0, excp->addrcnt = 0; cmdlen > 0;)
1188 switch (*cmd) {
1189 case ';': /* Semi-colon delimiter. */
1191 * Comma delimiters delimit; semi-colon delimiters
1192 * change the current address for the 2nd address
1193 * to be the first address. Trailing or multiple
1194 * delimiters are discarded.
1196 if (excp->addrcnt == 0)
1197 goto done;
1198 if (!savecursor_set) {
1199 savecursor.lno = sp->lno;
1200 savecursor.cno = sp->cno;
1201 sp->lno = excp->addr1.lno;
1202 sp->cno = excp->addr1.cno;
1203 savecursor_set = 1;
1205 ++cmd;
1206 --cmdlen;
1207 break;
1208 case ',': /* Comma delimiter. */
1209 /* If no addresses yet, defaults to ".". */
1210 if (excp->addrcnt == 0) {
1211 excp->addr1.lno = sp->lno;
1212 excp->addr1.cno = sp->cno;
1213 excp->addrcnt = 1;
1215 /* FALLTHROUGH */
1216 case ' ': /* Whitespace. */
1217 case '\t': /* Whitespace. */
1218 ++cmd;
1219 --cmdlen;
1220 break;
1221 default:
1222 if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
1223 return (1);
1224 if (!tmp)
1225 goto done;
1228 * Extra addresses are discarded, starting with
1229 * the first.
1231 switch (excp->addrcnt) {
1232 case 0:
1233 excp->addr1 = cur;
1234 excp->addrcnt = 1;
1235 break;
1236 case 1:
1237 excp->addr2 = cur;
1238 excp->addrcnt = 2;
1239 break;
1240 case 2:
1241 excp->addr1 = excp->addr2;
1242 excp->addr2 = cur;
1243 break;
1245 break;
1249 * XXX
1250 * This is probably not right behavior for savecursor -- need
1251 * to figure out what the historical ex did for ";,;,;5p" or
1252 * similar stupidity.
1254 done: if (savecursor_set) {
1255 sp->lno = savecursor.lno;
1256 sp->cno = savecursor.cno;
1258 if (excp->addrcnt == 2 &&
1259 (excp->addr2.lno < excp->addr1.lno ||
1260 excp->addr2.lno == excp->addr1.lno &&
1261 excp->addr2.cno < excp->addr1.cno)) {
1262 msgq(sp, M_ERR,
1263 "The second address is smaller than the first.");
1264 return (1);
1266 *cmdp = cmd;
1267 *cmdlenp = cmdlen;
1268 return (0);
1272 * Get a single line address specifier.
1274 static int
1275 ep_line(sp, ep, cur, cmdp, cmdlenp, addr_found)
1276 SCR *sp;
1277 EXF *ep;
1278 MARK *cur;
1279 char **cmdp;
1280 size_t *cmdlenp;
1281 int *addr_found;
1283 MARK m, *mp;
1284 long total;
1285 u_int flags;
1286 size_t cmdlen;
1287 char *cmd, *endp;
1289 *addr_found = 0;
1291 cmd = *cmdp;
1292 cmdlen = *cmdlenp;
1293 switch (*cmd) {
1294 case '$': /* Last line in the file. */
1295 *addr_found = 1;
1296 cur->cno = 0;
1297 if (file_lline(sp, ep, &cur->lno))
1298 return (1);
1299 ++cmd;
1300 --cmdlen;
1301 break; /* Absolute line number. */
1302 case '0': case '1': case '2': case '3': case '4':
1303 case '5': case '6': case '7': case '8': case '9':
1304 *addr_found = 1;
1306 * The way the vi "previous context" mark worked was that
1307 * "non-relative" motions set it. While vi wasn't totally
1308 * consistent about this, ANY numeric address was considered
1309 * non-relative, and set the value. Which is why we're
1310 * hacking marks down here.
1312 if (IN_VI_MODE(sp)) {
1313 m.lno = sp->lno;
1314 m.cno = sp->cno;
1315 if (mark_set(sp, ep, ABSMARK1, &m, 1))
1316 return (1);
1318 cur->cno = 0;
1319 /* 8-bit XXX */ cur->lno = strtol(cmd, &endp, 10);
1320 cmdlen -= (endp - cmd);
1321 cmd = endp;
1322 break;
1323 case '\'': /* Use a mark. */
1324 *addr_found = 1;
1325 if (cmdlen == 1) {
1326 msgq(sp, M_ERR, "No mark name supplied.");
1327 return (1);
1329 if ((mp = mark_get(sp, ep, cmd[1])) == NULL)
1330 return (1);
1331 *cur = *mp;
1332 cmd += 2;
1333 cmdlen -= 2;
1334 break;
1335 case '\\': /* Search: forward/backward. */
1337 * !!!
1338 * I can't find any difference between // and \/ or
1339 * between ?? and \?. Mark Horton doesn't remember
1340 * there being any difference. C'est la vie.
1342 if (cmdlen < 2 || cmd[1] != '/' && cmd[1] != '?') {
1343 msgq(sp, M_ERR, "\\ not followed by / or ?.");
1344 return (1);
1346 ++cmd;
1347 --cmdlen;
1348 if (cmd[0] == '/')
1349 goto forward;
1350 if (cmd[0] == '?')
1351 goto backward;
1352 /* NOTREACHED */
1353 case '/': /* Search forward. */
1354 forward: *addr_found = 1;
1355 m.lno = sp->lno;
1356 m.cno = sp->cno;
1357 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1358 if (f_search(sp, ep, &m, &m, cmd, &endp, &flags))
1359 return (1);
1360 cur->lno = m.lno;
1361 cur->cno = m.cno;
1362 cmdlen -= (endp - cmd);
1363 cmd = endp;
1364 break;
1365 case '?': /* Search backward. */
1366 backward: *addr_found = 1;
1367 m.lno = sp->lno;
1368 m.cno = sp->cno;
1369 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1370 if (b_search(sp, ep, &m, &m, cmd, &endp, &flags))
1371 return (1);
1372 cur->lno = m.lno;
1373 cur->cno = m.cno;
1374 cmdlen -= (endp - cmd);
1375 cmd = endp;
1376 break;
1377 case '.': /* Current position. */
1378 *addr_found = 1;
1379 cur->cno = sp->cno;
1381 /* If an empty file, then '.' is 0, not 1. */
1382 if (sp->lno == 1) {
1383 if (file_lline(sp, ep, &cur->lno))
1384 return (1);
1385 if (cur->lno != 0)
1386 cur->lno = 1;
1387 } else
1388 cur->lno = sp->lno;
1389 ++cmd;
1390 --cmdlen;
1391 break;
1395 * Evaluate any offset. Offsets are +/- any number, or any number
1396 * of +/- signs, or any combination thereof. If no address found
1397 * yet, offset is relative to ".".
1399 for (total = 0; cmdlen > 0 && (cmd[0] == '-' || cmd[0] == '+');) {
1400 if (!*addr_found) {
1401 cur->lno = sp->lno;
1402 cur->cno = sp->cno;
1403 *addr_found = 1;
1406 if (cmdlen > 1 && isdigit(cmd[1])) {
1407 /* 8-bit XXX */ total += strtol(cmd, &endp, 10);
1408 cmdlen -= (endp - cmd);
1409 cmd = endp;
1410 } else {
1411 total += cmd[0] == '-' ? -1 : 1;
1412 --cmdlen;
1413 ++cmd;
1416 if (total < 0 && -total > cur->lno) {
1417 msgq(sp, M_ERR, "Reference to a line number less than 0.");
1418 return (1);
1420 cur->lno += total;
1422 *cmdp = cmd;
1423 *cmdlenp = cmdlen;
1424 return (0);
1428 * ex_is_abbrev -
1429 * The vi text input routine needs to know if ex thinks this is
1430 * an [un]abbreviate command, so it can turn off abbreviations.
1431 * Usual ranting in the vi/v_ntext:txt_abbrev() routine.
1434 ex_is_abbrev(name, len)
1435 char *name;
1436 size_t len;
1438 EXCMDLIST const *cp;
1440 return ((cp = ex_comm_search(name, len)) != NULL &&
1441 (cp == &cmds[C_ABBR] || cp == &cmds[C_UNABBREVIATE]));
1444 static inline EXCMDLIST const *
1445 ex_comm_search(name, len)
1446 char *name;
1447 size_t len;
1449 EXCMDLIST const *cp;
1451 for (cp = &cmds[C_APPEND]; cp->name != NULL; ++cp) {
1452 if (cp->name[0] > name[0])
1453 return (NULL);
1454 if (cp->name[0] != name[0])
1455 continue;
1456 if (!memcmp(name, cp->name, len))
1457 return (cp);
1459 return (NULL);