|
|
1.1 root 1: /* Copyright (c) 1980 Regents of the University of California */
2: static char *sccsid = "@(#)ex_subr.c 6.2 11/6/80";
3: #include "ex.h"
4: #include "ex_re.h"
5: #include "ex_tty.h"
6: #include "ex_vis.h"
7:
8: /*
9: * Random routines, in alphabetical order.
10: */
11:
12: any(c, s)
13: int c;
14: register char *s;
15: {
16: register int x;
17:
18: while (x = *s++)
19: if (x == c)
20: return (1);
21: return (0);
22: }
23:
24: backtab(i)
25: register int i;
26: {
27: register int j;
28:
29: j = i % value(SHIFTWIDTH);
30: if (j == 0)
31: j = value(SHIFTWIDTH);
32: i -= j;
33: if (i < 0)
34: i = 0;
35: return (i);
36: }
37:
38: change()
39: {
40:
41: tchng++;
42: chng = tchng;
43: }
44:
45: /*
46: * Column returns the number of
47: * columns occupied by printing the
48: * characters through position cp of the
49: * current line.
50: */
51: column(cp)
52: register char *cp;
53: {
54:
55: if (cp == 0)
56: cp = &linebuf[LBSIZE - 2];
57: return (qcolumn(cp, (char *) 0));
58: }
59:
60: /*
61: * Ignore a comment to the end of the line.
62: * This routine eats the trailing newline so don't call newline().
63: */
64: comment()
65: {
66: register int c;
67:
68: do {
69: c = getchar();
70: } while (c != '\n' && c != EOF);
71: if (c == EOF)
72: ungetchar(c);
73: }
74:
75: Copy(to, from, size)
76: register char *from, *to;
77: register int size;
78: {
79:
80: if (size > 0)
81: do
82: *to++ = *from++;
83: while (--size > 0);
84: }
85:
86: copyw(to, from, size)
87: register line *from, *to;
88: register int size;
89: {
90:
91: if (size > 0)
92: do
93: *to++ = *from++;
94: while (--size > 0);
95: }
96:
97: copywR(to, from, size)
98: register line *from, *to;
99: register int size;
100: {
101:
102: while (--size >= 0)
103: to[size] = from[size];
104: }
105:
106: ctlof(c)
107: int c;
108: {
109:
110: return (c == TRIM ? '?' : c | ('A' - 1));
111: }
112:
113: dingdong()
114: {
115:
116: if (VB)
117: putpad(VB);
118: else if (value(ERRORBELLS))
119: putch('\207');
120: }
121:
122: fixindent(indent)
123: int indent;
124: {
125: register int i;
126: register char *cp;
127:
128: i = whitecnt(genbuf);
129: cp = vpastwh(genbuf);
130: if (*cp == 0 && i == indent && linebuf[0] == 0) {
131: genbuf[0] = 0;
132: return (i);
133: }
134: CP(genindent(i), cp);
135: return (i);
136: }
137:
138: filioerr(cp)
139: char *cp;
140: {
141: register int oerrno = errno;
142:
143: lprintf("\"%s\"", cp);
144: errno = oerrno;
145: syserror();
146: }
147:
148: char *
149: genindent(indent)
150: register int indent;
151: {
152: register char *cp;
153:
154: for (cp = genbuf; indent >= value(TABSTOP); indent -= value(TABSTOP))
155: *cp++ = '\t';
156: for (; indent > 0; indent--)
157: *cp++ = ' ';
158: return (cp);
159: }
160:
161: getDOT()
162: {
163:
164: getline(*dot);
165: }
166:
167: line *
168: getmark(c)
169: register int c;
170: {
171: register line *addr;
172:
173: for (addr = one; addr <= dol; addr++)
174: if (names[c - 'a'] == (*addr &~ 01)) {
175: return (addr);
176: }
177: return (0);
178: }
179:
180: getn(cp)
181: register char *cp;
182: {
183: register int i = 0;
184:
185: while (isdigit(*cp))
186: i = i * 10 + *cp++ - '0';
187: if (*cp)
188: return (0);
189: return (i);
190: }
191:
192: ignnEOF()
193: {
194: register int c = getchar();
195:
196: if (c == EOF)
197: ungetchar(c);
198: else if (c=='"')
199: comment();
200: }
201:
202: iswhite(c)
203: int c;
204: {
205:
206: return (c == ' ' || c == '\t');
207: }
208:
209: junk(c)
210: register int c;
211: {
212:
213: if (c && !value(BEAUTIFY))
214: return (0);
215: if (c >= ' ' && c != TRIM)
216: return (0);
217: switch (c) {
218:
219: case '\t':
220: case '\n':
221: case '\f':
222: return (0);
223:
224: default:
225: return (1);
226: }
227: }
228:
229: killed()
230: {
231:
232: killcnt(addr2 - addr1 + 1);
233: }
234:
235: killcnt(cnt)
236: register int cnt;
237: {
238:
239: if (inopen) {
240: notecnt = cnt;
241: notenam = notesgn = "";
242: return;
243: }
244: if (!notable(cnt))
245: return;
246: printf("%d lines", cnt);
247: if (value(TERSE) == 0) {
248: printf(" %c%s", Command[0] | ' ', Command + 1);
249: if (Command[strlen(Command) - 1] != 'e')
250: putchar('e');
251: putchar('d');
252: }
253: putNFL();
254: }
255:
256: lineno(a)
257: line *a;
258: {
259:
260: return (a - zero);
261: }
262:
263: lineDOL()
264: {
265:
266: return (lineno(dol));
267: }
268:
269: lineDOT()
270: {
271:
272: return (lineno(dot));
273: }
274:
275: markDOT()
276: {
277:
278: markpr(dot);
279: }
280:
281: markpr(which)
282: line *which;
283: {
284:
285: if ((inglobal == 0 || inopen) && which <= endcore) {
286: names['z'-'a'+1] = *which & ~01;
287: if (inopen)
288: ncols['z'-'a'+1] = cursor;
289: }
290: }
291:
292: markreg(c)
293: register int c;
294: {
295:
296: if (c == '\'' || c == '`')
297: return ('z' + 1);
298: if (c >= 'a' && c <= 'z')
299: return (c);
300: return (0);
301: }
302:
303: /*
304: * Mesg decodes the terse/verbose strings. Thus
305: * 'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
306: * 'xxx|yyy' -> 'xxx' if terse, else 'yyy'
307: * All others map to themselves.
308: */
309: char *
310: mesg(str)
311: register char *str;
312: {
313: register char *cp;
314:
315: str = strcpy(genbuf, str);
316: for (cp = str; *cp; cp++)
317: switch (*cp) {
318:
319: case '@':
320: if (value(TERSE))
321: *cp = 0;
322: else
323: *cp = ' ';
324: break;
325:
326: case '|':
327: if (value(TERSE) == 0)
328: return (cp + 1);
329: *cp = 0;
330: break;
331: }
332: return (str);
333: }
334:
335: /*VARARGS2*/
336: merror(seekpt, i)
337: #ifdef VMUNIX
338: char *seekpt;
339: #else
340: # ifdef lint
341: char *seekpt;
342: # else
343: int seekpt;
344: # endif
345: #endif
346: int i;
347: {
348: register char *cp = linebuf;
349:
350: if (seekpt == 0)
351: return;
352: merror1(seekpt);
353: if (*cp == '\n')
354: putnl(), cp++;
355: if (inopen && CE)
356: vclreol();
357: if (SO && SE)
358: putpad(SO);
359: printf(mesg(cp), i);
360: if (SO && SE)
361: putpad(SE);
362: }
363:
364: merror1(seekpt)
365: #ifdef VMUNIX
366: char *seekpt;
367: #else
368: # ifdef lint
369: char *seekpt;
370: # else
371: int seekpt;
372: # endif
373: #endif
374: {
375:
376: #ifdef VMUNIX
377: strcpy(linebuf, seekpt);
378: #else
379: lseek(erfile, (long) seekpt, 0);
380: if (read(erfile, linebuf, 128) < 2)
381: CP(linebuf, "ERROR");
382: #endif
383: }
384:
385: morelines()
386: {
387:
388: if ((int) sbrk(1024 * sizeof (line)) == -1)
389: return (-1);
390: endcore += 1024;
391: return (0);
392: }
393:
394: nonzero()
395: {
396:
397: if (addr1 == zero) {
398: notempty();
399: error("Nonzero address required@on this command");
400: }
401: }
402:
403: notable(i)
404: int i;
405: {
406:
407: return (hush == 0 && !inglobal && i > value(REPORT));
408: }
409:
410:
411: notempty()
412: {
413:
414: if (dol == zero)
415: error("No lines@in the buffer");
416: }
417:
418:
419: netchHAD(cnt)
420: int cnt;
421: {
422:
423: netchange(lineDOL() - cnt);
424: }
425:
426: netchange(i)
427: register int i;
428: {
429: register char *cp;
430:
431: if (i > 0)
432: notesgn = cp = "more ";
433: else
434: notesgn = cp = "fewer ", i = -i;
435: if (inopen) {
436: notecnt = i;
437: notenam = "";
438: return;
439: }
440: if (!notable(i))
441: return;
442: printf(mesg("%d %slines@in file after %s"), i, cp, Command);
443: putNFL();
444: }
445:
446: putmark(addr)
447: line *addr;
448: {
449:
450: putmk1(addr, putline());
451: }
452:
453: putmk1(addr, n)
454: register line *addr;
455: int n;
456: {
457: register line *markp;
458: register oldglobmk;
459:
460: oldglobmk = *addr & 1;
461: *addr &= ~1;
462: for (markp = (anymarks ? names : &names['z'-'a'+1]);
463: markp <= &names['z'-'a'+1]; markp++)
464: if (*markp == *addr)
465: *markp = n;
466: *addr = n | oldglobmk;
467: }
468:
469: char *
470: plural(i)
471: long i;
472: {
473:
474: return (i == 1 ? "" : "s");
475: }
476:
477: int qcount();
478: short vcntcol;
479:
480: qcolumn(lim, gp)
481: register char *lim, *gp;
482: {
483: register int x;
484: int (*OO)();
485:
486: OO = Outchar;
487: Outchar = qcount;
488: vcntcol = 0;
489: if (lim != NULL)
490: x = lim[1], lim[1] = 0;
491: pline(0);
492: if (lim != NULL)
493: lim[1] = x;
494: if (gp)
495: while (*gp)
496: putchar(*gp++);
497: Outchar = OO;
498: return (vcntcol);
499: }
500:
501: int
502: qcount(c)
503: int c;
504: {
505:
506: if (c == '\t') {
507: vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
508: return;
509: }
510: vcntcol++;
511: }
512:
513: reverse(a1, a2)
514: register line *a1, *a2;
515: {
516: register line t;
517:
518: for (;;) {
519: t = *--a2;
520: if (a2 <= a1)
521: return;
522: *a2 = *a1;
523: *a1++ = t;
524: }
525: }
526:
527: save(a1, a2)
528: line *a1;
529: register line *a2;
530: {
531: register int more;
532:
533: if (!FIXUNDO)
534: return;
535: #ifdef TRACE
536: if (trace)
537: vudump("before save");
538: #endif
539: undkind = UNDNONE;
540: undadot = dot;
541: more = (a2 - a1 + 1) - (unddol - dol);
542: while (more > (endcore - truedol))
543: if (morelines() < 0)
544: error("Out of memory@saving lines for undo - try using ed");
545: if (more)
546: (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
547: (truedol - unddol));
548: unddol += more;
549: truedol += more;
550: copyw(dol + 1, a1, a2 - a1 + 1);
551: undkind = UNDALL;
552: unddel = a1 - 1;
553: undap1 = a1;
554: undap2 = a2 + 1;
555: #ifdef TRACE
556: if (trace)
557: vudump("after save");
558: #endif
559: }
560:
561: save12()
562: {
563:
564: save(addr1, addr2);
565: }
566:
567: saveall()
568: {
569:
570: save(one, dol);
571: }
572:
573: span()
574: {
575:
576: return (addr2 - addr1 + 1);
577: }
578:
579: sync()
580: {
581:
582: chng = 0;
583: tchng = 0;
584: xchng = 0;
585: }
586:
587:
588: skipwh()
589: {
590: register int wh;
591:
592: wh = 0;
593: while (iswhite(peekchar())) {
594: wh++;
595: ignchar();
596: }
597: return (wh);
598: }
599:
600: /*VARARGS2*/
601: smerror(seekpt, cp)
602: #ifdef lint
603: char *seekpt;
604: #else
605: int seekpt;
606: #endif
607: char *cp;
608: {
609:
610: if (seekpt == 0)
611: return;
612: merror1(seekpt);
613: if (inopen && CE)
614: vclreol();
615: if (SO && SE)
616: putpad(SO);
617: lprintf(mesg(linebuf), cp);
618: if (SO && SE)
619: putpad(SE);
620: }
621:
622: #define std_nerrs (sizeof std_errlist / sizeof std_errlist[0])
623:
624: #define error(i) i
625:
626: #ifdef lint
627: char *std_errlist[] = {
628: #else
629: # ifdef VMUNIX
630: char *std_errlist[] = {
631: # else
632: short std_errlist[] = {
633: # endif
634: #endif
635: error("Error 0"),
636: error("Not super-user"),
637: error("No such file or directory"),
638: error("No such process"),
639: error("Interrupted system call"),
640: error("Physical I/O error"),
641: error("No such device or address"),
642: error("Argument list too long"),
643: error("Exec format error"),
644: error("Bad file number"),
645: error("No children"),
646: error("No more processes"),
647: error("Not enough core"),
648: error("Permission denied"),
649: error("Bad address"),
650: error("Block device required"),
651: error("Mount device busy"),
652: error("File exists"),
653: error("Cross-device link"),
654: error("No such device"),
655: error("Not a directory"),
656: error("Is a directory"),
657: error("Invalid argument"),
658: error("File table overflow"),
659: error("Too many open files"),
660: error("Not a typewriter"),
661: error("Text file busy"),
662: error("File too large"),
663: error("No space left on device"),
664: error("Illegal seek"),
665: error("Read-only file system"),
666: error("Too many links"),
667: error("Broken pipe"),
668: #ifndef V6
669: error("Math argument"),
670: error("Result too large"),
671: #endif
672: error("Quota exceeded") /* Berkeley quota systems only */
673: };
674:
675: #undef error
676:
677: char *
678: strend(cp)
679: register char *cp;
680: {
681:
682: while (*cp)
683: cp++;
684: return (cp);
685: }
686:
687: strcLIN(dp)
688: char *dp;
689: {
690:
691: CP(linebuf, dp);
692: }
693:
694: syserror()
695: {
696: register int e = errno;
697:
698: dirtcnt = 0;
699: putchar(' ');
700: edited = 0; /* for temp file errors, for example */
701: if (e >= 0 && errno <= std_nerrs)
702: error(std_errlist[e]);
703: else
704: error("System error %d", e);
705: }
706:
707: /*
708: * Return the column number that results from being in column col and
709: * hitting a tab, where tabs are set every ts columns. Work right for
710: * the case where col > COLUMNS, even if ts does not divide COLUMNS.
711: */
712: tabcol(col, ts)
713: int col, ts;
714: {
715: int offset, result;
716:
717: if (col >= COLUMNS) {
718: offset = COLUMNS * (col/COLUMNS);
719: col -= offset;
720: } else
721: offset = 0;
722: result = col + ts - (col % ts) + offset;
723: return (result);
724: }
725:
726: char *
727: vfindcol(i)
728: int i;
729: {
730: register char *cp;
731: register int (*OO)() = Outchar;
732:
733: Outchar = qcount;
734: ignore(qcolumn(linebuf - 1, NOSTR));
735: for (cp = linebuf; *cp && vcntcol < i; cp++)
736: putchar(*cp);
737: if (cp != linebuf)
738: cp--;
739: Outchar = OO;
740: return (cp);
741: }
742:
743: char *
744: vskipwh(cp)
745: register char *cp;
746: {
747:
748: while (iswhite(*cp) && cp[1])
749: cp++;
750: return (cp);
751: }
752:
753:
754: char *
755: vpastwh(cp)
756: register char *cp;
757: {
758:
759: while (iswhite(*cp))
760: cp++;
761: return (cp);
762: }
763:
764: whitecnt(cp)
765: register char *cp;
766: {
767: register int i;
768:
769: i = 0;
770: for (;;)
771: switch (*cp++) {
772:
773: case '\t':
774: i += value(TABSTOP) - i % value(TABSTOP);
775: break;
776:
777: case ' ':
778: i++;
779: break;
780:
781: default:
782: return (i);
783: }
784: }
785:
786: #ifdef lint
787: Ignore(a)
788: char *a;
789: {
790:
791: a = a;
792: }
793:
794: Ignorf(a)
795: int (*a)();
796: {
797:
798: a = a;
799: }
800: #endif
801:
802: markit(addr)
803: line *addr;
804: {
805:
806: if (addr != dot && addr >= one && addr <= dol)
807: markDOT();
808: }
809:
810: /*
811: * The following code is defensive programming against a bug in the
812: * pdp-11 overlay implementation. Sometimes it goes nuts and asks
813: * for an overlay with some garbage number, which generates an emt
814: * trap. This is a less than elegant solution, but it is somewhat
815: * better than core dumping and losing your work, leaving your tty
816: * in a weird state, etc.
817: */
818: int _ovno;
819: onemt()
820: {
821: int oovno;
822:
823: signal(SIGEMT, onemt);
824: oovno = _ovno;
825: /* 2 and 3 are valid on 11/40 type vi, so */
826: if (_ovno < 0 || _ovno > 3)
827: _ovno = 0;
828: error("emt trap, _ovno is %d @ - try again");
829: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.