Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 7u83 1
/*
2
 * This code contains changes by
3
 *      Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
4
 *
5
 * Conditions 1, 2, and 4 and the no-warranty notice below apply
6
 * to these changes.
7
 *
8
 *
9
 * Copyright (c) 1980, 1993
10
 * 	The Regents of the University of California.  All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in the
19
 *    documentation and/or other materials provided with the distribution.
20
 * 3. All advertising materials mentioning features or use of this software
21
 *    must display the following acknowledgement:
22
 * 	This product includes software developed by the University of
23
 * 	California, Berkeley and its contributors.
24
 * 4. Neither the name of the University nor the names of its contributors
25
 *    may be used to endorse or promote products derived from this software
26
 *    without specific prior written permission.
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38
 * SUCH DAMAGE.
39
 *
40
 *
41
 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
42
 *
43
 * Redistribution and use in source and binary forms, with or without
44
 * modification, are permitted provided that the following conditions
45
 * are met:
46
 *   Redistributions of source code and documentation must retain the
47
 *    above copyright notice, this list of conditions and the following
48
 *    disclaimer.
49
 *   Redistributions in binary form must reproduce the above copyright
50
 *    notice, this list of conditions and the following disclaimer in the
51
 *    documentation and/or other materials provided with the distribution.
52
 *   All advertising materials mentioning features or use of this software
53
 *    must display the following acknowledgement:
54
 *      This product includes software developed or owned by Caldera
55
 *      International, Inc.
56
 *   Neither the name of Caldera International, Inc. nor the names of
57
 *    other contributors may be used to endorse or promote products
58
 *    derived from this software without specific prior written permission.
59
 *
60
 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61
 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64
 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
65
 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
66
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
68
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
69
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
71
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72
 */
73
 
74
#ifndef	lint
75
#ifdef	DOSCCS
76
static char sccsid[] = "@(#)ex_temp.c	1.24 (gritter) 11/24/04";
77
#endif
78
#endif
79
 
80
/* from ex_temp.c	7.5.1.1 (Berkeley) 8/12/86 */
81
 
82
#include "ex.h"
83
#include "ex_temp.h"
84
#include "ex_vis.h"
85
#include "ex_tty.h"
86
#include <sys/wait.h>
87
#include <time.h>
88
 
89
/*
90
 * Editor temporary file routines.
91
 * Very similar to those of ed, except uses 2 input buffers.
92
 */
93
#define	READ	0
94
#define	WRITE	1
95
 
96
/*
97
 * Maximum number of attempts to create temporary file.
98
 */
99
#define	ATTEMPTS	20
100
 
101
char	*tfname;
102
char	*rfname;
103
int	havetmp;
104
int	tfile = -1;
105
int	rfile = -1;
106
 
107
void
108
fileinit(void)
109
{
110
	register char *p;
111
	struct stat stbuf;
112
	register int i, j;
113
	pid_t mypid = getpid();
114
	char *tfend;
115
	int attempts = 0;
116
 
117
	CLOBBGRD(attempts);
118
	if (tline == INCRMT * (HBLKS+2))
119
		return;
120
	cleanup(0);
121
	if (tfile != -1)
122
		close(tfile);
123
	tline = INCRMT * (HBLKS+2);
124
	blocks[0] = HBLKS;
125
	blocks[1] = HBLKS+1;
126
	blocks[2] = -1;
127
	dirtcnt = 0;
128
	iblock = -1;
129
	iblock2 = -1;
130
	oblock = -1;
131
	tfname = realloc(tfname, strlen(svalue(DIRECTORY)) + 14);
132
	CP(tfname, svalue(DIRECTORY));
133
	if (stat(tfname, &stbuf)) {
134
dumbness:
135
		if (setexit() == 0)
136
			filioerr(tfname);
137
		else
138
			putNFL();
139
		cleanup(1);
140
		exitex(1);
141
	}
142
	if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
143
		errno = ENOTDIR;
144
		goto dumbness;
145
	}
