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