Subversion Repositories planix.SVN

Rev

Rev 105 | 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_temp.c	7.5.1.1 (Berkeley) 8/12/86";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_temp.h"
13
#include "ex_vis.h"
14
#include "ex_tty.h"
15
 
113 7u83 16
void rbflush();
17
void  blkio(short , char * , int (*f)());
18
 
105 7u83 19
/*
20
 * Editor temporary file routines.
21
 * Very similar to those of ed, except uses 2 input buffers.
22
 */
23
#define	READ	0
24
#define	WRITE	1
25
 
26
char	tfname[40];
27
char	rfname[40];
28
int	havetmp;
29
short	tfile = -1;
30
short	rfile = -1;
31
 
113 7u83 32
void
105 7u83 33
fileinit()
34
{
35
	register char *p;
36
	register int i, j;
37
	struct stat stbuf;
38
 
39
	if (tline == INCRMT * (HBLKS+2))
40
		return;
41
	cleanup(0);
42
	close(tfile);
43
	tline = INCRMT * (HBLKS+2);
44
	blocks[0] = HBLKS;
45
	blocks[1] = HBLKS+1;
46
	blocks[2] = -1;
47
	dirtcnt = 0;
48
	iblock = -1;
49
	iblock2 = -1;
50
	oblock = -1;
113 7u83 51
	strcpy(tfname, svalue(DIRECTORY));
105 7u83 52
	if (stat(tfname, &stbuf)) {
53
dumbness:
54
		if (setexit() == 0)
55
			filioerr(tfname);
56
		else
57
			putNFL();
58
		cleanup(1);
59
		exit(1);
60
	}
61
	if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
62
		errno = ENOTDIR;
63
		goto dumbness;
64
	}
65
	ichanged = 0;
66
	ichang2 = 0;
67
	ignore(strcat(tfname, "/ExXXXXX"));
68
	for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
69
		*--p = j % 10 | '0';
70
	tfile = creat(tfname, 0600);
71
	if (tfile < 0)
72
		goto dumbness;
73
#ifdef VMUNIX
74
	{
75
		extern stilinc;		/* see below */
76
		stilinc = 0;
77
	}
78
#endif
79
	havetmp = 1;
80
	close(tfile);
81
	tfile = open(tfname, 2);
82
	if (tfile < 0)
83
		goto dumbness;
84
/* 	brk((char *)fendcore); */
85
}
86
 
87
cleanup(all)
88
	bool all;
89
{
90
	if (all) {
91
		putpad(TE);
92
		flush();
93
	}
94
	if (havetmp)
95
		unlink(tfname);
96
	havetmp = 0;
97
	if (all && rfile >= 0) {
98
		unlink(rfname);
99
		close(rfile);
100
		rfile = -1;
101
	}
102
}
103
 
104
getline(tl)
105
	line tl;
106
{
107
	register char *bp, *lp;
108
	register int nl;
109
 
110
	lp = linebuf;
111
	bp = getblock(tl, READ);
112
	nl = nleft;
113
	tl &= ~OFFMSK;
114
	while (*lp++ = *bp++)
115
		if (--nl == 0) {
116
			bp = getblock(tl += INCRMT, READ);
117
			nl = nleft;
118
		}
119
}
120
 
121
putline()
122
{
123
	register char *bp, *lp;
124
	register int nl;
125
	line tl;
126
 
127
	dirtcnt++;
128
	lp = linebuf;
129
	change();
130
	tl = tline;
131
	bp = getblock(tl, WRITE);
132
	nl = nleft;
133
	tl &= ~OFFMSK;
134
	while (*bp = *lp++) {
135
		if (*bp++ == '\n') {
136
			*--bp = 0;
137
			linebp = lp;
138
			break;
139
		}
140
		if (--nl == 0) {
141
			bp = getblock(tl += INCRMT, WRITE);
142
			nl = nleft;
143
		}
144
	}
145
	tl = tline;
146
	tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
147
	return (tl);
148
}
149
 
150
int	read();
151
int	write();
152
 
153
char *
154
getblock(atl, iof)
155
	line atl;
156
	int iof;
