BSD 2 development
[unix-history] / src / ex / ex_subr.c
CommitLineData
851aa263
BJ
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]); markp <= &names['z'-'a'+1]; markp++)
431 if (*markp == *addr)
432 *markp = n;
433 *addr = n;
434}
435
436char *
437plural(i)
438 long i;
439{
440
441 return (i == 1 ? "" : "s");
442}
443
444int qcount();
445short vcntcol;
446
447qcolumn(lim, gp)
448 register char *lim, *gp;
449{
450 register int x;
451 int (*OO)();
452
453 OO = Outchar;
454 Outchar = qcount;
455 vcntcol = 0;
456 if (lim != NULL)
457 x = lim[1], lim[1] = 0;
458 pline(0);
459 if (lim != NULL)
460 lim[1] = x;
461 if (gp)
462 while (*gp)
463 putchar(*gp++);
464 Outchar = OO;
465 return (vcntcol);
466}
467
468int
469qcount(c)
470 int c;
471{
472
473 if (c == '\t') {
474 vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
475 return;
476 }
477 vcntcol++;
478}
479
480reverse(a1, a2)
481 register line *a1, *a2;
482{
483 register line t;
484
485 for (;;) {
486 t = *--a2;
487 if (a2 <= a1)
488 return;
489 *a2 = *a1;
490 *a1++ = t;
491 }
492}
493
494save(a1, a2)
495 line *a1;
496 register line *a2;
497{
498 register int more;
499
500 undkind = UNDNONE;
501 undadot = dot;
502 more = (a2 - a1 + 1) - (unddol - dol);
503 while (more > (endcore - truedol))
504 if (morelines() < 0)
505 error("Out of memory@saving lines for undo - try using ed or re");
506 if (more)
507 (*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
508 (truedol - unddol));
509 unddol += more;
510 truedol += more;
511 copyw(dol + 1, a1, a2 - a1 + 1);
512 undkind = UNDALL;
513 unddel = a1 - 1;
514 undap1 = a1;
515 undap2 = a2 + 1;
516}
517
518save12()
519{
520
521 save(addr1, addr2);
522}
523
524saveall()
525{
526
527 save(one, dol);
528}
529
530span()
531{
532
533 return (addr2 - addr1 + 1);
534}
535
536sync()
537{
538
539 chng = 0;
540 tchng = 0;
541 xchng = 0;
542}
543
544
545skipwh()
546{
547 register int wh;
548
549 wh = 0;
550 while (iswhite(peekchar())) {
551 wh++;
552 ignchar();
553 }
554 return (wh);
555}
556
557/*VARARGS2*/
558smerror(seekpt, cp)
559#ifdef lint
560 char *seekpt;
561#else
562 int seekpt;
563#endif
564 char *cp;
565{
566
567 if (seekpt == 0)
568 return;
569 merror1(seekpt);
570 if (inopen && CE)
571 vclreol();
572 if (SO && SE)
573 putpad(SO);
574 lprintf(mesg(linebuf), cp);
575 if (SO && SE)
576 putpad(SE);
577}
578
579#define std_nerrs (sizeof std_errlist / sizeof std_errlist[0])
580
581#define error(i) i
582
583#ifdef lint
584char *std_errlist[] = {
585#else
586short std_errlist[] = {
587#endif
588 error("Error 0"),
589 error("Not super-user"),
590 error("No such file or directory"),
591 error("No such process"),
592 error("Interrupted system call"),
593 error("Physical I/O error"),
594 error("No such device or address"),
595 error("Argument list too long"),
596 error("Exec format error"),
597 error("Bad file number"),
598 error("No children"),
599 error("No more processes"),
600 error("Not enough core"),
601 error("Permission denied"),
602 error("Bad address"),
603 error("Block device required"),
604 error("Mount device busy"),
605 error("File exists"),
606 error("Cross-device link"),
607 error("No such device"),
608 error("Not a directory"),
609 error("Is a directory"),
610 error("Invalid argument"),
611 error("File table overflow"),
612 error("Too many open files"),
613 error("Not a typewriter"),
614 error("Text file busy"),
615 error("File too large"),
616 error("No space left on device"),
617 error("Illegal seek"),
618 error("Read-only file system"),
619 error("Too many links"),
620 error("Broken pipe")
621#ifndef QUOTA
622 , error("Math argument")
623 , error("Result too large")
624#else
625 , error("Quota exceeded")
626#endif
627};
628
629#undef error
630
631char *
632strend(cp)
633 register char *cp;
634{
635
636 while (*cp)
637 cp++;
638 return (cp);
639}
640
641strcLIN(dp)
642 char *dp;
643{
644
645 CP(linebuf, dp);
646}
647
648syserror()
649{
650 register int e = errno;
651
652 dirtcnt = 0;
653 putchar(' ');
654 if (e >= 0 && errno <= std_nerrs)
655 error(std_errlist[e]);
656 else
657 error("System error %d", e);
658}
659
660char *
661vfindcol(i)
662 int i;
663{
664 register char *cp;
665 register int (*OO)() = Outchar;
666
667 Outchar = qcount;
668 ignore(qcolumn(linebuf - 1, NOSTR));
669 for (cp = linebuf; *cp && vcntcol < i; cp++)
670 putchar(*cp);
671 if (cp != linebuf)
672 cp--;
673 Outchar = OO;
674 return (cp);
675}
676
677char *
678vskipwh(cp)
679 register char *cp;
680{
681
682 while (iswhite(*cp) && cp[1])
683 cp++;
684 return (cp);
685}
686
687
688char *
689vpastwh(cp)
690 register char *cp;
691{
692
693 while (iswhite(*cp))
694 cp++;
695 return (cp);
696}
697
698whitecnt(cp)
699 register char *cp;
700{
701 register int i;
702
703 i = 0;
704 for (;;)
705 switch (*cp++) {
706
707 case '\t':
708 i += value(TABSTOP) - i % value(TABSTOP);
709 break;
710
711 case ' ':
712 i++;
713 break;
714
715 default:
716 return (i);
717 }
718}
719
720#ifdef lint
721Ignore(a)
722 char *a;
723{
724
725 a = a;
726}
727
728Ignorf(a)
729 int (*a)();
730{
731
732 a = a;
733}
734#endif
735
736markit(addr)
737 line *addr;
738{
739
740 if (addr != dot && addr >= one && addr <= dol)
741 markDOT();
742}
743