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