1 /* $NetBSD: ifile.c,v 1.4 2013/09/04 19:44:21 tron Exp $ */
4 * Copyright (C) 1984-2012 Mark Nudelman
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.
14 * An IFILE represents an input file.
16 * It is actually a pointer to an ifile structure,
17 * but is opaque outside this module.
18 * Ifile structures are kept in a linked list in the order they
19 * appear on the command line.
20 * Any new file which does not already appear in the list is
21 * inserted after the current file.
26 extern IFILE curr_ifile
;
29 struct ifile
*h_next
; /* Links for command line list */
31 char *h_filename
; /* Name of the file */
32 void *h_filestate
; /* File state (used in ch.c) */
33 int h_index
; /* Index within command line list */
34 int h_hold
; /* Hold count */
35 char h_opened
; /* Has this ifile been opened? */
36 struct scrpos h_scrpos
; /* Saved position within the file */
40 * Convert an IFILE (external representation)
41 * to a struct file (internal representation), and vice versa.
43 #define int_ifile(h) ((struct ifile *)(h))
44 #define ext_ifile(h) ((IFILE)(h))
47 * Anchor for linked list.
49 static struct ifile anchor
= { &anchor
, &anchor
, NULL
, NULL
, 0, 0, '\0',
50 { NULL_POSITION
, 0 } };
51 static int ifiles
= 0;
53 static void incr_index
__P((struct ifile
*, int));
54 static void link_ifile
__P((struct ifile
*, struct ifile
*));
55 static void unlink_ifile
__P((struct ifile
*));
56 static struct ifile
*new_ifile
__P((char *, struct ifile
*));
57 static struct ifile
*find_ifile
__P((char *));
61 register struct ifile
*p
;
64 for (; p
!= &anchor
; p
= p
->h_next
)
69 * Link an ifile into the ifile list.
81 p
->h_next
= prev
->h_next
;
83 prev
->h_next
->h_prev
= p
;
86 * Calculate index for the new one,
87 * and adjust the indexes for subsequent ifiles in the list.
89 p
->h_index
= prev
->h_index
+ 1;
90 incr_index(p
->h_next
, 1);
95 * Unlink an ifile from the ifile list.
101 p
->h_next
->h_prev
= p
->h_prev
;
102 p
->h_prev
->h_next
= p
->h_next
;
103 incr_index(p
->h_next
, -1);
108 * Allocate a new ifile structure and stick a filename in it.
109 * It should go after "prev" in the list
110 * (or at the beginning of the list if "prev" is NULL).
111 * Return a pointer to the new ifile structure.
113 static struct ifile
*
114 new_ifile(filename
, prev
)
118 register struct ifile
*p
;
121 * Allocate and initialize structure.
123 p
= (struct ifile
*) ecalloc(1, sizeof(struct ifile
));
124 p
->h_filename
= save(filename
);
125 p
->h_scrpos
.pos
= NULL_POSITION
;
128 p
->h_filestate
= NULL
;
134 * Delete an existing ifile structure.
140 register struct ifile
*p
;
145 * If the ifile we're deleting is the currently open ifile,
150 curr_ifile
= getoff_ifile(curr_ifile
);
158 * Get the ifile after a given one in the list.
164 register struct ifile
*p
;
166 p
= (h
== NULL_IFILE
) ? &anchor
: int_ifile(h
);
167 if (p
->h_next
== &anchor
)
169 return (ext_ifile(p
->h_next
));
173 * Get the ifile before a given one in the list.
179 register struct ifile
*p
;
181 p
= (h
== NULL_IFILE
) ? &anchor
: int_ifile(h
);
182 if (p
->h_prev
== &anchor
)
184 return (ext_ifile(p
->h_prev
));
188 * Return a different ifile from the given one.
196 if ((newifile
= prev_ifile(ifile
)) != NULL_IFILE
)
198 if ((newifile
= next_ifile(ifile
)) != NULL_IFILE
)
204 * Return the number of ifiles.
213 * Find an ifile structure, given a filename.
215 static struct ifile
*
219 register struct ifile
*p
;
221 for (p
= anchor
.h_next
; p
!= &anchor
; p
= p
->h_next
)
222 if (strcmp(filename
, p
->h_filename
) == 0)
228 * Get the ifile associated with a filename.
229 * If the filename has not been seen before,
230 * insert the new ifile after "prev" in the list.
233 get_ifile(filename
, prev
)
237 register struct ifile
*p
;
239 if ((p
= find_ifile(filename
)) == NULL
)
240 p
= new_ifile(filename
, int_ifile(prev
));
241 return (ext_ifile(p
));
245 * Get the filename associated with a ifile.
253 return (int_ifile(ifile
)->h_filename
);
257 * Get the index of the file associated with a ifile.
263 return (int_ifile(ifile
)->h_index
);
267 * Save the file position to be associated with a given file.
270 store_pos(ifile
, scrpos
)
272 struct scrpos
*scrpos
;
274 int_ifile(ifile
)->h_scrpos
= *scrpos
;
278 * Recall the file position associated with a file.
279 * If no position has been associated with the file, return NULL_POSITION.
282 get_pos(ifile
, scrpos
)
284 struct scrpos
*scrpos
;
286 *scrpos
= int_ifile(ifile
)->h_scrpos
;
290 * Mark the ifile as "opened".
296 int_ifile(ifile
)->h_opened
= 1;
300 * Return whether the ifile has been opened previously.
306 return (int_ifile(ifile
)->h_opened
);
310 hold_ifile(ifile
, incr
)
314 int_ifile(ifile
)->h_hold
+= incr
;
321 return (int_ifile(ifile
)->h_hold
);
328 return (int_ifile(ifile
)->h_filestate
);
332 set_filestate(ifile
, filestate
)
336 int_ifile(ifile
)->h_filestate
= filestate
;
343 register struct ifile
*p
;
345 for (p
= anchor
.h_next
; p
!= &anchor
; p
= p
->h_next
)
347 printf("%x: %d. <%s> pos %d,%x\n",
348 p
, p
->h_index
, p
->h_filename
,
349 p
->h_scrpos
.ln
, p
->h_scrpos
.pos
);
350 ch_dump(p
->h_filestate
);