GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/less/less/../ifile.c Lines: 64 77 83.1 %
Date: 2017-11-07 Branches: 10 22 45.5 %

Line Branch Exec Source
1
/*
2
 * Copyright (C) 1984-2012  Mark Nudelman
3
 * Modified for use with illumos by Garrett D'Amore.
4
 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
5
 *
6
 * You may distribute under the terms of either the GNU General Public
7
 * License or the Less License, as specified in the README file.
8
 *
9
 * For more information, see the README file.
10
 */
11
12
/*
13
 * An IFILE represents an input file.
14
 *
15
 * It is actually a pointer to an ifile structure,
16
 * but is opaque outside this module.
17
 * Ifile structures are kept in a linked list in the order they
18
 * appear on the command line.
19
 * Any new file which does not already appear in the list is
20
 * inserted after the current file.
21
 */
22
23
#include "less.h"
24
25
extern IFILE	curr_ifile;
26
27
struct ifile {
28
	struct ifile *h_next;		/* Links for command line list */
29
	struct ifile *h_prev;
30
	char *h_filename;		/* Name of the file */
31
	void *h_filestate;		/* File state (used in ch.c) */
32
	int h_index;			/* Index within command line list */
33
	int h_hold;			/* Hold count */
34
	char h_opened;			/* Has this ifile been opened? */
35
	struct scrpos h_scrpos;		/* Saved position within the file */
36
};
37
38
/*
39
 * Convert an IFILE (external representation)
40
 * to a struct file (internal representation), and vice versa.
41
 */
42
#define	int_ifile(h)	((struct ifile *)(h))
43
#define	ext_ifile(h)	((IFILE)(h))
44
45
/*
46
 * Anchor for linked list.
47
 */
48
static struct ifile anchor = { &anchor, &anchor, NULL, NULL, 0, 0, '\0',
49
				{ -1, 0 } };
50
static int ifiles = 0;
51
52
static void
53
incr_index(struct ifile *p, int incr)
54
{
55
123
	for (; p != &anchor; p = p->h_next)
56
		p->h_index += incr;
57
41
}
58
59
/*
60
 * Link an ifile into the ifile list.
61
 */
62
static void
63
link_ifile(struct ifile *p, struct ifile *prev)
64
{
65
	/*
66
	 * Link into list.
67
	 */
68
78
	if (prev == NULL)
69
		prev = &anchor;
70
39
	p->h_next = prev->h_next;
71
39
	p->h_prev = prev;
72
39
	prev->h_next->h_prev = p;
73
39
	prev->h_next = p;
74
	/*
75
	 * Calculate index for the new one,
76
	 * and adjust the indexes for subsequent ifiles in the list.
77
	 */
78
39
	p->h_index = prev->h_index + 1;
79
39
	incr_index(p->h_next, 1);
80
39
	ifiles++;
81
39
}
82
83
/*
84
 * Unlink an ifile from the ifile list.
85
 */
86
static void
87
unlink_ifile(struct ifile *p)
88
{
89
4
	p->h_next->h_prev = p->h_prev;
90
2
	p->h_prev->h_next = p->h_next;
91
2
	incr_index(p->h_next, -1);
92
2
	ifiles--;
93
2
}
94
95
/*
96
 * Allocate a new ifile structure and stick a filename in it.
97
 * It should go after "prev" in the list
98
 * (or at the beginning of the list if "prev" is NULL).
99
 * Return a pointer to the new ifile structure.
100
 */
101
static struct ifile *
102
new_ifile(char *filename, struct ifile *prev)
103
{
104
	struct ifile *p;
105
106
	/*
107
	 * Allocate and initialize structure.
108
	 */
109
78
	p = ecalloc(1, sizeof (struct ifile));
110
39
	p->h_filename = estrdup(filename);
111
39
	p->h_scrpos.pos = -1;
112
39
	p->h_opened = 0;
113
39
	p->h_hold = 0;
114
39
	p->h_filestate = NULL;
115
39
	link_ifile(p, prev);
116
39
	return (p);
117
}
118
119
/*
120
 * Delete an existing ifile structure.
121
 */
122
void
123
del_ifile(IFILE h)
124
{
125
	struct ifile *p;
126
127
4
	if (h == NULL)
128
		return;
129
	/*
130
	 * If the ifile we're deleting is the currently open ifile,
131
	 * move off it.
132
	 */
133
2
	unmark(h);
134
2
	if (h == curr_ifile)
135
		curr_ifile = getoff_ifile(curr_ifile);
136
2
	p = int_ifile(h);
137
2
	unlink_ifile(p);
138
2
	free(p->h_filename);
139
2
	free(p);
140
4
}
141
142
/*
143
 * Get the ifile after a given one in the list.
144
 */
