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