146
	ichanged = 0;
147
	ichang2 = 0;
148
#ifdef	notdef	/* GR */
149
	ignore(strcat(tfname, "/ExXXXXX"));
150
	for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
151
		*--p = j % 10 | '0';
152
	tfile = creat(tfname, 0600);
153
#else
154
	ignore(strcat(tfname, "/ExXXXXXXXXXX"));
155
	tfend = strend(tfname);
156
	do {
157
		for (p = tfend, i = 10, j = mypid + attempts;
158
				i > 0; i--, j /= 10)
159
			*--p = j % 10 | '0';
160
		tfile = open(tfname, O_CREAT|O_EXCL|O_RDWR
161
#ifdef	O_NOFOLLOW
162
				|O_NOFOLLOW
163
#endif	/* O_NOFOLLOW */
164
				, 0600);
165
	} while (tfile < 0 && attempts++ < ATTEMPTS);
166
#endif	/* !notdef */
167
	if (tfile < 0)
168
		goto dumbness;
169
#ifdef INCORB
170
	{
171
		extern bloc stilinc;		/* see below */
172
		stilinc = 0;
173
	}
174
#endif
175
	havetmp = 1;
176
/* 	brk((char *)fendcore); */
177
}
178
 
179
void
180
cleanup(bool all)
181
{
182
	if (all) {
183
		putpad(TE);
184
		flush();
185
	}
186
	if (havetmp)
187
		unlink(tfname);
188
	havetmp = 0;
189
	if (all && rfile >= 0) {
190
		unlink(rfname);
191
		close(rfile);
192
		rfile = -1;
193
	}
194
}
195
 
196
void
197
getline(line tl)
198
{
199
	register char *bp, *lp;
200
	register bbloc nl;
201
 
202
	lp = linebuf;
203
	bp = getblock(tl, READ);
204
	nl = nleft;
205
	tl &= ~OFFMSK;
206
	while (*lp++ = *bp++)
207
		if (--nl == 0) {
208
			bp = getblock(tl += INCRMT, READ);
209
			nl = nleft;
210
		}
211
}
212
 
213
line
214
putline(void)
215
{
216
	register char *bp, *lp;
217
	register bbloc nl;
218
	line tl;
219
 
220
	dirtcnt++;
221
	lp = linebuf;
222
	change();
223
	tl = tline;
224
	bp = getblock(tl, WRITE);
225
	nl = nleft;
226
	tl &= ~OFFMSK;
227
	while (*bp = *lp++) {
228
		if (*bp++ == '\n') {
229
			*--bp = 0;
230
			linebp = lp;
231
			break;
232
		}
233
		if (--nl == 0) {
234
			bp = getblock(tl += INCRMT, WRITE);
235
			nl = nleft;
236
		}
237
	}
238
	tl = tline;
239
	tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
240
	return (tl);
241
}
242
 
243
char *
244
getblock(line atl, int iof)
245
{
246
	register bbloc bno, off;
247
 
248
	bno = (atl >> OFFBTS) & BLKMSK;
249
	off = (atl << SHFT) & LBTMSK;
250
	if (bno >= NMBLKS)
251
		error(catgets(catd, 1, 183, " Tmp file too large"));
252
	nleft = BUFSIZ - off;
253
	if (bno == iblock) {
254
		ichanged |= iof;
255
		hitin2 = 0;
256
		return (ibuff + off);
257
	}
258
	if (bno == iblock2) {
259
		ichang2 |= iof;
260
		hitin2 = 1;
261
		return (ibuff2 + off);
262
	}
263
	if (bno == oblock)
264
		return (obuff + off);
265
	if (iof == READ) {
266
		if (hitin2 == 0) {
267
			if (ichang2) {
268
				blkio(iblock2, ibuff2, (ssize_t(*)())write);
269
			}
270
			ichang2 = 0;
271
			iblock2 = bno;
272
			blkio(bno, ibuff2, (ssize_t(*)())read);
273
			hitin2 = 1;
274
			return (ibuff2 + off);
275
		}
276
		hitin2 = 0;
277
		if (ichanged) {
278
			blkio(iblock, ibuff, (ssize_t(*)())write);
279
		}
280
		ichanged = 0;
281
		iblock = bno;
282
		blkio(bno, ibuff, (ssize_t(*)())read);
283
		return (ibuff + off);
284
	}
285
	if (oblock >= 0) {
286
			blkio(oblock, obuff, (ssize_t(*)())write);
287
	}
288
	oblock = bno;
289
	return (obuff + off);
290
}
291
 