157
{
158
	register int bno, off;
159
        register char *p1, *p2;
160
        register int n;
161
 
162
	bno = (atl >> OFFBTS) & BLKMSK;
163
	off = (atl << SHFT) & LBTMSK;
164
	if (bno >= NMBLKS)
165
		error(" Tmp file too large");
166
	nleft = BUFSIZ - off;
167
	if (bno == iblock) {
168
		ichanged |= iof;
169
		hitin2 = 0;
170
		return (ibuff + off);
171
	}
172
	if (bno == iblock2) {
173
		ichang2 |= iof;
174
		hitin2 = 1;
175
		return (ibuff2 + off);
176
	}
177
	if (bno == oblock)
178
		return (obuff + off);
179
	if (iof == READ) {
180
		if (hitin2 == 0) {
181
			if (ichang2) {
182
				blkio(iblock2, ibuff2, write);
183
			}
184
			ichang2 = 0;
185
			iblock2 = bno;
186
			blkio(bno, ibuff2, read);
187
			hitin2 = 1;
188
			return (ibuff2 + off);
189
		}
190
		hitin2 = 0;
191
		if (ichanged) {
192
			blkio(iblock, ibuff, write);
193
		}
194
		ichanged = 0;
195
		iblock = bno;
196
		blkio(bno, ibuff, read);
197
		return (ibuff + off);
198
	}
199
	if (oblock >= 0) {
200
			blkio(oblock, obuff, write);
201
	}
202
	oblock = bno;
203
	return (obuff + off);
204
}
205
 
206
#ifdef	VMUNIX
207
#define	INCORB	64
208
char	incorb[INCORB+1][BUFSIZ];
209
#define	pagrnd(a)	((char *)(((int)a)&~(BUFSIZ-1)))
210
int	stilinc;	/* up to here not written yet */
211
#endif
212
 
113 7u83 213
/*void
105 7u83 214
blkio(b, buf, iofcn)
215
	short b;
216
	char *buf;
113 7u83 217
	int (*iofcn)(); */
218
void  blkio(short b, char *buf , int (*iofcn)())
105 7u83 219
{
220
 
221
#ifdef VMUNIX
222
	if (b < INCORB) {
223
		if (iofcn == read) {
224
			bcopy(pagrnd(incorb[b+1]), buf, BUFSIZ);
225
			return;
226
		}
227
		bcopy(buf, pagrnd(incorb[b+1]), BUFSIZ);
228
		if (laste) {
229
			if (b >= stilinc)
230
				stilinc = b + 1;
231
			return;
232
		}
233
	} else if (stilinc)
234
		tflush();
235
#endif
236
	lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
237
	if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
238
		filioerr(tfname);
239
}
240
 
241
#ifdef VMUNIX
242
tlaste()
243
{
244
 
245
	if (stilinc)
246
		dirtcnt = 0;
247
}
248
 
249
tflush()
250
{
251
	int i = stilinc;
252
 
253
	stilinc = 0;
254
	lseek(tfile, (long) 0, 0);
255
	if (write(tfile, pagrnd(incorb[1]), i * BUFSIZ) != (i * BUFSIZ))
256
		filioerr(tfname);
257
}
258
#endif
259
 
260
/*
261
 * Synchronize the state of the temporary file in case
262
 * a crash occurs.
263
 */
113 7u83 264
void
105 7u83 265
synctmp()
266
{
267
	register int cnt;
268
	register line *a;
269
	register short *bp;
270
 
271
#ifdef VMUNIX
272
	if (stilinc)
273
		return;
274
#endif
275
	if (dol == zero)
276
		return;
277
	if (ichanged)
278
		blkio(iblock, ibuff, write);
279
	ichanged = 0;
280
	if (ichang2)
281
		blkio(iblock2, ibuff2, write);
282
	ichang2 = 0;
283
	if (oblock != -1)
284
		blkio(oblock, obuff, write);
285
	time(&H.Time);
286
	uid = getuid();
287
	*zero = (line) H.Time;
288
	for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
289
		if (*bp < 0) {
290
			tline = (tline + OFFMSK) &~ OFFMSK;
291
			*bp = ((tline >> OFFBTS) & BLKMSK);
292
			if (*bp > NMBLKS)
293
				error(" Tmp file too large");
294
			tline += INCRMT;
295
			oblock = *bp + 1;
296
			bp[1] = -1;
297
		}
298
		lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
299
		cnt = ((dol - a) + 2) * sizeof (line);
300
		if (cnt > BUFSIZ)
301
			cnt = BUFSIZ;
302
		if (write(tfile, (char *) a, cnt) != cnt) {
303
oops:
304
			*zero = 0;
305
			filioerr(tfname);
306
		}
307
		*zero = 0;
308
	}
309
	flines = lineDOL();
310
	lseek(tfile, 0l, 0);
311
	if (write(tfile, (char *) &H, sizeof H) != sizeof H)
312
		goto oops;
313
#ifdef notdef
314
	/*
315
	 * This will insure that exrecover gets as much
316
	 * back after a crash as is absolutely possible,
317
	 * but can result in pregnant pauses between commands
318
	 * when the TSYNC call is made, so...
319
	 */
320
	(void) fsync(tfile);
321
#endif
322
}
323
 
324
TSYNC()
325
{
326
 
327
	if (dirtcnt > MAXDIRT) {	/* mjm: 12 --> MAXDIRT */
328
#ifdef VMUNIX
329
		if (stilinc)
330
			tflush();
331
#endif
332
		dirtcnt = 0;
333
		synctmp();
334
	}
335
}
336
 
