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>
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.
9 * For more information, see the README file.
13 * An IFILE represents an input file.
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.
25 extern IFILE curr_ifile
;
28 struct ifile
*h_next
; /* Links for command line list */
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 */
39 * Convert an IFILE (external representation)
40 * to a struct file (internal representation), and vice versa.
42 #define int_ifile(h) ((struct ifile *)(h))
43 #define ext_ifile(h) ((IFILE)(h))
46 * Anchor for linked list.
48 static struct ifile anchor
= { &anchor
, &anchor
, NULL
, NULL
, 0, 0, '\0',
50 static int ifiles
= 0;
53 incr_index(struct ifile
*p
, int incr
)
55 for (; p
!= &anchor
; p
= p
->h_next
)
60 * Link an ifile into the ifile list.
63 link_ifile(struct ifile
*p
, struct ifile
*prev
)
70 p
->h_next
= prev
->h_next
;
72 prev
->h_next
->h_prev
= p
;
75 * Calculate index for the new one,
76 * and adjust the indexes for subsequent ifiles in the list.
78 p
->h_index
= prev
->h_index
+ 1;
79 incr_index(p
->h_next
, 1);
84 * Unlink an ifile from the ifile list.
87 unlink_ifile(struct ifile
*p
)
89 p
->h_next
->h_prev
= p
->h_prev
;
90 p
->h_prev
->h_next
= p
->h_next
;
91 incr_index(p
->h_next
, -1);
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.
101 static struct ifile
*
102 new_ifile(char *filename
, struct ifile
*prev
)
107 * Allocate and initialize structure.
109 p
= ecalloc(1, sizeof (struct ifile
));
110 p
->h_filename
= estrdup(filename
);
111 p
->h_scrpos
.pos
= -1;
114 p
->h_filestate
= NULL
;
120 * Delete an existing ifile structure.
130 * If the ifile we're deleting is the currently open ifile,
135 curr_ifile
= getoff_ifile(curr_ifile
);
143 * Get the ifile after a given one in the list.
150 p
= (h
== NULL
) ? &anchor
: int_ifile(h
);
151 if (p
->h_next
== &anchor
)
153 return (ext_ifile(p
->h_next
));
157 * Get the ifile before a given one in the list.
164 p
= (h
== NULL
) ? &anchor
: int_ifile(h
);
165 if (p
->h_prev
== &anchor
)
167 return (ext_ifile(p
->h_prev
));
171 * Return a different ifile from the given one.
174 getoff_ifile(IFILE ifile
)
178 if ((newifile
= prev_ifile(ifile
)) != NULL
)
180 if ((newifile
= next_ifile(ifile
)) != NULL
)
186 * Return the number of ifiles.
195 * Find an ifile structure, given a filename.
197 static struct ifile
*
198 find_ifile(const char *filename
)
202 for (p
= anchor
.h_next
; p
!= &anchor
; p
= p
->h_next
)
203 if (strcmp(filename
, p
->h_filename
) == 0)
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.
214 get_ifile(char *filename
, IFILE prev
)
218 if ((p
= find_ifile(filename
)) == NULL
)
219 p
= new_ifile(filename
, int_ifile(prev
));
220 return (ext_ifile(p
));
224 * Get the filename associated with a ifile.
227 get_filename(IFILE ifile
)
231 return (int_ifile(ifile
)->h_filename
);
235 * Get the index of the file associated with a ifile.
238 get_index(IFILE ifile
)
240 return (int_ifile(ifile
)->h_index
);
244 * Save the file position to be associated with a given file.
247 store_pos(IFILE ifile
, struct scrpos
*scrpos
)
249 int_ifile(ifile
)->h_scrpos
= *scrpos
;
253 * Recall the file position associated with a file.
254 * If no position has been associated with the file, return -1.
257 get_pos(IFILE ifile
, struct scrpos
*scrpos
)
259 *scrpos
= int_ifile(ifile
)->h_scrpos
;
263 * Mark the ifile as "opened".
266 set_open(IFILE ifile
)
268 int_ifile(ifile
)->h_opened
= 1;
272 * Return whether the ifile has been opened previously.
277 return (int_ifile(ifile
)->h_opened
);
281 hold_ifile(IFILE ifile
, int incr
)
283 int_ifile(ifile
)->h_hold
+= incr
;
287 held_ifile(IFILE ifile
)
289 return (int_ifile(ifile
)->h_hold
);
293 get_filestate(IFILE ifile
)
295 return (int_ifile(ifile
)->h_filestate
);
299 set_filestate(IFILE ifile
, void *filestate
)
301 int_ifile(ifile
)->h_filestate
= filestate
;