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