Subversion Repositories planix.SVN

Rev

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