Subversion Repositories planix.SVN

Rev

Rev 118 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
105 7u83 1
/*
2
 * Copyright (c) 1980 Regents of the University of California.
3
 * All rights reserved.  The Berkeley software License Agreement
4
 * specifies the terms and conditions for redistribution.
5
 */
6
 
7
#if	!defined(lint) && defined(DOSCCS)
8
static char *sccsid = "@(#)ex_subr.c	7.10.1 (2.11BSD) 1996/3/22";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_re.h"
13
#include "ex_tty.h"
14
#include "ex_vis.h"
15
 
16
/*
17
 * Random routines, in alphabetical order.
18
 */
19
 
20
any(c, s)
21
	int c;
22
	register char *s;
23
{
24
	register int x;
25
 
26
	while (x = *s++)
27
		if (x == c)
28
			return (1);
29
	return (0);
30
}
31
 
32
backtab(i)
33
	register int i;
34
{
35
	register int j;
36
 
37
	j = i % value(SHIFTWIDTH);
38
	if (j == 0)
39
		j = value(SHIFTWIDTH);
40
	i -= j;
41
	if (i < 0)
42
		i = 0;
43
	return (i);
44
}
45
 
46
change()
47
{
48
 
49
	tchng++;
50
	chng = tchng;
51
}
52
 
53
/*
54
 * Column returns the number of
55
 * columns occupied by printing the
56
 * characters through position cp of the
57
 * current line.
58
 */
59
column(cp)
60
	register char *cp;
61
{
62
 
63
	if (cp == 0)
64
		cp = &linebuf[LBSIZE - 2];
65
	return (qcolumn(cp, (char *) 0));
66
}
67
 
68
/*
69
 * Ignore a comment to the end of the line.
70
 * This routine eats the trailing newline so don't call newline().
71
 */
72
comment()
73
{
74
	register int c;
75
 
76
	do {
77
		c = getchar();
78
	} while (c != '\n' && c != EOF);
79
	if (c == EOF)
80
		ungetchar(c);
81
}
82
 
83
Copy(to, from, size)
84
	register char *from, *to;
85
	register int size;
86
{
87
 
88
	if (size > 0)
89
		do
90
			*to++ = *from++;
91
		while (--size > 0);
92
}
93
 
94
copyw(to, from, size)
95
	register line *from, *to;
96
	register int size;
97
{
98
 
99
	if (size > 0)
100
		do
101
			*to++ = *from++;
102
		while (--size > 0);
103
}
104
 
105
copywR(to, from, size)
106
	register line *from, *to;
107
	register int size;
108
{
109
 
110
	while (--size >= 0)
111
		to[size] = from[size];
112
}
113
 
114
ctlof(c)
115
	int c;
116
{
117
 
118
	return (c == TRIM ? '?' : c | ('A' - 1));
119
}
120
 
121
dingdong()
122
{
123
 
124
	if (VB)
125
		putpad(VB);
126
	else if (value(ERRORBELLS))
127
		putch('\207');
128
}
129
 
130
fixindent(indent)
131
	int indent;
132
{
133
	register int i;
134
	register char *cp;
135
 
136
	i = whitecnt(genbuf);
137
	cp = vpastwh(genbuf);
138
	if (*cp == 0 && i == indent && linebuf[0] == 0) {
139
		genbuf[0] = 0;
140
		return (i);
141
	}
115 7u83 142
	CP(genindent(i), cp);
105 7u83 143
	return (i);
144
}
145
 
146
filioerr(cp)
147
	char *cp;
148
{
149
	register int oerrno = errno;
150
 
151
	lprintf("\"%s\"", cp);
152
	errno = oerrno;
153
	syserror();
154
}
155
 
156
char *
157
genindent(indent)
158
	register int indent;
159
{
160
	register char *cp;
161
 
162
	for (cp = genbuf; indent >= value(TABSTOP); indent -= value(TABSTOP))
163
		*cp++ = '\t';
164
	for (; indent > 0; indent--)
165
		*cp++ = ' ';
166
	return (cp);
167
}
168
 