292
#ifdef	INCORB
293
char	incorb[INCORB+1][BUFSIZ];
294
#define	pagrnd(a)	((char *)(((size_t)a)&~(BUFSIZ-1)))
295
bloc	stilinc;	/* up to here not written yet */
296
#endif
297
 
298
void
299
blkio(bloc b, char *buf, ssize_t (*iofcn)(int, void *, size_t))
300
{
301
 
302
#ifdef INCORB
303
	if (b < INCORB) {
304
		if (iofcn == (ssize_t(*)())read) {
305
			copy(buf, pagrnd(incorb[b+1]), (size_t) BUFSIZ);
306
			return;
307
		}
308
		copy(pagrnd(incorb[b+1]), buf, (size_t) BUFSIZ);
309
		if (laste) {
310
			if (b >= stilinc)
311
				stilinc = b + 1;
312
			return;
313
		}
314
	} else if (stilinc)
315
		tflush();
316
#endif
317
	lseek(tfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET);
318
	if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
319
		filioerr(tfname);
320
}
321
 
322
#ifdef INCORB
323
void
324
tlaste(void)
325
{
326
 
327
	if (stilinc)
328
		dirtcnt = 0;
329
}
330
 
331
void
332
tflush(void)
333
{
334
	bbloc i = stilinc;
335
 
336
	stilinc = 0;
337
	lseek(tfile, (off_t) 0, SEEK_SET);
338
	if (write(tfile, pagrnd(incorb[1]), i * BUFSIZ) != (i * BUFSIZ))
339
		filioerr(tfname);
340
}
341
#endif
342
 
343
/*
344
 * Synchronize the state of the temporary file in case
345
 * a crash occurs.
346
 */
347
void
348
synctmp(void)
349
{
350
	register bbloc cnt;
351
	register line *a;
352
	register bloc *bp, *up;
353
 
354
#ifdef INCORB
355
	if (stilinc)
356
		return;
357
#endif
358
	if (dol == zero)
359
		return;
360
	if (ichanged)
361
		blkio(iblock, ibuff, (ssize_t(*)())write);
362
	ichanged = 0;
363
	if (ichang2)
364
		blkio(iblock2, ibuff2, (ssize_t(*)())write);
365
	ichang2 = 0;
366
	if (oblock != -1)
367
		blkio(oblock, obuff, (ssize_t(*)())write);
368
	time(&H.Time);
369
	uid = getuid();
370
	*zero = (line) H.Time;
371
	up = blocks + LBLKS;
372
	for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
373
		if (bp >= up)
374
			error(catgets(catd, 1, 184, " Tmp file too large"));
375
		if (*bp < 0) {
376
			tline = (tline + OFFMSK) &~ OFFMSK;
377
			*bp = ((tline >> OFFBTS) & BLKMSK);
378
			if (*bp > NMBLKS)
379
				error(catgets(catd, 1, 185,
380
						" Tmp file too large"));
381
			tline += INCRMT;
382
			oblock = *bp + 1;
383
			bp[1] = -1;
384
		}
385
		lseek(tfile, (off_t) ((*bp & BLKMSK) * BUFSIZ), SEEK_SET);
386
		cnt = ((dol - a) + 2) * sizeof (line);
387
		if (cnt > BUFSIZ)
388
			cnt = BUFSIZ;
389
		if (write(tfile, (char *) a, cnt) != cnt) {
390
oops:
391
			*zero = 0;
392
			filioerr(tfname);
393
		}
394
		*zero = 0;
395
	}