337
/*
338
 * Named buffer routines.
339
 * These are implemented differently than the main buffer.
340
 * Each named buffer has a chain of blocks in the register file.
341
 * Each block contains roughly 508 chars of text,
342
 * and a previous and next block number.  We also have information
343
 * about which blocks came from deletes of multiple partial lines,
344
 * e.g. deleting a sentence or a LISP object.
345
 *
346
 * We maintain a free map for the temp file.  To free the blocks
347
 * in a register we must read the blocks to find how they are chained
348
 * together.
349
 *
350
 * BUG:		The default savind of deleted lines in numbered
351
 *		buffers may be rather inefficient; it hasn't been profiled.
352
 */
353
struct	strreg {
354
	short	rg_flags;
355
	short	rg_nleft;
356
	short	rg_first;
357
	short	rg_last;
358
} strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
359
 
360
struct	rbuf {
361
	short	rb_prev;
362
	short	rb_next;
363
	char	rb_text[BUFSIZ - 2 * sizeof (short)];
364
} *rbuf, KILLrbuf, putrbuf, YANKrbuf, regrbuf;
365
#ifdef VMUNIX
366
short	rused[256];
367
#else
368
short	rused[32];
369
#endif
370
short	rnleft;
371
short	rblock;
372
short	rnext;
373
char	*rbufcp;
374
 
375
regio(b, iofcn)
376
	short b;
377
	int (*iofcn)();
378
{
379
 
380
	if (rfile == -1) {
113 7u83 381
		strcpy(rfname, tfname);
105 7u83 382
		*(strend(rfname) - 7) = 'R';
383
		rfile = creat(rfname, 0600);
384
		if (rfile < 0)
385
oops:
386
			filioerr(rfname);
387
		close(rfile);
388
		rfile = open(rfname, 2);
389
		if (rfile < 0)
390
			goto oops;
391
	}
392
	lseek(rfile, (long) b * BUFSIZ, 0);
393
	if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
394
		goto oops;
395
	rblock = b;
396
}
397
 
398
REGblk()
399
{
400
	register int i, j, m;
401
 
402
	for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
403
		m = (rused[i] ^ 0177777) & 0177777;
404
		if (i == 0)
405
			m &= ~1;
406
		if (m != 0) {
407
			j = 0;
408
			while ((m & 1) == 0)
409
				j++, m >>= 1;
410
			rused[i] |= (1 << j);
411
#ifdef RDEBUG
412
			printf("allocating block %d\n", i * 16 + j);
413
#endif
414
			return (i * 16 + j);
415
		}
416
	}
417
	error("Out of register space (ugh)");
418
	/*NOTREACHED*/
419
}
420
 
421
struct	strreg *
422
mapreg(c)
423
	register int c;
424
{
425
 
426
	if (isupper(c))
427
		c = tolower(c);
428
	return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
429
}
430
 
431
int	shread();
432
 
433
KILLreg(c)
434
	register int c;
435
{
436
	register struct strreg *sp;
437
 
438
	rbuf = &KILLrbuf;
439
	sp = mapreg(c);
440
	rblock = sp->rg_first;
441
	sp->rg_first = sp->rg_last = 0;
442
	sp->rg_flags = sp->rg_nleft = 0;
443
	while (rblock != 0) {
444
#ifdef RDEBUG
445
		printf("freeing block %d\n", rblock);
446
#endif
447
		rused[rblock / 16] &= ~(1 << (rblock % 16));
448
		regio(rblock, shread);
449
		rblock = rbuf->rb_next;
450
	}
451
}
452
 
453
/*VARARGS*/
454
shread()
455
{
456
	struct front { short a; short b; };
457
 
458
	if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
459
		return (sizeof (struct rbuf));
460
	return (0);
461
}
462
 
463
int	getREG();
464
 
113 7u83 465
void
105 7u83 466
putreg(c)
467
	char c;
468
{
469
	register line *odot = dot;
470
	register line *odol = dol;
471
	register int cnt;
472
 
473
	deletenone();
474
	appendnone();
475
	rbuf = &putrbuf;
476
	rnleft = 0;
477
	rblock = 0;
478
	rnext = mapreg(c)->rg_first;
479
	if (rnext == 0) {
480
		if (inopen) {
481
			splitw++;
482
			vclean();
483
			vgoto(WECHO, 0);
484
		}
485
		vreg = -1;
486
		error("Nothing in register %c", c);
487
	}
488
	if (inopen && partreg(c)) {
489
		if (!FIXUNDO) {
490
			splitw++; vclean(); vgoto(WECHO, 0); vreg = -1;
491
			error("Can't put partial line inside macro");
492
		}
493
		squish();
494
		addr1 = addr2 = dol;
495
	}
496
	cnt = append(getREG, addr2);
497
	if (inopen && partreg(c)) {
498
		unddol = dol;
499
		dol = odol;
500
		dot = odot;
501
		pragged(0);
502
	}
503
	killcnt(cnt);
504
	notecnt = cnt;
505
}
506
 
