Subversion Repositories planix.SVN

Rev

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