GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/vi/build/../common/delete.c Lines: 0 65 0.0 %
Date: 2017-11-07 Branches: 0 188 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: delete.c,v 1.11 2016/01/06 22:28:52 millert Exp $	*/
2
3
/*-
4
 * Copyright (c) 1992, 1993, 1994
5
 *	The Regents of the University of California.  All rights reserved.
6
 * Copyright (c) 1992, 1993, 1994, 1995, 1996
7
 *	Keith Bostic.  All rights reserved.
8
 *
9
 * See the LICENSE file for redistribution information.
10
 */
11
12
#include "config.h"
13
14
#include <sys/types.h>
15
#include <sys/queue.h>
16
17
#include <bitstring.h>
18
#include <errno.h>
19
#include <stdint.h>
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include "common.h"
25
26
/*
27
 * del --
28
 *	Delete a range of text.
29
 *
30
 * PUBLIC: int del(SCR *, MARK *, MARK *, int);
31
 */
32
int
33
del(SCR *sp, MARK *fm, MARK *tm, int lmode)
34
{
35
	recno_t lno;
36
	size_t blen, len, nlen, tlen;
37
	char *bp, *p;
38
	int eof, rval;
39
40
	bp = NULL;
41
42
	/* Case 1 -- delete in line mode. */
43
	if (lmode) {
44
		for (lno = tm->lno; lno >= fm->lno; --lno) {
45
			if (db_delete(sp, lno))
46
				return (1);
47
			++sp->rptlines[L_DELETED];
48
			if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
49
				break;
50
		}
51
		goto done;
52
	}
53
54
	/*
55
	 * Case 2 -- delete to EOF.  This is a special case because it's
56
	 * easier to pick it off than try and find it in the other cases.
57
 	 */
58
	if (db_last(sp, &lno))
59
		return (1);
60
	if (tm->lno >= lno) {
61
		if (tm->lno == lno) {
62
			if (db_get(sp, lno, DBG_FATAL, &p, &len))
63
				return (1);
64
			eof = tm->cno != -1 && tm->cno >= len ? 1 : 0;
65
		} else
66
			eof = 1;
67
		if (eof) {
68
			for (lno = tm->lno; lno > fm->lno; --lno) {
69
				if (db_delete(sp, lno))
70
					return (1);
71
				++sp->rptlines[L_DELETED];
72
				if (lno %
73
				    INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
74
					break;
75
			}
76
			if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
77
				return (1);
78
			GET_SPACE_RET(sp, bp, blen, fm->cno);
79
			memcpy(bp, p, fm->cno);
80
			if (db_set(sp, fm->lno, bp, fm->cno))
81
				return (1);
82
			goto done;
83
		}
84
	}
85
86
	/* Case 3 -- delete within a single line. */
87
	if (tm->lno == fm->lno) {
88
		if (db_get(sp, fm->lno, DBG_FATAL, &p, &len))
89
			return (1);
90
		GET_SPACE_RET(sp, bp, blen, len);
91
		if (fm->cno != 0)
92
			memcpy(bp, p, fm->cno);
93
		memcpy(bp + fm->cno, p + (tm->cno + 1), len - (tm->cno + 1));
94
		if (db_set(sp, fm->lno,
95
		    bp, len - ((tm->cno - fm->cno) + 1)))
96
			goto err;
97
		goto done;
98
	}
99
100
	/*
101
	 * Case 4 -- delete over multiple lines.
102
	 *
103
	 * Copy the start partial line into place.
104
	 */
105
	if ((tlen = fm->cno) != 0) {
106
		if (db_get(sp, fm->lno, DBG_FATAL, &p, NULL))
107
			return (1);
108
		GET_SPACE_RET(sp, bp, blen, tlen + 256);
109
		memcpy(bp, p, tlen);
110
	}
111
112
	/* Copy the end partial line into place. */
113
	if (db_get(sp, tm->lno, DBG_FATAL, &p, &len))
114
		goto err;
115
	if (len != 0 && tm->cno != len - 1) {
116
		if (len < tm->cno + 1 || len - (tm->cno + 1) > SIZE_MAX - tlen) {
117
			msgq(sp, M_ERR, "Line length overflow");
118
			goto err;
119
		}
120
		nlen = (len - (tm->cno + 1)) + tlen;
121
		if (tlen == 0) {
122
			GET_SPACE_RET(sp, bp, blen, nlen);
123
		} else
124
			ADD_SPACE_RET(sp, bp, blen, nlen);
125
126
		memcpy(bp + tlen, p + (tm->cno + 1), len - (tm->cno + 1));
127
		tlen += len - (tm->cno + 1);
128
	}
129
130
	/* Set the current line. */
131
	if (db_set(sp, fm->lno, bp, tlen))
132
		goto err;
133
134
	/* Delete the last and intermediate lines. */
135
	for (lno = tm->lno; lno > fm->lno; --lno) {
136
		if (db_delete(sp, lno))
137
			goto err;
138
		++sp->rptlines[L_DELETED];
139
		if (lno % INTERRUPT_CHECK == 0 && INTERRUPTED(sp))
140
			break;
141
	}
142
143
done:	rval = 0;
144
	if (0)
145
err:		rval = 1;
146
	if (bp != NULL)
147
		FREE_SPACE(sp, bp, blen);
148
	return (rval);
149
}