396
	flines = lineDOL();
397
	lseek(tfile, (off_t) 0, SEEK_SET);
398
	if (write(tfile, (char *) &H, sizeof H) != sizeof H)
399
		goto oops;
400
#ifdef notdef
401
	/*
402
	 * This will insure that exrecover gets as much
403
	 * back after a crash as is absolutely possible,
404
	 * but can result in pregnant pauses between commands
405
	 * when the TSYNC call is made, so...
406
	 */
407
	fsync(tfile);
408
#endif
409
}
410
 
411
void
412
TSYNC(void)
413
{
414
 
415
	if (dirtcnt > MAXDIRT) {	/* mjm: 12 --> MAXDIRT */
416
#ifdef INCORB
417
		if (stilinc)
418
			tflush();
419
#endif
420
		dirtcnt = 0;
421
		synctmp();
422
	}
423
}
424
 
425
/*
426
 * Named buffer routines.
427
 * These are implemented differently than the main buffer.
428
 * Each named buffer has a chain of blocks in the register file.
429
 * Each block contains roughly 508 chars of text,
430
 * and a previous and next block number.  We also have information
431
 * about which blocks came from deletes of multiple partial lines,
432
 * e.g. deleting a sentence or a LISP object.
433
 *
434
 * We maintain a free map for the temp file.  To free the blocks
435
 * in a register we must read the blocks to find how they are chained
436
 * together.
437
 *
438
 * BUG:		The default savind of deleted lines in numbered
439
 *		buffers may be rather inefficient; it hasn't been profiled.
440
 */
441
struct	strreg {
442
	short	rg_flags;
443
	short	rg_nleft;
444
	short	rg_first;
445
	short	rg_last;
446
} strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
447
 
448
struct	rbuf {
449
	short	rb_prev;
450
	short	rb_next;
451
	char	rb_text[BUFSIZ - 2 * sizeof (short)];
452
} *rbuf, KILLrbuf, putrbuf, YANKrbuf, regrbuf;
453
#ifdef	VMUNIX
454
#ifdef	LARGEF
455
short	rused[4096];
456
#else	/* !LARGEF */
457
short	rused[256];
458
#endif	/* !LARGEF */
459
#else	/* !VMUNIX */
460
short	rused[32];
461
#endif	/* !VMUNIX */
462
short	rnleft;
463
short	rblock;
464
short	rnext;
465
char	*rbufcp;
466
 
467
void
468
regio(short b, ssize_t (*iofcn)(int, void *, size_t))
469
{
470
	register char *p;
471
	char *rfend;
472
	int attempts = 0;
473
	register int i, j;
474
	pid_t mypid = getpid();
475
 
476
	if (rfile == -1) {
477
		rfname = realloc(rfname, strlen(svalue(DIRECTORY)) + 14);
478
		CP(rfname, tfname);
479
		rfend = strend(rfname);
480
#ifdef	notdef	/* GR */
481
		*(rfend - 7) = 'R';
482
#else
483
		*(rfend - 12) = 'R';
484
#endif
485
		do {
486
			for (p = rfend, i = 10, j = mypid + attempts;
487
					i > 0; i--, j /= 10)
488
				*--p = j % 10 | '0';
489
			rfile = open(rfname, O_CREAT|O_EXCL|O_RDWR
490
#ifdef	O_NOFOLLOW
491
					|O_NOFOLLOW
492
#endif	/* O_NOFOLLOW */
493
					, 0600);
494
		} while (rfile < 0 && attempts++ < ATTEMPTS);
495
		if (rfile < 0)
496
oops:
497
			filioerr(rfname);
498
	}
499
	lseek(rfile, (off_t) ((b & BLKMSK) * BUFSIZ), SEEK_SET);
500
	if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
501
		goto oops;
502
	rblock = b;
503
}
504
 