507
partreg(c)
508
	char c;
509
{
510
 
511
	return (mapreg(c)->rg_flags);
512
}
513
 
514
notpart(c)
515
	register int c;
516
{
517
 
518
	if (c)
519
		mapreg(c)->rg_flags = 0;
520
}
521
 
522
getREG()
523
{
524
	register char *lp = linebuf;
525
	register int c;
526
 
527
	for (;;) {
528
		if (rnleft == 0) {
529
			if (rnext == 0)
530
				return (EOF);
531
			regio(rnext, read);
532
			rnext = rbuf->rb_next;
533
			rbufcp = rbuf->rb_text;
534
			rnleft = sizeof rbuf->rb_text;
535
		}
536
		c = *rbufcp;
537
		if (c == 0)
538
			return (EOF);
539
		rbufcp++, --rnleft;
540
		if (c == '\n') {
541
			*lp++ = 0;
542
			return (0);
543
		}
544
		*lp++ = c;
545
	}
546
}
547
 
548
YANKreg(c)
549
	register int c;
550
{
551
	register line *addr;
552
	register struct strreg *sp;
553
	char savelb[LBSIZE];
554
 
555
	if (isdigit(c))
556
		kshift();
557
	if (islower(c))
558
		KILLreg(c);
559
	strp = sp = mapreg(c);
560
	sp->rg_flags = inopen && cursor && wcursor;
561
	rbuf = &YANKrbuf;
562
	if (sp->rg_last) {
563
		regio(sp->rg_last, read);
564
		rnleft = sp->rg_nleft;
565
		rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
566
	} else {
567
		rblock = 0;
568
		rnleft = 0;
569
	}
113 7u83 570
	strcpy(savelb,linebuf);
105 7u83 571
	for (addr = addr1; addr <= addr2; addr++) {
572
		getline(*addr);
573
		if (sp->rg_flags) {
574
			if (addr == addr2)
575
				*wcursor = 0;
576
			if (addr == addr1)
577
				strcpy(linebuf, cursor);
578
		}
579
		YANKline();
580
	}
581
	rbflush();
582
	killed();
113 7u83 583
	strcpy(linebuf,savelb);
105 7u83 584
}
585
 
586
kshift()
587
{
588
	register int i;
589
 
590
	KILLreg('9');
591
	for (i = '8'; i >= '0'; i--)
592
		copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
593
}
594
 
595
YANKline()
596
{
597
	register char *lp = linebuf;
598
	register struct rbuf *rp = rbuf;
599
	register int c;
600
 
601
	do {
602
		c = *lp++;
603
		if (c == 0)
604
			c = '\n';
605
		if (rnleft == 0) {
606
			rp->rb_next = REGblk();
607
			rbflush();
608
			rblock = rp->rb_next;
609
			rp->rb_next = 0;
610
			rp->rb_prev = rblock;
611
			rnleft = sizeof rp->rb_text;
612
			rbufcp = rp->rb_text;
613
		}
614
		*rbufcp++ = c;
615
		--rnleft;
616
	} while (c != '\n');
617
	if (rnleft)
618
		*rbufcp = 0;
619
}
620
 
113 7u83 621
void
105 7u83 622
rbflush()
623
{
624
	register struct strreg *sp = strp;
625
 
626
	if (rblock == 0)
627
		return;
628
	regio(rblock, write);
629
	if (sp->rg_first == 0)
630
		sp->rg_first = rblock;
631
	sp->rg_last = rblock;
632
	sp->rg_nleft = rnleft;
633
}
634
 
635
/* Register c to char buffer buf of size buflen */
636
regbuf(c, buf, buflen)
637
char c;
638
char *buf;
639
int buflen;
640
{
641
	register char *p, *lp;
642
 
643
	rbuf = &regrbuf;
644
	rnleft = 0;
645
	rblock = 0;
646
	rnext = mapreg(c)->rg_first;
647
	if (rnext==0) {
648
		*buf = 0;
649
		error("Nothing in register %c",c);
650
	}
651
	p = buf;
652
	while (getREG()==0) {
653
		for (lp=linebuf; *lp;) {
654
			if (p >= &buf[buflen])
655
				error("Register too long@to fit in memory");
656
			*p++ = *lp++;
657
		}
658
		*p++ = '\n';
659
	}
660
	if (partreg(c)) p--;
661
	*p = '\0';
662
	getDOT();
663
}
664
 
665
/*
666
 * Encryption routines.  These are essentially unmodified from ed.
667
 */
668