169
getDOT()
170
{
171
 
118 7u83 172
	ex_getline(*dot);
105 7u83 173
}
174
 
175
line *
176
getmark(c)
177
	register int c;
178
{
179
	register line *addr;
180
 
181
	for (addr = one; addr <= dol; addr++)
182
		if (names[c - 'a'] == (*addr &~ 01)) {
183
			return (addr);
184
		}
185
	return (0);
186
}
187
 
188
getn(cp)
189
	register char *cp;
190
{
191
	register int i = 0;
192
 
193
	while (isdigit(*cp))
194
		i = i * 10 + *cp++ - '0';
195
	if (*cp)
196
		return (0);
197
	return (i);
198
}
199
 
200
ignnEOF()
201
{
202
	register int c = getchar();
203
 
204
	if (c == EOF)
205
		ungetchar(c);
206
	else if (c=='"')
207
		comment();
208
}
209
 
119 7u83 210
 
211
int
105 7u83 212
iswhite(c)
213
	int c;
214
{
215
	return (c == ' ' || c == '\t');
216
}
217
 
218
junk(c)
219
	register int c;
220
{
221
 
222
	if (c && !value(BEAUTIFY))
223
		return (0);
224
	if (c >= ' ' && c != TRIM)
225
		return (0);
226
#ifdef	ISO
227
	if (c & QUOTE && !niso(c))
228
		return (0);
229
#endif
230
	switch (c) {
231
 
232
	case '\t':
233
	case '\n':
234
	case '\f':
235
		return (0);
236
 
237
	default:
238
		return (1);
239
	}
240
}
241
 
242
killed()
243
{
244
 
245
	killcnt(addr2 - addr1 + 1);
246
}
247
 
248
killcnt(cnt)
249
	register int cnt;
250
{
251
 
252
	if (inopen) {
253
		notecnt = cnt;
254
		notenam = notesgn = "";
255
		return;
256
	}
257
	if (!notable(cnt))
258
		return;
259
	printf("%d lines", cnt);
260
	if (value(TERSE) == 0) {
261
		printf(" %c%s", Command[0] | ' ', Command + 1);
262
		if (Command[strlen(Command) - 1] != 'e')
263
			putchar('e');
264
		putchar('d');
265
	}
266
	putNFL();
267
}
268
 
269
lineno(a)
270
	line *a;
271
{
272
 
273
	return (a - zero);
274
}
275
 
276
lineDOL()
277
{
278
 
279
	return (lineno(dol));
280
}
281
 
282
lineDOT()
283
{
284
 
285
	return (lineno(dot));
286
}
287
 
288
markDOT()
289
{
290
 
291
	markpr(dot);
292
}
293
 
294
markpr(which)
295
	line *which;
296
{
297
 
298
	if ((inglobal == 0 || inopen) && which <= endcore) {
299
		names['z'-'a'+1] = *which & ~01;
300
		if (inopen)
301
			ncols['z'-'a'+1] = cursor;
302
	}
303
}
304
 
305
markreg(c)
306
	register int c;
307
{
308
 
309
	if (c == '\'' || c == '`')
310
		return ('z' + 1);
311
	if (c >= 'a' && c <= 'z')
312
		return (c);
313
	return (0);
314
}
315
 
316
/*
317
 * Mesg decodes the terse/verbose strings. Thus
318
 *	'xxx@yyy' -> 'xxx' if terse, else 'xxx yyy'
319
 *	'xxx|yyy' -> 'xxx' if terse, else 'yyy'
320
 * All others map to themselves.
321
 */
322
char *
323
mesg(str)
324
	register char *str;
