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