rework terminal interface to use a single buffer, and keep track
[nvi.git] / ex / ex.c
blob2c0cdee09afe758cc306e44be228fcbfe52d1920
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.64 1993/11/29 20:01:50 bostic Exp $ (Berkeley) $Date: 1993/11/29 20:01:50 $";
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 u_int saved_mode;
44 int eval;
45 char defcom[sizeof(DEFCOM)];
47 if (ex_init(sp, ep))
48 return (1);
50 if (sp->s_refresh(sp, ep))
51 return (ex_end(sp));
53 /* If reading from a file, messages should have line info. */
54 if (!F_ISSET(sp->gp, G_ISFROMTTY)) {
55 sp->if_lno = 1;
56 sp->if_name = strdup("input");
58 for (eval = 0;; ++sp->if_lno) {
59 /* Get the next command. */
60 switch (sp->s_get(sp, ep, &sp->tiq, ':', TXT_CR | TXT_PROMPT)) {
61 case INP_OK:
62 break;
63 case INP_EOF:
64 F_SET(sp, S_EXIT_FORCE);
65 goto ret;
66 case INP_ERR:
67 continue;
70 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
71 tp = sp->tiq.cqh_first;
72 if (tp->len == 0) {
73 if (F_ISSET(sp->gp, G_ISFROMTTY)) {
74 (void)fputc('\r', stdout);
75 (void)fflush(stdout);
77 memmove(defcom, DEFCOM, sizeof(DEFCOM));
78 (void)ex_cstring(sp, ep, defcom, sizeof(DEFCOM) - 1);
79 } else {
80 if (F_ISSET(sp->gp, G_ISFROMTTY))
81 (void)fputc('\n', stdout);
82 (void)ex_cstring(sp, ep, tp->lb, tp->len);
84 (void)msg_rpt(sp, 0);
86 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
87 break;
89 if (sp->s_refresh(sp, ep)) {
90 eval = 1;
91 break;
94 ret: if (sp->if_name != NULL) {
95 FREE(sp->if_name, strlen(sp->if_name) + 1);
96 sp->if_name = NULL;
98 return (ex_end(sp) || eval);
102 * ex_cfile --
103 * Execute ex commands from a file.
106 ex_cfile(sp, ep, filename)
107 SCR *sp;
108 EXF *ep;
109 char *filename;
111 struct stat sb;
112 int fd, len, rval;
113 char *bp;
115 bp = NULL;
116 if ((fd = open(filename, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
117 goto err;
120 * XXX
121 * We'd like to test if the file is too big to malloc. Since we don't
122 * know what size or type off_t's or size_t's are, what the largest
123 * unsigned integral type is, or what random insanity the local C
124 * compiler will perpetrate, doing the comparison in a portable way
125 * is flatly impossible. Hope that malloc fails if the file is too
126 * large.
128 if ((bp = malloc((size_t)sb.st_size)) == 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 = 0;
142 sp->if_name = strdup(filename);
143 rval = ex_cstring(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 (but we don't care).
152 if (bp != NULL)
153 FREE(bp, sb.st_size);
154 if (fd >= 0)
155 (void)close(fd);
156 return (rval);
160 * ex_cstring --
161 * Execute EX commands from a string.
164 ex_cstring(sp, ep, cmd, len)
165 SCR *sp;
166 EXF *ep;
167 char *cmd;
168 int len;
170 u_int saved_mode;
171 int ch, arg1_len;
172 char *p, *t, *arg1;
175 * Ex goes through here for each vi :colon command and for each ex
176 * command, however, globally executed commands don't go through
177 * here, instead, they call ex_cmd directly. So, reset all of the
178 * interruptible flags now.
180 F_CLR(sp, S_INTERRUPTED | S_INTERRUPTIBLE);
182 /* This is probably not necessary, but it's worth being safe. */
183 if (len == 0)
184 return (0);
187 * QUOTING NOTE:
189 * Commands may be separated by newline or '|' characters, and may
190 * be escaped by literal next characters. The quote characters are
191 * stripped here since they are no longer useful.
193 * There are seven exceptions to this. The filter versions of read
194 * and write are delimited by newlines (the filter command can contain
195 * shell pipes) ex and edit take ex commands as arguments, and global,
196 * vglobal and substitute take RE's as arguments and want their first
197 * argument be specially delimited, not necessarily by '|' characters.
198 * See ep_comm(), ep_re() and ep_rw() below for the horrifying details.
200 arg1 = NULL;
201 arg1_len = 0;
202 for (p = t = cmd;;) {
203 /* The beginning of a line. */
204 if (p == cmd) {
205 /* Skip leading "\t |\n". */
206 for (; len > 0; ++t, --len) {
207 ch = *t;
208 if (isblank(ch) || ch == '|')
209 continue;
210 if (term_key_val(sp, ch) == K_NL) {
211 ++sp->if_lno;
212 continue;
214 break;
218 * Special case comments, because the upcoming special
219 * cases are looking at the command syntax. A comment
220 * line could match a syntax, leading to all sorts of
221 * strangeness.
223 if (ch == '"') {
224 for (; len > 0; ++t, --len) {
225 if (term_key_val(sp, *t) == K_NL)
226 break;
228 p = cmd;
229 goto cend;
233 * Special case read/write, ex/edit, RE commands. We
234 * have to identify the command, so skip the leading
235 * address. Addresses are complex, so skip forward
236 * until reach the start of the command, i.e. the first
237 * alphabetic character. Copy the command up to then,
238 * just in case it's not an address at all.
240 for (; len > 0; ++p, ++t, --len) {
241 ch = *p = *t;
242 if (isalpha(ch) || term_key_val(sp, ch) == K_NL)
243 break;
245 if (len > 0 &&
246 strchr("egrvws", t[0] == ':' ? t[1] : t[0]))
247 switch (t[0] == ':' ? t[1] : t[0]) {
248 case 'e':
249 ep_comm(sp,
250 &p, &t, &len, &arg1, &arg1_len);
251 break;
252 case 'r':
253 case 'w':
254 ep_rw(sp, &p, &t, &len);
255 break;
256 case 'g':
257 case 'v':
258 case 's':
259 ep_re(sp, &p, &t, &len);
260 break;
262 if (len == 0)
263 goto cend;
266 ch = *t++; /* Get the next character. */
267 --len; /* Characters remaining. */
270 * Historically, vi permitted ^V's to escape <newline>'s in
271 * the .exrc file. It was almost certainly a bug, but that's
272 * what bug-for-bug compatibility means, Grasshopper. Also,
273 * escape command separators.
275 if (term_key_val(sp, ch) == K_VLNEXT && len > 0 &&
276 (t[0] == '|' || term_key_val(sp, t[0]) == K_NL)) {
277 --len;
278 *p++ = *t++;
279 if (term_key_val(sp, t[0]) == K_NL)
280 ++sp->if_lno;
281 continue;
284 /* Increment line counter. */
285 if (term_key_val(sp, ch) == K_NL)
286 ++sp->if_lno;
289 * If the end of the string, or a command separator, run
290 * the command.
292 if (len == 0 || ch == '|' || term_key_val(sp, ch) == K_NL) {
294 * If we got here because we ran out of line, not
295 * because we ran into a separator, put the last
296 * character into the command buffer.
298 if (len == 0 && ch != '|' &&
299 term_key_val(sp, ch) != K_NL)
300 *p++ = ch;
303 * If we actually got a command, run it. If it
304 * errors or the modes change, we're outta here.
306 cend: if (p > cmd) {
307 saved_mode =
308 F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
309 *p = '\0';
310 if (ex_cmd(sp, ep, cmd, arg1_len)) {
311 if (len)
312 msgq(sp, M_ERR,
313 "Ex command failed: remaining command input discarded.");
314 term_map_flush(sp, "Ex command failed");
315 return (1);
317 p = cmd;
318 if (saved_mode !=
319 F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
320 break;
322 if (len == 0)
323 return (0);
324 } else
325 *p++ = ch;
328 * Only here if the mode of the underlying file changed, the user
329 * switched files or is exiting. There are two things that we may
330 * have to save. First, any "+cmd" field that ep_comm() set up will
331 * have to be saved for later. Also, there may be part of the
332 * current ex command which we haven't executed:
334 * :edit +25 file.c|s/abc/ABC/|1
336 * for example.
338 * The historic vi just hung, of course; we handle by pushing the
339 * keys onto the SCR's tty buffer. If we're switching modes to
340 * vi, since the commands are intended as ex commands, add the extra
341 * characters to make it work.
343 * For the fun of it, if you want to see if a vi clone got the ex
344 * argument parsing right, try:
346 * echo 'foo|bar' > file1; echo 'foo/bar' > file2;
347 * vi
348 * :edit +1|s/|/PIPE/|w file1| e file2|1 | s/\//SLASH/|wq
350 if (arg1 == NULL && len == 0)
351 return (0);
352 if (IN_VI_MODE(sp) && term_push(sp, "\n", 1, 0, 0))
353 goto err;
354 if (len != 0)
355 if (term_push(sp, t, len, 0, 0))
356 goto err;
357 if (arg1 != NULL) {
358 if (IN_VI_MODE(sp) && len != 0 &&
359 term_push(sp, "|", 1, 0, 0))
360 goto err;
361 if (term_push(sp, arg1, arg1_len, 0, 0))
362 goto err;
364 if (IN_VI_MODE(sp) && term_push(sp, ":", 1, 0, 0))
365 err: term_map_flush(sp, "Error");
366 return (0);
370 * ex_cmd --
371 * Parse and execute an ex command.
374 ex_cmd(sp, ep, exc, arg1_len)
375 SCR *sp;
376 EXF *ep;
377 char *exc;
378 int arg1_len;
380 EX_PRIVATE *exp;
381 EXCMDARG cmd;
382 EXCMDLIST const *cp;
383 MARK cur;
384 recno_t lcount, lno, num;
385 long flagoff;
386 u_int saved_mode;
387 int ch, cmdlen, esc, flags, uselastcmd;
388 char *p, *t, *endp;
390 #if defined(DEBUG) && 0
391 TRACE(sp, "ex: {%s}\n", exc);
392 #endif
394 * !!!
395 * Permit extra colons at the start of the line. Historically,
396 * ex/vi allowed a single extra one. It's simpler not to count.
397 * The stripping is done here because, historically, any command
398 * could have preceding colons, e.g. ":g/pattern/:p" worked.
400 for (; *exc == ':'; ++exc);
402 /* Ignore command lines that start with a double-quote. */
403 if (*exc == '"')
404 return (0);
406 /* Skip whitespace. */
407 for (; isblank(*exc); ++exc);
409 /* Initialize the argument structure. */
410 memset(&cmd, 0, sizeof(EXCMDARG));
411 exp = EXP(sp);
412 exp->ex_argv[0] = "";
413 exp->ex_argv[1] = NULL;
414 cmd.argc = 0;
415 cmd.argv = exp->ex_argv;
418 * Parse line specifiers if the command uses addresses.
419 * New command line position is returned, or NULL on error.
421 if ((exc = ep_range(sp, ep, exc, &cmd)) == NULL)
422 return (1);
424 /* Skip whitespace. */
425 for (; isblank(*exc); ++exc);
428 * If no command, ex does the last specified of p, l, or #, and vi
429 * moves to the line. Otherwise, find out how long the command name
430 * is. There are a few commands that aren't alphabetic, but they
431 * are all single character commands.
433 #define SINGLE_CHAR_COMMANDS "!#&<=>@~"
434 if (*exc) {
435 if (strchr(SINGLE_CHAR_COMMANDS, *exc)) {
436 p = exc;
437 exc++;
438 cmdlen = 1;
439 } else {
440 for (p = exc; isalpha(*exc); ++exc);
441 cmdlen = exc - p;
442 if (cmdlen == 0) {
443 msgq(sp, M_ERR, "Unknown command name.");
444 return (1);
447 for (cp = cmds; cp->name && memcmp(p, cp->name, cmdlen); ++cp);
450 * !!!
451 * Historic vi permitted the mark to immediately follow the 'k'
452 * in the 'k' command. Make it work.
454 * Use of msgq below is safe, command names are all alphabetics.
456 if (cp->name == NULL)
457 if (p[0] == 'k' && p[1] && !p[2]) {
458 exc = p + 1;
459 cp = &cmds[C_K];
460 } else {
461 msgq(sp, M_ERR,
462 "The %.*s command is unknown.", cmdlen, p);
463 return (1);
465 uselastcmd = 0;
467 /* Some commands are turned off. */
468 if (F_ISSET(cp, E_NOPERM)) {
469 msgq(sp, M_ERR,
470 "The %.*s command is not currently supported.",
471 cmdlen, p);
472 return (1);
475 /* Some commands aren't okay in globals. */
476 if (F_ISSET(sp, S_GLOBAL) && F_ISSET(cp, E_NOGLOBAL)) {
477 msgq(sp, M_ERR,
478 "The %.*s command can't be used as part of a global command.", cmdlen, p);
479 return (1);
483 * Multiple < and > characters; another "special" feature.
484 * NOTE: The string may not be nul terminated in this case.
486 if ((cp == &cmds[C_SHIFTL] && *p == '<') ||
487 (cp == &cmds[C_SHIFTR] && *p == '>')) {
488 exp->ex_argv[0] = p;
489 exp->ex_argv[1] = NULL;
490 cmd.argc = 1;
491 cmd.argv = exp->ex_argv;
492 for (ch = *p, exc = p; *++exc == ch;);
496 * The visual command has a different syntax when called
497 * from ex than when called from a vi colon command. FMH.
499 if (cp == &cmds[C_VISUAL_EX] && IN_VI_MODE(sp))
500 cp = &cmds[C_VISUAL_VI];
501 } else {
502 cp = exp->lastcmd;
503 uselastcmd = 1;
505 LF_INIT(cp->flags);
508 * File state must be checked throughout this code, because it is
509 * called when reading the .exrc file and similar things. There's
510 * this little chicken and egg problem -- if we read the file first,
511 * we won't know how to display it. If we read/set the exrc stuff
512 * first, we can't allow any command that requires file state.
513 * Historic vi generally took the easy way out and dropped core.
515 if (LF_ISSET(E_NORC) && ep == NULL) {
516 msgq(sp, M_ERR,
517 "The %s command requires a file to already have been read in.",
518 cp->name);
519 return (1);
523 * Set the default addresses. It's an error to specify an address for
524 * a command that doesn't take them. If two addresses are specified
525 * for a command that only takes one, lose the first one. Two special
526 * cases here, some commands take 0 or 2 addresses. For most of them
527 * (the E_ADDR2_ALL flag), 0 defaults to the entire file. For one
528 * (the `!' command, the E_ADDR2_NONE flag), 0 defaults to no lines.
530 * Also, if the file is empty, some commands want to use an address of
531 * 0, i.e. the entire file is 0 to 0, and the default first address is
532 * 0. Otherwise, an entire file is 1 to N and the default line is 1.
533 * Note, we also add the E_ZERO flag to the command flags, for the case
534 * where the 0 address is only valid if it's a default address.
536 * Also, set a flag if we set the default addresses. Some commands
537 * (ex: z) care if the user specified an address of if we just used
538 * the current cursor.
540 flagoff = 0;
541 switch (flags & (E_ADDR1|E_ADDR2|E_ADDR2_ALL|E_ADDR2_NONE)) {
542 case E_ADDR1: /* One address: */
543 switch (cmd.addrcnt) {
544 case 0: /* Default cursor/empty file. */
545 cmd.addrcnt = 1;
546 F_SET(&cmd, E_ADDRDEF);
547 if (LF_ISSET(E_ZERODEF)) {
548 if (file_lline(sp, ep, &lno))
549 return (1);
550 if (lno == 0) {
551 cmd.addr1.lno = 0;
552 LF_SET(E_ZERO);
553 } else
554 cmd.addr1.lno = sp->lno;
555 } else
556 cmd.addr1.lno = sp->lno;
557 cmd.addr1.cno = sp->cno;
558 break;
559 case 1:
560 break;
561 case 2: /* Lose the first address. */
562 cmd.addrcnt = 1;
563 cmd.addr1 = cmd.addr2;
565 break;
566 case E_ADDR2_NONE: /* Zero/two addresses: */
567 if (cmd.addrcnt == 0) /* Default to nothing. */
568 break;
569 goto two;
570 case E_ADDR2_ALL: /* Zero/two addresses: */
571 if (cmd.addrcnt == 0) { /* Default entire/empty file. */
572 cmd.addrcnt = 2;
573 F_SET(&cmd, E_ADDRDEF);
574 if (file_lline(sp, ep, &cmd.addr2.lno))
575 return (1);
576 if (LF_ISSET(E_ZERODEF) && cmd.addr2.lno == 0) {
577 cmd.addr1.lno = 0;
578 LF_SET(E_ZERO);
579 } else
580 cmd.addr1.lno = 1;
581 cmd.addr1.cno = cmd.addr2.cno = 0;
582 F_SET(&cmd, E_ADDR2_ALL);
583 break;
585 /* FALLTHROUGH */
586 case E_ADDR2: /* Two addresses: */
587 two: switch (cmd.addrcnt) {
588 case 0: /* Default cursor/empty file. */
589 cmd.addrcnt = 2;
590 F_SET(&cmd, E_ADDRDEF);
591 if (LF_ISSET(E_ZERODEF) && sp->lno == 1) {
592 if (file_lline(sp, ep, &lno))
593 return (1);
594 if (lno == 0) {
595 cmd.addr1.lno = cmd.addr2.lno = 0;
596 LF_SET(E_ZERO);
597 } else
598 cmd.addr1.lno = cmd.addr2.lno = sp->lno;
599 } else
600 cmd.addr1.lno = cmd.addr2.lno = sp->lno;
601 cmd.addr1.cno = cmd.addr2.cno = sp->cno;
602 break;
603 case 1: /* Default to first address. */
604 cmd.addrcnt = 2;
605 cmd.addr2 = cmd.addr1;
606 break;
607 case 2:
608 break;
610 break;
611 default:
612 if (cmd.addrcnt) /* Error. */
613 goto usage;
617 * YASC. The "set tags" command historically used a backslash, not
618 * the user's literal next character, to escape whitespace. Handle
619 * it here instead of complicating the argv_exp3() code. Note, this
620 * isn't a particularly complex trap, and if backslashes were legal
621 * in set commands, this would have to be much more complicated.
623 if (cp == &cmds[C_SET]) {
624 esc = sp->gp->original_termios.c_cc[VLNEXT];
625 for (p = exc; (ch = *p) != '\0'; ++p)
626 if (ch == '\\')
627 *p = esc;
630 for (lcount = 0, p = cp->syntax; *p != '\0'; ++p) {
632 * The write command is sensitive to leading whitespace,
633 * i.e. "write !" is different from "write!". If not write,
634 * skip leading whitespace.
636 if (cp != &cmds[C_WRITE])
637 for (; isblank(*exc); ++exc);
640 * When reach the end of the command, quit, unless it's
641 * a command that does its own parsing, in which case we
642 * want to build a reasonable argv for it.
644 if (*p != 's' && *p != 'S' && *exc == '\0')
645 break;
647 switch (*p) {
648 case '!': /* ! */
649 if (*exc == '!') {
650 ++exc;
651 F_SET(&cmd, E_FORCE);
653 break;
654 case '+': /* +cmd */
655 if (*exc != '+')
656 break;
657 exc += arg1_len + 1;
658 if (*exc)
659 *exc++ = '\0';
660 break;
661 case '1': /* +, -, #, l, p */
663 * !!!
664 * Historically, some flags were ignored depending
665 * on where they occurred in the command line. For
666 * example, in the command, ":3+++p--#", historic vi
667 * acted on the '#' flag, but ignored the '-' flags.
668 * It's unambiguous what the flags mean, so we just
669 * handle them regardless of the stupidity of their
670 * location.
672 for (;; ++exc)
673 switch (*exc) {
674 case '+':
675 ++flagoff;
676 break;
677 case '-':
678 --flagoff;
679 break;
680 case '#':
681 F_SET(&cmd, E_F_HASH);
682 break;
683 case 'l':
684 F_SET(&cmd, E_F_LIST);
685 break;
686 case 'p':
687 F_SET(&cmd, E_F_PRINT);
688 break;
689 default:
690 goto end1;
692 end1: break;
693 case '2': /* -, ., +, ^ */
694 case '3': /* -, ., +, ^, = */
695 for (;; ++exc)
696 switch (*exc) {
697 case '-':
698 F_SET(&cmd, E_F_DASH);
699 break;
700 case '.':
701 F_SET(&cmd, E_F_DOT);
702 break;
703 case '+':
704 F_SET(&cmd, E_F_PLUS);
705 break;
706 case '^':
707 F_SET(&cmd, E_F_CARAT);
708 break;
709 case '=':
710 if (*p == '3') {
711 F_SET(&cmd, E_F_EQUAL);
712 break;
714 /* FALLTHROUGH */
715 default:
716 goto end2;
718 end2: break;
719 case 'b': /* buffer */
720 cmd.buffer = *exc++;
721 F_SET(&cmd, E_BUFFER);
722 break;
723 case 'C': /* count */
724 case 'n':
725 case 'c': /* count (address) */
726 if (!isdigit(*exc) &&
727 (*p != 'n' || (*exc != '+' && *exc != '-')))
728 break;
729 lcount = strtol(exc, &endp, 10);
730 if (lcount == 0) {
731 msgq(sp, M_ERR,
732 "Count may not be zero.");
733 return (1);
735 exc = endp;
737 * Count as address offsets occur in commands taking
738 * two addresses. Historic vi practice was to use
739 * the count as an offset from the *second* address.
741 * Set the count flag; some underlying commands (see
742 * join) do different things with counts than with
743 * line addresses.
745 if (*p == 'C' || *p == 'n')
746 cmd.count = lcount;
747 else {
748 cmd.addr1 = cmd.addr2;
749 cmd.addr2.lno = cmd.addr1.lno + lcount - 1;
751 F_SET(&cmd, E_COUNT);
752 break;
753 case 'f': /* file */
754 if (argv_exp2(sp, ep, &cmd, exc, cp == &cmds[C_BANG]))
755 return (1);
756 goto countchk;
757 case 'l': /* line */
758 endp = ep_line(sp, ep, exc, &cur);
759 if (endp == NULL || exc == endp) {
760 msgq(sp, M_ERR,
761 "%s: bad line specification", exc);
762 return (1);
763 } else {
764 cmd.lineno = cur.lno;
765 exc = endp;
767 break;
768 case 'S': /* string, file exp. */
769 if (argv_exp1(sp, ep, &cmd, exc, cp == &cmds[C_BANG]))
770 return (1);
771 goto addr2;
772 case 's': /* string */
773 exp->ex_argv[0] = exc;
774 exp->ex_argv[1] = NULL;
775 cmd.argc = 1;
776 cmd.argv = exp->ex_argv;
777 goto addr2;
778 case 'W': /* word string */
780 * QUOTING NOTE:
782 * Literal next characters escape the following
783 * character. The quote characters are stripped
784 * here since they are no longer useful.
786 * Word.
788 for (p = t = exc; (ch = *p) != '\0'; *t++ = ch, ++p)
789 if (term_key_val(sp, ch) == K_VLNEXT &&
790 p[1] != '\0')
791 ch = *++p;
792 else if (isblank(ch))
793 break;
794 if (*p == '\0')
795 goto usage;
796 exp->ex_argv[0] = exc;
798 /* Delete leading whitespace. */
799 for (*t++ = '\0'; (ch = *++p) != '\0' && isblank(ch););
801 /* String. */
802 exp->ex_argv[1] = p;
803 for (t = p; (ch = *p++) != '\0'; *t++ = ch)
804 if (term_key_val(sp, ch) == K_VLNEXT &&
805 p[0] != '\0')
806 ch = *p++;
807 *t = '\0';
808 exp->ex_argv[2] = NULL;
809 cmd.argc = 2;
810 cmd.argv = exp->ex_argv;
811 goto addr2;
812 case 'w': /* word */
813 if (argv_exp3(sp, ep, &cmd, exc))
814 return (1);
815 countchk: if (*++p != 'N') { /* N */
817 * If a number is specified, must either be
818 * 0 or that number, if optional, and that
819 * number, if required.
821 num = *p - '0';
822 if ((*++p != 'o' || cmd.argc != 0) &&
823 cmd.argc != num)
824 goto usage;
826 goto addr2;
827 default:
828 msgq(sp, M_ERR,
829 "Internal syntax table error (%s).", cp->name);
834 * Shouldn't be anything left, and no more required fields.
835 * That means neither 'l' or 'r' in the syntax.
837 for (; *exc && isblank(*exc); ++exc);
838 if (*exc || strpbrk(p, "lr")) {
839 usage: msgq(sp, M_ERR, "Usage: %s.", cp->usage);
840 return (1);
843 /* Verify that the addresses are legal. */
844 addr2: switch (cmd.addrcnt) {
845 case 2:
846 if (file_lline(sp, ep, &lcount))
847 return (1);
849 * Historic ex/vi permitted commands with counts to go past
850 * EOF. So, for example, if the file only had 5 lines, the
851 * ex command "1,6>" would fail, but the command ">300"
852 * would succeed. Since we don't want to have to make all
853 * of the underlying commands handle random line numbers,
854 * fix it here.
856 if (cmd.addr2.lno > lcount)
857 if (F_ISSET(&cmd, E_COUNT))
858 cmd.addr2.lno = lcount;
859 else {
860 if (lcount == 0)
861 msgq(sp, M_ERR, "The file is empty.");
862 else
863 msgq(sp, M_ERR,
864 "Only %lu line%s in the file",
865 lcount, lcount > 1 ? "s" : "");
866 return (1);
868 /* FALLTHROUGH */
869 case 1:
870 num = cmd.addr1.lno;
872 * If it's a "default vi command", zero is okay. Historic
873 * vi allowed this, note, it's also the hack that allows
874 * "vi + nonexistent_file" to work.
876 if (num == 0 && (!IN_VI_MODE(sp) || uselastcmd != 1) &&
877 !LF_ISSET(E_ZERO)) {
878 msgq(sp, M_ERR,
879 "The %s command doesn't permit an address of 0.",
880 cp->name);
881 return (1);
883 if (file_lline(sp, ep, &lcount))
884 return (1);
885 if (num > lcount) {
886 if (lcount == 0)
887 msgq(sp, M_ERR, "The file is empty.");
888 else
889 msgq(sp, M_ERR, "Only %lu line%s in the file",
890 lcount, lcount > 1 ? "s" : "");
891 return (1);
893 break;
896 /* If doing a default command, vi just moves to the line. */
897 if (IN_VI_MODE(sp) && uselastcmd) {
898 switch (cmd.addrcnt) {
899 case 2:
900 sp->lno = cmd.addr2.lno ? cmd.addr2.lno : 1;
901 sp->cno = cmd.addr2.cno;
902 break;
903 case 1:
904 sp->lno = cmd.addr1.lno ? cmd.addr1.lno : 1;
905 sp->cno = cmd.addr1.cno;
906 break;
908 return (0);
911 /* Reset "last" command. */
912 if (LF_ISSET(E_SETLAST))
913 exp->lastcmd = cp;
915 cmd.cmd = cp;
916 #if defined(DEBUG) && 0
918 int __cnt;
920 TRACE(sp, "ex_cmd: %s", cmd.cmd->name);
921 if (cmd.addrcnt > 0) {
922 TRACE(sp, "\taddr1 %d", cmd.addr1.lno);
923 if (cmd.addrcnt > 1)
924 TRACE(sp, " addr2: %d", cmd.addr2.lno);
925 TRACE(sp, "\n");
927 if (cmd.lineno)
928 TRACE(sp, "\tlineno %d", cmd.lineno);
929 if (cmd.flags)
930 TRACE(sp, "\tflags %0x", cmd.flags);
931 if (F_ISSET(&cmd, E_BUFFER))
932 TRACE(sp, "\tbuffer %c", cmd.buffer);
933 TRACE(sp, "\n");
934 if (cmd.argc) {
935 for (__cnt = 0; __cnt < cmd.argc; ++__cnt)
936 TRACE(sp, "\targ %d: {%s}", __cnt, cmd.argv[__cnt]);
937 TRACE(sp, "\n");
940 #endif
941 /* Clear autoprint. */
942 F_CLR(sp, S_AUTOPRINT);
945 * If file state and not doing a global command, log the start of
946 * an action.
948 if (ep != NULL && !F_ISSET(sp, S_GLOBAL))
949 (void)log_cursor(sp, ep);
951 /* Save the current mode. */
952 saved_mode = F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE);
954 /* Increment the command count if not called from vi. */
955 if (!IN_VI_MODE(sp))
956 ++sp->ccnt;
958 /* Do the command. */
959 if ((cp->fn)(sp, ep, &cmd))
960 return (1);
962 #ifdef DEBUG
963 /* Make sure no function left the temporary space locked. */
964 if (F_ISSET(sp->gp, G_TMP_INUSE)) {
965 msgq(sp, M_ERR, "Error: ex: temporary buffer not released.");
966 return (1);
968 #endif
970 /* If the world changed, we're done. */
971 if (saved_mode != F_ISSET(sp, S_SCREENS | S_MAJOR_CHANGE))
972 return (0);
974 /* If just starting up, or not in ex mode, we're done. */
975 if (ep == NULL || !IN_EX_MODE(sp))
976 return (0);
979 * The print commands have already handled the `print' flags.
980 * If so, clear them. Don't return, autoprint may still have
981 * stuff to print out.
983 if (LF_ISSET(E_F_PRCLEAR))
984 F_CLR(&cmd, E_F_HASH | E_F_LIST | E_F_PRINT);
987 * If the command was successful, and there was an explicit flag to
988 * display the new cursor line, or we're in ex mode, autoprint is set,
989 * and a change was made, display the line.
991 if (flagoff) {
992 if (flagoff < 0) {
993 if (sp->lno < -flagoff) {
994 msgq(sp, M_ERR, "Flag offset before line 1.");
995 return (1);
997 } else {
998 if (file_lline(sp, ep, &lno))
999 return (1);
1000 if (sp->lno + flagoff > lno) {
1001 msgq(sp, M_ERR,
1002 "Flag offset past end-of-file.");
1003 return (1);
1006 sp->lno += flagoff;
1009 if (F_ISSET(sp, S_AUTOPRINT) && O_ISSET(sp, O_AUTOPRINT))
1010 LF_INIT(E_F_PRINT);
1011 else
1012 LF_INIT(F_ISSET(&cmd, E_F_HASH | E_F_LIST | E_F_PRINT));
1014 memset(&cmd, 0, sizeof(EXCMDARG));
1015 cmd.addrcnt = 2;
1016 cmd.addr1.lno = cmd.addr2.lno = sp->lno;
1017 cmd.addr1.cno = cmd.addr2.cno = sp->cno;
1018 if (flags) {
1019 switch (flags) {
1020 case E_F_HASH:
1021 cmd.cmd = &cmds[C_HASH];
1022 ex_number(sp, ep, &cmd);
1023 break;
1024 case E_F_LIST:
1025 cmd.cmd = &cmds[C_LIST];
1026 ex_list(sp, ep, &cmd);
1027 break;
1028 case E_F_PRINT:
1029 cmd.cmd = &cmds[C_PRINT];
1030 ex_pr(sp, ep, &cmd);
1031 break;
1034 return (0);
1038 * ep_comm, ep_re, ep_rw --
1040 * Historically, '|' characters in the first argument of the ex, edit,
1041 * global, vglobal and substitute commands did not separate commands.
1042 * And, in the filter cases for read and write, they did not delimit
1043 * the command at all.
1045 * For example, the following commands were legal:
1047 * :edit +25|s/abc/ABC/ file.c
1048 * :substitute s/|/PIPE/
1049 * :read !spell % | columnate
1051 * It's not quite as simple as it looks, however. The command:
1053 * :substitute s/a/b/|s/c/d|set
1055 * was also legal, i.e. the historic ex parser (and I use the word loosely,
1056 * since "parser" implies some regularity of syntax) delimited the RE's
1057 * based on its delimiter and not anything so vulgar as a command syntax.
1059 * The ep_comm(), ep_re(), and ep_rw routines make this work. They're passed
1060 * the state from ex_cstring(), and, if it's a special case, they parse the
1061 * first (or entire) argument and return the new state. For the +cmd field,
1062 * since we don't want to parse the line more than once, a pointer to, and the
1063 * length of, the first argument is returned to ex_cstring(), which passes it
1064 * to ex_cmd(). Barf-O-Rama.
1066 static void
1067 ep_comm(sp, pp, tp, lenp, arg1p, arg1_lenp)
1068 SCR *sp;
1069 char **pp, **tp, **arg1p;
1070 int *lenp, *arg1_lenp;
1072 char *cp, *p, *t;
1073 int ch, cnt, len;
1075 /* Copy the state to local variables. */
1076 p = *pp;
1077 cp = t = *tp;
1078 len = *lenp;
1081 * Move to the next non-lower-case, alphabetic character. We can
1082 * do this fairly brutally because we know that the command names
1083 * are all lower-case alphabetics, and there has to be a '+' to
1084 * start the arguments. If there isn't one, we're done.
1086 if (*t == ':') {
1087 ++cp;
1088 *p++ = *t++;
1089 --len;
1091 for (; len && islower(*p = *t); ++p, ++t, --len);
1092 if (len == 0)
1093 goto ret;
1096 * Make sure it's the ex or edit command. Note, 'e' has
1097 * to map to the edit command or the strncmp's aren't right.
1099 cnt = t - cp;
1100 if (strncmp(cp, "ex", cnt) && strncmp(cp, "edit", cnt))
1101 goto ret;
1104 * Move to the '+'. We don't check syntax here, if it's not
1105 * there, we're done.
1107 while (len--) {
1108 ch = *++p = *++t;
1109 if (!isblank(ch))
1110 break;
1112 if (len == 0 || *p != '+')
1113 goto ret;
1116 * QUOTING NOTE:
1118 * The historic implementation of this "feature" ignored any escape
1119 * characters so there was no way to put a space or newline into the
1120 * +cmd field. We do a simplistic job of handling it by moving to
1121 * the first whitespace character that isn't escaped by a literal next
1122 * character. The literal next quote characters are stripped here
1123 * since they are no longer useful.
1125 * Move to the first non-escaped space.
1127 for (cp = p; len;) {
1128 ch = *++p = *++t;
1129 --len;
1130 if (term_key_val(sp, ch) == K_VLNEXT && len > 0) {
1131 *p = *++t;
1132 if (--len == 0)
1133 break;
1134 } else if (isblank(ch))
1135 break;
1138 /* Return information about the first argument. */
1139 *arg1p = cp + 1;
1140 *arg1_lenp = (p - cp) - 1;
1142 /* Restore the state. */
1143 ret: *pp = p;
1144 *tp = t;
1145 *lenp = len;
1148 static void
1149 ep_re(sp, pp, tp, lenp)
1150 SCR *sp;
1151 char **pp, **tp;
1152 int *lenp;
1154 char *cp, *p, *t;
1155 int ch, cnt, delim, len;
1157 /* Copy the state to local variables. */
1158 p = *pp;
1159 cp = t = *tp;
1160 len = *lenp;
1163 * Move to the next non-lower-case, alphabetic character. We can
1164 * do this fairly brutally because we know that the command names
1165 * are all lower-case alphabetics, and there has to be a delimiter
1166 * to start the arguments. If there isn't one, we're done.
1168 if (*t == ':') {
1169 ++cp;
1170 *p++ = *t++;
1171 --len;
1173 for (; len; ++p, ++t, --len) {
1174 ch = *p = *t;
1175 if (!islower(ch))
1176 break;
1178 if (len == 0)
1179 goto ret;
1182 * Make sure it's the substitute, global or vglobal command.
1183 * Note, 's', 'g and 'v' have to map to these commands or the
1184 * strncmp's aren't right.
1186 cnt = t - cp;
1187 if (strncmp(cp, "substitute", cnt) &&
1188 strncmp(cp, "global", cnt) && strncmp(cp, "vglobal", cnt))
1189 goto ret;
1192 * Move to the delimiter. (The first character; if it's an illegal
1193 * one, the RE code will catch it.)
1195 if (isblank(ch))
1196 while (len--) {
1197 ch = *++p = *++t;
1198 if (!isblank(ch))
1199 break;
1201 delim = ch;
1202 if (len == 0)
1203 goto ret;
1206 * QUOTING NOTE:
1208 * Backslashes quote delimiter characters for regular expressions.
1209 * The backslashes are left here since they'll be needed by the RE
1210 * code.
1212 * Move to the third (non-escaped) delimiter.
1214 for (cnt = 2; len && cnt;) {
1215 ch = *++p = *++t;
1216 --len;
1217 if (ch == '\\' && len > 0) {
1218 *++p = *++t;
1219 if (--len == 0)
1220 break;
1221 } else if (ch == delim)
1222 --cnt;
1225 /* Move past the delimiter if it's possible. */
1226 if (len > 0) {
1227 ++t;
1228 ++p;
1229 --len;
1232 /* Restore the state. */
1233 ret: *pp = p;
1234 *tp = t;
1235 *lenp = len;
1238 static void
1239 ep_rw(sp, pp, tp, lenp)
1240 SCR *sp;
1241 char **pp, **tp;
1242 int *lenp;
1244 char *cp, *p, *t;
1245 int ch, cnt, len;
1247 /* Copy the state to local variables. */
1248 p = *pp;
1249 cp = t = *tp;
1250 len = *lenp;
1253 * Move to the next non-lower-case, alphabetic character. We can
1254 * do this fairly brutally because we know that the command names
1255 * are all lower-case alphabetics, and there has to be a delimiter
1256 * to start the arguments. If there isn't one, we're done.
1258 if (*t == ':') {
1259 ++cp;
1260 *p++ = *t++;
1261 --len;
1263 for (; len; ++p, ++t, --len) {
1264 ch = *p = *t;
1265 if (!islower(ch))
1266 break;
1268 if (len == 0)
1269 goto ret;
1272 * Make sure it's the read or write command. Note, 'r' and 'w'
1273 * have to map to these commands or the strncmp's aren't right.
1275 cnt = t - cp;
1276 if (strncmp(cp, "read", cnt) && strncmp(cp, "write", cnt))
1277 goto ret;
1280 * Move to the next character. If it's a '!', it's a filter
1281 * command we want to eat it all, otherwise, we're done.
1283 if (isblank(ch))
1284 while (len--) {
1285 ch = *++p = *++t;
1286 if (!isblank(ch))
1287 break;
1289 if (ch != '!')
1290 goto ret;
1292 for (; len; --len)
1293 *++p = *++t;
1295 /* Restore the state. */
1296 ret: *pp = p;
1297 *tp = t;
1298 *lenp = len;
1302 * ep_range --
1303 * Get a line range for ex commands.
1305 static char *
1306 ep_range(sp, ep, cmd, cp)
1307 SCR *sp;
1308 EXF *ep;
1309 char *cmd;
1310 EXCMDARG *cp;
1312 MARK cur, savecursor;
1313 int savecursor_set;
1314 char *endp;
1316 /* Percent character is all lines in the file. */
1317 if (*cmd == '%') {
1318 cp->addr1.lno = 1;
1319 if (file_lline(sp, ep, &cp->addr2.lno))
1320 return (NULL);
1321 /* If an empty file, then the first line is 0, not 1. */
1322 if (cp->addr2.lno == 0)
1323 cp->addr1.lno = 0;
1324 cp->addr1.cno = cp->addr2.cno = 0;
1325 cp->addrcnt = 2;
1326 return (++cmd);
1329 /* Parse comma or semi-colon delimited line specs. */
1330 for (savecursor_set = 0, cp->addrcnt = 0;;)
1331 switch (*cmd) {
1332 case ';': /* Semi-colon delimiter. */
1334 * Comma delimiters delimit; semi-colon delimiters
1335 * change the current address for the 2nd address
1336 * to be the first address. Trailing or multiple
1337 * delimiters are discarded.
1339 if (cp->addrcnt == 0)
1340 goto done;
1341 if (!savecursor_set) {
1342 savecursor.lno = sp->lno;
1343 savecursor.cno = sp->cno;
1344 sp->lno = cp->addr1.lno;
1345 sp->cno = cp->addr1.cno;
1346 savecursor_set = 1;
1348 /* FALLTHROUGH */
1349 case ' ':
1350 case '\t':
1351 case ',': /* Comma delimiter. */
1352 ++cmd;
1353 break;
1354 default:
1355 if ((endp = ep_line(sp, ep, cmd, &cur)) == NULL)
1356 return (NULL);
1357 if (cmd != endp) {
1358 cmd = endp;
1361 * Extra addresses are discarded, starting with
1362 * the first.
1364 switch (cp->addrcnt) {
1365 case 0:
1366 cp->addr1 = cur;
1367 cp->addrcnt = 1;
1368 break;
1369 case 1:
1370 cp->addr2 = cur;
1371 cp->addrcnt = 2;
1372 break;
1373 case 2:
1374 cp->addr1 = cp->addr2;
1375 cp->addr2 = cur;
1376 break;
1378 break;
1380 /* FALLTHROUGH */
1381 case '\0':
1382 goto done;
1386 * XXX
1387 * This is probably not right for treatment of savecursor -- figure
1388 * out what the historical ex did for ";,;,;5p" or similar stupidity.
1390 done: if (savecursor_set) {
1391 sp->lno = savecursor.lno;
1392 sp->cno = savecursor.cno;
1394 if (cp->addrcnt == 2 &&
1395 (cp->addr2.lno < cp->addr1.lno ||
1396 cp->addr2.lno == cp->addr1.lno && cp->addr2.cno < cp->addr1.cno)) {
1397 msgq(sp, M_ERR,
1398 "The second address is smaller than the first.");
1399 return (NULL);
1401 return (cmd);
1405 * Get a single line address specifier.
1407 static char *
1408 ep_line(sp, ep, cmd, cur)
1409 SCR *sp;
1410 EXF *ep;
1411 char *cmd;
1412 MARK *cur;
1414 MARK m, *mp;
1415 long num, total;
1416 u_int flags;
1417 char *endp;
1419 for (;;) {
1420 switch (*cmd) {
1421 case '$': /* Last line. */
1422 if (file_lline(sp, ep, &cur->lno))
1423 return (NULL);
1424 cur->cno = 0;
1425 ++cmd;
1426 break; /* Absolute line number. */
1427 case '0': case '1': case '2': case '3': case '4':
1428 case '5': case '6': case '7': case '8': case '9':
1430 * The way the vi "previous context" mark worked was
1431 * that "non-relative" motions set it. While vi was
1432 * not completely consistent about this, ANY numeric
1433 * address was considered non-relative, and set the
1434 * value.
1436 if (IN_VI_MODE(sp)) {
1437 m.lno = sp->lno;
1438 m.cno = sp->cno;
1439 if (mark_set(sp, ep, ABSMARK1, &m, 1))
1440 return (NULL);
1442 cur->lno = strtol(cmd, &endp, 10);
1443 cur->cno = 0;
1444 cmd = endp;
1445 break;
1446 case '\'': /* Set mark. */
1447 if (cmd[1] == '\0') {
1448 msgq(sp, M_ERR,
1449 "No mark name; use 'a' to 'z'.");
1450 return (NULL);
1452 if ((mp = mark_get(sp, ep, cmd[1])) == NULL)
1453 return (NULL);
1454 *cur = *mp;
1455 cmd += 2;
1456 break;
1457 case '/': /* Search forward. */
1458 m.lno = sp->lno;
1459 m.cno = sp->cno;
1460 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1461 if (f_search(sp, ep, &m, &m, cmd, &endp, &flags))
1462 return (NULL);
1463 cur->lno = m.lno;
1464 cur->cno = m.cno;
1465 cmd = endp;
1466 break;
1467 case '?': /* Search backward. */
1468 m.lno = sp->lno;
1469 m.cno = sp->cno;
1470 flags = SEARCH_MSG | SEARCH_PARSE | SEARCH_SET;
1471 if (b_search(sp, ep, &m, &m, cmd, &endp, &flags))
1472 return (NULL);
1473 cur->lno = m.lno;
1474 cur->cno = m.cno;
1475 cmd = endp;
1476 break;
1477 case '.': /* Current position. */
1478 ++cmd;
1479 /* FALLTHROUGH */
1480 case '+': /* Increment. */
1481 case '-': /* Decrement. */
1482 /* If an empty file, then '.' is 0, not 1. */
1483 if (sp->lno == 1) {
1484 if (file_lline(sp, ep, &cur->lno))
1485 return (NULL);
1486 if (cur->lno != 0)
1487 cur->lno = 1;
1488 } else
1489 cur->lno = sp->lno;
1490 cur->cno = sp->cno;
1491 break;
1492 default:
1493 return (cmd);
1497 * Evaluate any offset. Offsets are +/- any number, or,
1498 * any number of +/- signs, or any combination thereof.
1500 for (total = 0; *cmd == '-' || *cmd == '+'; total += num) {
1501 num = *cmd == '-' ? -1 : 1;
1502 if (isdigit(*++cmd)) {
1503 num *= strtol(cmd, &endp, 10);
1504 cmd = endp;
1507 if (total < 0 && -total > cur->lno) {
1508 msgq(sp, M_ERR,
1509 "Reference to a line number less than 0.");
1510 return (NULL);
1512 cur->lno += total;