325
{
326
	register char *cp;
327
 
328
	str = strcpy(genbuf, str);
329
	for (cp = str; *cp; cp++)
330
		switch (*cp) {
331
 
332
		case '@':
333
			if (value(TERSE))
334
				*cp = 0;
335
			else
336
				*cp = ' ';
337
			break;
338
 
339
		case '|':
340
			if (value(TERSE) == 0)
341
				return (cp + 1);
342
			*cp = 0;
343
			break;
344
		}
345
	return (str);
346
}
347
 
348
/*VARARGS2*/
349
merror(seekpt, i)
350
#ifdef VMUNIX
351
	char *seekpt;
352
#else
353
# ifdef lint
354
	char *seekpt;
355
# else
356
	int seekpt;
357
# endif
358
#endif
359
	int i;
360
{
361
	register char *cp = linebuf;
362
 
363
	if (seekpt == 0)
364
		return;
365
	merror1(seekpt);
366
	if (*cp == '\n')
367
		putnl(), cp++;
368
	if (inopen > 0 && CE)
369
		vclreol();
370
	if (SO && SE)
371
		putpad(SO);
372
	printf(mesg(cp), i);
373
	if (SO && SE)
374
		putpad(SE);
375
}
376
 
377
merror1(seekpt)
378
#ifdef VMUNIX
379
	char *seekpt;
380
#else
381
# ifdef lint
382
	char *seekpt;
383
# else
384
	int seekpt;
385
# endif
386
#endif
387
{
388
 
389
#ifdef VMUNIX
390
	strcpy(linebuf, seekpt);
391
#else
392
	lseek(erfile, (long) seekpt, 0);
393
	if (read(erfile, linebuf, 128) < 2)
115 7u83 394
		CP(linebuf, "ERROR");
105 7u83 395
#endif
396
}
397
 
398
morelines()
399
{
400
 
401
	if ((int) sbrk(1024 * sizeof (line)) == -1)
402
		return (-1);
403
	endcore += 1024;
404
	return (0);
405
}
406
 
407
nonzero()
408
{
409
 
410
	if (addr1 == zero) {
411
		notempty();
412
		error("Nonzero address required@on this command");
413
	}
414
}
415
 
416
notable(i)
417
	int i;
418
{
419
 
420
	return (hush == 0 && !inglobal && i > value(REPORT));
421
}
422
 
423
 
424
notempty()
425
{
426
 
427
	if (dol == zero)
428
		error("No lines@in the buffer");
429
}
430
 
431
 
432
netchHAD(cnt)
433
	int cnt;
434
{
435
 
436
	netchange(lineDOL() - cnt);
437
}
438
 
439
netchange(i)
440
	register int i;
441
{
442
	register char *cp;
443
 
444
	if (i > 0)
445
		notesgn = cp = "more ";
446
	else
447
		notesgn = cp = "fewer ", i = -i;
448
	if (inopen) {
449
		notecnt = i;
450
		notenam = "";
451
		return;
452
	}
453
	if (!notable(i))
454
		return;
455
	printf(mesg("%d %slines@in file after %s"), i, cp, Command);
456
	putNFL();
457
}
458
 
459
putmark(addr)
460
	line *addr;
461
{
462
 
463
	putmk1(addr, putline());
464
}
465
 
466
putmk1(addr, n)
467
	register line *addr;
468
	int n;
469
{
470
	register line *markp;
471
	register oldglobmk;
472
 
473
	oldglobmk = *addr & 1;
474
	*addr &= ~1;
475
	for (markp = (anymarks ? names : &names['z'-'a'+1]);
476
	  markp <= &names['z'-'a'+1]; markp++)
477
		if (*markp == *addr)
478
			*markp = n;
479
	*addr = n | oldglobmk;
480
}
481
 
482
char *
483
plural(i)
484
	long i;
485
{
486
 
487
	return (i == 1 ? "" : "s");
488
}
489
 
115 7u83 490
int	qcount();
105 7u83 491
short	vcntcol;
492
 
493
qcolumn(lim, gp)
494
	register char *lim, *gp;
