date and time created 80/07/31 23:00:25 by mark
[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)
319#ifdef lint
320 char *seekpt;
321#else
322 int seekpt;
323#endif
324 int i;
325{
326 register char *cp = linebuf;
327
328 if (seekpt == 0)
329 return;
330 merror1(seekpt);
331 if (*cp == '\n')
332 putnl(), cp++;
333 if (inopen && CE)
334 vclreol();
335 if (SO && SE)
336 putpad(SO);
337 printf(mesg(cp), i);
338 if (SO && SE)
339 putpad(SE);
340}
341
342merror1(seekpt)
343#ifdef lint
344 char *seekpt;
345#else
346 int seekpt;
347#endif
348{
349
350 lseek(erfile, (long) seekpt, 0);
351 if (read(erfile, linebuf, 128) < 2)
352 CP(linebuf, "ERROR");
353}
354
355morelines()
356{
357
358 if ((int) sbrk(1024 * sizeof (line)) == -1)
359 return (-1);
360 endcore += 1024;
361 return (0);
362}
363
364nonzero()
365{
366
367 if (addr1 == zero) {
368 notempty();
369 error("Nonzero address required@on this command");
370 }
371}
372
373notable(i)
374 int i;
375{
376
377 return (hush == 0 && !inglobal && i > value(REPORT));
378}
379
380
381notempty()
382{
383
384 if (dol == zero)
385 error("No lines@in the buffer");
386}
387
388
389netchHAD(cnt)
390 int cnt;
391{
392
393 netchange(lineDOL() - cnt);
394}
395
396netchange(i)
397 register int i;
398{
399 register char *cp;
400
401 if (i > 0)
402 notesgn = cp = "more ";
403 else
404 notesgn = cp = "fewer ", i = -i;
405 if (inopen) {
406 notecnt = i;
407 notenam = "";
408 return;
409 }
410 if (!notable(i))
411 return;
412 printf(mesg("%d %slines@in file after %s"), i, cp, Command);
413 putNFL();
414}
415
416putmark(addr)
417 line *addr;
418{
419
420 putmk1(addr, putline());
421}
422
423putmk1(addr, n)
424 register line *addr;
425 int n;
426{
427 register line *markp;
428
429 *addr &= ~1;
430 for (markp = (anymarks ? names : &names['z'-'a'+1]);
431 markp <= &names['z'-'a'+1]; markp++)
432 if (*markp == *addr)
433 *markp = n;
434 *addr = n;
435}
436
437char *
438plural(i)
439 long i;
440{
441
442 return (i == 1 ? "" : "s");
443}
444
445int qcount();
446short vcntcol;
447
448qcolumn(lim, gp)
449 register char *lim, *gp;
450{
451 register int x;
452 int (*OO)();
453
454 OO = Outchar;
455 Outchar = qcount;
456 vcntcol = 0;
457 if (lim != NULL)
458 x = lim[1], lim[1] = 0;
459 pline(0);
460 if (lim != NULL)
461 lim[1] = x;
462 if (gp)
463 while (*gp)
464 putchar(*gp++);
465 Outchar = OO;
466 return (vcntcol);
467}
468
469int
470qcount(c)
471 int c;
472{
473
474 if (c == '\t') {
475 vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
476 return;
477 }
478 vcntcol++;
479}
480
481reverse(a1, a2)
482 register line *a1, *a2;
483{
484 register line t;
485
486 for (;;) {
487 t = *--a2;
488 if (a2 <= a1)
489 return;
490 *a2 = *a1;
491 *a1++ = t;
492 }
493}
494
495save(a1, a2)
496 line *a1;
497 register line *a2;
498{
499 register int more;
500
501 undkind = UNDNONE;
502 undadot = dot;
503 more = (a2 - a1 + 1) - (unddol - dol);
504 while (more > (endcore - truedol))
505 if (morelines() < 0)
506 error("Out of memory@saving lines for undo - try using ed or re");
507 if (more)
508 (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
509 (truedol - unddol));
510 unddol += more;
511 truedol += more;
512 copyw(dol + 1, a1, a2 - a1 + 1);
513 undkind = UNDALL;
514 unddel = a1 - 1;
515 undap1 = a1;
516 undap2 = a2 + 1;
517}
518
519save12()
520{
521
522 save(addr1, addr2);
523}
524
525saveall()
526{
527
528 save(one, dol);
529}
530
531span()
532{
533
534 return (addr2 - addr1 + 1);
535}
536
537sync()
538{
539
540 chng = 0;
541 tchng = 0;
542 xchng = 0;
543}
544
545
546skipwh()
547{
548 register int wh;
549
550 wh = 0;
551 while (iswhite(peekchar())) {
552 wh++;
553 ignchar();
554 }
555 return (wh);
556}
557
558/*VARARGS2*/
559smerror(seekpt, cp)
560#ifdef lint
561 char *seekpt;
562#else
563 int seekpt;
564#endif
565 char *cp;
566{
567
568 if (seekpt == 0)
569 return;
570 merror1(seekpt);
571 if (inopen && CE)
572 vclreol();
573 if (SO && SE)
574 putpad(SO);
575 lprintf(mesg(linebuf), cp);
576 if (SO && SE)
577 putpad(SE);
578}
579
580#define std_nerrs (sizeof std_errlist / sizeof std_errlist[0])
581
582#define error(i) i
583
584#ifdef lint
585char *std_errlist[] = {
586#else
587short std_errlist[] = {
588#endif
589 error("Error 0"),
590 error("Not super-user"),
591 error("No such file or directory"),
592 error("No such process"),
593 error("Interrupted system call"),
594 error("Physical I/O error"),
595 error("No such device or address"),
596 error("Argument list too long"),
597 error("Exec format error"),
598 error("Bad file number"),
599 error("No children"),
600 error("No more processes"),
601 error("Not enough core"),
602 error("Permission denied"),
603 error("Bad address"),
604 error("Block device required"),
605 error("Mount device busy"),
606 error("File exists"),
607 error("Cross-device link"),
608 error("No such device"),
609 error("Not a directory"),
610 error("Is a directory"),
611 error("Invalid argument"),
612 error("File table overflow"),
613 error("Too many open files"),
614 error("Not a typewriter"),
615 error("Text file busy"),
616 error("File too large"),
617 error("No space left on device"),
618 error("Illegal seek"),
619 error("Read-only file system"),
620 error("Too many links"),
621 error("Broken pipe")
622#ifndef QUOTA
623 , error("Math argument")
624 , error("Result too large")
625#else
626 , error("Quota exceeded")
627#endif
628};
629
630#undef error
631
632char *
633strend(cp)
634 register char *cp;
635{
636
637 while (*cp)
638 cp++;
639 return (cp);
640}
641
642strcLIN(dp)
643 char *dp;
644{
645
646 CP(linebuf, dp);
647}
648
649syserror()
650{
651 register int e = errno;
652
653 dirtcnt = 0;
654 putchar(' ');
655 if (e >= 0 && errno <= std_nerrs)
656 error(std_errlist[e]);
657 else
658 error("System error %d", e);
659}
660
661char *
662vfindcol(i)
663 int i;
664{
665 register char *cp;
666 register int (*OO)() = Outchar;
667
668 Outchar = qcount;
669 ignore(qcolumn(linebuf - 1, NOSTR));
670 for (cp = linebuf; *cp && vcntcol < i; cp++)
671 putchar(*cp);
672 if (cp != linebuf)
673 cp--;
674 Outchar = OO;
675 return (cp);
676}
677
678char *
679vskipwh(cp)
680 register char *cp;
681{
682
683 while (iswhite(*cp) && cp[1])
684 cp++;
685 return (cp);
686}
687
688
689char *
690vpastwh(cp)
691 register char *cp;
692{
693
694 while (iswhite(*cp))
695 cp++;
696 return (cp);
697}
698
699whitecnt(cp)
700 register char *cp;
701{
702 register int i;
703
704 i = 0;
705 for (;;)
706 switch (*cp++) {
707
708 case '\t':
709 i += value(TABSTOP) - i % value(TABSTOP);
710 break;
711
712 case ' ':
713 i++;
714 break;
715
716 default:
717 return (i);
718 }
719}
720
721#ifdef lint
722Ignore(a)
723 char *a;
724{
725
726 a = a;
727}
728
729Ignorf(a)
730 int (*a)();
731{
732
733 a = a;
734}
735#endif
736
737markit(addr)
738 line *addr;
739{
740
741 if (addr != dot && addr >= one && addr <= dol)
742 markDOT();
743}
744