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