495
{
496
	register int x;
115 7u83 497
	int (*OO)();
105 7u83 498
 
499
	OO = Outchar;
500
	Outchar = qcount;
501
	vcntcol = 0;
502
	if (lim != NULL)
503
		x = lim[1], lim[1] = 0;
504
	pline(0);
505
	if (lim != NULL)
506
		lim[1] = x;
507
	if (gp)
508
		while (*gp)
509
			putchar(*gp++);
510
	Outchar = OO;
511
	return (vcntcol);
512
}
513
 
115 7u83 514
int
105 7u83 515
qcount(c)
516
	int c;
517
{
518
 
519
	if (c == '\t') {
520
		vcntcol += value(TABSTOP) - vcntcol % value(TABSTOP);
521
		return;
522
	}
523
	vcntcol++;
524
}
525
 
526
reverse(a1, a2)
527
	register line *a1, *a2;
528
{
529
	register line t;
530
 
531
	for (;;) {
532
		t = *--a2;
533
		if (a2 <= a1)
534
			return;
535
		*a2 = *a1;
536
		*a1++ = t;
537
	}
538
}
539
 
540
save(a1, a2)
541
	line *a1;
542
	register line *a2;
543
{
544
	register int more;
545
 
546
	if (!FIXUNDO)
547
		return;
548
#ifdef TRACE
549
	if (trace)
550
		vudump("before save");
551
#endif
552
	undkind = UNDNONE;
553
	undadot = dot;
554
	more = (a2 - a1 + 1) - (unddol - dol);
555
	while (more > (endcore - truedol))
556
		if (morelines() < 0)
557
			error("Out of memory@saving lines for undo - try using ed");
558
	if (more)
559
		(*(more > 0 ? copywR : copyw))(unddol + more + 1, unddol + 1,
560
		    (truedol - unddol));
561
	unddol += more;
562
	truedol += more;
563
	copyw(dol + 1, a1, a2 - a1 + 1);
564
	undkind = UNDALL;
565
	unddel = a1 - 1;
566
	undap1 = a1;
567
	undap2 = a2 + 1;
568
#ifdef TRACE
569
	if (trace)
570
		vudump("after save");
571
#endif
572
}
573
 
574
save12()
575
{
576
 
577
	save(addr1, addr2);
578
}
579
 
580
saveall()
581
{
582
 
583
	save(one, dol);
584
}
585
 
586
span()
587
{
588
 
589
	return (addr2 - addr1 + 1);
590
}
591
 
592
sync()
593
{
594
 
595
	chng = 0;
596
	tchng = 0;
597
	xchng = 0;
598
}
599
 
600
 
601
skipwh()
602
{
603
	register int wh;
604
 
605
	wh = 0;
606
	while (iswhite(peekchar())) {
607
		wh++;
608
		ignchar();
609
	}
610
	return (wh);
611
}
612
 
613
/*VARARGS2*/
614
smerror(seekpt, cp)
615
#ifdef lint
616
	char *seekpt;
617
#else
618
	int seekpt;
619
#endif
620
	char *cp;
621
{
622
 
623
	if (seekpt == 0)
624
		return;
625
	merror1(seekpt);
626
	if (inopen && CE)
627
		vclreol();
628
	if (SO && SE)
629
		putpad(SO);
630
	lprintf(mesg(linebuf), cp);
631
	if (SO && SE)
632
		putpad(SE);
633
}
634
 
635
char *
636
strend(cp)
637
	register char *cp;
638
{
639
 
640
	while (*cp)
641
		cp++;
642
	return (cp);
643
}
644
 
645
strcLIN(dp)
646
	char *dp;
647
{
648
 
115 7u83 649
	CP(linebuf, dp);
105 7u83 650
}
651
 
652
syserror()
653
{
654
 
655
	dirtcnt = 0;
656
	putchar(' ');
657
	error("%s", strerror(errno));
658
}
659
 
660
/*
661
 * Return the column number that results from being in column col and
662
 * hitting a tab, where tabs are set every ts columns.  Work right for
663
 * the case where col > COLUMNS, even if ts does not divide COLUMNS.
664
 */
