8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / vi / port / ex_cmds2.c
blob189374d02733c56fd6674dcfd55118db3ce31dba
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 /* Copyright (c) 1981 Regents of the University of California */
32 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include "ex.h"
35 #include "ex_argv.h"
36 #include "ex_temp.h"
37 #include "ex_tty.h"
38 #include "ex_vis.h"
39 #include <unistd.h>
41 extern bool pflag, nflag; /* extern; also in ex_cmds.c */
42 extern int poffset; /* extern; also in ex_cmds.c */
43 extern short slevel; /* extern; has level of source() */
46 * Subroutines for major command loop.
50 * Is there a single letter indicating a named buffer next?
52 int
53 cmdreg(void)
55 int c = 0;
56 int wh = skipwh();
58 #ifdef XPG4
59 if (wh && isalpha(c = peekchar()) && isascii(c) && !isdigit(c))
60 #else /* XPG4 */
61 if (wh && isalpha(c = peekchar()) && isascii(c))
62 #endif /* XPG4 */
63 c = getchar();
65 #ifdef XPG4
66 if (isdigit(c)) {
67 c = 0;
69 #endif /* XPG4 */
70 return (c);
74 * Tell whether the character ends a command
76 int
77 endcmd(int ch)
79 switch (ch) {
81 case '\n':
82 case EOF:
83 endline = 1;
84 return (1);
86 case '|':
87 case '"':
88 endline = 0;
89 return (1);
91 return (0);
95 * Insist on the end of the command.
97 void
98 eol(void)
101 if (!skipend())
102 error(value(vi_TERSE) ? gettext("Extra chars") :
103 gettext("Extra characters at end of command"));
104 ignnEOF();
107 #ifdef XPG4
109 * Print out the message in the error message file at str,
110 * with i an integer argument to printf.
112 /*VARARGS2*/
113 void
114 error(str, i)
115 unsigned char *str;
116 int i;
118 tagflg = 0;
119 errcnt++;
120 noerror(str, i);
124 * noerror(): like error(), but doesn't inc errcnt.
125 * the reason why we created this routine, instead of fixing up errcnt
126 * after error() is called, is because we will do a longjmp, and
127 * not a return. it does other things closing file i/o, reset, etc;
128 * so we follow those procedures.
130 /*VARARGS2*/
131 void
132 noerror(str, i)
133 unsigned char *str;
134 int i;
137 error0();
138 merror(str, i);
139 if (writing) {
140 serror((unsigned char *)
141 gettext(" [Warning - %s is incomplete]"), file);
142 writing = 0;
144 error1(str);
147 #else /* !XPG4 */
149 * Print out the message in the error message file at str,
150 * with i an integer argument to printf.
152 /*VARARGS2*/
153 void
154 error(str, i)
155 unsigned char *str;
156 int i;
158 tagflg = 0;
159 errcnt++;
160 error0();
161 merror(str, i);
162 if (writing) {
163 serror((unsigned char *)
164 gettext(" [Warning - %s is incomplete]"), file);
165 writing = 0;
167 error1(str);
169 #endif /* XPG4 */
172 * Rewind the argument list.
174 void
175 erewind(void)
178 argc = argc0;
179 argv = argv0;
180 args = args0;
181 if (argc > 1 && !hush && cur_term) {
182 viprintf(mesg(value(vi_TERSE) ? gettext("%d files") :
183 gettext("%d files to edit")), argc);
184 if (inopen)
185 putchar(' ');
186 else
187 putNFL();
192 * Guts of the pre-printing error processing.
193 * If in visual and catching errors, then we don't mung up the internals,
194 * just fixing up the echo area for the print.
195 * Otherwise we reset a number of externals, and discard unused input.
197 void
198 error0(void)
201 if (laste) {
202 #ifdef VMUNIX
203 tlaste();
204 #endif
205 laste = 0;
206 sync();
208 if (vcatch) {
209 if (splitw == 0)
210 fixech();
211 if (!enter_standout_mode || !exit_bold)
212 dingdong();
213 return;
215 if (input) {
216 input = strend(input) - 1;
217 if (*input == '\n')
218 setlastchar('\n');
219 input = 0;
221 setoutt();
222 flush();
223 resetflav();
224 if (!enter_standout_mode || !exit_bold)
225 dingdong();
226 if (inopen) {
228 * We are coming out of open/visual ungracefully.
229 * Restore columns, undo, and fix tty mode.
231 columns = OCOLUMNS;
232 undvis();
233 ostop(normf);
234 /* ostop should be doing this
235 putpad(cursor_normal);
236 putpad(key_eol);
238 putnl();
240 inopen = 0;
241 holdcm = 0;
245 * Post error printing processing.
246 * Close the i/o file if left open.
247 * If catching in visual then throw to the visual catch,
248 * else if a child after a fork, then exit.
249 * Otherwise, in the normal command mode error case,
250 * finish state reset, and throw to top.
252 void
253 error1(unsigned char *str)
255 bool die;
256 extern short ttyindes;
258 if ((io > 0) && (io != ttyindes)) {
259 close(io);
260 io = -1;
263 die = (getpid() != ppid); /* Only children die */
264 inappend = inglobal = 0;
265 globp = vglobp = vmacp = 0;
266 if (vcatch && !die) {
267 inopen = 1;
268 vcatch = 0;
269 if (str)
270 noonl();
271 fixol();
272 if (slevel > 0)
273 reset();
274 longjmp(vreslab,1);
276 if (str && !vcatch)
277 putNFL();
278 if (die)
279 exit(++errcnt);
280 lseek(0, 0L, 2);
281 if (inglobal)
282 setlastchar('\n');
284 if (inexrc) {
286 * Set inexrc to 0 so that this error is printed only
287 * once (eg. when stdin is redirected from /dev/null and
288 * vi prints "Input read error" because it is unable to
289 * read() the <CR>).
291 inexrc = 0;
292 lprintf(gettext(
293 "Error detected in .exrc.[Hit return to continue] "),
295 putNFL();
296 getkey();
299 while ((lastchar() != '\n') && (lastchar() != EOF))
300 ignchar();
301 ungetchar(0);
302 endline = 1;
303 reset();
306 void
307 fixol(void)
309 if (Outchar != vputchar) {
310 flush();
311 if (state == ONEOPEN || state == HARDOPEN)
312 outline = destline = 0;
313 Outchar = vputchar;
314 vcontin(1);
316 * Outchar could be set to termchar() through vcontin().
317 * So reset it again.
319 Outchar = vputchar;
320 } else {
321 if (destcol)
322 vclreol();
323 vclean();
328 * Does an ! character follow in the command stream?
331 exclam(void)
334 if (peekchar() == '!') {
335 ignchar();
336 return (1);
338 return (0);
342 * Make an argument list for e.g. next.
344 void
345 makargs(void)
348 glob(&frob);
349 argc0 = frob.argc0;
350 argv0 = frob.argv;
351 args0 = argv0[0];
352 erewind();
356 * Advance to next file in argument list.
358 void
359 next(void)
361 extern short isalt; /* defined in ex_io.c */
363 if (argc == 0)
364 error(value(vi_TERSE) ?
365 (unsigned char *)gettext("No more files") :
366 (unsigned char *)gettext("No more files to edit"));
367 morargc = argc;
368 isalt = (strcmp(altfile, args)==0) + 1;
369 if (savedfile[0])
370 CP(altfile, savedfile);
371 (void) strlcpy(savedfile, args, sizeof (savedfile));
372 argc--;
373 args = argv ? *++argv : strend(args) + 1;
374 #if i386 || i286
375 destcol = 0;
376 #endif
380 * Eat trailing flags and offsets after a command,
381 * saving for possible later post-command prints.
383 void
384 donewline(void)
386 int c;
388 resetflav();
389 for (;;) {
390 c = getchar();
391 switch (c) {
393 case '^':
394 case '-':
395 poffset--;
396 break;
398 case '+':
399 poffset++;
400 break;
402 case 'l':
403 listf++;
404 break;
406 case '#':
407 nflag++;
408 break;
410 case 'p':
411 listf = 0;
412 break;
414 case ' ':
415 case '\t':
416 continue;
418 case '"':
419 comment();
420 setflav();
421 return;
423 default:
424 if (!endcmd(c))
425 serror(value(vi_TERSE) ?
426 (unsigned char *)gettext("Extra chars") :
427 (unsigned char *)gettext(
428 "Extra characters at end of \"%s\" command"),
429 Command);
430 if (c == EOF)
431 ungetchar(c);
432 setflav();
433 return;
435 pflag++;
440 * Before quit or respec of arg list, check that there are
441 * no more files in the arg list.
444 nomore(void)
447 if (argc == 0 || morargc == argc)
448 return(0);
449 morargc = argc;
450 if (argc == 1) {
451 merror(value(vi_TERSE) ? gettext("1 more file") :
452 gettext("1 more file to edit"), argc);
453 } else {
454 merror(value(vi_TERSE) ? gettext("%d more files") :
455 gettext("%d more files to edit"), argc);
457 return(1);
461 * Before edit of new file check that either an ! follows
462 * or the file has not been changed.
465 quickly(void)
468 if (exclam())
469 return (1);
470 if (chng && dol > zero) {
472 chng = 0;
474 xchng = 0;
475 error(value(vi_TERSE) ? (unsigned char *)gettext("No write") :
476 (unsigned char *)
477 gettext("No write since last change (:%s! overrides)"),
478 Command);
480 return (0);
484 * Reset the flavor of the output to print mode with no numbering.
486 void
487 resetflav(void)
490 if (inopen)
491 return;
492 listf = 0;
493 nflag = 0;
494 pflag = 0;
495 poffset = 0;
496 setflav();
500 * Print an error message with a %s type argument to printf.
501 * Message text comes from error message file.
503 void
504 serror(unsigned char *str, unsigned char *cp)
506 tagflg = 0;
507 error0();
508 smerror(str, cp);
509 error1(str);
513 * Set the flavor of the output based on the flags given
514 * and the number and list options to either number or not number lines
515 * and either use normally decoded (ARPAnet standard) characters or list mode,
516 * where end of lines are marked and tabs print as ^I.
518 void
519 setflav(void)
522 if (inopen)
523 return;
524 setnumb(nflag || value(vi_NUMBER));
525 setlist(listf || value(vi_LIST));
526 if (!inopen)
527 setoutt();
531 * Skip white space and tell whether command ends then.
534 skipend(void)
537 pastwh();
538 return (endcmd(peekchar()) && peekchar() != '"');
542 * Set the command name for non-word commands.
544 void
545 tailspec(int c)
547 static unsigned char foocmd[2];
549 foocmd[0] = c;
550 Command = foocmd;
554 * Try to read off the rest of the command word.
555 * If alphabetics follow, then this is not the command we seek.
557 void
558 tail(unsigned char *comm)
561 tailprim(comm, 1, 0);
564 void
565 tail2of(unsigned char *comm)
568 tailprim(comm, 2, 0);
571 unsigned char tcommand[20];
573 void
574 tailprim(unsigned char *comm, int i, bool notinvis)
576 unsigned char *cp;
577 int c;
579 Command = comm;
580 for (cp = tcommand; i > 0; i--)
581 *cp++ = *comm++;
582 while (*comm && peekchar() == *comm)
583 *cp++ = getchar(), comm++;
584 c = peekchar();
585 if (notinvis || (isalpha(c) && isascii(c))) {
587 * Of the trailing lp funny business, only dl and dp
588 * survive the move from ed to ex.
590 if (tcommand[0] == 'd' && any(c, "lp"))
591 goto ret;
592 if (tcommand[0] == 's' && any(c, "gcr"))
593 goto ret;
594 while (cp < &tcommand[19] && isalpha(c = peekchar()) && isascii(c))
595 *cp++ = getchar();
596 *cp = 0;
597 if (notinvis)
598 serror(value(vi_TERSE) ?
599 (unsigned char *)gettext("What?") :
600 (unsigned char *)gettext(
601 "%s: No such command from open/visual"), tcommand);
602 else
603 serror(value(vi_TERSE) ?
604 (unsigned char *)gettext("What?") :
605 (unsigned char *)gettext(
606 "%s: Not an editor command"), tcommand);
608 ret:
609 *cp = 0;
613 * Continue after a : command from open/visual.
615 void
616 vcontin(bool ask)
619 if (vcnt > 0)
620 vcnt = -vcnt;
621 if (inopen) {
622 if (state != VISUAL) {
624 * We don't know what a shell command may have left on
625 * the screen, so we move the cursor to the right place
626 * and then put out a newline. But this makes an extra
627 * blank line most of the time so we only do it for :sh
628 * since the prompt gets left on the screen.
630 * BUG: :!echo longer than current line \\c
631 * will mess it up.
633 if (state == CRTOPEN) {
634 termreset();
635 vgoto(WECHO, 0);
637 if (!ask) {
638 (void) putch('\r');
639 (void) putch('\n');
641 return;
643 if (ask) {
644 merror(gettext("[Hit return to continue] "));
645 flush();
647 #ifndef CBREAK
648 vraw();
649 #endif
650 if (ask) {
651 #ifdef notdef
653 * Gobble ^Q/^S since the tty driver should be eating
654 * them (as far as the user can see)
656 while (peekkey() == CTRL('Q') || peekkey() == CTRL('S'))
657 ignore(getkey());
658 #endif
659 if(getkey() == ':') {
660 /* Extra newlines, but no other way */
661 (void) putch('\n');
662 outline = WECHO;
663 ungetkey(':');
666 vclrech(1);
667 if (Peekkey != ':') {
668 fixterm();
669 putpad((unsigned char *)enter_ca_mode);
670 tostart();
676 * Put out a newline (before a shell escape)
677 * if in open/visual.
679 void
680 vnfl(void)
683 if (inopen) {
684 if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
685 vclean();
686 else
687 vmoveitup(1, 0);
688 vgoto(WECHO, 0);
689 vclrbyte(vtube[WECHO], WCOLS);
690 tostop();
691 /* replaced by the ostop above
692 putpad(cursor_normal);
693 putpad(key_eol);
696 flush();