Subversion Repositories planix.SVN

Rev

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