Annotation of src/usr.bin/less/ifile.c, Revision 1.1.1.1
1.1 etheisen 1: /*
2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice in the documentation and/or other materials provided with
12: * the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27:
28: /*
29: * An IFILE represents an input file.
30: *
31: * It is actually a pointer to an ifile structure,
32: * but is opaque outside this module.
33: * Ifile structures are kept in a linked list in the order they
34: * appear on the command line.
35: * Any new file which does not already appear in the list is
36: * inserted after the current file.
37: */
38:
39: #include "less.h"
40:
41: extern IFILE curr_ifile;
42:
43: struct ifile {
44: struct ifile *h_next; /* Links for command line list */
45: struct ifile *h_prev;
46: char *h_filename; /* Name of the file */
47: void *h_filestate; /* File state (used in ch.c) */
48: int h_index; /* Index within command line list */
49: int h_opened; /* Only need one bit */
50: struct scrpos h_scrpos; /* Saved position within the file */
51: };
52:
53: /*
54: * Convert an IFILE (external representation)
55: * to a struct file (internal representation), and vice versa.
56: */
57: #define int_ifile(h) ((struct ifile *)(h))
58: #define ext_ifile(h) ((IFILE)(h))
59:
60: /*
61: * Anchor for linked list.
62: */
63: static struct ifile anchor = { &anchor, &anchor, 0 };
64: static int ifiles = 0;
65:
66: static void
67: incr_index(p, incr)
68: register struct ifile *p;
69: int incr;
70: {
71: for (; p != &anchor; p = p->h_next)
72: p->h_index += incr;
73: }
74:
75: static void
76: link_ifile(p, prev)
77: struct ifile *p;
78: struct ifile *prev;
79: {
80: /*
81: * Link into list.
82: */
83: if (prev == NULL)
84: prev = &anchor;
85: p->h_next = prev->h_next;
86: p->h_prev = prev;
87: prev->h_next->h_prev = p;
88: prev->h_next = p;
89: /*
90: * Calculate index for the new one,
91: * and adjust the indexes for subsequent ifiles in the list.
92: */
93: p->h_index = prev->h_index + 1;
94: incr_index(p->h_next, 1);
95: ifiles++;
96: }
97:
98: static void
99: unlink_ifile(p)
100: struct ifile *p;
101: {
102: p->h_next->h_prev = p->h_prev;
103: p->h_prev->h_next = p->h_next;
104: incr_index(p->h_next, -1);
105: ifiles--;
106: }
107:
108: /*
109: * Allocate a new ifile structure and stick a filename in it.
110: * It should go after "prev" in the list
111: * (or at the beginning of the list if "prev" is NULL).
112: * Return a pointer to the new ifile structure.
113: */
114: static struct ifile *
115: new_ifile(filename, prev)
116: char *filename;
117: struct ifile *prev;
118: {
119: register struct ifile *p;
120:
121: /*
122: * Allocate and initialize structure.
123: */
124: p = (struct ifile *) ecalloc(1, sizeof(struct ifile));
125: p->h_filename = save(filename);
126: p->h_scrpos.pos = NULL_POSITION;
127: p->h_opened = 0;
128: link_ifile(p, prev);
129: return (p);
130: }
131:
132: /*
133: * Delete an existing ifile structure.
134: */
135: public void
136: del_ifile(h)
137: IFILE h;
138: {
139: register struct ifile *p;
140:
141: if (h == NULL_IFILE)
142: return;
143: /*
144: * If the ifile we're deleting is the currently open ifile,
145: * move off it.
146: */
147: if (h == curr_ifile)
148: curr_ifile = getoff_ifile(curr_ifile);
149: p = int_ifile(h);
150: unlink_ifile(p);
151: free(p->h_filename);
152: free(p);
153: }
154:
155: /*
156: * Get the ifile after a given one in the list.
157: */
158: public IFILE
159: next_ifile(h)
160: IFILE h;
161: {
162: register struct ifile *p;
163:
164: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
165: if (p->h_next == &anchor)
166: return (NULL_IFILE);
167: return (ext_ifile(p->h_next));
168: }
169:
170: /*
171: * Get the ifile before a given one in the list.
172: */
173: public IFILE
174: prev_ifile(h)
175: IFILE h;
176: {
177: register struct ifile *p;
178:
179: p = (h == NULL_IFILE) ? &anchor : int_ifile(h);
180: if (p->h_prev == &anchor)
181: return (NULL_IFILE);
182: return (ext_ifile(p->h_prev));
183: }
184:
185: /*
186: * Return a different ifile from the given one.
187: */
188: public IFILE
189: getoff_ifile(ifile)
190: IFILE ifile;
191: {
192: IFILE newifile;
193:
194: if ((newifile = prev_ifile(ifile)) != NULL_IFILE)
195: return (newifile);
196: if ((newifile = next_ifile(ifile)) != NULL_IFILE)
197: return (newifile);
198: return (NULL_IFILE);
199: }
200:
201: /*
202: * Return the number of ifiles.
203: */
204: public int
205: nifile()
206: {
207: return (ifiles);
208: }
209:
210: /*
211: * Find an ifile structure, given a filename.
212: */
213: static struct ifile *
214: find_ifile(filename)
215: char *filename;
216: {
217: register struct ifile *p;
218:
219: for (p = anchor.h_next; p != &anchor; p = p->h_next)
220: if (strcmp(filename, p->h_filename) == 0)
221: return (p);
222: return (NULL);
223: }
224:
225: /*
226: * Get the ifile associated with a filename.
227: * If the filename has not been seen before,
228: * insert the new ifile after "prev" in the list.
229: */
230: public IFILE
231: get_ifile(filename, prev)
232: char *filename;
233: IFILE prev;
234: {
235: register struct ifile *p;
236:
237: if ((p = find_ifile(filename)) == NULL)
238: p = new_ifile(filename, int_ifile(prev));
239: return (ext_ifile(p));
240: }
241:
242: /*
243: * Get the filename associated with a ifile.
244: */
245: public char *
246: get_filename(ifile)
247: IFILE ifile;
248: {
249: if (ifile == NULL)
250: return (NULL);
251: return (int_ifile(ifile)->h_filename);
252: }
253:
254: /*
255: * Get the index of the file associated with a ifile.
256: */
257: public int
258: get_index(ifile)
259: IFILE ifile;
260: {
261: return (int_ifile(ifile)->h_index);
262: }
263:
264: /*
265: * Save the file position to be associated with a given file.
266: */
267: public void
268: store_pos(ifile, scrpos)
269: IFILE ifile;
270: struct scrpos *scrpos;
271: {
272: int_ifile(ifile)->h_scrpos = *scrpos;
273: }
274:
275: /*
276: * Recall the file position associated with a file.
277: * If no position has been associated with the file, return NULL_POSITION.
278: */
279: public void
280: get_pos(ifile, scrpos)
281: IFILE ifile;
282: struct scrpos *scrpos;
283: {
284: *scrpos = int_ifile(ifile)->h_scrpos;
285: }
286:
287: /*
288: * Mark the ifile as "opened".
289: */
290: public void
291: set_open(ifile)
292: IFILE ifile;
293: {
294: int_ifile(ifile)->h_opened = 1;
295: }
296:
297: /*
298: * Return whether the ifile has been opened previously.
299: */
300: public int
301: opened(ifile)
302: IFILE ifile;
303: {
304: return (int_ifile(ifile)->h_opened);
305: }
306:
307: public void *
308: get_filestate(ifile)
309: IFILE ifile;
310: {
311: return (int_ifile(ifile)->h_filestate);
312: }
313:
314: public void
315: set_filestate(ifile, filestate)
316: IFILE ifile;
317: void *filestate;
318: {
319: int_ifile(ifile)->h_filestate = filestate;
320: }
321:
322: #if 0
323: public void
324: if_dump()
325: {
326: register struct ifile *p;
327:
328: for (p = anchor.h_next; p != &anchor; p = p->h_next)
329: {
330: printf("%x: %d. <%s> pos %d,%x\n",
331: p, p->h_index, p->h_filename,
332: p->h_scrpos.ln, p->h_scrpos.pos);
333: ch_dump(p->h_filestate);
334: }
335: }
336: #endif