change ep_line to handle offsets in the historic fashion (.+3p
[nvi.git] / ex / ex.c
blobb5fe2f02fcdb79f359701c017baeae323f86fbd6
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.76 1993/12/19 16:06:08 bostic Exp $ (Berkeley) $Date: 1993/12/19 16:06:08 $";
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 int ep_line __P((SCR *, EXF *, MARK *, char **, size_t *, int *));
26 static int ep_range __P((SCR *, EXF *, EXCMDARG *, char **, size_t *));
28 #define DEFCOM ".+1"
31 * ex --
32 * Read an ex command and execute it.
34 int
35 ex(sp, ep)
36 SCR *sp;
37 EXF *ep;
39 TEXT *tp;
40 u_int saved_mode;
41 int eval;
42 char defcom[sizeof(DEFCOM)];
44 if (ex_init(sp, ep))
45 return (1);
47 if (sp->s_refresh(sp, ep))
48 return (ex_end(sp));
50 /* If reading from a file, messages should have line info. */
51 if (!F_ISSET(sp->gp, G_ISFROMTTY)) {
52 sp->if_lno = 1;
53 sp->if_name = strdup("input");
55 for (eval = 0;; ++sp->if_lno) {
56 /* Get the next command. */
57 switch (sp->s_get(sp, ep, &sp->tiq, ':', TXT_CR | TXT_PROMPT)) {
58 case INP_OK:
59 break;
60 case INP_EOF:
61 F_SET(sp, S_EXIT_FORCE);
62 goto ret;
63 case INP_ERR:
64 continue;
67 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
68 tp = sp->tiq.cqh_first;
69 if (tp->len == 0) {
70 if (F_ISSET(sp->gp, G_ISFROMTTY)) {
71 (void)fputc('\r', stdout);
72 (void)fflush(stdout);
74 memmove(defcom, DEFCOM, sizeof(DEFCOM));
75 (void)ex_icmd(sp, ep, defcom, sizeof(DEFCOM) - 1);
76 } else {
77 if (F_ISSET(sp->gp, G_ISFROMTTY))
78 (void)fputc('\n', stdout);
79 (void)ex_icmd(sp, ep, tp->lb, tp->len);
81 (void)msg_rpt(sp, 0);
83 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
84 break;
86 if (sp->s_refresh(sp, ep)) {
87 eval = 1;
88 break;
91 ret: if (sp->if_name != NULL) {
92 FREE(sp->if_name, strlen(sp->if_name) + 1);
93 sp->if_name = NULL;
95 return (ex_end(sp) || eval);
99 * ex_cfile --
100 * Execute ex commands from a file.
103 ex_cfile(sp, ep, filename)
104 SCR *sp;
105 EXF *ep;
106 char *filename;
108 struct stat sb;
109 int fd, len, rval;
110 char *bp;
112 bp = NULL;
113 if ((fd = open(filename, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
114 goto err;
117 * XXX
118 * We'd like to test if the file is too big to malloc. Since we don't
119 * know what size or type off_t's or size_t's are, what the largest
120 * unsigned integral type is, or what random insanity the local C
121 * compiler will perpetrate, doing the comparison in a portable way
122 * is flatly impossible. Hope that malloc fails if the file is too
123 * large.
125 MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
126 if (bp == NULL)
127 goto err;
129 len = read(fd, bp, (int)sb.st_size);
130 if (len == -1 || len != sb.st_size) {
131 if (len != sb.st_size)
132 errno = EIO;
133 err: rval = 1;
134 msgq(sp, M_SYSERR, filename);
135 } else {
136 bp[sb.st_size] = '\0'; /* XXX */
138 /* Run the command. Messages include file/line information. */
139 sp->if_lno = 1;
140 sp->if_name = strdup(filename);
141 rval = ex_icmd(sp, ep, bp, len);
142 FREE(sp->if_name, strlen(sp->if_name) + 1);
143 sp->if_name = NULL;
147 * !!!
148 * THE UNDERLYING EXF MAY HAVE CHANGED.
150 if (bp != NULL)
151 FREE(bp, sb.st_size);
152 if (fd >= 0)
153 (void)close(fd);
154 return (rval);
158 * ex_icmd --
159 * Call ex_cmd() after turning off interruptible bits.
162 ex_icmd(sp, ep, cmd, len)
163 SCR *sp;
164 EXF *ep;
165 char *cmd;
166 size_t len;
169 * Ex goes through here for each vi :colon command and for each ex
170 * command, however, globally executed commands don't go through
171 * here, instead, they call ex_cmd directly. So, reset all of the
172 * interruptible flags now.
174 F_CLR(sp, S_INTERRUPTED | S_INTERRUPTIBLE);
176 return (ex_cmd(sp, ep, cmd, len));
180 * ex_cmd --
181 * Parse and execute a string containing ex commands.
184 ex_cmd(sp, ep, cmd, cmdlen)
185 SCR *sp;
186 EXF *ep;
187 char *cmd;
188 size_t cmdlen;
190 CHAR_T vlit;
191 EX_PRIVATE *exp;
192 EXCMDARG exc;
193 EXCMDLIST const *cp;
194 MARK cur;
195 recno_t lno, num;
196 size_t arg1_len, len, save_cmdlen;
197 long flagoff;
198 u_int saved_mode;
199 int ch, cnt, delim, flags, namelen, nl, uselastcmd, tmp;
200 char *arg1, *save_cmd, *p, *t;
202 /* Init. */
203 nl = 0;
204 loop: if (nl) {
205 nl = 0;
206 ++sp->if_lno;
208 arg1 = NULL;
209 save_cmdlen = 0;
211 /* Skip whitespace, separators, newlines. */
212 for (; cmdlen > 0; ++cmd, --cmdlen)
213 if ((ch = *cmd) == '\n')
214 ++sp->if_lno;
215 else if (!isblank(ch))
216 break;
217 if (cmdlen == 0)
218 return (0);
220 /* Command lines that start with a double-quote are comments. */
221 if (ch == '"') {
222 while (--cmdlen > 0 && *++cmd != '\n');
223 if (*cmd == '\n') {
224 ++cmd;
225 --cmdlen;
226 ++sp->if_lno;
228 goto loop;
232 * !!!
233 * Permit extra colons at the start of the line. Historically,
234 * ex/vi allowed a single extra one. It's simpler not to count.
235 * The stripping is done here because, historically, any command
236 * could have preceding colons, e.g. ":g/pattern/:p" worked.
238 if (ch == ':')
239 while (--cmdlen > 0 && *++cmd == ':');
241 /* Skip whitespace. */
242 for (; cmdlen > 0; ++cmd, --cmdlen) {
243 ch = *cmd;
244 if (!isblank(ch))
245 break;
248 /* The last point at which an empty line means do nothing. */
249 if (cmdlen == 0)
250 return (0);
252 /* Initialize the structure passed to underlying functions. */
253 memset(&exc, 0, sizeof(EXCMDARG));
254 exp = EXP(sp);
255 if (argv_init(sp, ep, &exc))
256 goto err;
258 /* Parse command addresses. */
259 if (ep_range(sp, ep, &exc, &cmd, &cmdlen))
260 goto err;
262 /* Skip whitespace. */
263 for (; cmdlen > 0; ++cmd, --cmdlen) {
264 ch = *cmd;
265 if (!isblank(ch))
266 break;
270 * If no command, ex does the last specified of p, l, or #, and vi
271 * moves to the line. Otherwise, determine the length of the command
272 * name by looking for the first non-alphabetic character. (There
273 * a few non-alphabetic characters in command names, but they're all
274 * single character commands.) This isn't a great test, because it
275 * means that, for the command ":e +cut.c file", we'll report that the
276 * command "cut" wasn't known. However, it makes ":e+35 file" work
277 * correctly.
279 #define SINGLE_CHAR_COMMANDS "!#&<=>@~"
280 if (cmdlen != 0 && cmd[0] != '|' && cmd[0] != '\n') {
281 if (strchr(SINGLE_CHAR_COMMANDS, *cmd)) {
282 p = cmd;
283 ++cmd;
284 --cmdlen;
285 namelen = 1;
286 } else {
287 for (p = cmd; cmdlen > 0; --cmdlen, ++cmd)
288 if (!isalpha(*cmd))
289 break;
290 if ((namelen = cmd - p) == 0) {
291 msgq(sp, M_ERR, "Unknown command name.");
292 goto err;
295 /* Search the table for the command. */
296 for (cp = cmds;
297 cp->name && memcmp(p, cp->name, namelen); ++cp);
300 * !!!
301 * Historic vi permitted the mark to immediately follow the
302 * 'k' in the 'k' command. Make it work.
304 * Use of msgq below is safe, command names are all alphabetics.
306 if (cp->name == NULL)
307 if (p[0] == 'k' && p[1] && !p[2]) {
308 cmd -= namelen - 1;
309 cmdlen += namelen - 1;
310 cp = &cmds[C_K];
311 } else {
312 msgq(sp, M_ERR,
313 "The %.*s command is unknown.", namelen, p);
314 goto err;
317 /* Some commands are either not implemented or turned off. */
318 if (F_ISSET(cp, E_NOPERM)) {
319 msgq(sp, M_ERR,
320 "The %s command is not currently supported.",
321 cp->name);
322 goto err;
325 /* Some commands aren't okay in globals. */
326 if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) {
327 msgq(sp, M_ERR,
328 "The %s command can't be used as part of a global command.",
329 cp->name);
330 goto err;
334 * Multiple < and > characters; another "feature". Note,
335 * The string passed to the underlying function may not be
336 * nul terminated in this case.
338 if ((cp == &cmds[C_SHIFTL] && *p == '<') ||
339 (cp == &cmds[C_SHIFTR] && *p == '>')) {
340 for (ch = *p; cmdlen > 0; --cmdlen, ++cmd)
341 if (*cmd != ch)
342 break;
343 if (argv_exp0(sp, ep, &exc, p, cmd - p))
344 goto err;
348 * The visual command has a different syntax when called
349 * from ex than when called from a vi colon command. FMH.
351 if (cp == &cmds[C_VISUAL_EX] && IN_VI_MODE(sp))
352 cp = &cmds[C_VISUAL_VI];
354 uselastcmd = 0;
355 } else {
356 cp = exp->lastcmd;
357 uselastcmd = 1;
360 /* Initialize local flags to the command flags. */
361 LF_INIT(cp->flags);
364 * File state must be checked throughout this code, because it is
365 * called when reading the .exrc file and similar things. There's
366 * this little chicken and egg problem -- if we read the file first,
367 * we won't know how to display it. If we read/set the exrc stuff
368 * first, we can't allow any command that requires file state.
369 * Historic vi generally took the easy way out and dropped core.
371 if (LF_ISSET(E_NORC) && ep == NULL) {
372 msgq(sp, M_ERR,
373 "The %s command requires that a file already have been read in.",
374 cp->name);
375 goto err;
379 * There are three normal termination cases for an ex command. They
380 * are the end of the string (cmdlen), or unescaped (by literal next
381 * characters) newline or '|' characters. As we're past any addresses,
382 * we can now determine how long the command is, so we don't have to
383 * look for all the possible terminations. There are three exciting
384 * special cases:
386 * 1: The bang, global, vglobal and the filter versions of the read and
387 * write commands are delimited by newlines (they can contain shell
388 * pipes).
389 * 2: The ex, edit and visual in vi mode commands take ex commands as
390 * their first arguments.
391 * 3: The substitute command takes an RE as its first argument, and
392 * wants it to be specially delimited.
394 * Historically, '|' characters in the first argument of the ex, edit,
395 * and substitute commands did not delimit the command. And, in the
396 * filter cases for read and write, and the bang, global and vglobal
397 * commands, they did not delimit the command at all.
399 * For example, the following commands were legal:
401 * :edit +25|s/abc/ABC/ file.c
402 * :substitute s/|/PIPE/
403 * :read !spell % | columnate
404 * :global/pattern/p|l
406 * It's not quite as simple as it sounds, however. The command:
408 * :substitute s/a/b/|s/c/d|set
410 * was also legal, i.e. the historic ex parser (using the word loosely,
411 * since "parser" implies some regularity) delimited the RE's based on
412 * its delimiter and not anything so irretrievably vulgar as a command
413 * syntax.
415 * One thing that makes this easier is that we can ignore most of the
416 * command termination conditions for the commands that want to take
417 * the command up to the next newline. None of them are legal in .exrc
418 * files, so if we're here, we only dealing with a single line, and we
419 * can just eat it.
421 * Anyhow, the following code makes this all work. First, for the
422 * special cases we move past their special argument. Then, we do
423 * normal command processing on whatever is left. Barf-O-Rama.
425 * QUOTING NOTE:
427 * Historically, vi permitted ^V's to escape <newline>'s in the .exrc
428 * file. It was almost certainly a bug, but that's what bug-for-bug
429 * compatibility means, Grasshopper. Also, permit command separators
430 * to be escaped. The literal next quote characters in front of the
431 * newlines, '|' characters or literal next characters are stripped as
432 * as they're no longer useful.
434 save_cmd = cmd;
435 (void)term_key_ch(sp, K_VLNEXT, &vlit);
436 if (cp == &cmds[C_EDIT] ||
437 cp == &cmds[C_EX] || cp == &cmds[C_VISUAL_VI]) {
439 * Move to the next non-whitespace character. As '+' must
440 * be the character after the command name, if there isn't
441 * one, we're done.
443 for (; cmdlen > 0; --cmdlen, ++cmd) {
444 ch = *cmd;
445 if (!isblank(ch))
446 break;
449 * QUOTING NOTE:
451 * The historic implementation ignored all escape characters
452 * so there was no way to put a space or newline into the +cmd
453 * field. We do a simplistic job of fixing it by moving to the
454 * first whitespace character that isn't escaped by a literal
455 * next character. The literal next characters are stripped
456 * as they're no longer useful.
458 if (cmdlen > 0 && ch == '+') {
459 ++cmd;
460 --cmdlen;
461 for (arg1 = p = cmd; cmdlen > 0; --cmdlen, ++cmd) {
462 if ((ch = *cmd) == vlit && cmdlen > 1) {
463 --cmdlen;
464 ch = *++cmd;
465 } else if (isblank(ch))
466 break;
467 *p++ = ch;
469 arg1_len = cmd - arg1;
471 /* Reset, so the first argument isn't reparsed. */
472 save_cmd = cmd;
474 } else if (cp == &cmds[C_BANG] ||
475 cp == &cmds[C_GLOBAL] || cp == &cmds[C_VGLOBAL]) {
476 cmd += cmdlen;
477 cmdlen = 0;
478 } else if (cp == &cmds[C_READ] || cp == &cmds[C_WRITE]) {
480 * Move to the next character. If it's a '!', it's a filter
481 * command and we want to eat it all, otherwise, we're done.
483 for (; cmdlen > 0; --cmdlen, ++cmd) {
484 ch = *cmd;
485 if (!isblank(ch))
486 break;
488 if (cmdlen > 0 && ch == '!') {
489 cmd += cmdlen;
490 cmdlen = 0;
492 } else if (cp == &cmds[C_SUBSTITUTE]) {
494 * Move to the next non-whitespace character, we'll use it as
495 * the delimiter. Ignore if it's legal, the RE code will take
496 * care of it if it's not.
498 for (; cmdlen > 0; --cmdlen, ++cmd)
499 if (!isblank(*cmd))
500 break;
501 if (cmdlen > 0) {
503 * QUOTING NOTE:
505 * Backslashes quote delimiter characters for RE's.
506 * The backslashes are NOT reomved since they'll be
507 * used by the RE code. Move to the second or third
508 * delimiter that's not escaped.
510 delim = *cmd;
511 ++cmd;
512 --cmdlen;
513 for (cnt = cp == &cmds[C_SUBSTITUTE] ? 2 : 1;
514 cmdlen > 0 && cnt; --cmdlen, ++cmd)
515 if (*cmd == delim)
516 --cnt;
520 * Use normal quoting and termination rules to find the end
521 * of this command.
523 for (p = cmd; cmdlen > 0; --cmdlen, ++cmd) {
524 if ((ch = *cmd) == vlit && cmdlen > 1) {
525 ch = cmd[1];
526 if (ch == '\n' || ch == '|') {
527 if (ch == '\n')
528 ++sp->if_lno;
529 --cmdlen;
530 ++cmd;
531 } else
532 ch = vlit;
533 } else if (ch == '\n' || ch == '|') {
534 if (ch == '\n')
535 nl = 1;
536 --cmdlen;
537 break;
539 *p++ = ch;
543 * Save off the next command information, go back to the
544 * original start of the command.
546 p = cmd + 1;
547 cmd = save_cmd;
548 save_cmd = p;
549 save_cmdlen = cmdlen;
550 cmdlen = (save_cmd - cmd) - 1;
553 * !!!
554 * The "set tags" command historically used a backslash, not the
555 * user's literal next character, to escape whitespace. Handle
556 * it here instead of complicating the argv_exp3() code. Note,
557 * this isn't a particularly complex trap, and if backslashes were
558 * legal in set commands, this would have to be much more complicated.
560 if (cp == &cmds[C_SET])
561 for (p = cmd, len = cmdlen; len > 0; --len, ++p)
562 if (*p == '\\')
563 *p = vlit;
566 * Set the default addresses. It's an error to specify an address for
567 * a command that doesn't take them. If two addresses are specified
568 * for a command that only takes one, lose the first one. Two special
569 * cases here, some commands take 0 or 2 addresses. For most of them
570 * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
571 * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
573 * Also, if the file is empty, some commands want to use an address of
574 * 0, i.e. the entire file is 0 to 0, and the default first address is
575 * 0. Otherwise, an entire file is 1 to N and the default line is 1.
576 * Note, we also add the E_ZERO flag to the command flags, for the case
577 * where the 0 address is only valid if it's a default address.
579 * Also, set a flag if we set the default addresses. Some commands
580 * (ex: z) care if the user specified an address of if we just used
581 * the current cursor.
583 switch (LF_ISSET(E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) {
584 case E_ADDR1: /* One address: */
585 switch (exc.addrcnt) {
586 case 0: /* Default cursor/empty file. */
587 exc.addrcnt = 1;
588 F_SET(&exc, E_ADDRDEF);
589 if (LF_ISSET(E_ZERODEF)) {
590 if (file_lline(sp, ep, &lno))
591 goto err;
592 if (lno == 0) {
593 exc.addr1.lno = 0;
594 LF_SET(E_ZERO);
595 } else
596 exc.addr1.lno = sp->lno;
597 } else
598 exc.addr1.lno = sp->lno;
599 exc.addr1.cno = sp->cno;
600 break;
601 case 1:
602 break;
603 case 2: /* Lose the first address. */
604 exc.addrcnt = 1;
605 exc.addr1 = exc.addr2;
607 break;
608 case E_ADDR2_NONE: /* Zero/two addresses: */
609 if (exc.addrcnt == 0) /* Default to nothing. */
610 break;
611 goto two;
612 case E_ADDR2_ALL: /* Zero/two addresses: */
613 if (exc.addrcnt == 0) { /* Default entire/empty file. */
614 exc.addrcnt = 2;
615 F_SET(&exc, E_ADDRDEF);
616 if (file_lline(sp, ep, &exc.addr2.lno))
617 goto err;
618 if (LF_ISSET(E_ZERODEF) && exc.addr2.lno == 0) {
619 exc.addr1.lno = 0;
620 LF_SET(E_ZERO);
621 } else
622 exc.addr1.lno = 1;
623 exc.addr1.cno = exc.addr2.cno = 0;
624 F_SET(&exc, E_ADDR2_ALL);
625 break;
627 /* FALLTHROUGH */
628 case E_ADDR2: /* Two addresses: */
629 two: switch (exc.addrcnt) {
630 case 0: /* Default cursor/empty file. */
631 exc.addrcnt = 2;
632 F_SET(&exc, E_ADDRDEF);
633 if (LF_ISSET(E_ZERODEF) && sp->lno == 1) {
634 if (file_lline(sp, ep, &lno))
635 goto err;
636 if (lno == 0) {
637 exc.addr1.lno = exc.addr2.lno = 0;
638 LF_SET(E_ZERO);
639 } else
640 exc.addr1.lno = exc.addr2.lno = sp->lno;
641 } else
642 exc.addr1.lno = exc.addr2.lno = sp->lno;
643 exc.addr1.cno = exc.addr2.cno = sp->cno;
644 break;
645 case 1: /* Default to first address. */
646 exc.addrcnt = 2;
647 exc.addr2 = exc.addr1;
648 break;
649 case 2:
650 break;
652 break;
653 default:
654 if (exc.addrcnt) /* Error. */
655 goto usage;
658 flagoff = 0;
659 for (p = cp->syntax; *p != '\0'; ++p) {
661 * The write command is sensitive to leading whitespace, e.g.
662 * "write !" is different from "write!". If not the write
663 * command, skip leading whitespace.
665 if (cp != &cmds[C_WRITE])
666 for (; cmdlen > 0; --cmdlen, ++cmd) {
667 ch = *cmd;
668 if (!isblank(ch))
669 break;
673 * Quit when reach the end of the command, unless it's a
674 * command that does its own parsing, in which case we want
675 * to build a reasonable argv for it. This code guarantees
676 * that there will be an argv when the function gets called,
677 * so the correct test is for a length of 0, not for the
678 * argc > 0.
680 if (cmdlen == 0 && *p != '!' && *p != 'S' && *p != 's')
681 break;
683 switch (*p) {
684 case '!': /* ! */
685 if (*cmd == '!') {
686 ++cmd;
687 --cmdlen;
688 F_SET(&exc, E_FORCE);
690 break;
691 case '1': /* +, -, #, l, p */
693 * !!!
694 * Historically, some flags were ignored depending
695 * on where they occurred in the command line. For
696 * example, in the command, ":3+++p--#", historic vi
697 * acted on the '#' flag, but ignored the '-' flags.
698 * It's unambiguous what the flags mean, so we just
699 * handle them regardless of the stupidity of their
700 * location.
702 for (; cmdlen; --cmdlen, ++cmd)
703 switch (*cmd) {
704 case '+':
705 ++flagoff;
706 break;
707 case '-':
708 --flagoff;
709 break;
710 case '#':
711 F_SET(&exc, E_F_HASH);
712 break;
713 case 'l':
714 F_SET(&exc, E_F_LIST);
715 break;
716 case 'p':
717 F_SET(&exc, E_F_PRINT);
718 break;
719 default:
720 goto end1;
722 end1: break;
723 case '2': /* -, ., +, ^ */
724 case '3': /* -, ., +, ^, = */
725 for (; cmdlen; --cmdlen, ++cmd)
726 switch (*cmd) {
727 case '-':
728 F_SET(&exc, E_F_DASH);
729 break;
730 case '.':
731 F_SET(&exc, E_F_DOT);
732 break;
733 case '+':
734 F_SET(&exc, E_F_PLUS);
735 break;
736 case '^':
737 F_SET(&exc, E_F_CARAT);
738 break;
739 case '=':
740 if (*p == '3') {
741 F_SET(&exc, E_F_EQUAL);
742 break;
744 /* FALLTHROUGH */
745 default:
746 goto end2;
748 end2: break;
749 case 'b': /* buffer */
750 exc.buffer = *cmd;
751 ++cmd;
752 --cmdlen;
753 F_SET(&exc, E_BUFFER);
754 break;
755 case 'c': /* count [01+a] */
756 ++p;
757 if (!isdigit(*cmd) &&
758 (*p != '+' || (*cmd != '+' && *cmd != '-')))
759 break;
760 /* 8-bit XXX */ if ((lno = strtol(cmd, &t, 10)) == 0 && *p != '0') {
761 msgq(sp, M_ERR, "Count may not be zero.");
762 goto err;
764 cmdlen -= (t - cmd);
765 cmd = t;
767 * Count as address offsets occur in commands taking
768 * two addresses. Historic vi practice was to use
769 * the count as an offset from the *second* address.
771 * Set a count flag; some underlying commands (see
772 * join) do different things with counts than with
773 * line addresses.
775 if (*p == 'a') {
776 exc.addr1 = exc.addr2;
777 exc.addr2.lno = exc.addr1.lno + lno - 1;
778 } else
779 exc.count = lno;
780 F_SET(&exc, E_COUNT);
781 break;
782 case 'f': /* file */
783 if (argv_exp2(sp, ep,
784 &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
785 goto err;
786 goto countchk;
787 case 'l': /* line */
788 if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
789 goto err;
790 /* Line specifications are always required. */
791 if (!tmp) {
792 msgq(sp, M_ERR,
793 "%s: bad line specification", cmd);
794 goto err;
796 exc.lineno = cur.lno;
797 break;
798 case 'S': /* string, file exp. */
799 if (argv_exp1(sp, ep,
800 &exc, cmd, cmdlen, cp == &cmds[C_BANG]))
801 goto err;
802 goto addr2;
803 case 's': /* string */
804 if (argv_exp0(sp, ep, &exc, cmd, cmdlen))
805 goto err;
806 goto addr2;
807 case 'W': /* word string */
809 * QUOTING NOTE:
811 * Literal next characters escape the following
812 * character. Quoting characters are stripped
813 * here since they are no longer useful.
815 * First there was the word.
817 for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd) {
818 if ((ch = *cmd) == vlit && cmdlen > 1) {
819 --cmdlen;
820 *p++ = *++cmd;
821 } else if (isblank(ch)) {
822 ++cmd;
823 --cmdlen;
824 break;
825 } else
826 *p++ = ch;
828 if (argv_exp0(sp, ep, &exc, t, p - t))
829 goto err;
831 /* Delete intervening whitespace. */
832 for (; cmdlen > 0; --cmdlen, ++cmd) {
833 ch = *cmd;
834 if (!isblank(ch))
835 break;
837 if (cmdlen == 0)
838 goto usage;
840 /* Followed by the string. */
841 for (p = t = cmd; cmdlen > 0; --cmdlen, ++cmd, ++p)
842 if ((ch = *cmd) == vlit && cmdlen > 1) {
843 --cmdlen;
844 *p = *++cmd;
845 } else
846 *p = ch;
847 if (argv_exp0(sp, ep, &exc, t, p - t))
848 goto err;
849 goto addr2;
850 case 'w': /* word */
851 if (argv_exp3(sp, ep, &exc, cmd, cmdlen))
852 goto err;
853 countchk: if (*++p != 'N') { /* N */
855 * If a number is specified, must either be
856 * 0 or that number, if optional, and that
857 * number, if required.
859 num = *p - '0';
860 if ((*++p != 'o' || exp->argsoff != 0) &&
861 exp->argsoff != num)
862 goto usage;
864 goto addr2;
865 default:
866 msgq(sp, M_ERR,
867 "Internal syntax table error (%s: %c).",
868 cp->name, *p);
872 /* Skip trailing whitespace. */
873 for (; cmdlen; --cmdlen) {
874 ch = *cmd++;
875 if (!isblank(ch))
876 break;
880 * There shouldn't be anything left, and no more required
881 * fields, i.e neither 'l' or 'r' in the syntax string.
883 if (cmdlen || strpbrk(p, "lr")) {
884 usage: msgq(sp, M_ERR, "Usage: %s.", cp->usage);
885 goto err;
888 /* Verify that the addresses are legal. */
889 addr2: switch (exc.addrcnt) {
890 case 2:
891 if (file_lline(sp, ep, &lno))
892 goto err;
894 * Historic ex/vi permitted commands with counts to go past
895 * EOF. So, for example, if the file only had 5 lines, the
896 * ex command "1,6>" would fail, but the command ">300"
897 * would succeed. Since we don't want to have to make all
898 * of the underlying commands handle random line numbers,
899 * fix it here.
901 if (exc.addr2.lno > lno)
902 if (F_ISSET(&exc, E_COUNT))
903 exc.addr2.lno = lno;
904 else {
905 if (lno == 0)
906 msgq(sp, M_ERR, "The file is empty.");
907 else
908 msgq(sp, M_ERR,
909 "Only %lu line%s in the file",
910 lno, lno > 1 ? "s" : "");
911 goto err;
913 /* FALLTHROUGH */
914 case 1:
915 num = exc.addr1.lno;
917 * If it's a "default vi command", zero is okay. Historic
918 * vi allowed this, note, it's also the hack that allows
919 * "vi + nonexistent_file" to work.
921 if (num == 0 && (!IN_VI_MODE(sp) || uselastcmd != 1) &&
922 !LF_ISSET(E_ZERO)) {
923 msgq(sp, M_ERR,
924 "The %s command doesn't permit an address of 0.",
925 cp->name);
926 goto err;
928 if (file_lline(sp, ep, &lno))
929 goto err;
930 if (num > lno) {
931 if (lno == 0)
932 msgq(sp, M_ERR, "The file is empty.");
933 else
934 msgq(sp, M_ERR, "Only %lu line%s in the file",
935 lno, lno > 1 ? "s" : "");
936 goto err;
938 break;
941 /* If doing a default command, vi just moves to the line. */
942 if (IN_VI_MODE(sp) && uselastcmd) {
943 switch (exc.addrcnt) {
944 case 2:
945 sp->lno = exc.addr2.lno ? exc.addr2.lno : 1;
946 sp->cno = exc.addr2.cno;
947 break;
948 case 1:
949 sp->lno = exc.addr1.lno ? exc.addr1.lno : 1;
950 sp->cno = exc.addr1.cno;
951 break;
953 cmd = save_cmd;
954 cmdlen = save_cmdlen;
955 goto loop;
958 /* Reset "last" command. */
959 if (LF_ISSET(E_SETLAST))
960 exp->lastcmd = cp;
962 /* Final setup for the command. */
963 exc.cmd = cp;
965 #if defined(DEBUG) && 0
966 TRACE(sp, "ex_cmd: %s", exc.cmd->name);
967 if (exc.addrcnt > 0) {
968 TRACE(sp, "\taddr1 %d", exc.addr1.lno);
969 if (exc.addrcnt > 1)
970 TRACE(sp, " addr2: %d", exc.addr2.lno);
971 TRACE(sp, "\n");
973 if (exc.lineno)
974 TRACE(sp, "\tlineno %d", exc.lineno);
975 if (exc.flags)
976 TRACE(sp, "\tflags %0x", exc.flags);
977 if (F_ISSET(&exc, E_BUFFER))
978 TRACE(sp, "\tbuffer %c", exc.buffer);
979 TRACE(sp, "\n");
980 if (exc.argc) {
981 for (cnt = 0; cnt < exc.argc; ++cnt)
982 TRACE(sp, "\targ %d: {%s}", cnt, exc.argv[cnt]);
983 TRACE(sp, "\n");
985 #endif
986 /* Clear autoprint. */
987 F_CLR(sp, S_AUTOPRINT);
989 /* Increment the command count if not called from vi. */
990 if (!IN_VI_MODE(sp))
991 ++sp->ccnt;
994 * If file state and not doing a global command, log the start of
995 * an action.
997 if (ep != NULL && !F_ISSET(sp, S_GLOBAL))
998 (void)log_cursor(sp, ep);
1000 /* Save the current mode. */
1001 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
1003 /* Do the command. */
1004 if ((cp->fn)(sp, ep, &exc))
1005 goto err;
1007 #ifdef DEBUG
1008 /* Make sure no function left the temporary space locked. */
1009 if (F_ISSET(sp->gp, G_TMP_INUSE)) {
1010 F_CLR(sp->gp, G_TMP_INUSE);
1011 msgq(sp, M_ERR, "Error: ex: temporary buffer not released.");
1012 goto err;
1014 #endif
1015 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE)) {
1017 * Only here if the mode of the underlying file changed, e.g.
1018 * the user switched files or is exiting. There are two things
1019 * that we might have to save. First, any "+cmd" field set up
1020 * for an ex/edit command will have to be saved for later, also,
1021 * any not yet executed part of the current ex command.
1023 * :edit +25 file.c|s/abc/ABC/|1
1025 * for example.
1027 * The historic vi just hung, of course; we handle by
1028 * pushing the keys onto the tty queue. If we're
1029 * switching modes to vi, since the commands are intended
1030 * as ex commands, add the extra characters to make it
1031 * work.
1033 * For the fun of it, if you want to see if a vi clone got
1034 * the ex argument parsing right, try:
1036 * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
1037 * vi
1038 * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
1040 if (arg1_len == NULL && save_cmdlen == 0)
1041 return (0);
1042 if (IN_VI_MODE(sp) && term_push(sp, "\n", 1, 0, 0))
1043 goto err;
1044 if (save_cmdlen != 0)
1045 if (term_push(sp, save_cmd, save_cmdlen, 0, 0))
1046 goto err;
1047 if (arg1 != NULL) {
1048 if (IN_VI_MODE(sp) && save_cmdlen != 0 &&
1049 term_push(sp, "|", 1, 0, 0))
1050 goto err;
1051 if (term_push(sp, arg1, arg1_len, 0, 0))
1052 goto err;
1054 if (IN_VI_MODE(sp) && term_push(sp, ":", 1, 0, 0))
1055 goto err;
1056 return (0);
1059 if (IN_EX_MODE(sp) && ep != NULL) {
1061 * The print commands have already handled the `print' flags.
1062 * If so, clear them. Don't return, autoprint may still have
1063 * stuff to print out.
1065 if (LF_ISSET(E_F_PRCLEAR))
1066 F_CLR(&exc, E_F_HASH | E_F_LIST | E_F_PRINT);
1069 * If the command was successful, and there was an explicit
1070 * flag to display the new cursor line, or we're in ex mode,
1071 * autoprint is set, and a change was made, display the line.
1073 if (flagoff) {
1074 if (flagoff < 0) {
1075 if (sp->lno < -flagoff) {
1076 msgq(sp, M_ERR,
1077 "Flag offset before line 1.");
1078 goto err;
1080 } else {
1081 if (file_lline(sp, ep, &lno))
1082 goto err;
1083 if (sp->lno + flagoff > lno) {
1084 msgq(sp, M_ERR,
1085 "Flag offset past end-of-file.");
1086 goto err;
1089 sp->lno += flagoff;
1092 if (F_ISSET(sp, S_AUTOPRINT) && O_ISSET(sp, O_AUTOPRINT))
1093 LF_INIT(E_F_PRINT);
1094 else
1095 LF_INIT(F_ISSET(&exc, E_F_HASH | E_F_LIST | E_F_PRINT));
1097 memset(&exc, 0, sizeof(EXCMDARG));
1098 exc.addrcnt = 2;
1099 exc.addr1.lno = exc.addr2.lno = sp->lno;
1100 exc.addr1.cno = exc.addr2.cno = sp->cno;
1101 switch (LF_ISSET(E_F_HASH | E_F_LIST | E_F_PRINT)) {
1102 case E_F_HASH:
1103 exc.cmd = &cmds[C_HASH];
1104 ex_number(sp, ep, &exc);
1105 break;
1106 case E_F_LIST:
1107 exc.cmd = &cmds[C_LIST];
1108 ex_list(sp, ep, &exc);
1109 break;
1110 case E_F_PRINT:
1111 exc.cmd = &cmds[C_PRINT];
1112 ex_pr(sp, ep, &exc);
1113 break;
1117 cmd = save_cmd;
1118 cmdlen = save_cmdlen;
1119 goto loop;
1120 /* NOTREACHED */
1123 * On error, we discard any keys we have left, as well as any keys
1124 * that were mapped. The test of save_cmdlen isn't necessarily
1125 * correct. If we fail early enough we don't know if the entire
1126 * string was a single command or not. Try and guess, it's useful
1127 * to know if part of the command was discarded.
1129 if (save_cmdlen == 0)
1130 for (; cmdlen; --cmdlen)
1131 if ((ch = *cmd++) == vlit && cmdlen > 1) {
1132 --cmdlen;
1133 ++cmd;
1134 } else if (ch == '\n' || ch == '|') {
1135 if (cmdlen > 1)
1136 save_cmdlen = 1;
1137 break;
1139 if (save_cmdlen != 0)
1140 msgq(sp, M_ERR,
1141 "Ex command failed: remaining command input discarded.");
1142 err: term_map_flush(sp, "Ex command failed");
1143 return (1);
1147 * ep_range --
1148 * Get a line range for ex commands.
1150 static int
1151 ep_range(sp, ep, excp, cmdp, cmdlenp)
1152 SCR *sp;
1153 EXF *ep;
1154 EXCMDARG *excp;
1155 char **cmdp;
1156 size_t *cmdlenp;
1158 MARK cur, savecursor;
1159 size_t cmdlen;
1160 int savecursor_set, tmp;
1161 char *cmd;
1163 /* Percent character is all lines in the file. */
1164 cmd = *cmdp;
1165 cmdlen = *cmdlenp;
1166 if (*cmd == '%') {
1167 excp->addr1.lno = 1;
1168 if (file_lline(sp, ep, &excp->addr2.lno))
1169 return (1);
1171 /* If an empty file, then the first line is 0, not 1. */
1172 if (excp->addr2.lno == 0)
1173 excp->addr1.lno = 0;
1174 excp->addr1.cno = excp->addr2.cno = 0;
1175 excp->addrcnt = 2;
1177 ++*cmdp;
1178 --*cmdlenp;
1179 return (0);
1182 /* Parse comma or semi-colon delimited line specs. */
1183 for (savecursor_set = 0, excp->addrcnt = 0; cmdlen > 0;)
1184 switch (*cmd) {
1185 case ';': /* Semi-colon delimiter. */
1187 * Comma delimiters delimit; semi-colon delimiters
1188 * change the current address for the 2nd address
1189 * to be the first address. Trailing or multiple
1190 * delimiters are discarded.
1192 if (excp->addrcnt == 0)
1193 goto done;
1194 if (!savecursor_set) {
1195 savecursor.lno = sp->lno;
1196 savecursor.cno = sp->cno;
1197 sp->lno = excp->addr1.lno;
1198 sp->cno = excp->addr1.cno;
1199 savecursor_set = 1;
1201 ++cmd;
1202 --cmdlen;
1203 break;
1204 case ',': /* Comma delimiter. */
1205 /* If no addresses yet, defaults to ".". */
1206 if (excp->addrcnt == 0) {
1207 excp->addr1.lno = sp->lno;
1208 excp->addr1.cno = sp->cno;
1209 excp->addrcnt = 1;
1211 /* FALLTHROUGH */
1212 case ' ': /* Whitespace. */
1213 case '\t': /* Whitespace. */
1214 ++cmd;
1215 --cmdlen;
1216 break;
1217 default:
1218 if (ep_line(sp, ep, &cur, &cmd, &cmdlen, &tmp))
1219 return (1);
1220 if (!tmp)
1221 goto done;
1224 * Extra addresses are discarded, starting with
1225 * the first.
1227 switch (excp->addrcnt) {
1228 case 0:
1229 excp->addr1 = cur;
1230 excp->addrcnt = 1;
1231 break;
1232 case 1:
1233 excp->addr2 = cur;
1234 excp->addrcnt = 2;
1235 break;
1236 case 2:
1237 excp->addr1 = excp->addr2;
1238 excp->addr2 = cur;
1239 break;
1241 break;
1245 * XXX
1246 * This is probably not right behavior for savecursor -- need
1247 * to figure out what the historical ex did for ";,;,;5p" or
1248 * similar stupidity.
1250 done: if (savecursor_set) {
1251 sp->lno = savecursor.lno;
1252 sp->cno = savecursor.cno;
1254 if (excp->addrcnt == 2 &&
1255 (excp->addr2.lno < excp->addr1.lno ||
1256 excp->addr2.lno == excp->addr1.lno &&
1257 excp->addr2.cno < excp->addr1.cno)) {
1258 msgq(sp, M_ERR,
1259 "The second address is smaller than the first.");
1260 return (1);
1262 *cmdp = cmd;
1263 *cmdlenp = cmdlen;
1264 return (0);
1268 * Get a single line address specifier.
1270 static int
1271 ep_line(sp, ep, cur, cmdp, cmdlenp, addr_found)
1272 SCR *sp;
1273 EXF *ep;
1274 MARK *cur;
1275 char **cmdp;
1276 size_t *cmdlenp;
1277 int *addr_found;
1279 MARK m, *mp;
1280 long total;
1281 u_int flags;
1282 size_t cmdlen;
1283 char *cmd, *endp;
1285 *addr_found = 0;
1287 cmd = *cmdp;
1288 cmdlen = *cmdlenp;
1289 switch (*cmd) {
1290 case '$': /* Last line in the file. */
1291 *addr_found = 1;
1292 cur->cno = 0;
1293 if (file_lline(sp, ep, &cur->lno))
1294 return (1);
1295 ++cmd;
1296 --cmdlen;
1297 break; /* Absolute line number. */
1298 case '0': case '1': case '2': case '3': case '4':
1299 case '5': case '6': case '7': case '8': case '9':
1300 *addr_found = 1;
1302 * The way the vi "previous context" mark worked was that
1303 * "non-relative" motions set it. While vi wasn't totally
1304 * consistent about this, ANY numeric address was considered
1305 * non-relative, and set the value. Which is why we're
1306 * hacking marks down here.
1308 if (IN_VI_MODE(sp)) {
1309 m.lno = sp->lno;
1310 m.cno = sp->cno;
1311 if (mark_set(sp, ep, ABSMARK1, &m, 1))
1312 return (1);
1314 cur->cno = 0;
1315 /* 8-bit XXX */ cur->lno = strtol(cmd, &endp, 10);
1316 cmdlen -= (endp - cmd);
1317 cmd = endp;
1318 break;
1319 case '\'': /* Use a mark. */
1320 *addr_found = 1;
1321 if (cmdlen == 1) {
1322 msgq(sp, M_ERR, "No mark name supplied.");
1323 return (1);
1325 if ((mp = mark_get(sp, ep, cmd[1])) == NULL)
1326 return (1);
1327 *cur = *mp;
1328 cmd += 2;
1329 cmdlen -= 2;
1330 break;
1331 case '/': /* Search forward. */
1332 *addr_found = 1;
1333 m.lno = sp->lno;
1334 m.cno = sp->cno;
1335 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1336 if (f_search(sp, ep, &m, &m, cmd, &endp, &flags))
1337 return (1);
1338 cur->lno = m.lno;
1339 cur->cno = m.cno;
1340 cmdlen -= (endp - cmd);
1341 cmd = endp;
1342 break;
1343 case '?': /* Search backward. */
1344 *addr_found = 1;
1345 m.lno = sp->lno;
1346 m.cno = sp->cno;
1347 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1348 if (b_search(sp, ep, &m, &m, cmd, &endp, &flags))
1349 return (1);
1350 cur->lno = m.lno;
1351 cur->cno = m.cno;
1352 cmdlen -= (endp - cmd);
1353 cmd = endp;
1354 break;
1355 case '.': /* Current position. */
1356 *addr_found = 1;
1357 cur->cno = sp->cno;
1359 /* If an empty file, then '.' is 0, not 1. */
1360 if (sp->lno == 1) {
1361 if (file_lline(sp, ep, &cur->lno))
1362 return (1);
1363 if (cur->lno != 0)
1364 cur->lno = 1;
1365 } else
1366 cur->lno = sp->lno;
1367 ++cmd;
1368 --cmdlen;
1369 break;
1373 * Evaluate any offset. Offsets are +/- any number, or any number
1374 * of +/- signs, or any combination thereof. If no address found
1375 * yet, offset is relative to ".".
1377 for (total = 0; cmdlen > 0 && (cmd[0] == '-' || cmd[0] == '+');) {
1378 if (!*addr_found) {
1379 cur->lno = sp->lno;
1380 cur->cno = sp->cno;
1381 *addr_found = 1;
1384 if (cmdlen > 1 && isdigit(cmd[1])) {
1385 /* 8-bit XXX */ total += strtol(cmd, &endp, 10);
1386 cmdlen -= (endp - cmd);
1387 cmd = endp;
1388 } else {
1389 total += cmd[0] == '-' ? -1 : 1;
1390 --cmdlen;
1391 ++cmd;
1394 if (total < 0 && -total > cur->lno) {
1395 msgq(sp, M_ERR, "Reference to a line number less than 0.");
1396 return (1);
1398 cur->lno += total;
1400 *cmdp = cmd;
1401 *cmdlenp = cmdlen;
1402 return (0);