145
IFILE
146
next_ifile(IFILE h)
147
{
148
	struct ifile *p;
149
150
196
	p = (h == NULL) ? &anchor : int_ifile(h);
151
98
	if (p->h_next == &anchor)
152
71
		return (NULL);
153
27
	return (ext_ifile(p->h_next));
154
98
}
155
156
/*
157
 * Get the ifile before a given one in the list.
158
 */
159
IFILE
160
prev_ifile(IFILE h)
161
{
162
	struct ifile *p;
163
164
58
	p = (h == NULL) ? &anchor : int_ifile(h);
165
29
	if (p->h_prev == &anchor)
166
2
		return (NULL);
167
27
	return (ext_ifile(p->h_prev));
168
29
}
169
170
/*
171
 * Return a different ifile from the given one.
172
 */
173
IFILE
174
getoff_ifile(IFILE ifile)
175
{
176
	IFILE newifile;
177
178
	if ((newifile = prev_ifile(ifile)) != NULL)
179
		return (newifile);
180
	if ((newifile = next_ifile(ifile)) != NULL)
181
		return (newifile);
182
	return (NULL);
183
}
184
185
/*
186
 * Return the number of ifiles.
187
 */
188
int
189
nifile(void)
190
{
191
142
	return (ifiles);
192
}
193
194
/*
195
 * Find an ifile structure, given a filename.
196
 */
197
static struct ifile *
198
find_ifile(const char *filename)
199
{
200
	struct ifile *p;
201
202
117
	for (p = anchor.h_next; p != &anchor; p = p->h_next)
203
		if (strcmp(filename, p->h_filename) == 0)
204
			return (p);
205
39
	return (NULL);
206
39
}
207
208
/*
209
 * Get the ifile associated with a filename.
210
 * If the filename has not been seen before,
211
 * insert the new ifile after "prev" in the list.
212
 */
213
IFILE
214
get_ifile(char *filename, IFILE prev)
215
{
216
	struct ifile *p;
217
218
78
	if ((p = find_ifile(filename)) == NULL)
219
39
		p = new_ifile(filename, int_ifile(prev));
220
39
	return (ext_ifile(p));
221
}
222
223
/*
224
 * Get the filename associated with a ifile.
225
 */
226
char *
227
get_filename(IFILE ifile)
228
{
229
318
	if (ifile == NULL)
230
		return (NULL);
231
159
	return (int_ifile(ifile)->h_filename);
232
159
}
233
234
/*
235
 * Get the index of the file associated with a ifile.
236
 */
237
int
238
get_index(IFILE ifile)
239
{
240
	return (int_ifile(ifile)->h_index);
241
}
242
243
/*
244
 * Save the file position to be associated with a given file.
245
 */
246
void
247
store_pos(IFILE ifile, struct scrpos *scrpos)
248
{
249
74
	int_ifile(ifile)->h_scrpos = *scrpos;
250
37
}
251
252
/*
253
 * Recall the file position associated with a file.
254
 * If no position has been associated with the file, return -1.
255
 */
256
void
257
get_pos(IFILE ifile, struct scrpos *scrpos)
258
{
259
74
	*scrpos = int_ifile(ifile)->h_scrpos;
260
37
}
261
262
/*
263
 * Mark the ifile as "opened".
264
 */
265
void
266
set_open(IFILE ifile)
267
{
268
74
	int_ifile(ifile)->h_opened = 1;
269
37
}
270
271
/*
272
 * Return whether the ifile has been opened previously.
273
 */
274
int
275
opened(IFILE ifile)
276
{
277
50
	return (int_ifile(ifile)->h_opened);
278
}
279
280
void
281
hold_ifile(IFILE ifile, int incr)
282
{
283
192
	int_ifile(ifile)->h_hold += incr;
284
96
}
285
286
int
287
held_ifile(IFILE ifile)
288
{
289
	return (int_ifile(ifile)->h_hold);
290
}
291
292
void *
293
get_filestate(IFILE ifile)
294
{
295
74
	return (int_ifile(ifile)->h_filestate);
296
}
297
298
void
299
set_filestate(IFILE ifile, void *filestate)
300
{
301
124
	int_ifile(ifile)->h_filestate = filestate;
302
62
}