go to 0.81
[nvi.git] / ex / ex.c
blobe67234d1114ded6ee265003d833392a2d7101eea
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.48 1993/11/04 16:16:49 bostic Exp $ (Berkeley) $Date: 1993/11/04 16:16:49 $";
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 void ep_comm __P((SCR *, char **, char **, int *, char **, int *));
26 static char *ep_line __P((SCR *, EXF *, char *, MARK *));
27 static char *ep_range __P((SCR *, EXF *, char *, EXCMDARG *));
28 static void ep_re __P((SCR *, char **, char **, int *));
29 static void ep_rw __P((SCR *, char **, char **, int *));
31 #define DEFCOM ".+1"
34 * ex --
35 * Read an ex command and execute it.
37 int
38 ex(sp, ep)
39 SCR *sp;
40 EXF *ep;
42 TEXT *tp;
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 /* Edited as it can be. */
53 F_SET(sp->frp, FR_EDITED);
55 for (eval = 0;;) {
56 /* Get the next command. */
57 switch (sp->s_get(sp, ep,
58 &sp->txthdr, ':', TXT_CR | TXT_PROMPT)) {
59 case INP_OK:
60 break;
61 case INP_EOF:
62 F_SET(sp, S_EXIT_FORCE);
63 goto ret;
64 case INP_ERR:
65 continue;
68 tp = sp->txthdr.next;
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_cstring(sp, ep, defcom, sizeof(DEFCOM) - 1);
76 } else {
77 if (F_ISSET(sp->gp, G_ISFROMTTY))
78 (void)fputc('\n', stdout);
79 (void)ex_cstring(sp, ep, tp->lb, tp->len);
81 (void)msg_rpt(sp, 0);
83 if (!F_ISSET(sp, S_MODE_EX) || F_ISSET(sp, S_MAJOR_CHANGE))
84 break;
86 if (sp->s_refresh(sp, ep)) {
87 eval = 1;
88 break;
91 ret: return (ex_end(sp) || eval);
95 * ex_cfile --
96 * Execute ex commands from a file.
98 int
99 ex_cfile(sp, ep, filename)
100 SCR *sp;
101 EXF *ep;
102 char *filename;
104 struct stat sb;
105 int fd, len, rval;
106 char *bp;
108 if ((fd = open(filename, O_RDONLY, 0)) < 0)
109 goto e1;
110 if (fstat(fd, &sb))
111 goto e2;
114 * XXX
115 * We'd like to test if the file is too big to malloc. Since we don't
116 * know what size or type off_t's or size_t's are, what the largest
117 * unsigned integral type is, or what random insanity the local C
118 * compiler will perpetrate, doing the comparison in a portable way
119 * is flatly impossible. Hope that malloc fails if the file is too
120 * large.
122 if ((bp = malloc((size_t)sb.st_size)) == NULL)
123 goto e2;
125 len = read(fd, bp, (int)sb.st_size);
126 if (len == -1 || len != sb.st_size) {
127 if (len != sb.st_size)
128 errno = EIO;
129 goto e3;
131 bp[sb.st_size] = '\0';
133 rval = ex_cstring(sp, ep, bp, len);
135 * XXX
136 * THE UNDERLYING EXF MAY HAVE CHANGED (but we don't care).
138 free(bp);
139 (void)close(fd);
140 return (rval);
142 e3: free(bp);
143 e2: (void)close(fd);
144 e1: msgq(sp, M_ERR, "%s: %s.", filename, strerror(errno));
145 return (1);
149 * ex_cstring --
150 * Execute EX commands from a string.
153 ex_cstring(sp, ep, cmd, len)
154 SCR *sp;
155 EXF *ep;
156 char *cmd;
157 int len;
159 u_int saved_mode;
160 int ch, arg1_len;
161 char *p, *t, *arg1;
164 * Ex goes through here for each vi :colon command and for each ex
165 * command, however, globally executed commands don't go through
166 * here, instead, they call ex_cmd directly. So, reset all of the
167 * interruptible flags now.
169 F_CLR(sp, S_INTERRUPTED | S_INTERRUPTIBLE);
171 /* This is probably not necessary, but it's worth being safe. */
172 if (len == 0)
173 return (0);
176 * QUOTING NOTE:
178 * Commands may be separated by newline or '|' characters, and may
179 * be escaped by literal next characters. The quote characters are
180 * stripped here since they are no longer useful.
182 * There are seven exceptions to this. The filter versions of read
183 * and write are delimited by newlines (the filter command can contain
184 * shell pipes) ex and edit take ex commands as arguments, and global,
185 * vglobal and substitute take RE's as arguments and want their first
186 * argument be specially delimited, not necessarily by '|' characters.
187 * See ep_comm(), ep_re() and ep_rw() below for details.
189 arg1 = NULL;
190 arg1_len = 0;
191 saved_mode = F_ISSET(sp, S_MODE_EX | S_MODE_VI | S_MAJOR_CHANGE);
192 for (p = t = cmd;;) {
193 if (p == cmd) {
194 /* Skip leading whitespace. */
195 for (; len > 0 && (isblank(t[0]) || t[0] == '|' ||
196 sp->special[t[0]] == K_VLNEXT); ++t, --len);
199 * Skip leading address. The command starts with
200 * the first alphabetic character.
202 for (; len > 0; ++p, ++t, --len) {
203 ch = *p = *t;
204 if (isalpha(ch))
205 break;
208 /* Special case read/write, ex/edit, RE commands. */
209 if (len > 0 &&
210 strchr("egrvws", t[0] == ':' ? t[1] : t[0]))
211 switch (t[0] == ':' ? t[1] : t[0]) {
212 case 'e':
213 ep_comm(sp,
214 &p, &t, &len, &arg1, &arg1_len);
215 break;
216 case 'r':
217 case 'w':
218 ep_rw(sp, &p, &t, &len);
219 break;
220 case 'g':
221 case 'v':
222 case 's':
223 ep_re(sp, &p, &t, &len);
224 break;
226 if (len == 0)
227 goto cend;
230 ch = *t++;
231 --len; /* Characters remaining. */
234 * Historically, vi permitted ^V's to escape <newline>'s in
235 * the .exrc file. It was almost certainly a bug, but that's
236 * what bug-for-bug compatibility means, Grasshopper.
238 if (sp->special[ch] == K_VLNEXT && len > 0 &&
239 (t[0] == '|' || sp->special[t[0]] == K_NL)) {
240 --len;
241 *p++ = *t++;
242 continue;
244 if (len == 0 || ch == '|' || sp->special[ch] == K_NL) {
245 if (len == 0 && ch != '|' && sp->special[ch] != K_NL)
246 *p++ = ch;
247 cend: if (p > cmd) {
248 *p = '\0'; /* XXX: 8BIT */
249 if (ex_cmd(sp, ep, cmd, arg1_len)) {
250 if (len || TERM_KEY_MORE(sp)) {
251 TERM_KEY_FLUSH(sp);
252 msgq(sp, M_ERR,
253 "Ex command failed, remaining command input discarded.");
255 return (1);
257 p = cmd;
259 if (saved_mode !=
260 F_ISSET(sp, S_MODE_EX | S_MODE_VI | S_MAJOR_CHANGE))
261 break;
262 if (len == 0)
263 return (0);
264 } else
265 *p++ = ch;
268 * Only here if the mode of the underlying file changed, the user
269 * switched files or is exiting. There are two things that we may
270 * have to save. First, any "+cmd" field that ep_comm() set up will
271 * have to be saved for later. Also, there may be part of the
272 * current ex command which we haven't executed:
274 * :edit +25 file.c|s/abc/ABC/|1
276 * for example.
278 * The historic vi just hung, of course; we handle by pushing the
279 * keys onto the SCR's tty buffer. If we're switching modes to
280 * vi, since the commands are intended as ex commands, add the extra
281 * characters to make it work.
283 * For the fun of it, if you want to see if a vi clone got the ex
284 * argument parsing right, try:
286 * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
287 * vi
288 * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
290 if (arg1 == NULL && len == 0)
291 return (0);
292 if (F_ISSET(sp, S_MODE_VI) && term_push(sp, sp->gp->tty, "\n", 1))
293 goto err;
294 if (len != 0)
295 if (term_push(sp, sp->gp->tty, t, len))
296 goto err;
297 if (arg1 != NULL) {
298 if (F_ISSET(sp, S_MODE_VI) && len != 0 &&
299 term_push(sp, sp->gp->tty, "|", 1))
300 goto err;
301 if (term_push(sp, sp->gp->tty, arg1, arg1_len))
302 goto err;
304 if (F_ISSET(sp, S_MODE_VI) && term_push(sp, sp->gp->tty, ":", 1)) {
305 err: TERM_KEY_FLUSH(sp);
306 msgq(sp, M_ERR, "Error: %s: remaining command input discarded",
307 strerror(errno));
309 return (0);
313 * ex_cmd --
314 * Parse and execute an ex command.
317 ex_cmd(sp, ep, exc, arg1_len)
318 SCR *sp;
319 EXF *ep;
320 char *exc;
321 int arg1_len;
323 EXCMDARG cmd;
324 EXCMDLIST const *cp;
325 MARK cur;
326 recno_t lcount, lno, num;
327 long flagoff;
328 u_int saved_mode;
329 int ch, cmdlen, esc, flags, uselastcmd;
330 char *p, *t, *endp;
332 #if defined(DEBUG) && 0
333 TRACE(sp, "ex: {%s}\n", exc);
334 #endif
336 * Permit a single extra colon at the start of the line, for
337 * historical reasons.
339 if (*exc == ':')
340 ++exc;
342 /* Ignore command lines that start with a double-quote. */
343 if (*exc == '"')
344 return (0);
346 /* Skip whitespace. */
347 for (; isblank(*exc); ++exc);
349 /* Initialize the argument structure. */
350 memset(&cmd, 0, sizeof(EXCMDARG));
351 sp->ex_argv[0] = "";
352 sp->ex_argv[1] = NULL;
353 cmd.argc = 0;
354 cmd.argv = sp->ex_argv;
357 * Parse line specifiers if the command uses addresses.
358 * New command line position is returned, or NULL on error.
360 if ((exc = ep_range(sp, ep, exc, &cmd)) == NULL)
361 return (1);
363 /* Skip whitespace. */
364 for (; isblank(*exc); ++exc);
367 * If no command, ex does the last specified of p, l, or #, and vi
368 * moves to the line. Otherwise, find out how long the command name
369 * is. There are a few commands that aren't alphabetic, but they
370 * are all single character commands.
372 #define SINGLE_CHAR_COMMANDS "!#&<=>@~"
373 if (*exc) {
374 if (strchr(SINGLE_CHAR_COMMANDS, *exc)) {
375 p = exc;
376 exc++;
377 cmdlen = 1;
378 } else {
379 for (p = exc; isalpha(*exc); ++exc);
380 cmdlen = exc - p;
381 if (cmdlen == 0) {
382 msgq(sp, M_ERR, "Unknown command name.");
383 return (1);
386 for (cp = cmds; cp->name && memcmp(p, cp->name, cmdlen); ++cp);
389 * !!!
390 * Historic vi permitted the mark to immediately follow the 'k'
391 * in the 'k' command. Make it work.
393 * Use of msgq below is safe, command names are all alphabetics.
395 if (cp->name == NULL)
396 if (p[0] == 'k' && p[1] && !p[2]) {
397 exc = p + 1;
398 cp = &cmds[C_K];
399 } else {
400 msgq(sp, M_ERR,
401 "The %.*s command is unknown.", cmdlen, p);
402 return (1);
404 uselastcmd = 0;
406 /* Some commands are turned off. */
407 if (F_ISSET(cp, E_NOPERM)) {
408 msgq(sp, M_ERR,
409 "The %.*s command is not currently supported.",
410 cmdlen, p);
411 return (1);
414 /* Some commands aren't okay in globals. */
415 if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) {
416 msgq(sp, M_ERR,
417 "The %.*s command can't be used as part of a global command.", cmdlen, p);
418 return (1);
422 * Multiple < and > characters; another "special" feature.
423 * NOTE: The string may not be nul terminated in this case.
425 if ((cp == &cmds[C_SHIFTL] && *p == '<') ||
426 (cp == &cmds[C_SHIFTR] && *p == '>')) {
427 sp->ex_argv[0] = p;
428 sp->ex_argv[1] = NULL;
429 cmd.argc = 1;
430 cmd.argv = sp->ex_argv;
431 for (ch = *p, exc = p; *++exc == ch;);
435 * The visual command has a different syntax when called
436 * from ex than when called from a vi colon command. FMH.
438 if (cp == &cmds[C_VISUAL_EX] && F_ISSET(sp, S_MODE_VI))
439 cp = &cmds[C_VISUAL_VI];
440 } else {
441 cp = sp->lastcmd;
442 uselastcmd = 1;
444 LF_INIT(cp->flags);
447 * File state must be checked throughout this code, because it is
448 * called when reading the .exrc file and similar things. There's
449 * this little chicken and egg problem -- if we read the file first,
450 * we won't know how to display it. If we read/set the exrc stuff
451 * first, we can't allow any command that requires file state.
452 * Historic vi generally took the easy way out and dropped core.
454 if (LF_ISSET(E_NORC) && ep == NULL) {
455 msgq(sp, M_ERR,
456 "The %s command requires a file to already have been read in.",
457 cp->name);
458 return (1);
462 * Set the default addresses. It's an error to specify an address for
463 * a command that doesn't take them. If two addresses are specified
464 * for a command that only takes one, lose the first one. Two special
465 * cases here, some commands take 0 or 2 addresses. For most of them
466 * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
467 * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
469 * Also, if the file is empty, some commands want to use an address of
470 * 0, i.e. the entire file is 0 to 0, and the default first address is
471 * 0. Otherwise, an entire file is 1 to N and the default line is 1.
472 * Note, we also add the E_ZERO flag to the command flags, for the case
473 * where the 0 address is only valid if it's a default address.
475 * Also, set a flag if we set the default addresses. Some commands
476 * (ex: z) care if the user specified an address of if we just used
477 * the current cursor.
479 flagoff = 0;
480 switch (flags & (E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) {
481 case E_ADDR1: /* One address: */
482 switch (cmd.addrcnt) {
483 case 0: /* Default cursor/empty file. */
484 cmd.addrcnt = 1;
485 F_SET(&cmd, E_ADDRDEF);
486 if (LF_ISSET(E_ZERODEF)) {
487 if (file_lline(sp, ep, &lno))
488 return (1);
489 if (lno == 0) {
490 cmd.addr1.lno = 0;
491 LF_SET(E_ZERO);
492 } else
493 cmd.addr1.lno = sp->lno;
494 } else
495 cmd.addr1.lno = sp->lno;
496 cmd.addr1.cno = sp->cno;
497 break;
498 case 1:
499 break;
500 case 2: /* Lose the first address. */
501 cmd.addrcnt = 1;
502 cmd.addr1 = cmd.addr2;
504 break;
505 case E_ADDR2_NONE: /* Zero/two addresses: */
506 if (cmd.addrcnt == 0) /* Default to nothing. */
507 break;
508 goto two;
509 case E_ADDR2_ALL: /* Zero/two addresses: */
510 if (cmd.addrcnt == 0) { /* Default entire/empty file. */
511 cmd.addrcnt = 2;
512 F_SET(&cmd, E_ADDRDEF);
513 if (file_lline(sp, ep, &cmd.addr2.lno))
514 return (1);
515 if (LF_ISSET(E_ZERODEF) && cmd.addr2.lno == 0) {
516 cmd.addr1.lno = 0;
517 LF_SET(E_ZERO);
518 } else
519 cmd.addr1.lno = 1;
520 cmd.addr1.cno = cmd.addr2.cno = 0;
521 F_SET(&cmd, E_ADDR2_ALL);
522 break;
524 /* FALLTHROUGH */
525 case E_ADDR2: /* Two addresses: */
526 two: switch (cmd.addrcnt) {
527 case 0: /* Default cursor/empty file. */
528 cmd.addrcnt = 2;
529 F_SET(&cmd, E_ADDRDEF);
530 if (LF_ISSET(E_ZERODEF) && sp->lno == 1) {
531 if (file_lline(sp, ep, &lno))
532 return (1);
533 if (lno == 0) {
534 cmd.addr1.lno = cmd.addr2.lno = 0;
535 LF_SET(E_ZERO);
536 } else
537 cmd.addr1.lno = cmd.addr2.lno = sp->lno;
538 } else
539 cmd.addr1.lno = cmd.addr2.lno = sp->lno;
540 cmd.addr1.cno = cmd.addr2.cno = sp->cno;
541 break;
542 case 1: /* Default to first address. */
543 cmd.addrcnt = 2;
544 cmd.addr2 = cmd.addr1;
545 break;
546 case 2:
547 break;
549 break;
550 default:
551 if (cmd.addrcnt) /* Error. */
552 goto usage;
556 * YASC. The "set tags" command historically used a backslash, not
557 * the user's literal next character, to escape whitespace. Handle
558 * it here instead of complicating the argv_exp3() code. Note, this
559 * isn't a particularly complex trap, and if backslashes were legal
560 * in set commands, this would have to be much more complicated.
562 if (cp == &cmds[C_SET]) {
563 esc = sp->gp->original_termios.c_cc[VLNEXT];
564 for (p = exc; (ch = *p) != '\0'; ++p)
565 if (ch == '\\')
566 *p = esc;
569 for (lcount = 0, p = cp->syntax; *p != '\0'; ++p) {
571 * The write command is sensitive to leading whitespace,
572 * i.e. "write !" is different from "write!". If not write,
573 * skip leading whitespace.
575 if (cp != &cmds[C_WRITE])
576 for (; isblank(*exc); ++exc);
579 * When reach the end of the command, quit, unless it's
580 * a command that does its own parsing, in which case we
581 * want to build a reasonable argv for it.
583 if (*p != 's' && *p != 'S' && *exc == '\0')
584 break;
586 switch (*p) {
587 case '!': /* ! */
588 if (*exc == '!') {
589 ++exc;
590 F_SET(&cmd, E_FORCE);
592 break;
593 case '+': /* +cmd */
594 if (*exc != '+')
595 break;
596 exc += arg1_len + 1;
597 if (*exc)
598 *exc++ = '\0';
599 break;
600 case '1': /* +, -, #, l, p */
602 * !!!
603 * Historically, some flags were ignored depending
604 * on where they occurred in the command line. For
605 * example, in the command, ":3+++p--#", historic vi
606 * acted on the '#' flag, but ignored the '-' flags.
607 * It's unambiguous what the flags mean, so we just
608 * handle them regardless of the stupidity of their
609 * location.
611 for (;; ++exc)
612 switch (*exc) {
613 case '+':
614 ++flagoff;
615 break;
616 case '-':
617 --flagoff;
618 break;
619 case '#':
620 F_SET(&cmd, E_F_HASH);
621 break;
622 case 'l':
623 F_SET(&cmd, E_F_LIST);
624 break;
625 case 'p':
626 F_SET(&cmd, E_F_PRINT);
627 break;
628 default:
629 goto end1;
631 end1: break;
632 case '2': /* -, ., +, ^ */
633 case '3': /* -, ., +, ^, = */
634 for (;; ++exc)
635 switch (*exc) {
636 case '-':
637 F_SET(&cmd, E_F_DASH);
638 break;
639 case '.':
640 F_SET(&cmd, E_F_DOT);
641 break;
642 case '+':
643 F_SET(&cmd, E_F_PLUS);
644 break;
645 case '^':
646 F_SET(&cmd, E_F_CARAT);
647 break;
648 case '=':
649 if (*p == '3') {
650 F_SET(&cmd, E_F_EQUAL);
651 break;
653 /* FALLTHROUGH */
654 default:
655 goto end2;
657 end2: break;
658 case 'b': /* buffer */
659 cmd.buffer = *exc++;
660 F_SET(&cmd, E_BUFFER);
661 break;
662 case 'C': /* count */
663 case 'c': /* count (address) */
664 if (!isdigit(*exc))
665 break;
666 lcount = strtol(exc, &endp, 10);
667 if (lcount == 0) {
668 msgq(sp, M_ERR,
669 "Count may not be zero.");
670 return (1);
672 exc = endp;
674 * Count as address offsets occur in commands taking
675 * two addresses. Historic vi practice was to use
676 * the count as an offset from the *second* address.
678 * Set the count flag; some underlying commands (see
679 * join) do different things with counts than with
680 * line addresses.
682 if (*p == 'C')
683 cmd.count = lcount;
684 else {
685 cmd.addr1 = cmd.addr2;
686 cmd.addr2.lno = cmd.addr1.lno + lcount - 1;
688 F_SET(&cmd, E_COUNT);
689 break;
690 case 'f': /* file */
691 if (argv_exp2(sp, ep, &cmd, exc, cp == &cmds[C_BANG]))
692 return (1);
693 goto countchk;
694 case 'l': /* line */
695 endp = ep_line(sp, ep, exc, &cur);
696 if (endp == NULL || exc == endp) {
697 msgq(sp, M_ERR,
698 "%s: bad line specification", exc);
699 return (1);
700 } else {
701 cmd.lineno = cur.lno;
702 exc = endp;
704 break;
705 case 'S': /* string, file exp. */
706 if (argv_exp1(sp, ep, &cmd, exc, cp == &cmds[C_BANG]))
707 return (1);
708 goto addr2;
709 case 's': /* string */
710 sp->ex_argv[0] = exc;
711 sp->ex_argv[1] = NULL;
712 cmd.argc = 1;
713 cmd.argv = sp->ex_argv;
714 goto addr2;
715 case 'W': /* word string */
717 * QUOTING NOTE:
719 * Literal next characters escape the following
720 * character. The quote characters are stripped
721 * here since they are no longer useful.
723 * Word.
725 for (p = t = exc; (ch = *p) != '\0'; *t++ = ch, ++p)
726 if (sp->special[ch] == K_VLNEXT && p[1] != '\0')
727 ch = *++p;
728 else if (isblank(ch))
729 break;
730 if (*p == '\0')
731 goto usage;
732 sp->ex_argv[0] = exc;
734 /* Delete leading whitespace. */
735 for (*t++ = '\0'; (ch = *++p) != '\0' && isblank(ch););
737 /* String. */
738 sp->ex_argv[1] = p;
739 for (t = p; (ch = *p++) != '\0'; *t++ = ch)
740 if (sp->special[ch] == K_VLNEXT && p[0] != '\0')
741 ch = *p++;
742 *t = '\0';
743 sp->ex_argv[2] = NULL;
744 cmd.argc = 2;
745 cmd.argv = sp->ex_argv;
746 goto addr2;
747 case 'w': /* word */
748 if (argv_exp3(sp, ep, &cmd, exc))
749 return (1);
750 countchk: if (*++p != 'N') { /* N */
752 * If a number is specified, must either be
753 * 0 or that number, if optional, and that
754 * number, if required.
756 num = *p - '0';
757 if ((*++p != 'o' || cmd.argc != 0) &&
758 cmd.argc != num)
759 goto usage;
761 goto addr2;
762 default:
763 msgq(sp, M_ERR,
764 "Internal syntax table error (%s).", cp->name);
769 * Shouldn't be anything left, and no more required fields.
770 * That means neither 'l' or 'r' in the syntax.
772 for (; *exc && isblank(*exc); ++exc);
773 if (*exc || strpbrk(p, "lr")) {
774 usage: msgq(sp, M_ERR, "Usage: %s.", cp->usage);
775 return (1);
778 /* Verify that the addresses are legal. */
779 addr2: switch (cmd.addrcnt) {
780 case 2:
781 if (file_lline(sp, ep, &lcount))
782 return (1);
784 * Historic ex/vi permitted commands with counts to go past
785 * EOF. So, for example, if the file only had 5 lines, the
786 * ex command "1,6>" would fail, but the command ">300"
787 * would succeed. Since we don't want to have to make all
788 * of the underlying commands handle random line numbers,
789 * fix it here.
791 if (cmd.addr2.lno > lcount)
792 if (F_ISSET(&cmd, E_COUNT))
793 cmd.addr2.lno = lcount;
794 else {
795 if (lcount == 0)
796 msgq(sp, M_ERR, "The file is empty.");
797 else
798 msgq(sp, M_ERR,
799 "Only %lu line%s in the file",
800 lcount, lcount > 1 ? "s" : "");
801 return (1);
803 /* FALLTHROUGH */
804 case 1:
805 num = cmd.addr1.lno;
807 * If it's a "default vi command", zero is okay. Historic
808 * vi allowed this, note, it's also the hack that allows
809 * "vi + nonexistent_file" to work.
811 if (num == 0 && (!F_ISSET(sp, S_MODE_VI) || uselastcmd != 1) &&
812 !LF_ISSET(E_ZERO)) {
813 msgq(sp, M_ERR,
814 "The %s command doesn't permit an address of 0.",
815 cp->name);
816 return (1);
818 if (file_lline(sp, ep, &lcount))
819 return (1);
820 if (num > lcount) {
821 if (lcount == 0)
822 msgq(sp, M_ERR, "The file is empty.");
823 else
824 msgq(sp, M_ERR, "Only %lu line%s in the file",
825 lcount, lcount > 1 ? "s" : "");
826 return (1);
828 break;
831 /* If doing a default command, vi just moves to the line. */
832 if (F_ISSET(sp, S_MODE_VI) && uselastcmd) {
833 switch (cmd.addrcnt) {
834 case 2:
835 sp->lno = cmd.addr2.lno ? cmd.addr2.lno : 1;
836 sp->cno = cmd.addr2.cno;
837 break;
838 case 1:
839 sp->lno = cmd.addr1.lno ? cmd.addr1.lno : 1;
840 sp->cno = cmd.addr1.cno;
841 break;
843 return (0);
846 /* Reset "last" command. */
847 if (LF_ISSET(E_SETLAST))
848 sp->lastcmd = cp;
850 cmd.cmd = cp;
851 #if defined(DEBUG) && 0
853 int __cnt;
855 TRACE(sp, "ex_cmd: %s", cmd.cmd->name);
856 if (cmd.addrcnt > 0) {
857 TRACE(sp, "\taddr1 %d", cmd.addr1.lno);
858 if (cmd.addrcnt > 1)
859 TRACE(sp, " addr2: %d", cmd.addr2.lno);
860 TRACE(sp, "\n");
862 if (cmd.lineno)
863 TRACE(sp, "\tlineno %d", cmd.lineno);
864 if (cmd.flags)
865 TRACE(sp, "\tflags %0x", cmd.flags);
866 if (F_ISSET(&cmd, E_BUFFER))
867 TRACE(sp, "\tbuffer %c", cmd.buffer);
868 TRACE(sp, "\n");
869 if (cmd.argc) {
870 for (__cnt = 0; __cnt < cmd.argc; ++__cnt)
871 TRACE(sp, "\targ %d: {%s}", __cnt, cmd.argv[__cnt]);
872 TRACE(sp, "\n");
875 #endif
876 /* Clear autoprint. */
877 F_CLR(sp, S_AUTOPRINT);
880 * If file state and not doing a global command, log the start of
881 * an action.
883 if (ep != NULL && !F_ISSET(sp, S_GLOBAL))
884 (void)log_cursor(sp, ep);
886 /* Save the current mode. */
887 saved_mode = F_ISSET(sp, S_MODE_EX | S_MODE_VI | S_MAJOR_CHANGE);
889 /* Increment the command count if not called from vi. */
890 if (!F_ISSET(sp, S_MODE_VI))
891 ++sp->ccnt;
893 /* Do the command. */
894 if ((cp->fn)(sp, ep, &cmd))
895 return (1);
897 #ifdef DEBUG
898 /* Make sure no function left the temporary space locked. */
899 if (F_ISSET(sp->gp, G_TMP_INUSE)) {
900 msgq(sp, M_ERR, "Error: ex: temporary buffer not released.");
901 return (1);
903 #endif
905 /* If the world changed, we're done. */
906 if (saved_mode != F_ISSET(sp, S_MODE_EX | S_MODE_VI | S_MAJOR_CHANGE))
907 return (0);
909 /* If just starting up, or not in ex mode, we're done. */
910 if (ep == NULL || !F_ISSET(sp, S_MODE_EX))
911 return (0);
914 * The print commands have already handled the `print' flags.
915 * If so, clear them. Don't return, autoprint may still have
916 * stuff to print out.
918 if (LF_ISSET(E_F_PRCLEAR))
919 F_CLR(&cmd, E_F_HASH | E_F_LIST | E_F_PRINT);
922 * If the command was successful, and there was an explicit flag to
923 * display the new cursor line, or we're in ex mode, autoprint is set,
924 * and a change was made, display the line.
926 if (flagoff) {
927 if (flagoff < 0) {
928 if (sp->lno < -flagoff) {
929 msgq(sp, M_ERR, "Flag offset before line 1.");
930 return (1);
932 } else {
933 if (file_lline(sp, ep, &lno))
934 return (1);
935 if (sp->lno + flagoff > lno) {
936 msgq(sp, M_ERR,
937 "Flag offset past end-of-file.");
938 return (1);
941 sp->lno += flagoff;
944 if (F_ISSET(sp, S_AUTOPRINT) && O_ISSET(sp, O_AUTOPRINT))
945 LF_INIT(E_F_PRINT);
946 else
947 LF_INIT(F_ISSET(&cmd, E_F_HASH | E_F_LIST | E_F_PRINT));
949 memset(&cmd, 0, sizeof(EXCMDARG));
950 cmd.addrcnt = 2;
951 cmd.addr1.lno = cmd.addr2.lno = sp->lno;
952 cmd.addr1.cno = cmd.addr2.cno = sp->cno;
953 if (flags) {
954 switch (flags) {
955 case E_F_HASH:
956 cmd.cmd = &cmds[C_HASH];
957 ex_number(sp, ep, &cmd);
958 break;
959 case E_F_LIST:
960 cmd.cmd = &cmds[C_LIST];
961 ex_list(sp, ep, &cmd);
962 break;
963 case E_F_PRINT:
964 cmd.cmd = &cmds[C_PRINT];
965 ex_pr(sp, ep, &cmd);
966 break;
969 return (0);
973 * ep_comm, ep_re, ep_rw --
975 * Historically, '|' characters in the first argument of the ex, edit,
976 * global, vglobal and substitute commands did not separate commands.
977 * And, in the filter cases for read and write, they did not delimit
978 * the command at all.
980 * For example, the following commands were legal:
982 * :edit +25|s/abc/ABC/ file.c
983 * :substitute s/|/PIPE/
984 * :read !spell % | columnate
986 * It's not quite as simple as it looks, however. The command:
988 * :substitute s/a/b/|s/c/d|set
990 * was also legal, i.e. the historic ex parser (and I use the word loosely,
991 * since "parser" implies some regularity of syntax) delimited the RE's
992 * based on its delimiter and not anything so vulgar as a command syntax.
994 * The ep_comm(), ep_re(), and ep_rw routines make this work. They're passed
995 * the state from ex_cstring(), and, if it's a special case, they parse the
996 * first (or entire) argument and return the new state. For the +cmd field,
997 * since we don't want to parse the line more than once, a pointer to, and the
998 * length of, the first argument is returned to ex_cstring(), which passes it
999 * to ex_cmd(). Barf-O-Rama.
1001 static void
1002 ep_comm(sp, pp, tp, lenp, arg1p, arg1_lenp)
1003 SCR *sp;
1004 char **pp, **tp, **arg1p;
1005 int *lenp, *arg1_lenp;
1007 char *cp, *p, *t;
1008 int ch, cnt, len;
1010 /* Copy the state to local variables. */
1011 p = *pp;
1012 cp = t = *tp;
1013 len = *lenp;
1016 * Move to the next non-lower-case, alphabetic character. We can
1017 * do this fairly brutally because we know that the command names
1018 * are all lower-case alphabetics, and there has to be a '+' to
1019 * start the arguments. If there isn't one, we're done.
1021 if (*t == ':') {
1022 ++cp;
1023 *p++ = *t++;
1024 --len;
1026 for (; len && islower(*p = *t); ++p, ++t, --len);
1027 if (len == 0)
1028 goto ret;
1031 * Make sure it's the ex or edit command. Note, 'e' has
1032 * to map to the edit command or the strncmp's aren't right.
1034 cnt = t - cp;
1035 if (strncmp(cp, "ex", cnt) && strncmp(cp, "edit", cnt))
1036 goto ret;
1039 * Move to the '+'. We don't check syntax here, if it's not
1040 * there, we're done.
1042 while (len--) {
1043 ch = *++p = *++t;
1044 if (!isblank(ch))
1045 break;
1047 if (len == 0 || *p != '+')
1048 goto ret;
1051 * QUOTING NOTE:
1053 * The historic implementation of this "feature" ignored any escape
1054 * characters so there was no way to put a space or newline into the
1055 * +cmd field. We do a simplistic job of handling it by moving to
1056 * the first whitespace character that isn't escaped by a literal next
1057 * character. The literal next quote characters are stripped here
1058 * since they are no longer useful.
1060 * Move to the first non-escaped space.
1062 for (cp = p; len;) {
1063 ch = *++p = *++t;
1064 --len;
1065 if (sp->special[ch] == K_VLNEXT && len > 0) {
1066 *p = *++t;
1067 if (--len == 0)
1068 break;
1069 } else if (isblank(ch))
1070 break;
1073 /* Return information about the first argument. */
1074 *arg1p = cp + 1;
1075 *arg1_lenp = (p - cp) - 1;
1077 /* Restore the state. */
1078 ret: *pp = p;
1079 *tp = t;
1080 *lenp = len;
1083 static void
1084 ep_re(sp, pp, tp, lenp)
1085 SCR *sp;
1086 char **pp, **tp;
1087 int *lenp;
1089 char *cp, *p, *t;
1090 int ch, cnt, delim, len;
1092 /* Copy the state to local variables. */
1093 p = *pp;
1094 cp = t = *tp;
1095 len = *lenp;
1098 * Move to the next non-lower-case, alphabetic character. We can
1099 * do this fairly brutally because we know that the command names
1100 * are all lower-case alphabetics, and there has to be a delimiter
1101 * to start the arguments. If there isn't one, we're done.
1103 if (*t == ':') {
1104 ++cp;
1105 *p++ = *t++;
1106 --len;
1108 for (; len; ++p, ++t, --len) {
1109 ch = *p = *t;
1110 if (!islower(ch))
1111 break;
1113 if (len == 0)
1114 goto ret;
1117 * Make sure it's the substitute, global or vglobal command.
1118 * Note, 's', 'g and 'v' have to map to these commands or the
1119 * strncmp's aren't right.
1121 cnt = t - cp;
1122 if (strncmp(cp, "substitute", cnt) &&
1123 strncmp(cp, "global", cnt) && strncmp(cp, "vglobal", cnt))
1124 goto ret;
1127 * Move to the delimiter. (The first character; if it's an illegal
1128 * one, the RE code will catch it.)
1130 if (isblank(ch))
1131 while (len--) {
1132 ch = *++p = *++t;
1133 if (!isblank(ch))
1134 break;
1136 delim = ch;
1137 if (len == 0)
1138 goto ret;
1141 * QUOTING NOTE:
1143 * Backslashes quote delimiter characters for regular expressions.
1144 * The backslashes are left here since they'll be needed by the RE
1145 * code.
1147 * Move to the third (non-escaped) delimiter.
1149 for (cnt = 2; len && cnt;) {
1150 ch = *++p = *++t;
1151 --len;
1152 if (ch == '\\' && len > 0) {
1153 *++p = *++t;
1154 if (--len == 0)
1155 break;
1156 } else if (ch == delim)
1157 --cnt;
1160 /* Move past the delimiter if it's possible. */
1161 if (len > 0) {
1162 ++t;
1163 ++p;
1164 --len;
1167 /* Restore the state. */
1168 ret: *pp = p;
1169 *tp = t;
1170 *lenp = len;
1173 static void
1174 ep_rw(sp, pp, tp, lenp)
1175 SCR *sp;
1176 char **pp, **tp;
1177 int *lenp;
1179 char *cp, *p, *t;
1180 int ch, cnt, len;
1182 /* Copy the state to local variables. */
1183 p = *pp;
1184 cp = t = *tp;
1185 len = *lenp;
1188 * Move to the next non-lower-case, alphabetic character. We can
1189 * do this fairly brutally because we know that the command names
1190 * are all lower-case alphabetics, and there has to be a delimiter
1191 * to start the arguments. If there isn't one, we're done.
1193 if (*t == ':') {
1194 ++cp;
1195 *p++ = *t++;
1196 --len;
1198 for (; len; ++p, ++t, --len) {
1199 ch = *p = *t;
1200 if (!islower(ch))
1201 break;
1203 if (len == 0)
1204 goto ret;
1207 * Make sure it's the read or write command. Note, 'r' and 'w'
1208 * have to map to these commands or the strncmp's aren't right.
1210 cnt = t - cp;
1211 if (strncmp(cp, "read", cnt) && strncmp(cp, "write", cnt))
1212 goto ret;
1215 * Move to the next character. If it's a '!', it's a filter
1216 * command we want to eat it all, otherwise, we're done.
1218 if (isblank(ch))
1219 while (len--) {
1220 ch = *++p = *++t;
1221 if (!isblank(ch))
1222 break;
1224 if (ch != '!')
1225 goto ret;
1227 for (; len; --len)
1228 *++p = *++t;
1230 /* Restore the state. */
1231 ret: *pp = p;
1232 *tp = t;
1233 *lenp = len;
1237 * ep_range --
1238 * Get a line range for ex commands.
1240 static char *
1241 ep_range(sp, ep, cmd, cp)
1242 SCR *sp;
1243 EXF *ep;
1244 char *cmd;
1245 EXCMDARG *cp;
1247 MARK cur, savecursor;
1248 int savecursor_set;
1249 char *endp;
1251 /* Percent character is all lines in the file. */
1252 if (*cmd == '%') {
1253 cp->addr1.lno = 1;
1254 if (file_lline(sp, ep, &cp->addr2.lno))
1255 return (NULL);
1256 /* If an empty file, then the first line is 0, not 1. */
1257 if (cp->addr2.lno == 0)
1258 cp->addr1.lno = 0;
1259 cp->addr1.cno = cp->addr2.cno = 0;
1260 cp->addrcnt = 2;
1261 return (++cmd);
1264 /* Parse comma or semi-colon delimited line specs. */
1265 for (savecursor_set = 0, cp->addrcnt = 0;;)
1266 switch (*cmd) {
1267 case ';': /* Semi-colon delimiter. */
1269 * Comma delimiters delimit; semi-colon delimiters
1270 * change the current address for the 2nd address
1271 * to be the first address. Trailing or multiple
1272 * delimiters are discarded.
1274 if (cp->addrcnt == 0)
1275 goto done;
1276 if (!savecursor_set) {
1277 savecursor.lno = sp->lno;
1278 savecursor.cno = sp->cno;
1279 sp->lno = cp->addr1.lno;
1280 sp->cno = cp->addr1.cno;
1281 savecursor_set = 1;
1283 /* FALLTHROUGH */
1284 case ' ':
1285 case '\t':
1286 case ',': /* Comma delimiter. */
1287 ++cmd;
1288 break;
1289 default:
1290 if ((endp = ep_line(sp, ep, cmd, &cur)) == NULL)
1291 return (NULL);
1292 if (cmd != endp) {
1293 cmd = endp;
1296 * Extra addresses are discarded, starting with
1297 * the first.
1299 switch (cp->addrcnt) {
1300 case 0:
1301 cp->addr1 = cur;
1302 cp->addrcnt = 1;
1303 break;
1304 case 1:
1305 cp->addr2 = cur;
1306 cp->addrcnt = 2;
1307 break;
1308 case 2:
1309 cp->addr1 = cp->addr2;
1310 cp->addr2 = cur;
1311 break;
1313 break;
1315 /* FALLTHROUGH */
1316 case '\0':
1317 goto done;
1321 * XXX
1322 * This is probably not right for treatment of savecursor -- figure
1323 * out what the historical ex did for ";,;,;5p" or similar stupidity.
1325 done: if (savecursor_set) {
1326 sp->lno = savecursor.lno;
1327 sp->cno = savecursor.cno;
1329 if (cp->addrcnt == 2 &&
1330 (cp->addr2.lno < cp->addr1.lno ||
1331 cp->addr2.lno == cp->addr1.lno && cp->addr2.cno < cp->addr1.cno)) {
1332 msgq(sp, M_ERR,
1333 "The second address is smaller than the first.");
1334 return (NULL);
1336 return (cmd);
1340 * Get a single line address specifier.
1342 static char *
1343 ep_line(sp, ep, cmd, cur)
1344 SCR *sp;
1345 EXF *ep;
1346 char *cmd;
1347 MARK *cur;
1349 MARK m, *mp;
1350 long num, total;
1351 u_int flags;
1352 char *endp;
1354 for (;;) {
1355 switch (*cmd) {
1356 case '$': /* Last line. */
1357 if (file_lline(sp, ep, &cur->lno))
1358 return (NULL);
1359 cur->cno = 0;
1360 ++cmd;
1361 break; /* Absolute line number. */
1362 case '0': case '1': case '2': case '3': case '4':
1363 case '5': case '6': case '7': case '8': case '9':
1365 * The way the vi "previous context" mark worked was
1366 * that "non-relative" motions set it. While vi was
1367 * not completely consistent about this, ANY numeric
1368 * address was considered non-relative, and set the
1369 * value.
1371 if (F_ISSET(sp, S_MODE_VI)) {
1372 m.lno = sp->lno;
1373 m.cno = sp->cno;
1374 if (mark_set(sp, ep, ABSMARK1, &m, 1))
1375 return (NULL);
1377 cur->lno = strtol(cmd, &endp, 10);
1378 cur->cno = 0;
1379 cmd = endp;
1380 break;
1381 case '\'': /* Set mark. */
1382 if (cmd[1] == '\0') {
1383 msgq(sp, M_ERR,
1384 "No mark name; use 'a' to 'z'.");
1385 return (NULL);
1387 if ((mp = mark_get(sp, ep, cmd[1])) == NULL)
1388 return (NULL);
1389 *cur = *mp;
1390 cmd += 2;
1391 break;
1392 case '/': /* Search forward. */
1393 m.lno = sp->lno;
1394 m.cno = sp->cno;
1395 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1396 if (f_search(sp, ep, &m, &m, cmd, &endp, &flags))
1397 return (NULL);
1398 cur->lno = m.lno;
1399 cur->cno = m.cno;
1400 cmd = endp;
1401 break;
1402 case '?': /* Search backward. */
1403 m.lno = sp->lno;
1404 m.cno = sp->cno;
1405 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1406 if (b_search(sp, ep, &m, &m, cmd, &endp, &flags))
1407 return (NULL);
1408 cur->lno = m.lno;
1409 cur->cno = m.cno;
1410 cmd = endp;
1411 break;
1412 case '.': /* Current position. */
1413 ++cmd;
1414 /* FALLTHROUGH */
1415 case '+': /* Increment. */
1416 case '-': /* Decrement. */
1417 /* If an empty file, then '.' is 0, not 1. */
1418 if (sp->lno == 1) {
1419 if (file_lline(sp, ep, &cur->lno))
1420 return (NULL);
1421 if (cur->lno != 0)
1422 cur->lno = 1;
1423 } else
1424 cur->lno = sp->lno;
1425 cur->cno = sp->cno;
1426 break;
1427 default:
1428 return (cmd);
1432 * Evaluate any offset. Offsets are +/- any number, or,
1433 * any number of +/- signs, or any combination thereof.
1435 for (total = 0; *cmd == '-' || *cmd == '+'; total += num) {
1436 num = *cmd == '-' ? -1 : 1;
1437 if (isdigit(*++cmd)) {
1438 num *= strtol(cmd, &endp, 10);
1439 cmd = endp;
1442 if (total < 0 && -total > cur->lno) {
1443 msgq(sp, M_ERR,
1444 "Reference to a line number less than 0.");
1445 return (NULL);
1447 cur->lno += total;