|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)ex_cmds2.c 7.6 (Berkeley) 1/2/88";
9: #endif not lint
10:
11: #include "ex.h"
12: #include "ex_argv.h"
13: #include "ex_temp.h"
14: #include "ex_tty.h"
15: #include "ex_vis.h"
16:
17: extern bool pflag, nflag; /* mjm: extern; also in ex_cmds.c */
18: extern int poffset; /* mjm: extern; also in ex_cmds.c */
19:
20: /*
21: * Subroutines for major command loop.
22: */
23:
24: /*
25: * Is there a single letter indicating a named buffer next?
26: */
27: cmdreg()
28: {
29: register int c = 0;
30: register int wh = skipwh();
31:
32: if (wh && isalpha(peekchar()))
33: c = ex_getchar();
34: return (c);
35: }
36:
37: /*
38: * Tell whether the character ends a command
39: */
40: endcmd(ch)
41: int ch;
42: {
43: switch (ch) {
44:
45: case '\n':
46: case EOF:
47: endline = 1;
48: return (1);
49:
50: case '|':
51: case '"':
52: endline = 0;
53: return (1);
54: }
55: return (0);
56: }
57:
58: /*
59: * Insist on the end of the command.
60: */
61: eol()
62: {
63:
64: if (!skipend())
65: error("Extra chars|Extra characters at end of command");
66: ignnEOF();
67: }
68:
69: /*
70: * Print out the message in the error message file at str,
71: * with i an integer argument to printf.
72: */
73: /*VARARGS2*/
74: error(str, i)
75: #ifndef EXSTRINGS
76: char *str;
77: #else
78: # ifdef lint
79: char *str;
80: # else
81: int str;
82: # endif
83: #endif
84: int i;
85: {
86:
87: error0();
88: merror(str, i);
89: if (writing) {
90: serror(" [Warning - %s is incomplete]", file);
91: writing = 0;
92: }
93: error1(str);
94: }
95:
96: /*
97: * Rewind the argument list.
98: */
99: erewind()
100: {
101:
102: argc = argc0;
103: argv = argv0;
104: args = args0;
105: if (argc > 1 && !hush) {
106: ex_printf(mesg("%d files@to edit"), argc);
107: if (inopen)
108: ex_putchar(' ');
109: else
110: putNFL();
111: }
112: }
113:
114: /*
115: * Guts of the pre-printing error processing.
116: * If in visual and catching errors, then we dont mung up the internals,
117: * just fixing up the echo area for the print.
118: * Otherwise we reset a number of externals, and discard unused input.
119: */
120: error0()
121: {
122:
123: if (vcatch) {
124: if (splitw == 0)
125: fixech();
126: if (!SO || !SE)
127: dingdong();
128: return;
129: }
130: if (input) {
131: input = strend(input) - 1;
132: if (*input == '\n')
133: setlastchar('\n');
134: input = 0;
135: }
136: setoutt();
137: flush();
138: resetflav();
139: if (!SO || !SE)
140: dingdong();
141: if (inopen) {
142: /*
143: * We are coming out of open/visual ungracefully.
144: * Restore COLUMNS, undo, and fix tty mode.
145: */
146: COLUMNS = OCOLUMNS;
147: undvis();
148: ostop(normf);
149: /* ostop should be doing this
150: putpad(VE);
151: putpad(KE);
152: */
153: putnl();
154: }
155: inopen = 0;
156: holdcm = 0;
157: }
158:
159: /*
160: * Post error printing processing.
161: * Close the i/o file if left open.
162: * If catching in visual then throw to the visual catch,
163: * else if a child after a fork, then exit.
164: * Otherwise, in the normal command mode error case,
165: * finish state reset, and throw to top.
166: */
167: error1(str)
168: char *str;
169: {
170: bool die;
171:
172: if (io > 0) {
173: close(io);
174: io = -1;
175: }
176: die = (getpid() != ppid); /* Only children die */
177: inappend = inglobal = 0;
178: globp = vglobp = vmacp = 0;
179: if (vcatch && !die) {
180: inopen = 1;
181: vcatch = 0;
182: if (str)
183: noonl();
184: fixol();
185: longjmp(vreslab,1);
186: }
187: if (str && !vcatch)
188: putNFL();
189: if (die)
190: ex_exit(1);
191: lseek(0, 0L, 2);
192: if (inglobal)
193: setlastchar('\n');
194: while (lastchar() != '\n' && lastchar() != EOF)
195: ignchar();
196: ungetchar(0);
197: endline = 1;
198: reset();
199: }
200:
201: fixol()
202: {
203: if (Outchar != vputchar) {
204: flush();
205: if (state == ONEOPEN || state == HARDOPEN)
206: outline = destline = 0;
207: Outchar = vputchar;
208: vcontin(1);
209: } else {
210: if (destcol)
211: vclreol();
212: vclean();
213: }
214: }
215:
216: /*
217: * Does an ! character follow in the command stream?
218: */
219: exclam()
220: {
221:
222: if (peekchar() == '!') {
223: ignchar();
224: return (1);
225: }
226: return (0);
227: }
228:
229: /*
230: * Make an argument list for e.g. next.
231: */
232: makargs()
233: {
234:
235: glob(&frob);
236: argc0 = frob.argc0;
237: argv0 = frob.argv;
238: args0 = argv0[0];
239: erewind();
240: }
241:
242: /*
243: * Advance to next file in argument list.
244: */
245: next()
246: {
247: extern short isalt; /* defined in ex_io.c */
248:
249: if (argc == 0)
250: error("No more files@to edit");
251: morargc = argc;
252: isalt = (strcmp(altfile, args)==0) + 1;
253: if (savedfile[0])
254: CP(altfile, savedfile);
255: CP(savedfile, args);
256: argc--;
257: args = argv ? *++argv : strend(args) + 1;
258: }
259:
260: /*
261: * Eat trailing flags and offsets after a command,
262: * saving for possible later post-command prints.
263: */
264: newline()
265: {
266: register int c;
267:
268: resetflav();
269: for (;;) {
270: c = ex_getchar();
271: switch (c) {
272:
273: case '^':
274: case '-':
275: poffset--;
276: break;
277:
278: case '+':
279: poffset++;
280: break;
281:
282: case 'l':
283: listf++;
284: break;
285:
286: case '#':
287: nflag++;
288: break;
289:
290: case 'p':
291: listf = 0;
292: break;
293:
294: case ' ':
295: case '\t':
296: continue;
297:
298: case '"':
299: comment();
300: setflav();
301: return;
302:
303: default:
304: if (!endcmd(c))
305: serror("Extra chars|Extra characters at end of \"%s\" command", Command);
306: if (c == EOF)
307: ungetchar(c);
308: setflav();
309: return;
310: }
311: pflag++;
312: }
313: }
314:
315: /*
316: * Before quit or respec of arg list, check that there are
317: * no more files in the arg list.
318: */
319: nomore()
320: {
321:
322: if (argc == 0 || morargc == argc)
323: return;
324: morargc = argc;
325: merror("%d more file", argc);
326: serror("%s@to edit", plural((long) argc));
327: }
328:
329: /*
330: * Before edit of new file check that either an ! follows
331: * or the file has not been changed.
332: */
333: quickly()
334: {
335:
336: if (exclam())
337: return (1);
338: if (chng && dol > zero) {
339: /*
340: chng = 0;
341: */
342: xchng = 0;
343: serror("No write@since last change (:%s! overrides)", Command);
344: }
345: return (0);
346: }
347:
348: /*
349: * Reset the flavor of the output to print mode with no numbering.
350: */
351: resetflav()
352: {
353:
354: if (inopen)
355: return;
356: listf = 0;
357: nflag = 0;
358: pflag = 0;
359: poffset = 0;
360: setflav();
361: }
362:
363: /*
364: * Print an error message with a %s type argument to printf.
365: * Message text comes from error message file.
366: */
367: serror(str, cp)
368: #ifdef lint
369: register char *str;
370: #else
371: register int str;
372: #endif
373: char *cp;
374: {
375:
376: error0();
377: smerror(str, cp);
378: error1(str);
379: }
380:
381: /*
382: * Set the flavor of the output based on the flags given
383: * and the number and list options to either number or not number lines
384: * and either use normally decoded (ARPAnet standard) characters or list mode,
385: * where end of lines are marked and tabs print as ^I.
386: */
387: setflav()
388: {
389:
390: if (inopen)
391: return;
392: ignorf(setnumb(nflag || value(NUMBER)));
393: ignorf(setlist(listf || value(LIST)));
394: setoutt();
395: }
396:
397: /*
398: * Skip white space and tell whether command ends then.
399: */
400: skipend()
401: {
402:
403: pastwh();
404: return (endcmd(peekchar()) && peekchar() != '"');
405: }
406:
407: /*
408: * Set the command name for non-word commands.
409: */
410: tailspec(c)
411: int c;
412: {
413: static char foocmd[2];
414:
415: foocmd[0] = c;
416: Command = foocmd;
417: }
418:
419: /*
420: * Try to read off the rest of the command word.
421: * If alphabetics follow, then this is not the command we seek.
422: */
423: tail(comm)
424: char *comm;
425: {
426:
427: tailprim(comm, 1, 0);
428: }
429:
430: tail2of(comm)
431: char *comm;
432: {
433:
434: tailprim(comm, 2, 0);
435: }
436:
437: char tcommand[20];
438:
439: tailprim(comm, i, notinvis)
440: register char *comm;
441: int i;
442: bool notinvis;
443: {
444: register char *cp;
445: register int c;
446:
447: Command = comm;
448: for (cp = tcommand; i > 0; i--)
449: *cp++ = *comm++;
450: while (*comm && peekchar() == *comm)
451: *cp++ = ex_getchar(), comm++;
452: c = peekchar();
453: if (notinvis || isalpha(c)) {
454: /*
455: * Of the trailing lp funny business, only dl and dp
456: * survive the move from ed to ex.
457: */
458: if (tcommand[0] == 'd' && any(c, "lp"))
459: goto ret;
460: if (tcommand[0] == 's' && any(c, "gcr"))
461: goto ret;
462: while (cp < &tcommand[19] && isalpha(peekchar()))
463: *cp++ = ex_getchar();
464: *cp = 0;
465: if (notinvis)
466: serror("What?|%s: No such command from open/visual", tcommand);
467: else
468: serror("What?|%s: Not an editor command", tcommand);
469: }
470: ret:
471: *cp = 0;
472: }
473:
474: /*
475: * Continue after a : command from open/visual.
476: */
477: vcontin(ask)
478: bool ask;
479: {
480:
481: if (vcnt > 0)
482: vcnt = -vcnt;
483: if (inopen) {
484: if (state != VISUAL) {
485: /*
486: * We don't know what a shell command may have left on
487: * the screen, so we move the cursor to the right place
488: * and then put out a newline. But this makes an extra
489: * blank line most of the time so we only do it for :sh
490: * since the prompt gets left on the screen.
491: *
492: * BUG: :!echo longer than current line \\c
493: * will screw it up, but be reasonable!
494: */
495: if (state == CRTOPEN) {
496: termreset();
497: vgoto(WECHO, 0);
498: }
499: if (!ask) {
500: putch('\r');
501: putch('\n');
502: }
503: return;
504: }
505: if (ask) {
506: merror("[Hit return to continue] ");
507: flush();
508: }
509: #ifndef CBREAK
510: vraw();
511: #endif
512: if (ask) {
513: #ifdef EATQS
514: /*
515: * Gobble ^Q/^S since the tty driver should be eating
516: * them (as far as the user can see)
517: */
518: while (peekkey() == CTRL('Q') || peekkey() == CTRL('S'))
519: ignore(getkey());
520: #endif
521: if(getkey() == ':') {
522: /* Ugh. Extra newlines, but no other way */
523: putch('\n');
524: outline = WECHO;
525: ungetkey(':');
526: }
527: }
528: vclrech(1);
529: if (Peek_key != ':') {
530: putpad(TI);
531: tostart();
532: /* replaced by ostart.
533: putpad(VS);
534: putpad(KS);
535: */
536: }
537: }
538: }
539:
540: /*
541: * Put out a newline (before a shell escape)
542: * if in open/visual.
543: */
544: vnfl()
545: {
546:
547: if (inopen) {
548: if (state != VISUAL && state != CRTOPEN && destline <= WECHO)
549: vclean();
550: else
551: vmoveitup(1, 0);
552: vgoto(WECHO, 0);
553: vclrbyte(vtube[WECHO], WCOLS);
554: tostop();
555: /* replaced by the ostop above
556: putpad(VE);
557: putpad(KE);
558: */
559: }
560: flush();
561: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.