665
tabcol(col, ts)
666
int col, ts;
667
{
668
	int offset, result;
669
 
670
	if (col >= COLUMNS) {
671
		offset = COLUMNS * (col/COLUMNS);
672
		col -= offset;
673
	} else
674
		offset = 0;
675
	result = col + ts - (col % ts) + offset;
676
	return (result);
677
}
678
 
679
char *
680
vfindcol(i)
681
	int i;
682
{
683
	register char *cp;
115 7u83 684
	register int (*OO)() = Outchar;
105 7u83 685
 
686
	Outchar = qcount;
687
	ignore(qcolumn(linebuf - 1, NOSTR));
688
	for (cp = linebuf; *cp && vcntcol < i; cp++)
689
		putchar(*cp);
690
	if (cp != linebuf)
691
		cp--;
692
	Outchar = OO;
693
	return (cp);
694
}
695
 
696
char *
697
vskipwh(cp)
698
	register char *cp;
699
{
700
 
701
	while (iswhite(*cp) && cp[1])
702
		cp++;
703
	return (cp);
704
}
705
 
706
 
707
char *
708
vpastwh(cp)
709
	register char *cp;
710
{
711
 
712
	while (iswhite(*cp))
713
		cp++;
714
	return (cp);
715
}
716
 
717
whitecnt(cp)
718
	register char *cp;
719
{
720
	register int i;
721
 
722
	i = 0;
723
	for (;;)
724
		switch (*cp++) {
725
 
726
		case '\t':
727
			i += value(TABSTOP) - i % value(TABSTOP);
728
			break;
729
 
730
		case ' ':
731
			i++;
732
			break;
733
 
734
		default:
735
			return (i);
736
		}
737
}
738
 
739
#ifdef lint
740
Ignore(a)
741
	char *a;
742
{
743
 
744
	a = a;
745
}
746
 
747
Ignorf(a)
748
	int (*a)();
749
{
750
 
751
	a = a;
752
}
753
#endif
754
 
755
markit(addr)
756
	line *addr;
757
{
758
 
759
	if (addr != dot && addr >= one && addr <= dol)
760
		markDOT();
761
}
762
 
763
/*
764
 * The following code is defensive programming against a bug in the
765
 * pdp-11 overlay implementation.  Sometimes it goes nuts and asks
766
 * for an overlay with some garbage number, which generates an emt
767
 * trap.  This is a less than elegant solution, but it is somewhat
768
 * better than core dumping and losing your work, leaving your tty
769
 * in a weird state, etc.
770
 */
771
int _ovno;
772
onemt()
773
{
774
	int oovno;
775
 
776
#ifdef	SIGEMT
777
	signal(SIGEMT, onemt);
778
#endif
779
	oovno = _ovno;
780
	/* 2 and 3 are valid on 11/40 type vi, so */
781
	if (_ovno < 0 || _ovno > 3)
782
		_ovno = 0;
783
	error("emt trap, _ovno is %d @ - try again");
784
}
785
 
786
/*
787
 * When a hangup occurs our actions are similar to a preserve
788
 * command.  If the buffer has not been [Modified], then we do
789
 * nothing but remove the temporary files and exit.
790
 * Otherwise, we sync the temp file and then attempt a preserve.
791
 * If the preserve succeeds, we unlink our temp files.
792
 * If the preserve fails, we leave the temp files as they are
793
 * as they are a backup even without preservation if they
794
 * are not removed.
795
 */
106 7u83 796
void
105 7u83 797
onhup()
798
{
799
 
800
	/*
801
	 * USG tty driver can send multiple HUP's!!
802
	 */
803
	signal(SIGINT, SIG_IGN);
804
	signal(SIGHUP, SIG_IGN);
805
	if (chng == 0) {
806
		cleanup(1);
807
		exit(0);
808
	}
809
	if (setexit() == 0) {
810
		if (preserve()) {
811
			cleanup(1);
812
			exit(0);
813
		}
814
	}
815
	exit(1);
816
}
817
 
