|
|
1.1 root 1: /* EMACS_MODES: c, !fill */
2: #include "emacs_io.h"
3: #include "emacs_gb.h"
4: #include "emacs_cmds.h"
5: #include <signal.h>
6: #ifdef ux3
7: #include <fcntl.h>
8: #endif
9:
10: /* lext -- extend line up to position if necessary */
11:
12: lext(line,col)
13: /* Keywords: picture-mode movement insertion */
14: {
15: mvc (line,col);
16: if (column<col) insertc(col-column,' ');
17: }
18:
19: dput(c)
20: /* Keywords: insertion modes:10 overwrite-mode */
21: {
22: if (NODEL) insertc(1,c);
23: else put(c);
24: }
25:
26: /* move forward COUNT characters */
27: /* Keywords: movement commands forwards character-at-a-time picture-mode:20 */
28: forw(count)
29:
30: register int count;
31: {
32: register int retval;
33:
34: if (PICMODE) {
35: if (count>0) {
36: lext(curln,count+column);
37: return(1);
38: } else {
39: column += count;
40: if (column<0) {
41: beep();
42: column=0;
43: return(0);
44: } else return(1);
45: }
46: }
47: if (count < 0) {
48: retval = findb(-count);
49: } else {
50: retval = findf(count);
51: }
52: if (retval == 0) beep(); /* couldn't go all the way */
53: move(kline,kcol);
54: return(retval);
55: }
56:
57: /* backward COUNT characters */
58:
59: back(count)
60: /* Keywords: movement commands forwards character-at-a-time */
61: register int count;
62:
63: {
64: forw(-count); /* do it this way */
65: }
66:
67: /* move to previous line, same collumn */
68:
69: upl (count)
70:
71: /* Keywords: commands backwards:30 upward-movement movement text-lines */
72: register int count;
73:
74: {
75:
76: if (curln-count < 1) {
77: if (count == 1) {
78: beep();
79: return(0);
80: } else curln = 1;
81: } else curln -= count;
82: if (PICMODE) lext(curln,column);
83: else mvc(curln,column);
84: return(1);
85: }
86: /* move down one line, same column */
87:
88: downl (count)
89: /* Keywords: commands forwards:30 downward-movement movement text-lines */
90: register int count;
91:
92: {
93: register int retval;
94:
95: if (((curln += count) > nlines)&& (PICMODE == 0)) {
96: curln = nlines+NLRUN;
97: beep();
98: retval = 0;
99: } else retval = 1;
100: if (PICMODE) lext(curln,column);
101: else mvc(curln,column);
102: return(retval);
103: }
104:
105:
106: /* abort EMACS */
107:
108: int aborts = 0;
109: eabort(sig)
110: int sig;
111: {
112: /* Keywords: internal-errors unix-interface commands */
113: if (sig){
114: signal(sig,SIG_DFL); /* Prevent looping */
115: }
116: signal (SIGIOT,SIG_DFL);
117: cook();
118: if (aborts>3) exit(-1);
119: aborts++;
120: #ifdef MINFILES
121: rmtemp();
122: #endif
123: #ifdef PC
124: rmtemp();
125: exit(-1);
126: #else
127: #ifdef bsd
128: sigsetmask(0); /* ARGH, set mask to allow abort! */
129: #endif
130: abort();
131: exit(-1);
132: #endif PC
133: }
134:
135:
136: /* exit EMACS */
137:
138:
139: quit()
140:
141: {
142: /* Keywords: commands exit-processing user-interface:20 unix-interface:30 */
143: clear();
144: cook();
145: statout();
146: #ifdef MINFILES
147: rmtemp(); /* flush temp files */
148: #endif
149: #ifdef PC
150: rmtemp();
151: #else
152: flushproc();
153: #endif
154: exit(0);
155: }
156:
157: /* exit EMACS gracefully */
158:
159: gquit()
160: /* Keywords: commands exit-processing user-interface:20 unix-interface:30 macro-hooks:10 */
161: {
162: if (hooks[Exit_Emacs_Hook]) if (hook(Exit_Emacs_Hook) == 0) return;
163: if(bclean()== 0)quit();
164: }
165:
166: /* kill line */
167:
168: /* if the count is one, and if there is text on the line beyond column,
169: * only that text is killed
170: * if count is one, and column is at end of line, the end of line is killed */
171: /* if count is greater than one, the next count lines (and their end of
172: * lines) are killed */
173:
174: /* all killed text is put into the kill stack */
175:
176:
177: ekill (count)
178:
179: register int count;
180:
181: /* Keywords: commands deletion killstack:10 text-lines */
182:
183: {
184: register int l;
185: int opic,onodel;
186:
187: if (numarg == 0) {
188: if ((l=leng(curln)) > column) {
189: return(delc(l-column));
190: }
191: }
192: opic = PICMODE;
193: onodel =NODEL;
194: PICMODE=NODEL=0; /* Allow line kills! */
195:
196: kline = curln+count;
197: kcol = 0;
198: l= tkill();
199: PICMODE=opic;
200: NODEL=onodel;
201: return(l);
202: }
203:
204: /* goto beginning of current line */
205:
206: begin()
207: /* Keywords: text-lines commands movement backwards */
208: {
209: move(curln,0);
210: }
211:
212: /* goto end of line */
213:
214: endl()
215: /* Keywords: text-lines commands movement backwards */
216: {
217: mvc (curln,10000); /* mvc will adjust line length */
218: }
219:
220: mquote(arg)
221: int arg;
222: /* Keywords: quoting commands insertion */
223: {
224: quote(arg,0200);
225: }
226: rquote(arg)
227: int arg;
228: /* Keywords: quoting commands insertion */
229: {
230: quote(arg,0);
231: }
232:
233: /* insert the next character, whatever it is */
234:
235: /* note that newlines inserted ths way act just like unquoted newlines */
236:
237: quote(count,metf)
238:
239: register int metf;
240: register int count;
241:
242: {
243: /* Keywords: quoting commands insertion */
244: register int c;
245:
246: while(count--) {
247: if ((VERBOSE)&& (MOREIN == 0)) prompt1("%d ^Q: ",count+1);
248:
249: c = getchar();
250: c = c | metf;
251: insertc(1,c);
252: if (VERBOSE && (MOREIN == 0)) {
253: unprompt();
254: }
255: disup();
256: }
257: }
258:
259: /* numchar -- convert argument to a character to insert */
260:
261: numchar(count)
262: /* Keywords: quoting commands insertion argument-processing */
263: register int count;
264: {
265: insertc(1,count); /* insert the count */
266: }
267:
268:
269: /* deletes count characters going forward */
270:
271: fdel(count)
272: /* Keywords: commands deletion forwards character-at-a-time */
273: {
274: IGNORE(findf(count));
275: return(tkill());
276: }
277:
278: /* deletes count characters going backward */
279:
280: bdel(count)
281:
282: register int count;
283: /* Keywords: commands deletion backwards character-at-a-time */
284: {
285: IGNORE(findb(count));
286: return(tkill());
287: }
288:
289: /* file write command */
290:
291:
292: int fright(arg)
293:
294: int arg;
295: {
296: register char *np;
297: /* Keywords: files commands buffers:20 filenames:10 writing */
298: if ((np = expenv(getname("Write file? "))) != NULL) {
299: return(wout(np,arg));
300: }
301: return(0);
302: }
303:
304: /* fred -- read a file */
305:
306: fred(arg)
307:
308: int arg;
309: {
310: /* Keywords: files commands buffers:20 filenames:10 reading */
311:
312: register char *np;
313:
314: if ((np = expenv(getname("Read File? "))) != NULL) {
315: return(readin(np,arg));
316: } else return(0);
317: }
318:
319: /* forward words -- leaves kline, kcol at spot that is count words
320: *forward */
321:
322:
323: wordf(count)
324:
325: register int count;
326:
327: {
328: kmark();
329:
330: /* Keywords: commands:10 forwards movement:50 deletion:50 word-oriented-commands */
331:
332: while (count--) {
333: if (skipf(WRDSEP) || skipf(WRDCHR)) {
334: return;
335: }
336: }
337: }
338:
339: /* skips kline, kcol forward until a character without type bit on is
340: * found */
341:
342:
343: skipf(bit)
344:
345: register int bit;
346: /* Keywords: forwards sentence-commands word-oriented-commands movement:20 commands:10 */
347: {
348: while (bits[*klptr] & bit) {
349: if (mfk()) return(1);
350: }
351: return(0);
352: }
353:
354:
355: /* move forward count words */
356:
357: mfwrd(count)
358: /* Keywords: commands forwards movement word-oriented-commands */
359: register int count;
360:
361: {
362:
363: wordf(count);
364: move(kline,kcol);
365: }
366:
367: /* kill next count words */
368:
369:
370:
371: kfwrd(count)
372: /* Keywords: commands forwards deletion word-oriented-commands */
373: register int count;
374:
375: {
376: wordf(count);
377: return(tkill());
378: }
379:
380: /* skip kline, kcol back until a character without type bit is found */
381:
382:
383:
384: skipb(bit)
385:
386: register int bit;
387: /* Keywords: sentence-commands word-oriented-commands movement:20 backwards commands:10 */
388: {
389: do {
390: if (mbk()) return(1);
391: } while (bits[*klptr] &bit);
392: return(0);
393: }
394:
395: /* backward count words, leaves pointer in kline, kcol */
396:
397: wordb(count)
398:
399: register int count;
400: /* Keywords: commands:10 backwards movement:10 deletion:20 word-oriented-commands */
401: {
402: kmark();
403: while (count--) {
404: if ((skipb(WRDSEP) || skipb(WRDCHR))) {
405: return;
406: }
407: }
408: IGNORE(mfk());
409: }
410:
411: /* move back count words */
412:
413: mbwrd(count)
414:
415: register int count;
416: /* Keywords: commands backwards movement word-oriented-commands */
417: {
418: wordb(count);
419: move(kline,kcol);
420: }
421:
422: /* kill back count words */
423:
424: kbwrd(count)
425:
426:
427: register int count;
428: /* Keywords: commands backwards deletion word-oriented-commands */
429: {
430: wordb(count);
431: return(tkill());
432: }
433:
434: /* kmark -- set kline,kcol and klptr */
435:
436: kmark()
437:
438: /* Keywords: commands:5 movement:50 deletion:50 character-at-a-time:20 word-oriented-commands:20 sentence-commands:20 */
439:
440: {
441: kline = curln;
442: kcol = column;
443: klptr = mkline(kline)+kcol;
444: }
445:
446:
447: /* move kline,kcol forward one */
448:
449: mfk()
450: /* Keywords: commands:5 movement:50 deletion:50 character-at-a-time:20 word-oriented-commands:20 sentence-commands:20 forwards */
451: {
452: if ((*klptr++)!=EOL ) {
453: ++kcol;
454: return(0);
455: }
456: if (kline<nlines) {
457: ++kline;
458: klptr = mkline(kline);
459: kcol=0;
460: return(0);
461: }
462: return(1);
463: }
464:
465: /* move kline, kcol back one character */
466:
467: mbk()
468: /* Keywords: commands:5 movement:50 deletion:50 character-at-a-time:20 word-oriented-commands:20 sentence-commands:20 backwards */
469: {
470: if ((kcol--)>0) {
471: klptr--;
472:
473: return(0);
474: }
475: if (kline>1) {
476: --kline;
477: kcol = leng(kline);
478: klptr = mkline(kline) + kcol;
479: return(0);
480: }
481: kcol = 0;
482: return(1);
483: }
484:
485: /* forward to end of sentence */
486:
487: /* leaves resulting pointer in kline, kcol */
488:
489: fsent ()
490:
491: /* Keywords: commands:10 forwards movement:40 sentence-commands */
492:
493: {
494: kmark();
495:
496: while (mfk() == 0) {
497: if ((bits[*klptr] & SENTE) && (bits[klptr[1]]&WHITE)) {
498: return(1);
499: }
500: }
501: return(0);
502: }
503:
504: /* back one sentence, leaves pointer in kline, kcol */
505:
506: bsent()
507:
508: /* Keywords: commands:10 backwards movement:40 sentence-commands */
509:
510: {
511:
512: kmark();
513:
514: IGNORE(skipb(WRDSEP));
515: while (mbk() == 0) {
516: if (kcol == 0) {
517: if (kline>1) {
518: if (bits[*mkline(kline-1)] & SENTE) return(1);
519: }
520: }
521: if ((bits[*klptr] & SENTE) && (bits[klptr[1]] & WHITE)) {
522: IGNORE(skipf(WRDCHR));
523: IGNORE(skipf(WRDSEP));
524: return(1);
525: }
526: }
527: return(0);
528: }
529:
530: /* move back count sentences */
531:
532: ssent(count)
533: register int count;
534:
535: /* Keywords: commands backwards movement sentence-commands */
536:
537: {
538: while (count--) {
539: if(bsent()) move(kline,kcol);
540: }
541: }
542:
543: /* move forward count sentences */
544:
545:
546: esent(count)
547: register int count;
548:
549: /* Keywords: commands forwards movement sentence-commands */
550:
551: {
552: while (count--) {
553: if (fsent() == 0) break;
554: move(kline,kcol+1);
555: }
556: }
557:
558:
559: /* move to top of file */
560:
561: top()
562: /* Keywords: files:20 buffers:20 movement upward-movement commands */
563: {
564: move(1,0);
565: }
566:
567:
568: /* move to end of file */
569:
570: bot()
571:
572: /* Keywords: files:20 buffers:20 movement downward-movement commands */
573:
574: {
575: mvc(nlines,10000);
576: }
577:
578: /* new line handler */
579:
580: /* First, finishes off comment on the current line (if any) */
581:
582: /* Next, if the current buffer has a sub-process, the line is sent to the sub-process */
583:
584: /* Then, if the next line is non-empty, it creates an empty next line */
585: /* next, the next line is tab adjusted (if in C mode ) */
586:
587: /* now, any text on the current line beyond the current position, it is
588: * moved to the end of the next line */
589:
590: /* finally, the pointer is moved to the (tab adjusted) start of the next
591: * line */
592:
593: /* if count > 1, then count-1 blank lines will be inserted in between
594: * the current line and the 'next' line */
595:
596: nl(count)
597:
598: /* Keywords: commands C-mode:30 insertion text-lines comments:50 shell-escape:10 */
599:
600:
601:
602: register int count;
603:
604: {
605:
606: if (RARE == 0) {
607: if (comln == curln) putin(" */");
608: #ifndef PC
609: if (curbf == procbuf){
610: MARK *mp;
611:
612: mp = markptr(curbf);
613: if ((mp->markl == curln) && (mp->markc <= column)) {
614:
615: /* If this is the last line on which output was done from */
616: /* the sub-process, then send from mark and re-mark */
617:
618: sendproc (clptr+mp->markc, column+1-mp->markc);
619: mp->markl = curln+1;
620: mp->markc = 0;
621: } else {
622: sendproc(clptr,column+1);
623: }
624: }
625: #endif
626: }
627: comln = 0;
628: if ((count != 1) || (NLINS) || (isblank(curln+1)==0) || (clptr[column] != EOL)) {
629: openl(count);
630: }
631: if (TABMD&& (RARE == 0)) tabjust(curln+count);
632: else move(curln+count,0);
633: }
634:
635: /* sets mark at current position */
636:
637: mark(mnumb)
638:
639: /* Keywords: marking regions commands */
640:
641: {
642: MARK *markp;
643: markp = markptr(mnumb);
644: markp->markl = curln;
645: markp->markc = column;
646: }
647:
648: /* returns mark pointer */
649:
650: MARK *markptr(mnumb)
651:
652: register int mnumb;
653:
654: /* Keywords: commands:10 marking:50 regions deletion:50 movement:50 */
655: {
656:
657: if (mnumb >= NMARKS) {
658: error(WARN,44);
659: mnumb = curbf;
660: }
661: if ((mnumb == 1) && (numarg == 0)) mnumb = curbf;
662: return(&marks[mnumb]);
663: }
664:
665:
666: /* kills text between current position and mark position */
667:
668:
669: mkill(mnumb)
670: int mnumb;
671: /* Keywords: commands deletion regions */
672: {
673: register MARK *markp;
674:
675: markp = markptr(mnumb);
676: kline = markp->markl;
677: if (kline < 1) kline = 1;
678: if (kline > nlines) kline = nlines;
679: kcol = leng(kline);
680: if (markp->markc < kcol) kcol = markp->markc;
681: if (PICMODE) {
682: /* This pain is to get the
683: * mark to work in picture
684: * mode so that everything
685: * up to and including the
686: * marked position is killed */
687: if (kcol > column) {
688: kcol++;
689: } else {
690: forw(1);
691: }
692: }
693: return(tkill());
694: }
695:
696: /* retrieves text from the kill stack and inserts it (count times ) */
697:
698:
699: int yline;
700: int ycol;
701:
702: yank(count)
703:
704: /* Keywords: regions commands insertion killstack retrieval popping:10 */
705:
706: register int count;
707: {
708: register int result;
709: register int unp;
710:
711: unp = unstart();
712: mark(curbf);
713: while (count--) {
714: result = retrv();
715: }
716: unend(unp);
717: yline = curln;
718: ycol = column; /* Save, so we know when not to re-yank */
719:
720: return(result);
721: }
722:
723: /* kills the marked region, removes the top item from the kill stack,
724: * and then inserts the next area from the kill stack */
725:
726:
727: reyank(count) /* yank again */
728: register int count;
729: /* Keywords: regions commands insertion killstack retrieval deletion popping:10 */
730: {
731: register int unp;
732:
733: if ((curln != yline) || (column != ycol)) {
734: error (WARN,84); /* Prevent some nastyness */
735: return;
736: }
737: kbapp = 0;
738: unp = unstart();
739: mkill(curbf); /* flush last insertion */
740: kpop(); /* first pop the mkill */
741: kpop(); /* now pop that last insertion */
742: yank(count);
743: unend(unp);
744: }
745:
746: /* search subroutine */
747:
748: /* searches forward or backward for a string, starting at the
749: * given position. If the string is found, 1 is returned, and the start
750: * of the match is left in kline, kcol. Return of 0 indicates no match */
751:
752: /* Keywords: searching */
753:
754: srch(sline,scol,sp,direct)
755:
756: int sline;
757: int scol;
758: char *sp;
759: int direct;
760:
761: {
762: register char *lp;
763: register char *cp;
764: register int l;
765: int c;
766:
767: lp = sp;
768: while (c = *lp) *lp++ = casem[c&0177]; /* map string to allowed case */
769: lp = mkline(sline)+scol;
770: while (1) {
771: cp = sp;
772: l = sline;
773: while (*cp) {
774: if ((c = casem[(*lp++)&0177]) != *cp++) goto again;
775: if (c == EOL) {
776: if (l == nlines) {
777: if (direct>0) return(0);
778: goto again;
779: }
780: ++l;
781: lp = mkline(l);
782: }
783: }
784: kline = sline;
785: kcol = scol;
786: return(1);
787:
788: again: if (brkflg) brkit();
789: lp = mkline(sline)+scol;
790: if (direct>0) {
791: do {
792: if (*lp++ !=EOL) scol++;
793: else {
794: if (sline == nlines) return(0);
795: sline++;
796: scol = 0;
797: lp = mkline(sline);
798: }
799: } while (casem[*lp&0177] != *sp);
800: } else {
801:
802: do {
803: if (--scol<0) {
804: if (sline == 1) return(0);
805: scol = leng(--sline);
806: lp = mkline(sline)+scol;
807: } else lp--;
808: } while (casem[*lp&0177] != *sp);
809: }
810: }
811: }
812:
813: fisrch(arg)
814: int arg;
815: /* Keywords: searching commands forwards key-bindings:10 */
816: {
817: return(isrch(1,arg));
818: }
819: risrch(arg)
820: int arg;
821: /* Keywords: searching commands backwards key-bindings:10 */
822:
823: {
824: return(isrch(-1,arg));
825: }
826: /* incremental search command (either direction) */
827:
828:
829: isrch(d,arg)
830: int d;
831: int arg;
832:
833: /* Keywords: commands:80 searching user-interface:60 key-bindings:50 */
834:
835:
836: {
837: int oldln;
838: int oldcol;
839: register char *ilp;
840: register int c;
841: int lx;
842: int ly;
843: int nd;
844: int missed;
845: char sst[40];
846: char *xp;
847:
848: ilp = sst;
849: missed = 0;
850: lx = oldln = curln;
851: ly = oldcol = column;
852: if (infrn < 0) { /* if in a macro */
853: xp = getname(NULL); /* search argument */
854: ilp = mstrcpy(ilp,xp);
855: }
856: while (1) {
857: *ilp = 0;
858: if (missed == 0) {
859: psrch(d,sst); /* prompt */
860: if (infrn == 0) mflush(stdout);
861: if (srch(curln,column,sst,d) == NULL) {
862: move(lx,ly);
863: if (infrn >= 0) {
864: beep();
865: prompt1("Failing Search: %s", sst);
866: }
867: missed = 1;
868: } else {
869: move(lx = kline,ly = kcol);
870: if (ilp!=sst)strcpy (presst,sst);
871: missed = 0;
872: }
873: }
874: if (infrn < 0) return(missed == 0); /* macro invocation */
875: disup();
876: if ((missed == 0) && (incnt == 0)) {
877: psrch(d,sst); /* restore prompt */
878: mgo(nln,ncol); /* goback to display position */
879: }
880: c = getchar();
881: if ((c == CTRLH)||(c == RUBOUT)) {
882: if (ilp!=sst) ilp--;
883: missed=0;
884: move (oldln,oldcol);
885: continue; /* next loop */
886: }
887: if (c == CTRLG) {
888: move (oldln,oldcol);
889: unprompt();
890: beep();
891: return(0);
892: }
893: if (srch_nl?((c == '\n') || (c == '\r')) : (c == ESC)) {
894: goout: unprompt();
895: return(missed == 0);
896: }
897: if (nd=issrch(c)) {
898: if (nd == d) {
899: if (ilp == sst) {
900: ilp = mstrcpy(sst,presst);
901: continue;
902: } else {
903: if (missed) {
904: beep();
905: continue;
906: }
907: forw(d);
908: }
909: } else {
910: missed=0;
911: d = nd;
912: }
913: continue;
914: }
915: if (isquote(c)) {
916: c = getchar(); /* skip all other processing */
917: } else {
918: if (c == CTRLM) c = '\n';
919: if ((c < 040) && (c != '\n')) {
920: ungetch(c);
921: goto goout;
922: }
923: }
924: if (missed) {
925: beep();
926: continue;
927: }
928: *ilp++ = c;
929: }
930: }
931:
932: /* psrch -- print search prompt */
933:
934: psrch(dir,sstp)
935: register int dir;
936: char *sstp;
937:
938: /* Keywords: mode-line prompting searching */
939:
940: {
941: if (dir>0) prompt1("Search: %s",sstp);
942: else prompt1("Reverse Search: %s",sstp);
943: }
944:
945: /* handle a separator character in auto fill mode */
946:
947: /* if fill mode is on, and the current position is beyond FILLCOL, a
948: * newline is inserted before the last word. Otherwise, just insert the
949: * character at the current position */
950:
951:
952: afsep(count,chr)
953:
954: int count;
955: int chr;
956:
957: /* Keywords: commands:40 modes:30 text-filling comments:20 C-mode:10 */
958:
959: {
960: register int cc;
961: int newcol;
962: int oldcol;
963: char lbuf[MAXEL]; /* KLUDGE! */
964: register char *p1;
965: register char *p2;
966:
967: /* whitespace characters in a macro expansion must be quoted to be
968: * self-inserting. The following checks for non-zero character
969: * count, input from macro, and a whitespace character to be
970: * inserted. Under these conditions, no inserting is done. */
971:
972: if (count && (infrn < 0)&& (WHITE&bits[chr])) return(1);
973:
974:
975:
976: if (FILLMD && (RARE == 0)) {
977: insertc(count,chr);
978: oldcol = column;
979: cc = leng(curln) - column;
980: mline=0;
981: findpos(clptr,column);
982: if (mline || (mcol>FILLCOL)|| (column > FILLCOL)) {
983:
984: again: newcol = column;
985:
986: do {
987: column--;
988: } while ((column) &&
989: (((bits[clptr[column]] & WHITE) == 0) ||
990: (clptr[column+1] == '.') ||
991: (clptr[column+1] == '\'')));
992: mline=0;
993: findpos(clptr,column);
994: if (mline || (mcol>FILLCOL)|| (column > FILLCOL)) goto again;
995:
996:
997:
998: /* Now then, do the work. We are sitting at the right column to break the line */
999: /* First, save the rest of the line. Then, kill it, then, do a newline, */
1000: /* now, bring it back */
1001:
1002:
1003: if (column == 0) column = newcol; /* 1 word line */
1004: if (column == oldcol) return(1); /* Do absolutely nothing */
1005: p1 = clptr+column+1; /* Eat the whitespace character */
1006:
1007: p2 = lbuf;
1008: while ((*p2++= *p1++)!=EOL); /* copy line */
1009: sputl(curln,column,curln); /* Flag line is bad! */
1010: clptr[column]=EOL; /* truncate line */
1011: if (comln == curln) {
1012: comln = -1;
1013: nl(1);
1014: cment(1);
1015: *(clptr+column-3)=' ';
1016: } else nl(1);
1017: p1 = lbuf;
1018: while (*p1 != EOL) put(*p1++); /* restore line */
1019: forw(-cc); /* go back to right place. */
1020: }
1021: return(1);
1022: }
1023: insertc(count,chr);
1024: return(1);
1025: }
1026:
1027: /* unix escape */
1028:
1029: char *shell = "sh"; /* name of shell processor */
1030:
1031: ux(arg)
1032:
1033: int arg;
1034: {
1035: /* Keywords: commands buffers:20 unix-interface shell-escape */
1036:
1037: register char *sp;
1038:
1039: if (SAVEMD) fsave(0);
1040: do {
1041: sp = (getname("command line? "));
1042: } while (sp && (unx(sp,(arg != 1))== 0));
1043: return(cstatus);
1044: }
1045:
1046: #ifndef PC
1047:
1048: char *
1049: nvmatch(s1, s2)
1050: register char *s1, *s2;
1051:
1052: /* Keywords: unix-interface shell-escape environment-variables */
1053: {
1054: while(*s1 == *s2++)
1055: if(*s1++ == '=')
1056: return(s2);
1057: if(*s1 == '\0' && *(s2-1) == '=')
1058: return(s2);
1059: return(NULL);
1060: }
1061:
1062: /* Environment fixer-upper, adds definition of filename to the
1063: * environment and returns a pointer to it. */
1064:
1065: extern char **environ;
1066:
1067: char **
1068: fixenv(defp)
1069: register char *defp;
1070: /* Keywords: unix-interface shell-escape environment-variables */
1071:
1072: {
1073: register char **xp;
1074: register char **yp;
1075: int envd = 0;
1076:
1077: xp =((char **) &bbuf[0][0]); /* Overlay screen */
1078: yp = environ;
1079:
1080: while (*xp = *yp++) {
1081: if (nvmatch(defp,*xp++)) {
1082: xp[-1] = defp;
1083: envd=1;
1084: }
1085: }
1086: if (envd==0) {
1087: *xp++ = defp;
1088: *xp = NULL;
1089: }
1090: xp =((char **) &bbuf[0][0]); /* Overlay screen */
1091: return(xp);
1092: }
1093: #endif
1094:
1095:
1096: /* general unix escape -- */
1097:
1098: /* flag = 0 means just run it */
1099: /* flag = 1 means run and feed it the buffer */
1100: /* flag = 2 means run and replace .exec with the result */
1101: /* flag = 3 means run and append result to .exec */
1102: /* flag = 4 means run and bring results back in fnbuf */
1103: /* flag = 5 means run and hook up input and output pipes */
1104: /* flag = 6 means run it and hook up output to splfile, leave input in splfile */
1105: /* flag = 7 means run it and hook up input from splfile, leave output in splfile */
1106:
1107: #define UNEEDSIN 1
1108: #define UNEEDSOUT 2
1109: #define UDOTEXEC 4
1110: #define UNOSCREEN 8
1111: #define URETBUF 16
1112: #define UPROCESS 32
1113: #define USENDBUF 64
1114: #define UREADBUF 128
1115: #define UINITBUF 256
1116: #define USPLIN 512
1117: #define USPLOUT 1024
1118:
1119: int unxflags[8] = {
1120: 0,
1121: UNEEDSIN+USENDBUF,
1122: UNEEDSOUT+UDOTEXEC+UREADBUF+UINITBUF,
1123: UNEEDSOUT+UDOTEXEC+UREADBUF,
1124: UNEEDSOUT+UNOSCREEN+URETBUF,
1125: UNEEDSIN+UNEEDSOUT+UNOSCREEN+UPROCESS,
1126: UNEEDSIN+USPLOUT+UNOSCREEN,
1127: UNEEDSOUT+USPLIN+UNOSCREEN
1128: };
1129:
1130:
1131: unx(cmd,flag)
1132: /* Keywords: commands:80 buffers:10 files:10 environment-variables:20 unix-interface shell-escape dired:10 sub-processes:40 encryption:20 */
1133: register char *cmd;
1134: register int flag;
1135:
1136: {
1137: #ifdef PC
1138: return(1); /* Don't do this, just exit */
1139: #else
1140: struct pipes {
1141: int rdpipe;
1142: int wrpipe;
1143: } piped1,piped2;
1144: FILE tinbuf[1];
1145: FILE *infile;
1146: int (*istat)();
1147: int (*qstat)();
1148: register int i;
1149: int c;
1150: int obuf;
1151: int pid;
1152: char **evp;
1153: char *obname;
1154: char evbuf[256];
1155: char *myshell;
1156:
1157: if (*cmd == 0) return(1); /* Don't even bother with null commands */
1158: obname=fname();
1159: cstatus = -1; /* start off bad */
1160: flag = unxflags[flag]; /* Translate to bit-coded value */
1161:
1162: if ((flag & UPROCESS) && procpid) flushproc(); /* Zap old process */
1163:
1164: if (flag&UDOTEXEC) { /* if .exec in the business */
1165: obuf = curbf;
1166: if (chgbuf(".exec") == 0) return(0);
1167: }
1168:
1169: if ((USILENT == 0) && ((flag&UNOSCREEN) == 0)) {
1170: clear();
1171: putout("%s",cmd);
1172: istat = signal(SIGINT, SIG_IGN);
1173: qstat = signal(SIGQUIT, SIG_IGN);
1174: cook();
1175: }
1176: if (flag & UNEEDSIN) {
1177: if (pipe(&piped1)) {
1178: error (WARN,errno,cmd);
1179: goto done;
1180: }
1181: }
1182:
1183: if (flag & UNEEDSOUT) {
1184: if (pipe (&piped2)) {
1185: error (WARN,errno,cmd);
1186: if (flag & UNEEDSIN) {
1187: close(piped1.rdpipe);
1188: close(piped1.wrpipe);
1189: }
1190: goto done;
1191: }
1192: }
1193: if ((pid = fork()) == 0) { /* child process */
1194:
1195: if (flag &UNEEDSIN) {
1196: close(0);
1197: dup(piped1.rdpipe);
1198: } else if (flag & USPLIN) {
1199: close(0);
1200: dup(splfile);
1201: } else if ((USILENT)|| (flag & URETBUF)) {
1202: close(0);
1203: open("/dev/null",0);
1204: }
1205: if (flag &UNEEDSOUT) { /* if writing to .exec */
1206: close(1);
1207: dup(piped2.wrpipe);
1208: } else if (flag & USPLOUT) {
1209: close(1);
1210: dup(splfile);
1211:
1212: } else if (USILENT) { /* silent, throw away output */
1213: close(1);
1214: open("/dev/null",2);
1215: }
1216: signal(SIGINT, SIG_DFL);
1217: signal(SIGQUIT,SIG_DFL);
1218: xclose(2); /* close all irrelavent files */
1219: dup(1); /* restore stderr */
1220:
1221: myshell = getenv("SHELL");
1222: if ((myshell == NULL)|| (*myshell == '\0')) myshell = "/bin/sh";
1223: umask(mymask); /* Restore user's umask */
1224: seprintf(evbuf,"filename=%s",obname);
1225: evp = fixenv(evbuf); /* Add filename definition */
1226:
1227: if (streq(cmd,shell)) execl(myshell,shell,"-i",0,evp);
1228: execle(myshell, shell, "-c", cmd, 0,evp);
1229: execle("/bin/sh",shell, "-c", cmd, 0,evp);
1230: _exit(127);
1231: }
1232:
1233: /* parent process (the one that remains EMACS) */
1234:
1235: if (pid== -1) {
1236: error(WARN,73,cmd);
1237: goto done;
1238: }
1239: if (flag &UPROCESS) {
1240: close (piped1.rdpipe);
1241: close (piped2.wrpipe);
1242: inproc = piped2.rdpipe;
1243: outproc = piped1.wrpipe;
1244: #ifdef ux3
1245: fcntl(inproc,F_SETFL,O_NDELAY); /* Turn on non-blocking I/O */
1246: ioset(1); /* Set timeout on terminal short */
1247: #endif
1248: procbuf = curbf;
1249: procpid = pid;
1250: return(1);
1251: }
1252: if (flag & USPLIN) {
1253: close(splfile);
1254: splfile = piped2.rdpipe;
1255: close(piped2.wrpipe);
1256: return(1);
1257: }
1258: if (flag & USPLOUT) {
1259: close(splfile);
1260: splfile = piped1.wrpipe;
1261: close(piped1.rdpipe);
1262: return(1);
1263: }
1264: if (flag&USENDBUF) { /* if sending the buffer */
1265: close(piped1.rdpipe);
1266: infile = fdopen(tinbuf,piped1.wrpipe,"w");
1267: for (i = 1; i <=nlines; i++) {
1268: cmd = mkline(i);
1269: while ((c = *cmd++) != EOL) {
1270: putc(c,infile);
1271: }
1272: if (i != nlines) putc(EOL,infile);
1273: }
1274: mclose(infile);
1275: }
1276: if (flag&(UREADBUF|URETBUF)) { /* if writing */
1277: close(piped2.wrpipe);
1278: infile = fdopen(tinbuf,piped2.rdpipe,"r");
1279: if (flag&UINITBUF) bufinit();
1280: else if (flag&UREADBUF) {
1281: bot(); /* append */
1282: if (column != 0) nl(1);
1283: putin(cmd);
1284: nl(2);
1285: }
1286: if (flag&URETBUF) {
1287: cmd = fnbuf;
1288: i = 127;
1289: while (i--) {
1290: c = getc(infile);
1291: if ((c=='\0')||(c == '\n')||(c==' ')||(c=='\t')|| (c == EOF)) break;
1292: *cmd++ = c;
1293: }
1294: *cmd = 0; /* EOS */
1295: mclose(infile);
1296: } else {
1297: i = ((flag & UINITBUF) != 0);
1298: readsub(infile,i,cmd,1-(USILENT|NOECHO));
1299: chbuf(obuf);
1300: }
1301: }
1302: /* wait for child to finish */
1303:
1304: /* must wait for child else it becomes a <defunct> process */
1305:
1306: while ((i = wait(&cstatus)) != pid && i != -1);
1307:
1308: if (flag&URETBUF) return(cstatus);
1309: /* child is now done, go back to normal EMACS */
1310: mailcnt = 0;
1311:
1312: done: if ((USILENT == 0) && ((flag&UNOSCREEN) == 0)) {
1313: uncook();
1314: signal(SIGINT, istat);
1315: signal(SIGQUIT, qstat);
1316: junked++;
1317: }
1318: return(contin());
1319: #endif
1320: }
1321:
1322: bux(arg)
1323:
1324: int arg;
1325:
1326: /* Keywords: commands buffers unix-interface shell-escape */
1327:
1328: {
1329: register char *sp;
1330: register int flag;
1331: if (SAVEMD) fsave(0);
1332: if (arg == 0) flag = 5;
1333: else if (arg == 1) flag = 2;
1334: else flag = 3;
1335:
1336: do {
1337: sp = (getname("command line? "));
1338: } while (sp && (unx(sp,flag)== 0));
1339: return(cstatus);
1340: }
1341:
1342: /* query replace */
1343: /* prompts for strings and does conditional replacement */
1344:
1345: qrep(gflag)
1346: int gflag;
1347: /* Keywords: commands query-replace */
1348: {
1349: iqrep(0,gflag); /* no regular expressions */
1350: }
1351:
1352: rqrep(gflag)
1353: int gflag;
1354: /* Keywords: commands query-replace regular-expressions */
1355: {
1356: iqrep(1,gflag); /* regular expression version */
1357: }
1358:
1359:
1360: iqrep(regular,gflag)
1361:
1362: int regular;
1363: int gflag;
1364:
1365: /* Keywords: query-replace regular-expressions:20 user-interface key-bindings:20 commands:10 */
1366:
1367:
1368: {
1369:
1370: char sstring[128];
1371: int dir = 1;
1372: register char *sp;
1373: int bsflag = 0;
1374: int ask = 1;
1375: int show = 1;
1376: int l = 1;
1377: int stop = 0;
1378: int upt;
1379: register int c;
1380: int oldln;
1381: int oldcol;
1382:
1383: if((sp = getname("From? "))== NULL) return;
1384: if (*sp == NULL) sp = presst;
1385: strcpy(sstring,sp);
1386: if ((sp = getname("To? ")) == NULL) return;
1387: if (!streq(sp,"%")) strcpy(rstring,sp); /* Copy over return string unless it is a single % */
1388: oldln = curln;
1389: oldcol = column;
1390: upt = unstart();
1391: while (1) {
1392: if (regular) {
1393: if (rgsrch(curln,column,sstring,0,dir)== 0) break;
1394: } else {
1395: if (srch(curln,column,sstring,dir)== 0) break;
1396: }
1397: dir = 1;
1398: if ((l == 0) && (curln == kline) && (column == kcol)) {
1399: error(WARN,72,sstring,rstring);
1400: goto rdone;
1401: }
1402:
1403: prompt1("From %s To %s",sstring,rstring);
1404: strcpy(presst,sstring); /* save successful search */
1405: move(kline,kcol);
1406: if (show) {
1407: disup();
1408: }
1409: if (ask){
1410: c = getchar();
1411: donttime=0;
1412: } else c = 'y';
1413: switch(c) {
1414:
1415: case '.': stop = 1; /* stop after this one */
1416: goto rep_it; /* make this replacement. */
1417: case ESC: sp = getname("Replace with: ");
1418: if (sp) {
1419: strcpy(rstring,sp);
1420: goto rep_it;
1421: }
1422: case CTRLG: beep();
1423: done: unprompt(); /* wipe out help message */
1424: unend(upt);
1425: return;
1426:
1427: case '<':
1428: move (oldln,oldcol); /* return to last replacement */
1429: goto done;
1430:
1431:
1432: case 'R': show = 0;
1433: case 'r': ask = 0; /* do rest */
1434: NOBEL++; /* Inhibit ding on zero length deletes */
1435: /* fall through to do this one too */
1436: case ' ':
1437: case 'y':
1438: case 'Y':
1439: rep_it: kbapp = 0;
1440: oldln = curln;
1441: oldcol = column;
1442: if (regular) {
1443: l = (loc2-column);
1444: } else {
1445: l = (lng(sstring));
1446: }
1447: fdel(l);
1448: for (sp = rstring; *sp; sp++) {
1449: switch(*sp) {
1450: case '\\':
1451: if (!bsflag) {
1452: bsflag = 1;
1453: continue;
1454: }
1455: case '1':
1456: case '2':
1457: case '3':
1458: case '4':
1459: case '5':
1460: case '6':
1461: case '7':
1462: case '8':
1463: if (bsflag && regular && regrep(*sp-'1')) {
1464: bsflag = 0;
1465: continue; /* \number style replace */
1466: }
1467: /* fall through to default treatment of numbers */
1468:
1469: default:
1470: dput(*sp);
1471: bsflag = 0;
1472: break;
1473: case '&':
1474: if (bsflag) {
1475: dput(*sp);
1476: bsflag = 0;
1477: continue;
1478: } else {
1479: yank(1);
1480: unpop(1);
1481: }
1482: }
1483: }
1484: unins(oldln,oldcol); /* Make an undo entry */
1485: kpop(); /* clean up our stack */
1486: if (stop) goto done;
1487: if (show) {
1488: disup(); /* before next search */
1489: mflush(stdout);
1490: }
1491: break;
1492: case CTRLH:
1493: case RUBOUT:
1494: case 'n':
1495: case 'N':
1496: forw(1);
1497: break;
1498: case 'p':
1499: case 'b':
1500: dir = -1;
1501: forw(-1);
1502: break;
1503: default:
1504: beep();
1505: case '?':
1506: donttime=1; /* Avoid time mode */
1507: prompt3("Query replace -- 'y' to replace, 'n' to skip, ^G to quit,'R' or 'r' for rest");
1508:
1509: }
1510: if (gflag>1) move(kline+1,0); /* only do first one */
1511: }
1512: rdone: prompt1("Replace Done");
1513: if (ask==0) NOBEL--; /* Re-enable warning on 0 length deletes */
1514: unend(upt);
1515: }
1516: /* length of a string */
1517:
1518: lng(sp)
1519:
1520: char *sp;
1521: /* Keywords: string-handling length */
1522: {
1523: register char *spo;
1524:
1525: spo = sp;
1526: while(*spo++);
1527: return(spo-sp-1);
1528: }
1529:
1530: /* capitalize next count characters */
1531:
1532: capnxt(count)
1533:
1534: register int count;
1535:
1536: /* Keywords: commands character-at-a-time forwards capitalization */
1537: {
1538: register int c;
1539: int oldover;
1540: while (count--) {
1541: c = (clptr[column]);
1542: if ((c >= 'a') && (c <= 'z')) {
1543: oldover=OVERW;
1544: OVERW=1;
1545: insertc(1,c-040);
1546: OVERW=oldover;
1547: } else if (forw(1)==0) break; /* check for EOF */
1548: }
1549: }
1550:
1551:
1552: /* lowercase next count characters */
1553:
1554: lownxt(count)
1555:
1556: register int count;
1557:
1558: /* Keywords: commands character-at-a-time forwards capitalization */
1559: {
1560: register int c;
1561: int oldover;
1562: while (count--) {
1563: c = (clptr[column]);
1564: if ((c >= 'A') && (c <= 'Z')) {
1565: oldover=OVERW;
1566: OVERW=1;
1567: insertc(1,c+040);
1568: OVERW=oldover;
1569: } else if (forw(1)==0) break; /* check for EOF */
1570: }
1571: }
1572:
1573: /* capitalize first character of the next word */
1574:
1575: capwrd(count)
1576:
1577: register int count;
1578:
1579: /* Keywords: commands word-oriented-commands forwards capitalization */
1580: {
1581: while (count--) {
1582: kmark();
1583: IGNORE(skipf(WRDSEP));
1584: move(kline,kcol); /* to next word */
1585: capnxt(1);
1586: mfwrd(1);
1587: }
1588: }
1589:
1590: /* exchange current position and the marked position */
1591:
1592: exch(mnumb)
1593:
1594: /* Keywords: commands regions marking movement */
1595: {
1596: register int x;
1597: register int y;
1598: register MARK *markp;
1599:
1600: markp = markptr(mnumb);
1601: x = markp->markl;
1602: if (x < 1) x = 1;
1603: y = markp->markc;
1604: if ((x == curln) && (y == column)) {
1605: return(0);
1606: }
1607: if (x > nlines) x = nlines;
1608: mark(mnumb);
1609: mvc(x,y);
1610: return(1);
1611: }
1612:
1613: /* exchange next two chacters in the buffer and move forward one */
1614:
1615: xpose(count)
1616:
1617: register int count;
1618:
1619: /* Keywords: commands forwards movement:10 transposition */
1620: {
1621: int oldnodel,oldpic;
1622:
1623: register int undp;
1624:
1625: oldnodel=NODEL;
1626: oldpic=PICMODE;
1627: NODEL=0;
1628: PICMODE=0;
1629: kbapp = 0;
1630: undp = unstart();
1631: fdel(1);
1632: forw(count);
1633: yank(1);
1634: unend(undp);
1635: kpop();
1636: forw(-1);
1637: NODEL=oldnodel;
1638: PICMODE=oldpic;
1639: }
1640:
1641: /* changes a mode parameter. Mode parameters are of three types,
1642: * string, boolean, or integer.
1643:
1644: * Integer modes set from the count argument, boolean modes turn on if
1645: * count is one, off otherwise, and string modes prompt for new value
1646:
1647: * chmode returns the previous value of the mode set */
1648:
1649:
1650: chmode(count)
1651: register int count;
1652:
1653: /* Keywords: modes commands assignment */
1654: {
1655: register char *mp;
1656:
1657: if ((mp=getname("Mode? ")) != NULL) {
1658: if (*mp == '\0') {
1659: modisp(numarg);
1660: return(0);
1661: }
1662: return(setmode(mp,count,1));
1663: }
1664: return(0);
1665: }
1666:
1667: char *MDHEAD = "EMACS_MODES:";
1668:
1669: bfmodes() /* set modes from buffer */
1670: /* Keywords: modes buffers file-modes assignment:10 */
1671: {
1672: register char *cp;
1673: register char *cp1;
1674: char mdbuf[20];
1675: int onoff;
1676:
1677: kline = 11;
1678: if (kline > nlines) kline = nlines;
1679: while ((kline > 0) && srch(kline,leng(kline),MDHEAD,-1)) {
1680: /* if modes set */
1681:
1682: for (cp = mkline(kline)+kcol+12; *cp != EOL;) {
1683: cp1 = mdbuf;
1684: while ((*cp != EOL) && (*cp != '!') && ((bits[*cp] & WRDCHR) == 0)) cp++;
1685: if (*cp == '!') {
1686: onoff = 0;
1687: cp++;
1688: } else onoff = 1;
1689:
1690: while (bits[*cp] & WRDCHR) {
1691: *cp1++ = *cp++;
1692: }
1693: if (*cp == '=') {
1694: cp++;
1695: cp = nscan(cp,&onoff);
1696: }
1697:
1698: *cp1 = 0;
1699: if (mdbuf[0]) setmode(mdbuf,onoff,0); /* Set up mode */
1700: }
1701: kline--;
1702: }
1703: }
1704:
1705:
1706: setmode(mp,count,fudge)
1707: register char *mp;
1708: int count;
1709: int fudge;
1710: /* Keywords: modes macro-programming:10 assignment time-handling:20 display-format:10 */
1711: {
1712: register int i;
1713: extern char cbuf[];
1714: int retval;
1715: int mfield;
1716:
1717: for (i = 0; i < NMODES; i++) {
1718: if (streq(mdata[i].modename,mp)) {
1719: retval = *mdata[i].modeloc; /* old value */
1720: switch(mdata[i].modetype) {
1721: case ONOFF:
1722: if (fudge && (count != 1)) count = 0;
1723: *mdata[i].modeloc = count;
1724: break;
1725: case INT:
1726: *mdata[i].modeloc = count;
1727: break;
1728: }
1729: if ((mfield = mdata[i].moderset)&DSIZE) {
1730: SCRNLIN = SCRLINES+4;
1731: setsize();
1732: }
1733: /* customize the behavior of ^H in word commands */
1734:
1735: if (mfield|CTYPE) {
1736: if (BACKP) {
1737: bits[CTRLH] = bits['_'] = WRDCHR;
1738: ctype[CTRLH] = BACKSP;
1739: } else {
1740: bits[CTRLH] = bits['_'] = WRDSEP;
1741: ctype[CTRLH] = CONTRL;
1742: }
1743: if (NOTABS) ctype[CTRLI] = CONTRL;
1744: else ctype[CTRLI] = TAB;
1745: if (bit8) metal = 0;
1746: else metal = 2;
1747: }
1748: if (mfield & CSE) {
1749: if (NOCASE) count = 'a'-'A';
1750: else count = 0;
1751: for (i = 'A'; i <= 'Z'; i++) {
1752: casem[i] = i+count;
1753: }
1754: }
1755: if (timemd == 0) *cbuf = 0; /* Nullify current time */
1756: if (mfield&DISPLAY) {
1757: fclear(); /* force re-display */
1758: if (PICMODE==0) hcol=0;
1759: }
1760: return(retval);
1761: }
1762: }
1763: IGNORE(error (WARN,45,mp));
1764: return(0);
1765: }
1766:
1767:
1768: modval(mp)
1769: char *mp;
1770: /* Keywords: commands macro-programming modes */
1771: {
1772: register int i;
1773:
1774:
1775: for (i = 0; i < NMODES; i++) if (streq(mdata[i].modename,mp)) return(*mdata[i].modeloc);
1776: return(0);
1777: }
1778:
1779:
1780: /* display all active modes. Values displayed for integer and string
1781: * modes, all on boolean modes are displayed */
1782:
1783: modisp(arg)
1784: register int arg;
1785: /* Keywords: informational-displays modes commands user-interface */
1786: {
1787: register int i;
1788: char *mp;
1789:
1790: if ((arg < 0) && (mp = getname("Mode? "))) return(modval(mp));
1791:
1792: mtop();
1793: for (i = 0; i < NMODES; i++) {
1794: switch(mdata[i].modetype) {
1795:
1796: case ONOFF:
1797: if (*mdata[i].modeloc) putout("%s mode is on",mdata[i].modename);
1798: else if (arg) putout ("%s mode is off",mdata[i].modename);
1799: break;
1800: case INT:
1801: putout("%s = %d",mdata[i].modename,*mdata[i].modeloc);
1802: break;
1803: }
1804: }
1805: putout (endput);
1806: return(contin());
1807: }
1808:
1809: /* compare two strings */
1810:
1811: streq(cp,cp1)
1812:
1813: register char *cp;
1814: register char *cp1;
1815:
1816: /* Keywords: string-handling comparison */
1817: {
1818: while (*cp) if (*cp++ != *cp1++) return(0);
1819: if (*cp1) return(0);
1820: return(1);
1821: }
1822:
1823: char *
1824: mstrcpy(cp,cp1)
1825:
1826: /* Keywords: assignment string-handling */
1827: register char *cp;
1828: register char *cp1;
1829: {
1830: while (*cp++ = *cp1++);
1831: return(cp-1);
1832: }
1833:
1834: /* push the marked region onto the kill stack without killing it */
1835:
1836:
1837: pickup(mnumb)
1838:
1839: /* Keywords: regions commands killstack stacking */
1840:
1841:
1842: {
1843: register MARK *markp;
1844:
1845:
1846: markp = markptr(mnumb);
1847:
1848: if ((markp->markl < curln) || ((markp->markl == curln) && (markp->markc < column))) {
1849: killstk(markp->markl,markp->markc,curln,column);
1850: } else {
1851: killstk(curln,column,markp->markl,markp->markc);
1852: }
1853: }
1854:
1855: /* go to beginning of count line */
1856:
1857: absgoto(count)
1858: register int count;
1859: /* Keywords: commands movement text-lines */
1860:
1861: {
1862: move((count<nlines)?count:nlines, 0);
1863: }
1864:
1865: /* begin a C coment. comment begins in COMCOL, if current position is
1866: * not column 0, otherwise begins in column 0. the next newline will end
1867: * the coment */
1868:
1869: cment()
1870:
1871: /* Keywords: C-mode commands comments */
1872:
1873: {
1874:
1875: if (column) {
1876: disup();
1877: if (mcol<comcol) {
1878: while (mcol<comcol) {
1879: put(' ');
1880: disup();
1881: }
1882: } else {
1883: put (' ');
1884: }
1885: }
1886: putin ("\057* "); /* it's a slash, for stupid compilers! */
1887: comln = curln;
1888: }
1889:
1890: /* adjust the indentation of the current line to be consistent with that
1891: * in the last line. */
1892:
1893: tabjust(lno)
1894: register int lno;
1895: /* Keywords: insertion C-mode commands:10 */
1896: {
1897: register int lln;
1898: register int tabno;
1899: char *llp;
1900: int c;
1901:
1902: tabno = 0;
1903: for (lln = lno-1; lln > 0; lln--) {
1904: llp = mkline(lln);
1905: while (llp[tabno] == ' ') ++tabno;
1906: if ((llp[tabno]!= EOL) && (llp[tabno+1] != '*')) {
1907: while ((c = llp[tabno])!=EOL) {
1908: switch(c) {
1909: case '{':
1910: ++tabno;
1911: break;
1912: default:
1913: ++llp;
1914: }
1915: }
1916: goto tabout;
1917: }
1918: tabno = 0;
1919: }
1920: tabout:
1921: move(lno,0);
1922: while ((c = clptr[column]) == ' ') {
1923: tabno--;
1924: column++;
1925: }
1926: if ((c == '}') && tabno) tabno--;
1927: if (tabno) {
1928: if (tabno>0) tabc(tabno,' ');
1929: else {
1930: bdel(-tabno);
1931: kpop();
1932: unpop(1);
1933: }
1934: } else {
1935: sputl(curln,column,curln);
1936: move(curln,column);
1937: }
1938: }
1939:
1940: /* } handler, re-sets the indentation back one level */
1941:
1942: cbrak(count,brace)
1943:
1944: register int count;
1945: register int brace;
1946: /* Keywords: C-mode insertion commands */
1947: {
1948: if (TABMD &&(RARE == 0) && column && (*(clptr+column-1) == ' ')){
1949: bdel(1);
1950: kpop();
1951: unpop(1);
1952: };
1953: insertc(count,brace);
1954: }
1955:
1956:
1957: /* returns 1 if next line contains no non blank (or tab) characters */
1958:
1959: isblank(line)
1960:
1961: register int line;
1962: /* Keywords: commands:10 line-representation:50 */
1963: {
1964: register char *lp;
1965:
1966: if ((line <= nlines) && (ptrs[line] == 0)) return(1);
1967: lp = mkline(line);
1968: while (*lp!=EOL) {
1969: if ((bits[*lp++] & WHITE) == 0) return(0);
1970: }
1971: return(1);
1972: }
1973:
1974: /* change working dir */
1975:
1976: cwd()
1977:
1978: /* Keywords: commands directories unix-interface */
1979: {
1980: #ifndef PC
1981: char *np;
1982: np = expenv(getname("Directory? "));
1983: if (np) {
1984: if (SAVEMD) fsave(0);
1985: if (*np == 0) np = getenv("HOME"); /* null means home */
1986: if(chdir(np)) {
1987: IGNORE(error(WARN,errno,np));
1988: return(0);
1989: }
1990: return(1);
1991: }
1992: return(0);
1993: #endif PC
1994: }
1995:
1996: stats()
1997: {
1998: /* Keywords: commands informational-displays statistics */
1999:
2000: #ifdef COMPRESS
2001: extern long coutc;
2002: #endif
2003: mtop();
2004: putout ("%d chars from terminal",ninch);
2005: putout ("%D calls to mputc",nmput);
2006: putout ("%D chars written by mputc",noutc);
2007: #ifdef COMPRESS
2008: putout ("%D chars after compression",coutc);
2009: #endif
2010: putout ("%d terminal writes", ntwrite);
2011: putout ("%d calls to makeline",nmkline);
2012: putout ("%d buffer reads",nbread);
2013: putout ("%d file writes",nbwrite);
2014: putout ("%d file seeks", nbseek);
2015: putout ("%d characters of buffer left", (NBLOCK*BLEN)-macptr);
2016: IGNORE(contin());
2017: }
2018:
2019: uline(count)
2020:
2021: /* Keywords: word-oriented-commands commands underlining */
2022: register int count;
2023:
2024: {
2025: while (count--) {
2026: kmark();
2027: IGNORE(skipf(WRDSEP)); /* skip to begginning of word */
2028: move(kline,kcol);
2029: while (bits[*klptr] & WRDCHR) {
2030: put('_');
2031: put(CTRLH);
2032: forw(1);
2033: }
2034: }
2035: }
2036:
2037: infile(fn)
2038:
2039: /* Keywords: commands:40 files keyboard-macros:10 command-line-processing:10 command-files */
2040: register char *fn;
2041: {
2042: if (pushin(expenv(fn))) {
2043: edit(1);
2044: inpop();
2045: return(1);
2046: } else return(0);
2047: }
2048:
2049:
2050: inpsh(arg)
2051: int arg;
2052: {
2053: register char *fp;
2054: /* Keywords: commands files keyboard-macros:10 command-files */
2055:
2056: if (fp=getname("Input file? ")) {
2057: if (infile(fp)==0 ) {
2058: if (arg > 0) IGNORE(error(WARN,errno,fp));
2059: return(0);
2060: }
2061: }
2062: return(1);
2063: }
2064:
2065: /* send the contents of the buffer as mail */
2066:
2067: /* mtch -- see if current line matches header */
2068:
2069: mtch(cp)
2070: register char *cp;
2071: /* Keywords: mail-processing string-handling:20 comparison:40 */
2072:
2073: {
2074: register char *cl;
2075: cl = clptr;
2076: while (*cp) if (*cp++ != *cl++) return(0);
2077: return(1);
2078: }
2079:
2080: mailit()
2081:
2082: /* Keywords: mail-processing unix-interface commands */
2083:
2084:
2085: {
2086: char cmdbuf[256];
2087: register char *mp;
2088: register char *mp1;
2089: int mailstat;
2090: char *mailcom;
2091: #ifdef POSTHACK
2092: char *s;
2093: register int c;
2094: extern char *strrchr();
2095: #endif
2096: mailstat = 0;
2097: #ifndef PC
2098: #ifdef bsd
2099: #define DEFMAIL "/usr/lib/sendmail -t"
2100: #else
2101: #define DEFMAIL "mail"
2102: #endif
2103: if ((mailcom=getenv("MAILER"))==NULL) mailcom=DEFMAIL;
2104:
2105: mp = mstrcpy(cmdbuf,mailcom);
2106:
2107: #ifdef POSTHACK
2108: /* find the start of the mail command name */
2109: if ((s = strrchr(mailcom, '/')) != NULL) {
2110: ++s;
2111: }
2112: else {
2113: s = mailcom;
2114: }
2115: /* if this is post or Berkeley mail */
2116: if (streq(s, "post") || streq(s, "Mail")) {
2117: top();
2118: while (curln < 10 && *clptr != EOL) {
2119:
2120: /* if there is a subject line in the message */
2121: if (mtch("Subject: ")) {
2122:
2123: /* add -s 'subject' to the mail command */
2124: strcpy(mp, " -s '");
2125: mp += 5;
2126: mp1 = clptr + 9; /* skip "Subject: " */
2127: while ((c = *mp1) != EOL) {
2128: if (c == '\'') { /* ' becomes '\'' */
2129: *mp++ = '\'';
2130: *mp++ = '\\';
2131: *mp++ = '\'';
2132: *mp++ = '\'';
2133: }
2134: else {
2135: *mp++ = c;
2136: }
2137: ++mp1;
2138: }
2139: *mp++ = '\'';
2140: *mp = 0;
2141: break;
2142: }
2143: move(curln+1,0);
2144: }
2145: }
2146: /* get the list of addressees */
2147: #endif
2148: top();
2149: while (curln < 10 && *clptr != EOL) {
2150: if (mtch("TO: ") || mtch("To: ") || mtch("CC: ") || mtch("Cc: ")) {
2151: if (clptr[1] == 'O') clptr[1] = 'o';
2152: if (clptr[1] == 'C') clptr[1] = 'c';
2153: column = 3;
2154: if (((mp-cmdbuf)+leng(curln)-column) > 250) {
2155: mailstat += unx(cmdbuf,1); /* partial list */
2156: mp = mstrcpy(cmdbuf,mailcom);
2157: move(curln,column);
2158: }
2159: mp1 = clptr+column;
2160: while (*mp1 != EOL) *mp++ = *mp1++; /* copy mailing list */
2161: *mp = 0;
2162: }
2163: move(curln+1,0);
2164: }
2165: mp1 = cmdbuf+4;
2166: while (*mp1) if (*mp1++ != ' ') { /* Check for non-null destination list */
2167:
2168: mailstat += unx(cmdbuf,1); /* send to mail command */
2169: return(mailstat == 0);
2170: }
2171: IGNORE(error (WARN,46));
2172: #endif
2173: return(0);
2174: }
2175:
2176: /* contin -- ask user to continue */
2177:
2178:
2179: contin()
2180: {
2181: /* Keywords: informational-displays:20 user-interface:10 prompting:40 */
2182: register int c;
2183: if (infrn < 0) return(1); /* continue always in a macro */
2184: prompt1("Continue?");
2185: c = getchar();
2186: prompt1("");
2187: if ((c == 'y') || (c == ' ') || (c == '\n') || (c == '\015')) return(1);
2188: if ('n' == c) return(0);
2189: if (c == CTRLZ) {
2190: gquit();
2191: return(1);
2192: }
2193: ungetch(c);
2194: return(0);
2195: }
2196:
2197: /* buffer length and current position */
2198:
2199:
2200: /* If invoked from tty, prints buffer status info on the terminal. If */
2201: /* invoked from a macro, returns a value dependent on its argument */
2202:
2203: #define VLIN 0 /* return line number */
2204: #define VCOL 1 /* return column number */
2205: #define VDLIN 2 /* display line */
2206: #define VDCOL 3 /* display column */
2207: #define VMINLN 4 /* First file line on screen */
2208: #define VMAXLN 5 /* ditto last */
2209: #define VWTOP 6 /* First screen line of window */
2210: #define VWBOT 7 /* ditto last */
2211:
2212: buflng(arg)
2213:
2214: int arg;
2215: {
2216: /* Keywords: commands macro-programming:40 buffers statistics */
2217:
2218: long flng;
2219: long fpos;
2220: char xbuf[128];
2221: extern int minln;
2222: extern int maxln;
2223: register int i;
2224: if (infrn < 0) {
2225: /* If from macro, return useful info */
2226: switch(arg) {
2227:
2228: case VCOL: return(column);
2229: case VLIN: return(curln);
2230: case VDCOL:
2231: case VDLIN:
2232: if (findline(curln) == 0) return(-1);
2233: mline=nln;
2234: if (findpos(clptr,column) == 0) return(-1);
2235: if (arg == VDLIN) return(nln-wbase);
2236: else return(mcol);
2237: case VMINLN: return(minln);
2238: case VMAXLN: return(maxln);
2239: case VWTOP: return(wbase);
2240: case VWBOT: return(SCRLINES-1);
2241: }
2242: }
2243: flng = 0L;
2244: for (i = 1; i <= nlines; i++) {
2245: if (i != 1) flng++; /* linefeed from last line */
2246: if (i == curln) fpos = flng + column;
2247: flng += leng(i);
2248: }
2249: clptr=mkline(curln);
2250: seprintf(xbuf,"next char: %o, line: %d/%d: pos: %D/%D column: %d",
2251: clptr[column],curln,nlines-1,fpos,flng,column);
2252: prompt1(xbuf);
2253: return(0);
2254: }
2255:
2256: filler(arg)
2257: /* Keywords: regions:50 text-filling commands */
2258: int arg;
2259: {
2260: register int i;
2261: register char *cp;
2262: register int j;
2263: int unp;
2264:
2265: unp = unstart();
2266: if (arg != 1) {
2267: /* fill region only */
2268: register MARK *markp;
2269: markp = markptr(curbf);
2270: if ((i = markp->markl) > curln) fillreg(curln,i,1);
2271: else fillreg(i,curln,1);
2272: } else {
2273: undel();
2274: killstk(1,0,nlines,0);
2275: kpop();
2276: for (i = 1; i < nlines;i++ ) {
2277: cp = mkline(i);
2278: if ((*cp != '.') && (*cp != '\'') && (*cp != EOL)) {
2279: j = i;
2280: while (i < nlines) {
2281: cp = mkline(i);
2282: if ((*cp == '.') || (*cp == '\'') || (*cp == EOL)) break;
2283: i++;
2284: }
2285: fillreg(j,i,0);
2286: i = curln+1;
2287: }
2288: }
2289: unins(1,0);
2290: }
2291: unend(unp);
2292: }
2293:
2294: fillreg(i,j,u)
2295: register int i;
2296: register int j;
2297: int u;
2298: {
2299: /* Keywords: commands:10 text-filling regions:20 undo:10 */
2300:
2301: int onlin,ofill;
2302: onlin = NLINS;
2303: ofill = FILLMD;
2304: FILLMD = NLINS = 1; /* Turn on "rigid_newline" mode */
2305: move(i,0);
2306: if (u) {
2307:
2308: /* Make an undo record for this region */
2309:
2310: undel();
2311: killstk(i,0,j,0);
2312: kpop();
2313: }
2314: while (curln < j) {
2315: endl();
2316: do {
2317: i = curln;
2318: afsep(0,0);/* Note that we don't really put anything in */
2319: if (i != curln) j++;
2320: } while (i != curln);
2321: if (curln < j-1) {
2322: fdel(1);
2323: kpop();
2324: unpop(1);
2325: while ((clptr[column] == ' ') || (clptr[column] == ' ')) {
2326: fdel(1);
2327: kpop();
2328: unpop(1);
2329: }
2330: put(' ');
2331: j--;
2332: } else break;
2333: }
2334: if (u) {
2335: move(j,0);
2336: unins(i,0); /* Make a second undo record */
2337: }
2338: NLINS = onlin;
2339: FILLMD = ofill;
2340: }
2341:
2342: /* macro the region */
2343:
2344: macro(arg)
2345: int arg;
2346: {
2347: /* Keywords: key-bindings memory-allocation:10 parsing symbol-handling commands macro-hooks:20 */
2348:
2349: register int mychar;
2350: register int balance;
2351: register int machr;
2352: int oldpic;
2353: int compos;
2354: int hookp;
2355: int hash,ename;
2356: #ifdef u370
2357: int beepbeep();
2358: #else
2359: extern int beep();
2360: #endif
2361:
2362: oldpic=PICMODE;
2363: PICMODE=0;
2364: bot();
2365: back(2);
2366: if (clptr[column] != CTRLZ) {
2367:
2368: /* File does not end in ^Z, Try to catch a potential disaster */
2369:
2370: error(WARN,80,fname());
2371: PICMODE=oldpic;
2372: return(0);
2373: }
2374: if (arg != 1) {
2375: for (mychar = 0; mychar < NCHARS; mychar++) {
2376: if (map_it[mychar] > ISIZE) {
2377: map_it[mychar] = 0;
2378: }
2379: if (mychar < NMAC) machash[mychar] = 0;
2380: if (mychar < NHOOKS) hooks[mychar] = 0;
2381:
2382: }
2383: macptr = 0;
2384: fbkno = 0;
2385: }
2386: top();
2387:
2388: while (curln<nlines) {
2389:
2390: balance = 0;
2391: machr = clptr[column]&0377;
2392: if (machr == ESC) machr = (clptr[++column]&0377)+0200;
2393: if (machr == CTRLX) {
2394: machr = (clptr[++column]&0377)+0400;
2395: }
2396: if (machr == CTRLZ) {
2397: hookp = (clptr[++column]&0377);
2398: if (hookp > NHOOKS) {
2399: hookp = 0; /* Just ignore the bad ones */
2400: --column;
2401: }
2402: }
2403: forw(1);
2404: if (macptr == 0) pshchr(0); /* Can't use the first location! */
2405: compos = macptr;
2406: pshchr(0); /* Leave room for linkage chain */
2407: pshchr(0);
2408: hash = 0;
2409: ename = 1;
2410: if (clptr[column] == CTRLBACK) { /* if comment */
2411: pshchr(0);
2412: ++column;
2413: while (clptr[column] != EOL) {
2414: if ((clptr[column] == ' ')||(clptr[column] == ' ')) ename = 0;
2415: if (ename) hash += clptr[column];
2416: pshchr(clptr[column++]);
2417: }
2418: pshchr(0);
2419: forw(1); /* skip newline */
2420: }
2421: hash %= NMAC;
2422: bbuf[0][compos] = machash[hash];
2423: bbuf[0][compos+1] = machash[hash]>>8;
2424: machash[hash] = compos;
2425: if (machr == CTRLZ) hooks[hookp] = macptr; /* Define hook */
2426: else {
2427: /* Define character command */
2428:
2429: map_it[machr] = macptr+ISIZE;
2430: }
2431: while (curln < nlines) {
2432: mychar = clptr[column]&0377;
2433: if (column == 0) {
2434: while ((mychar==' ') || (mychar==' ')) {
2435: column++;
2436: mychar = clptr[column]&0377;
2437: }
2438: }
2439: if (mychar != CTRLBACK) {
2440: if (mychar == MTA({)) balance++;
2441: else if (mychar == MTA(})) balance--;
2442: pshchr(mychar);
2443: forw(1);
2444: if ((mychar == CTRLZ) && (clptr[column] == EOL)) {
2445: if (balance) {
2446: error(WARN,47,curln);
2447: }
2448: goto macdone; /* end of macro definition */
2449: }
2450: } else {
2451: move(curln+1,0); /* skip comment */
2452: }
2453: }
2454: error (WARN,48);
2455: pshchr(CTRLG); /* escape from bad macro */
2456:
2457: macdone: forw(1); /* on to next macro */
2458: }
2459: PICMODE=oldpic;
2460: if (hooks[Load_Macro_Hook]) {
2461: hook(Load_Macro_Hook);
2462: hooks[Load_Macro_Hook] = 0;
2463: }
2464: return(1);
2465: }
2466:
2467: ldmac(arg)
2468: int arg;
2469: /* Keywords: commands files reading macro-programming:20 */
2470: {
2471: register int oldbuf;
2472: register int tmpbuf;
2473: char *obname;
2474: int oldbin;
2475: int err;
2476:
2477: if (arg>0) err = 1;
2478: else {
2479: err = 0;
2480: arg = 1;
2481: }
2482: obname = fname(); /* Old file name */
2483: oldbuf = curbf;
2484: chgbuf("..."); /* temporary buffer */
2485: strcpy(fname(),obname); /* Restore file name */
2486: #ifdef PC
2487: oldbin = BINMODE;
2488: BINMODE = 1;
2489: #endif PC
2490: if (fred(err)) { /* read file */
2491: macro(arg);
2492: err = 1;
2493: } else {
2494: err = 0;
2495: }
2496: #ifdef PC
2497: BINMODE=oldbin;
2498: #endif PC
2499: tmpbuf = curbf;
2500: chbuf(oldbuf);
2501: klbfr(tmpbuf); /* kill temp buffer */
2502: return(err);
2503: }
2504: /* macro programming commands */
2505:
2506: /* these commands perform various utility functions for macro commands */
2507:
2508: bfchr() /* get a character from the buffer */
2509: {
2510: /* Keywords: macro-programming quoting character-at-a-time buffers:40 */
2511: return(clptr[column]&0377); /* Trim sign bits! */
2512: }
2513:
2514: litchr() /* literal character */
2515:
2516: {
2517: /* Keywords: macro-programming quoting */
2518: return(getchar());
2519: }
2520:
2521: compar(ctype) /* general comparison */
2522:
2523: /* comparison type definitions (pecular arangement for convenient */
2524: /* specification via ^U */
2525:
2526:
2527: #define CLE 0 /* <= */
2528: #define CEQ 1 /* = */
2529: #define CLS 2 /* < */
2530: #define CGT 3 /* > */
2531: #define CNE 4 /* != */
2532: #define CGE 5 /* >= */
2533: #define COR 6 /* OR */
2534: #define CAND 7 /* AND */
2535: #define CNOT 8 /* NOT */
2536: #define CFALSE 9 /* FALSE */
2537: #define CTRUE 10 /* TRUE */
2538: #define CPLUS 11 /* arg1 + arg2 */
2539: #define CMINUS 12 /* arg1 - arg2 */
2540: #define CTIMES 13 /* arg1 * arg2 */
2541: #define CDIV 14 /* arg1 / arg2 */
2542: #define CREM 15 /* arg1 % arg2 */
2543: #define CDTOS 16 /* arg1 convert to string on kill stack */
2544: #define CSTOD 17 /* convert ks to decimal and return */
2545: #define CBAND 18 /* Bitwise and */
2546: #define CBOR 19 /* Bitwise or */
2547: #define CXOR 20 /* Bitwise xor */
2548: #define CUNGET 21 /* Unget character */
2549: #define CPENDING 22 /* number of characters pending */
2550:
2551: /* Keywords: macro-programming arithmetic:50 comparison:50 */
2552:
2553: register int ctype;
2554: {
2555: register int r1;
2556: register int r2;
2557: char *sp;
2558: char sbuf[20];
2559: int res;
2560:
2561: if (ctype == CFALSE) return(0);
2562: if (ctype == CTRUE) return(1);
2563: if (ctype == CSTOD) {
2564: sp = getname("Number?");
2565: nscan(sp,&res);
2566: return(res);
2567: }
2568: if (ctype == CPENDING) {
2569: ttfill(); /* Read any pending tty input */
2570: return(ttcnt);
2571: }
2572: r1 = edit(0); /* first arg */
2573:
2574: if (ctype == CNOT) return(r1 == 0);
2575: if (ctype == CDTOS) {
2576: seprintf(sbuf,"%d",r1);
2577: stkstr(sbuf);
2578: return(r1);
2579: }
2580: if (ctype == CUNGET) {
2581: pushin(0); /* Force to tty */
2582: ungetch(r1);
2583: inpop();
2584: return(1);
2585: }
2586: r2 = edit(0); /* second arg */
2587:
2588: switch(ctype) {
2589:
2590: case CLE: return(r1<=r2);
2591: case CEQ: return(r1==r2);
2592: case CLS: return(r1<r2);
2593: case CGT: return(r1>r2);
2594: case CNE: return(r1!=r2);
2595: case CGE: return(r1>=r2);
2596: case CAND: return(r1 && r2);
2597: case COR: return(r1 || r2);
2598: case CPLUS: return(r1+r2);
2599: case CMINUS: return(r1-r2);
2600: case CTIMES: return (r1*r2);
2601: case CDIV: if (r2) return(r1/r2);
2602: else return(0);
2603: case CREM: if (r2) return(r1%r2);
2604: else return(0);
2605: case CBAND: return(r1&r2);
2606: case CBOR: return(r1|r2);
2607: case CXOR: return (r1^r2);
2608: default:return(0);
2609: }
2610: }
2611:
2612:
2613: pscan(lev) /* parenthesis scan */
2614: /* Keywords: macro-programming parsing control-flow:50 */
2615: register int lev; /* returns when lev+paren level = 0 */
2616: {
2617: register int c;
2618: register int ctlx;
2619: ctlx = 0;
2620: while (lev) {
2621: c = Mgetchar();
2622: if (c == CTRLX) {
2623: ctlx++;
2624: continue;
2625: }
2626: if (!ctlx && ((c == (CTRLQ)) || (c == MTA(q)) || (c == (CTRLQ+META)))) {
2627: c = Mgetchar();
2628: continue;
2629: }
2630: ctlx = 0;
2631: if (c == MTA({)) lev++;
2632: else if (c == MTA(})) lev--;
2633: }
2634: }
2635:
2636:
2637: cond() /* conditional execute */
2638: /* Keywords: control-flow parsing :5 conditionals macro-programming */
2639: {
2640: register int c;
2641:
2642: MACEXIT; /* Only in a macro */
2643:
2644: if ((c = Mgetchar()) != MTA({)) {
2645: /* must be M-{ */
2646: return(error(NORM,49));
2647: }
2648: while ((c = Mgetchar()) != MTA(})) {
2649: while ((c != MTA({)) && (c !=MTA(}))) c = Mgetchar();
2650: if (c == MTA(})) return(0); /* failed */
2651: if (edit(0)) {
2652: c = edit(1); /* scan command */
2653: pscan(1); /* skip to end of cond */
2654: return(c);
2655: } else pscan(1); /* skip to end of block */
2656: }
2657: return(0); /* cond failed */
2658: }
2659:
2660: /* macro case statement: syntax is ^x!M-{<expr>
2661: * M-{<char><sequence>M-}
2662: * ...
2663: * M-}
2664: */
2665:
2666:
2667: mcase()
2668:
2669:
2670:
2671: /* Keywords: cases parsing:5 control-flow macro-programming */
2672: {
2673: register int cchar;
2674: register int c;
2675:
2676: MACEXIT;
2677:
2678: while ((cchar =Mgetchar()) != MTA({));
2679: cchar = edit(0); /* match expression */
2680:
2681: while ((c = Mgetchar()) != MTA(})) {
2682: while ((c != MTA({)) && (c !=MTA(}))) c = Mgetchar();
2683: if (c == MTA(})) return(0); /* failed */
2684: c = Mgetchar();
2685: if ((c == cchar) || (c == 0377)) {
2686: c = edit(1); /* scan command */
2687: pscan(1); /* skip to end of case */
2688: return(c);
2689: } else pscan(1); /* skip to end of block */
2690: }
2691: return(0); /* case failed */
2692: }
2693:
2694: /* mbegin -- begin block in macro */
2695:
2696: mbegin()
2697:
2698:
2699: /* Keywords: macro-programming parsing:20 control-flow */
2700:
2701: {
2702: return(edit(1)); /* push command */
2703: }
2704:
2705: /* iteration handler */
2706:
2707: iter()
2708: {
2709: /* Keywords: macro-programming control-flow parsing:10 loops */
2710:
2711: register int c;
2712: register char *savptr;
2713:
2714: MACEXIT;
2715:
2716: while ((c =Mgetchar()) != MTA({)) {
2717: if ((c != ' ') && (c != ' ') && (c != EOL)) {
2718: return(error (NORM,50));
2719: }
2720: }
2721: savptr = inget();
2722: while (edit(0)) { /* test condition */
2723:
2724: c = edit(1); /* execute body */
2725:
2726: inset(savptr); /* backup */
2727:
2728: }
2729: pscan(1); /* skip body */
2730: return(c);
2731: }
2732:
2733: /* gparam -- get a parameter and push into the kill stack */
2734:
2735: /* with an argument of 1, it takes the parameter in line, with */
2736: /* other arguments, it takes the parameter from the tty, prompting with */
2737: /* the in line parameter4 */
2738:
2739:
2740: gparam(arg) /* get a parameter */
2741:
2742: int arg; /* with 1 arg, from macro text, else from tty */
2743:
2744:
2745: /* Keywords: macro-programming string-handling:20 string-variables:50 filenames:10 prompting:40 reading:20 killstack:20 */
2746: {
2747: char pbuf[128];
2748: register char *pb;
2749: register int pbch;
2750:
2751: MACEXIT;
2752: for (pb = pbuf;;) {
2753: *pb++ = pbch = Mgetchar();
2754: if (pbch == CTRLQ){
2755: --pb;
2756: *pb++ = Mgetchar();
2757: }
2758: if ((pbch == EOL)|| (pbch==CTRLZ)) break;
2759: if (pb>=(pbuf+128)) pb--; /* Truncate pb */
2760: }
2761: *(--pb) = 0; /* pickup prompt message */
2762: return(gpm(arg,pbuf)); /* pickup up parameter */
2763: }
2764:
2765: /* gkarm -- like gparm, except input is from the kill stack. */
2766:
2767:
2768: gkarm(arg)
2769:
2770: /* Keywords: macro-programming string-handling:20 string-variables:50 filenames:10 prompting:40 reading:20 killstack:20 */
2771: int arg;
2772: {
2773: char *pb;
2774:
2775: pb = getname(""); /* pick up parameter */
2776:
2777: return(gpm(arg,pb));
2778: }
2779:
2780:
2781: gpm(arg,pbuf)
2782: register int arg;
2783: register char *pbuf;
2784:
2785: /* Keywords: macro-programming string-handling:20 string-variables:50 filenames:10 prompting:40 reading:20 killstack:20 */
2786: {
2787: register char *pb;
2788: char pmpt[128];
2789: int pbch;
2790:
2791: if (arg == 3) {
2792: eprintf("%s",pbuf); /* Raw print, shouldn't mung screen */
2793:
2794: return(1);
2795: }
2796: if (arg != 1) {
2797: pushin(NULL);
2798: if (arg <= 0) {
2799: /* single character */
2800: prompt1("%s",pbuf);
2801: if (arg < 0) {
2802: mgo(nln,ncol);
2803: pbch = getchar();
2804: unprompt();
2805: }
2806: inpop();
2807: return(pbch);
2808: }
2809: strcpy(pmpt,pbuf); /* In case prompt is in pbuf already */
2810: pb = getname(pmpt);
2811: if (pb == NULL) pb = "";
2812: inpop();
2813: } else pb = pbuf;
2814: stkstr(pb);
2815: return(lng(pb));
2816: }
2817:
2818:
2819: char *
2820: maclook(mp)
2821: char *mp;
2822:
2823: /* Keywords: macro-programming:20 symbol-handling macro-invocation global-variables:50 */
2824: {
2825: int hash,ohash;
2826: register char *mp1,*mp2;
2827:
2828: /* now look up macro name */
2829:
2830: mp1 = mp;
2831: hash = 0;
2832: while (*mp1) hash += *mp1++;
2833: hash = hash %NMAC;
2834: ohash = hash;
2835: hash = machash[hash];
2836: while (hash) {
2837: for (mp1=mp,mp2= &bbuf[0][hash+3]; *mp1++ == *mp2++; ) {
2838: if ((*mp1 == 0) && ((*mp2 == 0)||(*mp2 == ' ')|| (*mp2 == ' '))) {
2839: while (*mp2++);
2840: return(mp2);
2841: }
2842: }
2843: hash = (bbuf[0][hash]&0377) + (bbuf[0][hash+1] <<8);
2844: }
2845: return(NULL);
2846: }
2847:
2848: /* macro call by name */
2849:
2850:
2851: macex(arg,ivchar)
2852:
2853: int arg;
2854: int ivchar;
2855:
2856: /* Keywords: macro-invocation macro-programming modes:10 reading:40 */
2857: {
2858: char mbuf[100];
2859: register char *mp1;
2860: register char *mp3;
2861: register int c;
2862:
2863: mp1 = mbuf;
2864: if (infrn < 0) {
2865: while ((c = Mgetchar()) != EOL) *mp1++ = c;
2866: *mp1 = 0;
2867: mp3 = mbuf;
2868: } else {
2869: mp3 = getname ("Macro name? ");
2870: }
2871: if (mp3 == NULL) return(0); /* aborted */
2872: if (mp1 = maclook(mp3)) {
2873: run: return(xmac(mp1-bbuf[0],arg,ivchar));
2874: } else {
2875: if (AUTOLOAD && (infrn < 0)) {
2876:
2877: /* Autoload mode, If an undefined macro is called from a macro, it */
2878: /* tries to load it from a standard library */
2879:
2880: char buf[128];
2881: #ifdef PC
2882: seprintf (buf,"%s",mp3);
2883: #else
2884: seprintf(buf,"~EMACS/macros/%s",mp3);
2885: #endif
2886: stkstr(buf);
2887: if (ldmac(-1) &&(mp1 = maclook(mp3))) {
2888: loaded: prompt(ECHOL,"Autoloaded %s",buf);
2889: goto run;
2890: }
2891: #ifdef PC
2892: seprintf(buf,"c:%s",mp3);
2893: #else
2894: seprintf(buf,"$EMACS_LIB/%s",mp3);
2895: #endif
2896: stkstr(buf);
2897: if (ldmac(-1) && (mp1 = maclook(mp3))) goto loaded;
2898: }
2899: error (WARN,51,mp3);
2900: return(NULL);
2901: }
2902: }
2903: hook(hookp)
2904: int hookp;
2905:
2906: /* Keywords: macro-programming macro-invoction:50 macro-hooks */
2907: {
2908: register int oldhook;
2909: int result;
2910: char xfnbuf[FNLEN];
2911:
2912: strcpy(xfnbuf,fnbuf); /* Preserve temp buffer, in case it's wiped by the macro */
2913:
2914: oldhook = hooks[hookp];
2915: hooks[hookp] = 0; /* Prevent recursion */
2916: result = xmac (oldhook,0,0);
2917: hooks[hookp] = oldhook;
2918: strcpy(fnbuf,xfnbuf);
2919: return(result);
2920: }
2921: /* xmac -- execute a macro */
2922:
2923:
2924: xmac(macp,arg,ivchar)
2925:
2926: register int macp;
2927: register int arg;
2928: int ivchar;
2929: {
2930: /* Keywords: macro-programming macro-invocation local-variables:60 argument-processing:20 */
2931:
2932: int mvars[NMVAR]; /* macro variables */
2933: int *omarg; /* old pointer to mvars */
2934:
2935: omarg = marg;
2936: marg = mvars;
2937: mvars[1]=arg; /* record macro argument */
2938: mvars[0] = ivchar; /* invoking character */
2939: pshmac(macp);
2940: if (etrace) putout("Entering macro: %s",hmap(macp));
2941:
2942: arg = edit(1);
2943:
2944: if (etrace) putout ("Exiting macro: %s",hmap(macp));
2945: marg = omarg;
2946: inpop();
2947: return(arg);
2948: }
2949:
2950: /* setvar -- set a local variable */
2951:
2952: setvar(arg)
2953: register int arg;
2954: {
2955: /* Keywords: assignment macro-programming local-variables */
2956: register int oldvar;
2957:
2958: if ((arg <NMVAR) && (arg >=0)) {
2959: oldvar = marg[arg];
2960: marg[arg] = edit(0); /* set new value */
2961: return(oldvar);
2962: } else {
2963: beep();
2964: return(0);
2965: }
2966: }
2967:
2968: /* getsharg -- get argument from shell command line */
2969:
2970: /* with argument of 1, gets one argument and pops. */
2971: /* with other argument, returns argument but does not pop */
2972:
2973: /* Value returned is 1 unless there are no more command line options. */
2974:
2975:
2976: getsharg(arg)
2977: int arg;
2978: {
2979: /* Keywords: argument-processing:10 command-line-processing macro-programming */
2980: extern char **sharg;
2981: extern int nsharg;
2982:
2983: if (nsharg) {
2984:
2985: stkstr(*sharg);
2986: if (arg==1) {
2987: nsharg--;
2988: sharg++;
2989: }
2990: return(1);
2991: }
2992: return(0);
2993: }
2994:
2995:
2996:
2997: /* string operations */
2998:
2999: /* compares same argument conventions as other comparisons */
3000:
3001: #define CAPP 7 /* Arg 2 appended to arg1 */
3002: #define CINDEX 8 /* index of arg 2 in arg1 */
3003: #define SBINARY 8
3004: #define CSUBSTR 9 /* string indexed by next 2 commands */
3005: #define CLENGTH 10 /* String length */
3006: #define SUNARY 10
3007: #define CPTR 11
3008: #define CSTRING 12
3009: #define CPRINTF 13 /* formatted I/O */
3010:
3011: cmpst(arg)
3012:
3013: register int arg;
3014:
3015: /* Keywords: macro-programming comparison string-variables string-handling:30 conversions:20 */
3016: {
3017: char buf[256];
3018:
3019: register char *bp1;
3020: register char *bp2;
3021: char *bp3;
3022: int i,j;
3023:
3024: if (arg <= SUNARY)bp1 = getname(""); /* get first string */
3025:
3026: if (arg <= SBINARY) {
3027: strcpy(buf,bp1);
3028: bp1 = buf;
3029: bp2 = getname("");
3030: }
3031:
3032: if (arg <= CGE) {
3033: while ((*bp1 == *bp2) && *bp1) {
3034: bp1++;
3035: bp2++;
3036: }
3037: }
3038: switch (arg) {
3039:
3040: case CLE: return(*bp1<=*bp2);
3041: case CEQ: return(*bp1==*bp2);
3042: case CLS: return(*bp1<*bp2);
3043: case CGT: return(*bp1>*bp2);
3044: case CNE: return(*bp1!=*bp2);
3045: case CGE: return(*bp1>=*bp2);
3046: case CAPP:
3047: strcpy(bp2+lng(bp2),bp1);
3048: stkstr(bp2);
3049: return(1);
3050: case CINDEX:
3051: i = 0;
3052: bp3 = bp2;
3053: while (*(bp2=bp3+i)) {
3054: bp1 = buf;
3055: while (*bp1++ == *bp2++) {
3056: if (*bp1 == 0) return(i);
3057: }
3058: i++;
3059: }
3060: return(-1);
3061: case CSUBSTR:
3062: i = edit(0);
3063: j = edit(0);
3064: bp1[j]=0;
3065: stkstr(bp1+i);
3066: return(1);
3067: case CLENGTH: return(lng(bp1));
3068: case CPTR: return(kgptr());
3069: case CSTRING:
3070: i = edit(0);
3071: kput(i);
3072: return(1);
3073: case CPRINTF:
3074: /* Printf like formatting. */
3075: {
3076: int pts[20],len;
3077: char buf2[256];
3078: bp1=bp2=getname(""); /* Format string */
3079:
3080: /* First, collect all of the parameters */
3081:
3082: i = 0;
3083: while(*bp1) {
3084: if (bp1[0] == '%') {
3085: if (bp1[1] == '%') bp1++;
3086: else pts[i++] = kgptr(); /* Collect one */
3087: }
3088: bp1++;
3089: }
3090: strcpy(buf2,bp2);
3091: bp2 = buf2;
3092: bp1 = buf;
3093: while (*bp2) {
3094: if (*bp2 == '%') {
3095: bp2 = nscan(bp2+1,&j);
3096: if (*bp2 == '%') {
3097: *bp1++ = *bp2++;
3098: continue;
3099: }
3100: kput(pts[--i]);
3101: bp3 = getname(""); /* get the param */
3102: len = lng(bp3);
3103:
3104: switch(*bp2++) {
3105:
3106: case 'l': bp1 = mstrcpy(bp1,bp3);
3107: j = j-len;
3108: if (j>0) while (j--) *bp1++ = ' ';
3109: break;
3110: case 'r':
3111: j = j-len;
3112: if (j>0) while (j--) *bp1++ = ' ';
3113: bp1 = mstrcpy(bp1,bp3);
3114: break;
3115: case 'c':
3116: len = (j-len);
3117: if (len>= 0) {
3118: j = len/2;
3119: len = len-j;
3120: while (j--) *bp1++ = ' ';
3121: }
3122: bp1 = mstrcpy(bp1,bp3);
3123: if (len> 0) while (len--) *bp1++ = ' ';
3124: break;
3125: }
3126: } else *bp1++ = *bp2++;
3127: }
3128: *bp1 = 0;
3129: stkstr(buf);
3130: return(1);
3131: }
3132: default: return(0);
3133: }
3134: }
3135:
3136:
3137: /* Global variable -- global variables are dynamically bound by
3138: * names. They are 2 or 4 bytes long and always stored in order of
3139: * lsB first. */
3140:
3141: glob(arg)
3142: int arg;
3143: {
3144: /* Keywords: global-variables assignment:50 macro-programming */
3145: int size;
3146: char *name;
3147: char *where;
3148: int hash;
3149:
3150:
3151: if (name= getname ("Global variable name? ")) {
3152: if ((where = maclook(name)) == NULL) {
3153: if (arg == 0) return(0);
3154: where = name;
3155: hash = 0;
3156: while (*where) hash += *where++;
3157: hash = hash %NMAC;
3158: pshchr(machash[hash]);
3159: pshchr(machash[hash]>>8);
3160: machash[hash] = macptr-2;
3161: where = name;
3162: pshchr(0);
3163: while (*where) pshchr(*where++);
3164: pshchr(0);
3165: for (size=0; size<sizeof(size); size++) pshchr(0);
3166: where = maclook(name);
3167: }
3168: switch(arg) {
3169:
3170: case 0:
3171: return(1);
3172: break;
3173: case 1:
3174: hash = 0;
3175: for (size=0; size<sizeof(size); size++) {
3176: hash+= ((*where++)&0377) << (size*8);
3177: }
3178: return(hash);
3179: case 2:
3180: hash = edit(0);
3181: for (size=0; size<sizeof(size); size++) {
3182: *where++ = hash;
3183: hash = hash >>8;
3184: }
3185: break;
3186: }
3187: }
3188: return(0);
3189: }
3190: /* envexp -- expand environment variables in a string */
3191:
3192: /* expansion takes place in the caller's string buffer */
3193: /* pointer is returned for convenience only */
3194:
3195: char *pwpath = "/etc/passwd";
3196:
3197: char *
3198: expenv(str)
3199: register char *str;
3200: /* Keywords: environment-variables unix-interface user-interface:20 shell-escape:10 */
3201: {
3202: char strtemp[128];
3203: char vartemp [64];
3204: register char *cp1;
3205: char *cp2;
3206: register int c;
3207: int oc;
3208:
3209: if (str == NULL) return(NULL);
3210:
3211: cp1 = strtemp;
3212: cp2 = str;
3213: while (*cp1++ = *str) {
3214: if ((*str== '`')||(*str=='*')||(*str=='{')||(*str=='[')||((*str++)=='?')) {
3215: seprintf(strtemp,"exec echo %s",cp2);
3216: unx(strtemp,4); /* expand through the shell */
3217: return(fnbuf);
3218: }
3219: }
3220: cp1 = strtemp;
3221: str = fnbuf; /* always copy back into file name */
3222: while (c = *cp1++) {
3223: if ((c == '$') || (c == '~')) {
3224:
3225: /* Environment variable or `logdir` */
3226:
3227: oc = c;
3228: cp2 = vartemp;
3229: while (bits[c=((*cp1++)&0377)]&WRDCHR) {
3230: *cp2++ = c;
3231: }
3232: cp1--; /* backspace pointer */
3233: *cp2 = 0;
3234: if (oc == '$') {
3235: cp2 = getenv(vartemp); /* environment variable */
3236: } else {
3237: #ifndef PC
3238: /* Home Directory */
3239:
3240: if (*vartemp == 0) {
3241: cp2 = getenv("HOME"); /* Bare ~ means home */
3242: } else if (streq(vartemp,"EMACS")) {
3243: cp2 = em_dir;
3244: } else if (streq(vartemp,"exptools") &&
3245: (cp2 = getenv("TOOLS")) && *cp2) {
3246: ;
3247: } else {
3248: FILE pwfile[1];
3249: FILE *pwptr;
3250: char *vp;
3251:
3252: cp2 = NULL;
3253: pwptr = xopen(pwfile,pwpath,"r");
3254: if (pwptr) {
3255: while ((c = getc(pwptr))!= EOF) {
3256: if (c == '\n') {
3257: vp = vartemp;
3258: /* Try to match the specified user ID */
3259: while (*vp++ == (c = getc(pwptr)));
3260: if ((vp[-1] == 0) && (c == ':')) {
3261: /* Found it, now skip 4 colons, and copy next field into vartemp; */
3262: c = 0;
3263: while (c < 4) if (getc(pwptr) == ':') c++;
3264: cp2 = vartemp;
3265: while ((c = getc(pwptr)) != ':') *cp2++=c;
3266: *cp2++=0;
3267: cp2=vartemp;
3268: break; /* Break out of password scan */
3269: }
3270: }
3271: }
3272: mclose(pwptr);
3273: } else error(WARN,errno,pwpath);
3274: }
3275: #endif PC
3276: }
3277: if (cp2 != NULL) {
3278: str = mstrcpy(str,cp2);
3279: } else {
3280: *str++ = oc;
3281: str = mstrcpy(str,vartemp);
3282: }
3283: } else {
3284: *str++ = c;
3285: }
3286: }
3287: *str++ = 0;
3288: return(fnbuf);
3289: }
3290: /*
3291: * envget takes a string and expands it into the string
3292: * stored in the shell variable by the same name.
3293: * If the shell variable did not exist, then envget
3294: * returns NULL.
3295: */
3296:
3297: envget()
3298: /* Keywords: commands environment-variables */
3299:
3300: {
3301: char * ptr;
3302:
3303: if (ptr = getenv(getname("Environment variable: "))) {
3304: stkstr(ptr);
3305: return(1);
3306: }
3307: else {
3308: stkstr("");
3309: return(0);
3310: }
3311: }
3312:
3313: stopjob ()
3314: {
3315: char x;
3316: clear();
3317: cook();
3318: #if (defined (bsd) || defined (v8))
3319: kill(mypid,SIGSTOP);
3320: #else
3321: eprintf ("Type ^Z to suspend emacs and <return> to continue");
3322: read(0,&x,1);
3323: #endif
3324: uncook();
3325: clear();
3326: }
3327:
3328: #ifdef u370
3329: beepbeep()
3330: {
3331: extern int beep();
3332: }
3333: #endif
3334:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.