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:
7: bool pflag, nflag;
8: int poffset;
9:
10: #define nochng() lchng = chng
11:
12: /*
13: * Main loop for command mode command decoding.
14: * A few commands are executed here, but main function
15: * is to strip command addresses, do a little address oriented
16: * processing and call command routines to do the real work.
17: */
18: commands(noprompt, exitoneof)
19: bool noprompt, exitoneof;
20: {
21: register line *addr;
22: register int c;
23: register int lchng;
24: int given;
25: int seensemi;
26: int cnt;
27: bool hadpr;
28:
29: resetflav();
30: nochng();
31: for (;;) {
32: /*
33: * If dot at last command
34: * ended up at zero, advance to one if there is a such.
35: */
36: if (dot <= zero) {
37: dot = zero;
38: if (dol > zero)
39: dot = one;
40: }
41: shudclob = 0;
42:
43: /*
44: * If autoprint or trailing print flags,
45: * print the line at the specified offset
46: * before the next command.
47: */
48: if (pflag ||
49: lchng != chng && value(AUTOPRINT) && !inglobal && !inopen && endline) {
50: pflag = 0;
51: nochng();
52: if (dol != zero) {
53: addr1 = addr2 = dot + poffset;
54: if (addr1 < one || addr1 > dol)
55: error("Offset out-of-bounds|Offset after command too large");
56: setdot1();
57: goto print;
58: }
59: }
60: nochng();
61:
62: /*
63: * Print prompt if appropriate.
64: * If not in global flush output first to prevent
65: * going into pfast mode unreasonably.
66: */
67: if (inglobal == 0) {
68: flush();
69: if (!hush && value(PROMPT) && !globp && !noprompt && endline) {
70: putchar(':');
71: hadpr = 1;
72: }
73: TSYNC();
74: }
75:
76: /*
77: * Gobble up the address.
78: * Degenerate addresses yield ".".
79: */
80: addr2 = 0;
81: given = seensemi = 0;
82: do {
83: addr1 = addr2;
84: addr = address(0);
85: c = getcd();
86: if (addr == 0)
87: if (c == ',')
88: addr = dot;
89: else if (addr1 != 0) {
90: addr2 = dot;
91: break;
92: } else
93: break;
94: addr2 = addr;
95: given++;
96: if (c == ';') {
97: c = ',';
98: dot = addr;
99: seensemi = 1;
100: }
101: } while (c == ',');
102: if (c == '%') {
103: /* %: same as 1,$ */
104: addr1 = one;
105: addr2 = dol;
106: given = 2;
107: c = getchar();
108: }
109: if (addr1 == 0)
110: addr1 = addr2;
111: if (c == ':')
112: c = getchar();
113:
114: /*
115: * Set command name for special character commands.
116: */
117: tailspec(c);
118:
119: /*
120: * If called via : escape from open or visual, limit
121: * the set of available commands here to save work below.
122: */
123: if (inopen) {
124: if (c=='\n' || c=='\r' || c==CTRL(d) || c==EOF) {
125: if (addr2)
126: dot = addr2;
127: if (c == EOF)
128: return;
129: continue;
130: }
131: if (any(c, "o"))
132: notinvis:
133: tailprim(Command, 1, 1);
134: }
135: choice:
136: switch (c) {
137:
138: case 'a':
139:
140: if (peekchar() == 'r') {
141: /* args */
142: tail("args");
143: setnoaddr();
144: eol();
145: pargs();
146: continue;
147: }
148:
149: /* append */
150: if (inopen)
151: goto notinvis;
152: tail("append");
153: setdot();
154: aiflag = exclam();
155: newline();
156: deletenone();
157: setin(addr2);
158: ignore(append(gettty, addr2));
159: nochng();
160: continue;
161:
162: case 'c':
163: switch (peekchar()) {
164:
165: /* copy */
166: case 'o':
167: tail("copy");
168: move();
169: continue;
170:
171: #ifdef CHDIR
172: /* cd */
173: case 'd':
174: tail("cd");
175: goto changdir;
176:
177: /* chdir */
178: case 'h':
179: ignchar();
180: if (peekchar() == 'd') {
181: register char *p;
182: tail2of("chdir");
183: changdir:
184: if (savedfile[0] == '/' || !value(WARN))
185: ignore(exclam());
186: else
187: ignore(quickly());
188: if (skipend()) {
189: p = getenv("HOME");
190: if (p == NULL)
191: error("Home directory unknown");
192: } else
193: getone(), p = file;
194: eol();
195: if (chdir(p) < 0)
196: filioerr(p);
197: if (savedfile[0] != '/')
198: edited = 0;
199: continue;
200: }
201: if (inopen)
202: tailprim("change", 2, 1);
203: tail2of("change");
204: break;
205:
206: #endif
207: default:
208: if (inopen)
209: goto notinvis;
210: tail("change");
211: break;
212: }
213: /* change */
214: aiflag = exclam();
215: setCNL();
216: setin(addr1);
217: delete(0);
218: ignore(append(gettty, addr1 - 1));
219: nochng();
220: continue;
221:
222: /* delete */
223: case 'd':
224: /*
225: * Caution: dp and dl have special meaning already.
226: */
227: tail("delete");
228: c = cmdreg();
229: setCNL();
230: if (c)
231: YANKreg(c);
232: delete(0);
233: appendnone();
234: continue;
235:
236: /* edit */
237: /* ex */
238: case 'e':
239: tail(peekchar() == 'x' ? "ex" : "edit");
240: editcmd:
241: if (!exclam() && chng)
242: c = 'E';
243: filename(c);
244: if (c == 'E') {
245: ungetchar(lastchar());
246: ignore(quickly());
247: }
248: setnoaddr();
249: doecmd:
250: init();
251: addr2 = zero;
252: laste++;
253: sync();
254: rop(c);
255: nochng();
256: continue;
257:
258: /* file */
259: case 'f':
260: tail("file");
261: setnoaddr();
262: filename(c);
263: noonl();
264: synctmp();
265: continue;
266:
267: /* global */
268: case 'g':
269: tail("global");
270: global(!exclam());
271: nochng();
272: continue;
273:
274: /* insert */
275: case 'i':
276: if (inopen)
277: goto notinvis;
278: tail("insert");
279: setdot();
280: nonzero();
281: aiflag = exclam();
282: newline();
283: deletenone();
284: setin(addr2);
285: ignore(append(gettty, addr2 - 1));
286: if (dot == zero && dol > zero)
287: dot = one;
288: nochng();
289: continue;
290:
291: /* join */
292: case 'j':
293: tail("join");
294: c = exclam();
295: setcount();
296: nonzero();
297: newline();
298: if (given < 2 && addr2 != dol)
299: addr2++;
300: join(c);
301: continue;
302:
303: /* k */
304: case 'k':
305: casek:
306: pastwh();
307: c = getchar();
308: if (endcmd(c))
309: serror("Mark what?|%s requires following letter", Command);
310: newline();
311: if (!islower(c))
312: error("Bad mark|Mark must specify a letter");
313: setdot();
314: nonzero();
315: names[c - 'a'] = *addr2 &~ 01;
316: anymarks = 1;
317: continue;
318:
319: /* list */
320: case 'l':
321: tail("list");
322: setCNL();
323: ignorf(setlist(1));
324: pflag = 0;
325: goto print;
326:
327: case 'm':
328: if (peekchar() == 'a') {
329: /* mark */
330: tail("mark");
331: goto casek;
332: }
333: /* move */
334: tail("move");
335: move();
336: continue;
337:
338: case 'n':
339: if (peekchar() == 'u') {
340: tail("number");
341: goto numberit;
342: }
343: /* next */
344: tail("next");
345: setnoaddr();
346: ckaw();
347: ignore(quickly());
348: if (getargs())
349: makargs();
350: next();
351: c = 'e';
352: filename(c);
353: goto doecmd;
354:
355: /* open */
356: case 'o':
357: tail("open");
358: oop();
359: pflag = 0;
360: nochng();
361: continue;
362:
363: case 'p':
364: case 'P':
365: switch (peekchar()) {
366:
367: /* put */
368: case 'u':
369: tail("put");
370: setdot();
371: c = cmdreg();
372: eol();
373: if (c)
374: putreg(c);
375: else
376: put();
377: continue;
378:
379: case 'r':
380: ignchar();
381: if (peekchar() == 'e') {
382: /* preserve */
383: tail2of("preserve");
384: eol();
385: if (preserve() == 0)
386: error("Preserve failed!");
387: else
388: error("File preserved.");
389: }
390: tail2of("print");
391: break;
392:
393: default:
394: tail("print");
395: break;
396: }
397: /* print */
398: setCNL();
399: pflag = 0;
400: print:
401: nonzero();
402: if (CL && span() > LINES) {
403: flush1();
404: vclear();
405: }
406: plines(addr1, addr2, 1);
407: continue;
408:
409: /* quit */
410: case 'q':
411: tail("quit");
412: setnoaddr();
413: c = quickly();
414: eol();
415: if (!c)
416: quit:
417: nomore();
418: if (inopen) {
419: vgoto(WECHO, 0);
420: if (!ateopr())
421: vnfl();
422: else
423: putpad(VE);
424: flush();
425: setty(normf);
426: }
427: cleanup(1);
428: exit(0);
429:
430: case 'r':
431: if (peekchar() == 'e') {
432: ignchar();
433: switch (peekchar()) {
434:
435: /* rewind */
436: case 'w':
437: tail2of("rewind");
438: setnoaddr();
439: eol();
440: ckaw();
441: ignore(quickly());
442: erewind();
443: next();
444: c = 'e';
445: ungetchar(lastchar());
446: filename(c);
447: goto doecmd;
448:
449: /* recover */
450: case 'c':
451: tail2of("recover");
452: setnoaddr();
453: c = 'e';
454: if (!exclam() && chng)
455: c = 'E';
456: filename(c);
457: if (c == 'E') {
458: ungetchar(lastchar());
459: ignore(quickly());
460: }
461: init();
462: addr2 = zero;
463: laste++;
464: sync();
465: recover();
466: rop2();
467: revocer();
468: if (status == 0)
469: rop3(c);
470: if (dol != zero)
471: change();
472: nochng();
473: continue;
474: }
475: tail2of("read");
476: } else
477: tail("read");
478: /* read */
479: if (savedfile[0] == 0 && dol == zero)
480: c = 'e';
481: pastwh();
482: if (peekchar() == '!') {
483: setdot();
484: ignchar();
485: unix0(0);
486: filter(0);
487: continue;
488: }
489: filename(c);
490: rop(c);
491: nochng();
492: if (inopen && endline && addr1 > zero && addr1 < dol)
493: dot = addr1 + 1;
494: continue;
495:
496: case 's':
497: switch (peekchar()) {
498:
499: /* set */
500: case 'e':
501: tail("set");
502: setnoaddr();
503: set();
504: continue;
505:
506: /* shell */
507: case 'h':
508: tail("shell");
509: setNAEOL();
510: vnfl();
511: putpad(TE);
512: flush();
513: unixwt(1, unixex("-i", (char *) 0, 0, 0));
514: vcontin(0);
515: putpad(TI);
516: continue;
517:
518: /* source */
519: case 'o':
520: if (inopen)
521: goto notinvis;
522: tail("source");
523: setnoaddr();
524: getone();
525: eol();
526: source(file, 0);
527: continue;
528: }
529: /* fall into ... */
530:
531: /* & */
532: /* ~ */
533: /* substitute */
534: case '&':
535: case '~':
536: Command = "substitute";
537: if (c == 's')
538: tail(Command);
539: if (!substitute(c))
540: pflag = 0;
541: continue;
542:
543: /* t */
544: case 't':
545: #ifdef TAGSCODE
546: if (peekchar() == 'a') {
547: tail("tag");
548: tagfind(exclam());
549: if (!inopen)
550: lchng = chng - 1;
551: else
552: nochng();
553: continue;
554: }
555: #endif
556: tail("t");
557: move();
558: continue;
559:
560: /* undo */
561: case 'u':
562: tail("undo");
563: setnoaddr();
564: markDOT();
565: c = exclam();
566: newline();
567: undo(c);
568: continue;
569:
570: case 'v':
571: switch (peekchar()) {
572:
573: case 'e':
574: /* version */
575: tail("version");
576: setNAEOL();
577: printf("Version 2.13, 9/5/80");
578: noonl();
579: continue;
580:
581: /* visual */
582: case 'i':
583: tail("visual");
584: if (inopen) {
585: c = 'e';
586: goto editcmd;
587: }
588: vop();
589: pflag = 0;
590: nochng();
591: continue;
592: }
593: /* v */
594: tail("v");
595: global(0);
596: nochng();
597: continue;
598:
599: /* write */
600: case 'w':
601: c = peekchar();
602: tail(c == 'q' ? "wq" : "write");
603: wq:
604: if (skipwh() && peekchar() == '!') {
605: ignchar();
606: setall();
607: unix0(0);
608: filter(1);
609: } else {
610: setall();
611: wop(1);
612: nochng();
613: }
614: if (c == 'q')
615: goto quit;
616: continue;
617:
618: /* xit */
619: case 'x':
620: tail("xit");
621: if (!chng)
622: goto quit;
623: c = 'q';
624: goto wq;
625:
626: /* yank */
627: case 'y':
628: tail("yank");
629: c = cmdreg();
630: setcount();
631: eol();
632: if (c)
633: YANKreg(c);
634: else
635: yank();
636: continue;
637:
638: /* z */
639: case 'z':
640: zop(0);
641: pflag = 0;
642: continue;
643:
644: /* | */
645: case '|':
646: endline = 0;
647: goto caseline;
648:
649: /* \n */
650: case '\n':
651: endline = 1;
652: caseline:
653: notempty();
654: if (addr2 == 0) {
655: if (UP != NOSTR && c == '\n' && !inglobal)
656: c = CTRL(k);
657: if (inglobal)
658: addr1 = addr2 = dot;
659: else {
660: if (dot == dol)
661: error("At EOF|At end-of-file");
662: addr1 = addr2 = dot + 1;
663: }
664: }
665: setdot();
666: nonzero();
667: if (seensemi)
668: addr1 = addr2;
669: getline(*addr1);
670: if (c == CTRL(k)) {
671: flush1();
672: destline--;
673: if (hadpr)
674: shudclob = 1;
675: }
676: plines(addr1, addr2, 1);
677: continue;
678:
679: /* " */
680: case '"':
681: comment();
682: continue;
683:
684: /* # */
685: case '#':
686: numberit:
687: setCNL();
688: ignorf(setnumb(1));
689: pflag = 0;
690: goto print;
691:
692: /* = */
693: case '=':
694: newline();
695: setall();
696: printf("%d", lineno(addr2));
697: noonl();
698: continue;
699:
700: /* ! */
701: case '!':
702: if (addr2 != 0) {
703: unix0(0);
704: setdot();
705: filter(2);
706: } else {
707: unix0(1);
708: vnfl();
709: putpad(TE);
710: flush();
711: unixwt(1, unixex("-c", uxb, 0, 0));
712: vcontin(1);
713: putpad(TI);
714: nochng();
715: }
716: continue;
717:
718: /* < */
719: /* > */
720: case '<':
721: case '>':
722: for (cnt = 1; peekchar() == c; cnt++)
723: ignchar();
724: setCNL();
725: shift(c, cnt);
726: continue;
727:
728: /* ^D */
729: /* EOF */
730: case CTRL(d):
731: case EOF:
732: if (exitoneof) {
733: if (addr2 != 0)
734: dot = addr2;
735: return;
736: }
737: if (!isatty(0)) {
738: if (intty)
739: /*
740: * Chtty sys call at UCB may cause a
741: * input which was a tty to suddenly be
742: * turned into /dev/null.
743: */
744: onhup();
745: return;
746: }
747: if (addr2 != 0) {
748: setlastchar('\n');
749: putnl();
750: }
751: if (dol == zero) {
752: if (addr2 == 0)
753: putnl();
754: notempty();
755: }
756: ungetchar(EOF);
757: zop(hadpr);
758: continue;
759:
760: default:
761: if (!isalpha(c))
762: break;
763: ungetchar(c);
764: tailprim("", 0, 0);
765: }
766: error("What?|Unknown command character '%c'", c);
767: }
768: }
Defined functions
Defined variables
nflag
defined in line
7;
never used
pflag
defined in line
7; used 9 times
Defined macros
nochng
defined in line
10; used 16 times
- in line 30,
51,
60,
159,
219,
255,
271,
288,
360,
472,
491,
552,
590,
596,
612,
714