505
int
506
REGblk(void)
507
{
508
	register int i, j, m;
509
 
510
	for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
511
		m = (rused[i] ^ 0177777) & 0177777;
512
		if (i == 0)
513
			m &= ~1;
514
		if (m != 0) {
515
			j = 0;
516
			while ((m & 1) == 0)
517
				j++, m >>= 1;
518
			rused[i] |= (1 << j);
519
#ifdef RDEBUG
520
			printf("allocating block %d\n", i * 16 + j);
521
#endif
522
			return (i * 16 + j);
523
		}
524
	}
525
	error(catgets(catd, 1, 186, "Out of register space (ugh)"));
526
	/*NOTREACHED*/
527
	return 0;
528
}
529
 
530
struct	strreg *
531
mapreg(register int c)
532
{
533
 
534
	if (isupper(c))
535
		c = tolower(c);
536
	return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
537
}
538
 
539
void
540
KILLreg(register int c)
541
{
542
	register struct strreg *sp;
543
 
544
	rbuf = &KILLrbuf;
545
	sp = mapreg(c);
546
	rblock = sp->rg_first;
547
	sp->rg_first = sp->rg_last = 0;
548
	sp->rg_flags = sp->rg_nleft = 0;
549
	while (rblock != 0) {
550
#ifdef RDEBUG
551
		printf("freeing block %d\n", rblock);
552
#endif
553
		rused[rblock / 16] &= ~(1 << (rblock % 16));
554
		regio(rblock, (ssize_t (*)(int, void *, size_t))shread);
555
		rblock = rbuf->rb_next;
556
	}
557
}
558
 
559
ssize_t
560
shread(void)
561
{
562
	struct front { short a; short b; };
563
 
564
	if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
565
		return (sizeof (struct rbuf));
566
	return (0);
567
}
568
 
569
int	getREG();
570
 
571
void
572
putreg(int c)
573
{
574
	register line *odot = dot;
575
	register line *odol = dol;
576
	register int cnt;
577
 
578
	deletenone();
579
	appendnone();
580
	rbuf = &putrbuf;
581
	rnleft = 0;
582
	rblock = 0;
583
	rnext = mapreg(c)->rg_first;
584
	if (rnext == 0) {
585
		if (inopen) {
586
			splitw++;
587
			vclean();
588
			vgoto(WECHO, 0);
589
		}
590
		vreg = -1;
591
		error(catgets(catd, 1, 187, "Nothing in register %c"), c);
592
	}
593
	if (inopen && partreg(c)) {
594
		if (!FIXUNDO) {
595
			splitw++; vclean(); vgoto(WECHO, 0); vreg = -1;
596
			error(catgets(catd, 1, 188,
597
				"Can't put partial line inside macro"));
598
		}
599
		squish();
600
		addr1 = addr2 = dol;
601
	}
602
	cnt = append(getREG, addr2);
603
	if (inopen && partreg(c)) {
604
		unddol = dol;
605
		dol = odol;
606
		dot = odot;
607
		pragged(0);
608
	}
609
	killcnt(cnt);
610
	notecnt = cnt;
611
}
612
 
613
int
614
partreg(int c)
615
{
616
 
617
	return (mapreg(c)->rg_flags);
618
}
619
 
620
void
621
notpart(register int c)
622
{
623
 
624
	if (c)
625
		mapreg(c)->rg_flags = 0;
626
}
627
 