818
/*
819
 * An interrupt occurred.  Drain any output which
820
 * is still in the output buffering pipeline.
821
 * Catch interrupts again.  Unless we are in visual
822
 * reset the output state (out of -nl mode, e.g).
823
 * Then like a normal error (with the \n before Interrupt
824
 * suppressed in visual mode).
825
 */
106 7u83 826
void
105 7u83 827
onintr()
828
{
829
 
830
#ifndef CBREAK
831
	signal(SIGINT, onintr);
832
#else
833
	signal(SIGINT, inopen ? vintr : onintr);
834
#endif
835
	alarm(0);	/* in case we were called from map */
836
	draino();
837
	if (!inopen) {
838
		pstop();
839
		setlastchar('\n');
840
#ifdef CBREAK
841
	}
842
#else
843
	} else
844
		vraw();
845
#endif
846
	error("\nInterrupt" + inopen);
847
}
848
 
849
/*
850
 * If we are interruptible, enable interrupts again.
851
 * In some critical sections we turn interrupts off,
852
 * but not very often.
853
 */
854
setrupt()
855
{
856
 
857
	if (ruptible) {
858
#ifndef CBREAK
859
		signal(SIGINT, onintr);
860
#else
861
		signal(SIGINT, inopen ? vintr : onintr);
862
#endif
863
#ifdef SIGTSTP
864
		if (dosusp)
865
			signal(SIGTSTP, onsusp);
866
#endif
867
	}
868
}
869
 
870
preserve()
871
{
872
 
873
#ifdef VMUNIX
874
	tflush();
875
#endif
876
	synctmp();
877
	pid = fork();
878
	if (pid < 0)
879
		return (0);
880
	if (pid == 0) {
881
		close(0);
882
		dup(tfile);
883
		execl(EXPRESERVE, "expreserve", (char *) 0);
884
		exit(1);
885
	}
886
	waitfor();
887
	if (rpid == pid && status == 0)
888
		return (1);
889
	return (0);
890
}
891
 
892
#ifndef V6
108 7u83 893
/* XXX
105 7u83 894
exit(i)
895
	int i;
896
{
897
 
898
# ifdef TRACE
899
	if (trace)
900
		fclose(trace);
901
# endif
902
	_exit(i);
903
}
108 7u83 904
*/
905
 
105 7u83 906
#endif
907
 
908
#ifdef SIGTSTP
909
/*
910
 * We have just gotten a susp.  Suspend and prepare to resume.
911
 */
106 7u83 912
void
105 7u83 913
onsusp()
914
{
915
	ttymode f;
916
	int omask;
917
	struct winsize win;
918
 
919
	f = setty(normf);
920
	vnfl();
921
	putpad(TE);
922
	flush();
923
 
108 7u83 924
/*XXX	(void) sigsetmask(0L); */
105 7u83 925
	signal(SIGTSTP, SIG_DFL);
926
	kill(0, SIGTSTP);
927
 
928
	/* the pc stops here */
929
 
930
	signal(SIGTSTP, onsusp);
931
	vcontin(0);
932
	setty(f);
933
	if (!inopen)
934
		error(0);
935
	else {
106 7u83 936
		/* XXX */
937
/*		if (ioctl(0, TIOCGWINSZ, &win) >= 0)
105 7u83 938
			if (win.ws_row != winsz.ws_row ||
939
			    win.ws_col != winsz.ws_col)
940
				winch();
941
		if (vcnt < 0) {
942
			vcnt = -vcnt;
943
			if (state == VISUAL)
944
				vclear();
945
			else if (state == CRTOPEN)
946
				vcnt = 0;
947
		}
948
		vdirty(0, LINES);
106 7u83 949
*/		vrepaint(cursor);
105 7u83 950
	}
951
}
952
#endif