release 3.2, Jan 4, 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
513 undkind = UNDNONE;
514 undadot = dot;
515 more = (a2 - a1 + 1) - (unddol - dol);
516 while (more > (endcore - truedol))
517 if (morelines() < 0)
518 error("Out of memory@saving lines for undo - try using ed or re");
519 if (more)
520 (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
521 (truedol - unddol));
522 unddol += more;
523 truedol += more;
524 copyw(dol + 1, a1, a2 - a1 + 1);
525 undkind = UNDALL;
526 unddel = a1 - 1;
527 undap1 = a1;
528 undap2 = a2 + 1;
529}
530
531save12()
532{
533
534 save(addr1, addr2);
535}
536
537saveall()
538{
539
540 save(one, dol);
541}
542
543span()
544{
545
546 return (addr2 - addr1 + 1);
547}
548
549sync()
550{
551
552 chng = 0;
553 tchng = 0;
554 xchng = 0;
555}
556
557
558skipwh()
559{
560 register int wh;
561
562 wh = 0;
563 while (iswhite(peekchar())) {
564 wh++;
565 ignchar();
566 }
567 return (wh);
568}
569
570/*VARARGS2*/
571smerror(seekpt, cp)
572#ifdef lint
573 char *seekpt;
574#else
575 int seekpt;
576#endif
577 char *cp;
578{
579
580 if (seekpt == 0)
581 return;
582 merror1(seekpt);
583 if (inopen && CE)
584 vclreol();
585 if (SO && SE)
586 putpad(SO);
587 lprintf(mesg(linebuf), cp);
588 if (SO && SE)
589 putpad(SE);
590}
591
592#define std_nerrs (sizeof std_errlist / sizeof std_errlist[0])
593
594#define error(i) i
595
596#ifdef lint
597char *std_errlist[] = {
598#else
44232d5b
MH
599#ifdef VMUNIX
600char *std_errlist[] = {
601#else
b6ea9402 602short std_errlist[] = {
44232d5b 603#endif
b6ea9402
MH
604#endif
605 error("Error 0"),
606 error("Not super-user"),
607 error("No such file or directory"),
608 error("No such process"),
609 error("Interrupted system call"),
610 error("Physical I/O error"),
611 error("No such device or address"),
612 error("Argument list too long"),
613 error("Exec format error"),
614 error("Bad file number"),
615 error("No children"),
616 error("No more processes"),
617 error("Not enough core"),
618 error("Permission denied"),
619 error("Bad address"),
620 error("Block device required"),
621 error("Mount device busy"),
622 error("File exists"),
623 error("Cross-device link"),
624 error("No such device"),
625 error("Not a directory"),
626 error("Is a directory"),
627 error("Invalid argument"),
628 error("File table overflow"),
629 error("Too many open files"),
630 error("Not a typewriter"),
631 error("Text file busy"),
632 error("File too large"),
633 error("No space left on device"),
634 error("Illegal seek"),
635 error("Read-only file system"),
636 error("Too many links"),
637 error("Broken pipe")
638#ifndef QUOTA
639 , error("Math argument")
640 , error("Result too large")
641#else
642 , error("Quota exceeded")
643#endif
644};
645
646#undef error
647
648char *
649strend(cp)
650 register char *cp;
651{
652
653 while (*cp)
654 cp++;
655 return (cp);
656}
657
658strcLIN(dp)
659 char *dp;
660{
661
662 CP(linebuf, dp);
663}
664
665syserror()
666{
667 register int e = errno;
668
669 dirtcnt = 0;
670 putchar(' ');
671 if (e >= 0 && errno <= std_nerrs)
672 error(std_errlist[e]);
673 else
674 error("System error %d", e);
675}
676
677char *
678vfindcol(i)
679 int i;
680{
681 register char *cp;
682 register int (*OO)() = Outchar;
683
684 Outchar = qcount;
685 ignore(qcolumn(linebuf - 1, NOSTR));
686 for (cp = linebuf; *cp && vcntcol < i; cp++)
687 putchar(*cp);
688 if (cp != linebuf)
689 cp--;
690 Outchar = OO;
691 return (cp);
692}
693
694char *
695vskipwh(cp)
696 register char *cp;
697{
698
699 while (iswhite(*cp) && cp[1])
700 cp++;
701 return (cp);
702}
703
704
705char *
706vpastwh(cp)
707 register char *cp;
708{
709
710 while (iswhite(*cp))
711 cp++;
712 return (cp);
713}
714
715whitecnt(cp)
716 register char *cp;
717{
718 register int i;
719
720 i = 0;
721 for (;;)
722 switch (*cp++) {
723
724 case '\t':
725 i += value(TABSTOP) - i % value(TABSTOP);
726 break;
727
728 case ' ':
729 i++;
730 break;
731
732 default:
733 return (i);
734 }
735}
736
737#ifdef lint
738Ignore(a)
739 char *a;
740{
741
742 a = a;
743}
744
745Ignorf(a)
746 int (*a)();
747{
748
749 a = a;
750}
751#endif
752
753markit(addr)
754 line *addr;
755{
756
757 if (addr != dot && addr >= one && addr <= dol)
758 markDOT();
759}
760