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