628
int
629
getREG(void)
630
{
631
	register char *lp = linebuf;
632
	register int c;
633
 
634
	for (;;) {
635
		if (rnleft == 0) {
636
			if (rnext == 0)
637
				return (EOF);
638
			regio(rnext, read);
639
			rnext = rbuf->rb_next;
640
			rbufcp = rbuf->rb_text;
641
			rnleft = sizeof rbuf->rb_text;
642
		}
643
		c = *rbufcp;
644
		if (c == 0)
645
			return (EOF);
646
		rbufcp++, --rnleft;
647
		if (c == '\n') {
648
			*lp++ = 0;
649
			return (0);
650
		}
651
		*lp++ = c;
652
	}
653
}
654
 
655
void
656
YANKreg(register int c)
657
{
658
	register line *addr;
659
	register struct strreg *sp;
660
	char savelb[LBSIZE];
661
 
662
	if (isdigit(c))
663
		kshift();
664
	if (islower(c))
665
		KILLreg(c);
666
	strp = sp = mapreg(c);
667
	sp->rg_flags = inopen && cursor && wcursor;
668
	rbuf = &YANKrbuf;
669
	if (sp->rg_last) {
670
		regio(sp->rg_last, read);
671
		rnleft = sp->rg_nleft;
672
		rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
673
	} else {
674
		rblock = 0;
675
		rnleft = 0;
676
	}
677
	CP(savelb,linebuf);
678
	for (addr = addr1; addr <= addr2; addr++) {
679
		getline(*addr);
680
		if (sp->rg_flags) {
681
			if (addr == addr2)
682
				*wcursor = 0;
683
			if (addr == addr1)
684
				strcpy(linebuf, cursor);
685
		}
686
		YANKline();
687
	}
688
	rbflush();
689
	killed();
690
	CP(linebuf,savelb);
691
}
692
 
693
void
694
kshift(void)
695
{
696
	register int i;
697
 
698
	KILLreg('9');
699
	for (i = '8'; i >= '0'; i--)
700
		copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
701
}
702
 
703
void
704
YANKline(void)
705
{
706
	register char *lp = linebuf;
707
	register struct rbuf *rp = rbuf;
708
	register int c;
709
 
710
	do {
711
		c = *lp++;
712
		if (c == 0)
713
			c = '\n';
714
		if (rnleft == 0) {
715
			rp->rb_next = REGblk();
716
			rbflush();
717
			rblock = rp->rb_next;
718
			rp->rb_next = 0;
719
			rp->rb_prev = rblock;
720
			rnleft = sizeof rp->rb_text;
721
			rbufcp = rp->rb_text;
722
		}
723
		*rbufcp++ = c;
724
		--rnleft;
725
	} while (c != '\n');
726
	if (rnleft)
727
		*rbufcp = 0;
728
}
729
 
730
void
731
rbflush(void)
732
{
733
	register struct strreg *sp = strp;
734
 
735
	if (rblock == 0)
736
		return;
737
	regio(rblock, (ssize_t (*)(int, void *, size_t))write);
738
	if (sp->rg_first == 0)
739
		sp->rg_first = rblock;
740
	sp->rg_last = rblock;
741
	sp->rg_nleft = rnleft;
742
}
743
 
744
/* Register c to char buffer buf of size buflen */
745
void
746
regbuf(char c, char *buf, int buflen)
747
{
748
	register char *p, *lp;
749
 
750
	rbuf = &regrbuf;
751
	rnleft = 0;
752
	rblock = 0;
753
	rnext = mapreg(c)->rg_first;
754
	if (rnext==0) {
755
		*buf = 0;
756
		error(catgets(catd, 1, 189, "Nothing in register %c"),c);
757
	}
758
	p = buf;
759
	while (getREG()==0) {
760
		for (lp=linebuf; *lp;) {
761
			if (p >= &buf[buflen])
762
				error(catgets(catd, 1, 190,
763
					"Register too long@to fit in memory"));
764
			*p++ = *lp++;
765
		}
766
		*p++ = '\n';
767
	}
768
	if (partreg(c)) p--;
769
	*p = '\0';
770
	getDOT();
771
}